about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock162
-rw-r--r--Cargo.toml2
-rw-r--r--RELEASES.md136
-rw-r--r--compiler/rustc_ast/src/token.rs1
-rw-r--r--compiler/rustc_ast_lowering/messages.ftl168
-rw-r--r--compiler/rustc_ast_lowering/src/asm.rs1
-rw-r--r--compiler/rustc_ast_passes/messages.ftl300
-rw-r--r--compiler/rustc_attr/messages.ftl128
-rw-r--r--compiler/rustc_borrowck/messages.ftl346
-rw-r--r--compiler/rustc_borrowck/src/def_use.rs1
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs41
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs28
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs7
-rw-r--r--compiler/rustc_borrowck/src/invalidation.rs6
-rw-r--r--compiler/rustc_borrowck/src/lib.rs19
-rw-r--r--compiler/rustc_borrowck/src/nll.rs2
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs6
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs3
-rw-r--r--compiler/rustc_borrowck/src/type_check/canonical.rs45
-rw-r--r--compiler/rustc_borrowck/src/type_check/free_region_relations.rs21
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/trace.rs18
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs69
-rw-r--r--compiler/rustc_borrowck/src/type_check/relate_tys.rs21
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs11
-rw-r--r--compiler/rustc_builtin_macros/messages.ftl232
-rw-r--r--compiler/rustc_builtin_macros/src/assert/context.rs16
-rw-r--r--compiler/rustc_builtin_macros/src/compile_error.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/clone.rs3
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs11
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs3
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs3
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/default.rs3
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/hash.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/errors.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/Readme.md26
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/common.rs2
-rw-r--r--compiler/rustc_codegen_gcc/messages.ftl66
-rw-r--r--compiler/rustc_codegen_gcc/src/common.rs42
-rw-r--r--compiler/rustc_codegen_gcc/src/consts.rs17
-rw-r--r--compiler/rustc_codegen_llvm/messages.ftl108
-rw-r--r--compiler/rustc_codegen_llvm/src/attributes.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/common.rs49
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs1
-rw-r--r--compiler/rustc_codegen_ssa/messages.ftl324
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs5
-rw-r--r--compiler/rustc_codegen_ssa/src/back/metadata.rs32
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/errors.rs8
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/analyze.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/mod.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/operand.rs75
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs11
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/consts.rs12
-rw-r--r--compiler/rustc_const_eval/messages.ftl92
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/terminator.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs4
-rw-r--r--compiler/rustc_data_structures/src/sharded.rs48
-rw-r--r--compiler/rustc_driver_impl/messages.ftl20
-rw-r--r--compiler/rustc_driver_impl/src/args.rs3
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs15
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0133.md19
-rw-r--r--compiler/rustc_error_messages/src/lib.rs32
-rw-r--r--compiler/rustc_errors/messages.ftl22
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs24
-rw-r--r--compiler/rustc_errors/src/diagnostic_builder.rs8
-rw-r--r--compiler/rustc_errors/src/emitter.rs2
-rw-r--r--compiler/rustc_errors/src/lib.rs14
-rw-r--r--compiler/rustc_expand/messages.ftl178
-rw-r--r--compiler/rustc_expand/src/base.rs6
-rw-r--r--compiler/rustc_expand/src/mbe/diagnostics.rs10
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl366
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs36
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs23
-rw-r--r--compiler/rustc_hir_analysis/src/check/dropck.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs25
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs41
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/collect/item_bounds.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs13
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/explicit.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs13
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/mod.rs37
-rw-r--r--compiler/rustc_hir_typeck/messages.ftl114
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs46
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs23
-rw-r--r--compiler/rustc_hir_typeck/src/errors.rs12
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs9
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/mod.rs12
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs6
-rw-r--r--compiler/rustc_incremental/messages.ftl140
-rw-r--r--compiler/rustc_infer/messages.ftl591
-rw-r--r--compiler/rustc_infer/src/infer/at.rs2
-rw-r--r--compiler/rustc_infer/src/infer/canonical/canonicalizer.rs2
-rw-r--r--compiler/rustc_infer/src/infer/canonical/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs17
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs23
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs10
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs33
-rw-r--r--compiler/rustc_infer/src/infer/higher_ranked/mod.rs20
-rw-r--r--compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs57
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs32
-rw-r--r--compiler/rustc_infer/src/infer/outlives/verify.rs2
-rw-r--r--compiler/rustc_infer/src/infer/region_constraints/leak_check.rs144
-rw-r--r--compiler/rustc_infer/src/infer/region_constraints/mod.rs19
-rw-r--r--compiler/rustc_infer/src/infer/undo_log.rs15
-rw-r--r--compiler/rustc_interface/messages.ftl54
-rw-r--r--compiler/rustc_lint/messages.ftl749
-rw-r--r--compiler/rustc_lint/src/context.rs4
-rw-r--r--compiler/rustc_lint/src/errors.rs2
-rw-r--r--compiler/rustc_lint/src/invalid_from_utf8.rs118
-rw-r--r--compiler/rustc_lint/src/levels.rs10
-rw-r--r--compiler/rustc_lint/src/lib.rs3
-rw-r--r--compiler/rustc_lint/src/lints.rs21
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs38
-rw-r--r--compiler/rustc_lint_defs/src/lib.rs10
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h1
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp2
-rw-r--r--compiler/rustc_metadata/messages.ftl382
-rw-r--r--compiler/rustc_metadata/src/locator.rs17
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs35
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs6
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs11
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs31
-rw-r--r--compiler/rustc_middle/messages.ftl48
-rw-r--r--compiler/rustc_middle/src/infer/canonical.rs2
-rw-r--r--compiler/rustc_middle/src/lint.rs2
-rw-r--r--compiler/rustc_middle/src/middle/stability.rs12
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs2
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs5
-rw-r--r--compiler/rustc_middle/src/mir/query.rs2
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs11
-rw-r--r--compiler/rustc_middle/src/mir/terminator.rs2
-rw-r--r--compiler/rustc_middle/src/mir/traversal.rs26
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs11
-rw-r--r--compiler/rustc_middle/src/traits/query.rs2
-rw-r--r--compiler/rustc_middle/src/ty/adt.rs2
-rw-r--r--compiler/rustc_middle/src/ty/codec.rs2
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs2
-rw-r--r--compiler/rustc_middle/src/ty/context.rs101
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs13
-rw-r--r--compiler/rustc_middle/src/ty/error.rs13
-rw-r--r--compiler/rustc_middle/src/ty/fold.rs13
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs6
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs4
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs6
-rw-r--r--compiler/rustc_middle/src/ty/opaque_types.rs2
-rw-r--r--compiler/rustc_middle/src/ty/print/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs87
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs59
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs108
-rw-r--r--compiler/rustc_middle/src/ty/subst.rs9
-rw-r--r--compiler/rustc_middle/src/ty/util.rs2
-rw-r--r--compiler/rustc_middle/src/values.rs4
-rw-r--r--compiler/rustc_mir_build/messages.ftl478
-rw-r--r--compiler/rustc_mir_build/src/build/custom/parse/instruction.rs1
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs1
-rw-r--r--compiler/rustc_mir_build/src/build/scope.rs8
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/mod.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs4
-rw-r--r--compiler/rustc_mir_dataflow/messages.ftl34
-rw-r--r--compiler/rustc_mir_dataflow/src/elaborate_drops.rs10
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/direction.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/liveness.rs3
-rw-r--r--compiler/rustc_mir_transform/messages.ftl81
-rw-r--r--compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs9
-rw-r--r--compiler/rustc_mir_transform/src/check_alignment.rs8
-rw-r--r--compiler/rustc_mir_transform/src/const_prop.rs1
-rw-r--r--compiler/rustc_mir_transform/src/copy_prop.rs1
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_drops.rs9
-rw-r--r--compiler/rustc_mir_transform/src/function_item_references.rs2
-rw-r--r--compiler/rustc_mir_transform/src/generator.rs6
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs14
-rw-r--r--compiler/rustc_mir_transform/src/inline/cycle.rs2
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs5
-rw-r--r--compiler/rustc_mir_transform/src/match_branches.rs9
-rw-r--r--compiler/rustc_mir_transform/src/prettify.rs150
-rw-r--r--compiler/rustc_mir_transform/src/shim.rs12
-rw-r--r--compiler/rustc_mir_transform/src/ssa.rs1
-rw-r--r--compiler/rustc_monomorphize/messages.ftl34
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs2
-rw-r--r--compiler/rustc_monomorphize/src/partitioning.rs1182
-rw-r--r--compiler/rustc_monomorphize/src/partitioning/default.rs568
-rw-r--r--compiler/rustc_monomorphize/src/partitioning/merging.rs111
-rw-r--r--compiler/rustc_monomorphize/src/partitioning/mod.rs672
-rw-r--r--compiler/rustc_monomorphize/src/util.rs4
-rw-r--r--compiler/rustc_parse/messages.ftl1188
-rw-r--r--compiler/rustc_parse/src/parser/generics.rs44
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs4
-rw-r--r--compiler/rustc_parse/src/parser/stmt.rs7
-rw-r--r--compiler/rustc_passes/messages.ftl1058
-rw-r--r--compiler/rustc_privacy/messages.ftl18
-rw-r--r--compiler/rustc_query_impl/Cargo.toml2
-rw-r--r--compiler/rustc_query_system/messages.ftl30
-rw-r--r--compiler/rustc_resolve/messages.ftl350
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs2
-rw-r--r--compiler/rustc_resolve/src/imports.rs83
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs28
-rw-r--r--compiler/rustc_resolve/src/lib.rs4
-rw-r--r--compiler/rustc_resolve/src/macros.rs4
-rw-r--r--compiler/rustc_session/messages.ftl124
-rw-r--r--compiler/rustc_session/src/options.rs5
-rw-r--r--compiler/rustc_session/src/parse.rs5
-rw-r--r--compiler/rustc_smir/src/rustc_smir/mod.rs2
-rw-r--r--compiler/rustc_span/src/hygiene.rs2
-rw-r--r--compiler/rustc_span/src/symbol.rs4
-rw-r--r--compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs11
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs2
-rw-r--r--compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs2
-rw-r--r--compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs2
-rw-r--r--compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs2
-rw-r--r--compiler/rustc_target/src/spec/mod.rs4
-rw-r--r--compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs2
-rw-r--r--compiler/rustc_target/src/spec/x86_64_pc_solaris.rs2
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs2
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs1
-rw-r--r--compiler/rustc_trait_selection/messages.ftl14
-rw-r--r--compiler/rustc_trait_selection/src/infer.rs10
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs8
-rw-r--r--compiler/rustc_trait_selection/src/solve/canonicalize.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs7
-rw-r--r--compiler/rustc_trait_selection/src/solve/mod.rs34
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs111
-rw-r--r--compiler/rustc_trait_selection/src/traits/engine.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs5
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs33
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/outlives_bounds.rs41
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs269
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs123
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs30
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/eq.rs14
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs181
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs68
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs24
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs16
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs20
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/subtype.rs14
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs7
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs24
-rw-r--r--compiler/rustc_trait_selection/src/traits/util.rs7
-rw-r--r--compiler/rustc_traits/src/chalk/db.rs4
-rw-r--r--compiler/rustc_traits/src/chalk/lowering.rs24
-rw-r--r--compiler/rustc_traits/src/dropck_outlives.rs266
-rw-r--r--compiler/rustc_traits/src/implied_outlives_bounds.rs171
-rw-r--r--compiler/rustc_traits/src/lib.rs3
-rw-r--r--compiler/rustc_traits/src/type_op.rs121
-rw-r--r--compiler/rustc_ty_utils/messages.ftl68
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs4
-rw-r--r--compiler/rustc_ty_utils/src/assoc.rs2
-rw-r--r--compiler/rustc_ty_utils/src/consts.rs2
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs2
-rw-r--r--compiler/rustc_ty_utils/src/needs_drop.rs2
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs11
-rw-r--r--compiler/rustc_type_ir/src/lib.rs23
-rw-r--r--compiler/rustc_type_ir/src/structural_impls.rs21
-rw-r--r--compiler/rustc_type_ir/src/sty.rs72
-rw-r--r--library/alloc/src/string.rs4
-rw-r--r--library/alloc/src/vec/mod.rs1
-rw-r--r--library/alloc/tests/str.rs2
-rw-r--r--library/core/src/alloc/global.rs3
-rw-r--r--library/core/src/alloc/mod.rs5
-rw-r--r--library/core/src/any.rs10
-rw-r--r--library/core/src/array/mod.rs28
-rw-r--r--library/core/src/hash/mod.rs4
-rw-r--r--library/core/src/iter/range.rs25
-rw-r--r--library/core/src/iter/traits/marker.rs2
-rw-r--r--library/core/src/macros/mod.rs2
-rw-r--r--library/core/src/slice/mod.rs15
-rw-r--r--library/core/src/str/converts.rs4
-rw-r--r--library/portable-simd/Cargo.toml2
-rw-r--r--library/std/src/ffi/mod.rs8
-rw-r--r--library/std/src/ffi/os_str.rs82
-rw-r--r--library/std/src/io/mod.rs7
-rw-r--r--library/std/src/panicking.rs120
-rw-r--r--library/std/src/path.rs52
-rw-r--r--library/std/src/sys/common/small_c_string.rs2
-rw-r--r--library/std/src/sys/common/tests.rs4
-rw-r--r--library/std/src/sys/unix/os_str.rs9
-rw-r--r--library/std/src/sys/unix/os_str/tests.rs9
-rw-r--r--library/std/src/sys/unix/path.rs2
-rw-r--r--library/std/src/sys/unix/process/process_common.rs4
-rw-r--r--library/std/src/sys/windows/args.rs6
-rw-r--r--library/std/src/sys/windows/os_str.rs10
-rw-r--r--library/std/src/sys/windows/path.rs42
-rw-r--r--library/std/src/sys/windows/process.rs4
-rw-r--r--library/std/src/sys_common/wtf8.rs8
-rw-r--r--library/test/src/options.rs6
-rw-r--r--src/bootstrap/Cargo.lock7
-rw-r--r--src/bootstrap/Cargo.toml1
-rw-r--r--src/bootstrap/bootstrap.py99
-rw-r--r--src/bootstrap/builder.rs58
-rw-r--r--src/bootstrap/builder/tests.rs14
-rw-r--r--src/bootstrap/check.rs79
-rw-r--r--src/bootstrap/compile.rs23
-rw-r--r--src/bootstrap/config.rs51
-rw-r--r--src/bootstrap/dist.rs6
-rw-r--r--src/bootstrap/doc.rs215
-rw-r--r--src/bootstrap/download.rs7
-rw-r--r--src/bootstrap/flags.rs4
-rw-r--r--src/bootstrap/format.rs4
-rw-r--r--src/bootstrap/lib.rs28
-rw-r--r--src/bootstrap/llvm.rs2
-rw-r--r--src/bootstrap/metrics.rs119
-rw-r--r--src/bootstrap/render_tests.rs2
-rw-r--r--src/bootstrap/sanity.rs2
-rw-r--r--src/bootstrap/setup.rs4
-rw-r--r--src/bootstrap/test.rs191
-rw-r--r--src/bootstrap/tool.rs3
-rw-r--r--src/bootstrap/toolstate.rs8
-rw-r--r--src/bootstrap/util.rs27
-rw-r--r--src/ci/docker/host-x86_64/test-various/uefi_qemu_test/Cargo.toml1
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version2
-rw-r--r--src/doc/rustc/src/exploit-mitigations.md119
-rw-r--r--src/doc/unstable-book/src/compiler-flags/sanitizer.md14
-rw-r--r--src/doc/unstable-book/src/language-features/asm-experimental-arch.md17
-rw-r--r--src/etc/test-float-parse/Cargo.toml1
-rw-r--r--src/librustdoc/clean/blanket_impl.rs14
-rw-r--r--src/librustdoc/clean/inline.rs4
-rw-r--r--src/librustdoc/clean/mod.rs12
-rw-r--r--src/librustdoc/clean/types.rs44
-rw-r--r--src/librustdoc/clean/utils.rs2
-rw-r--r--src/librustdoc/config.rs1
-rw-r--r--src/librustdoc/formats/cache.rs2
-rw-r--r--src/librustdoc/html/format.rs39
-rw-r--r--src/librustdoc/html/markdown.rs122
-rw-r--r--src/librustdoc/html/render/mod.rs7
-rw-r--r--src/librustdoc/html/render/print_item.rs169
-rw-r--r--src/librustdoc/html/render/search_index.rs23
-rw-r--r--src/librustdoc/html/render/type_layout.rs4
-rw-r--r--src/librustdoc/html/templates/item_union.html8
-rw-r--r--src/librustdoc/json/conversions.rs5
-rw-r--r--src/librustdoc/lib.rs12
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs180
-rw-r--r--src/librustdoc/passes/collect_trait_impls.rs34
-rw-r--r--src/librustdoc/passes/lint/bare_urls.rs29
-rw-r--r--src/librustdoc/passes/lint/html_tags.rs170
-rw-r--r--src/librustdoc/passes/lint/unescaped_backticks.rs4
-rw-r--r--src/librustdoc/visit_ast.rs66
-rw-r--r--src/tools/build_helper/src/lib.rs1
-rw-r--r--src/tools/build_helper/src/util.rs41
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_lints/src/declared_lints.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/eta_reduction.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/invalid_utf8_in_unchecked.rs74
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/needless_collect.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/renamed_lints.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/consts.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/diagnostics.rs22
-rw-r--r--src/tools/clippy/clippy_utils/src/sugg.rs6
-rw-r--r--src/tools/clippy/tests/ui/invalid_utf8_in_unchecked.rs20
-rw-r--r--src/tools/clippy/tests/ui/invalid_utf8_in_unchecked.stderr22
-rw-r--r--src/tools/clippy/tests/ui/rename.fixed2
-rw-r--r--src/tools/clippy/tests/ui/rename.rs2
-rw-r--r--src/tools/clippy/tests/ui/rename.stderr104
-rw-r--r--src/tools/compiletest/Cargo.toml3
-rw-r--r--src/tools/compiletest/src/common.rs8
-rw-r--r--src/tools/compiletest/src/header/needs.rs7
-rw-r--r--src/tools/compiletest/src/lib.rs1136
-rw-r--r--src/tools/compiletest/src/main.rs1137
-rw-r--r--src/tools/compiletest/src/runtest.rs52
-rw-r--r--src/tools/compiletest/src/util.rs2
-rw-r--r--src/tools/miri/src/concurrency/thread.rs19
-rw-r--r--src/tools/miri/src/diagnostics.rs15
-rw-r--r--src/tools/miri/src/shims/panic.rs5
-rw-r--r--src/tools/miri/tests/fail/panic/double_panic.rs3
-rw-r--r--src/tools/miri/tests/fail/panic/double_panic.stderr29
-rw-r--r--src/tools/miri/tests/pass/panic/nested_panic_caught.rs25
-rw-r--r--src/tools/miri/tests/pass/panic/nested_panic_caught.stderr4
-rw-r--r--src/tools/miri/tests/pass/shims/time-with-isolation2.stdout2
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-api/src/version.rs2
-rw-r--r--src/tools/rustdoc-gui-test/Cargo.toml10
-rw-r--r--src/tools/rustdoc-gui-test/src/config.rs62
-rw-r--r--src/tools/rustdoc-gui-test/src/main.rs156
-rw-r--r--src/tools/tidy/src/deps.rs1
-rw-r--r--src/tools/tidy/src/fluent_alphabetical.rs72
-rw-r--r--src/tools/tidy/src/lib.rs1
-rw-r--r--src/tools/tidy/src/main.rs1
-rw-r--r--src/tools/tidy/src/ui_tests.rs4
-rw-r--r--src/version2
-rw-r--r--tests/assembly/asm/mips-types.rs12
-rw-r--r--tests/codegen/array-map.rs11
-rw-r--r--tests/codegen/autovectorize-f32x4.rs7
-rw-r--r--tests/codegen/const_scalar_pair.rs8
-rw-r--r--tests/codegen/sanitizer-safestack-attr-check.rs11
-rw-r--r--tests/incremental/issue-110457-same-span-closures/auxiliary/egui_inspect_derive.rs90
-rw-r--r--tests/incremental/issue-110457-same-span-closures/main.rs47
-rw-r--r--tests/mir-opt/deref-patterns/string.foo.PreCodegen.after.mir62
-rw-r--r--tests/mir-opt/inline/cycle.g.Inline.diff16
-rw-r--r--tests/mir-opt/inline/cycle.main.Inline.diff16
-rw-r--r--tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir24
-rw-r--r--tests/mir-opt/inline/inline_diverging.h.Inline.diff38
-rw-r--r--tests/mir-opt/inline/inline_generator.main.Inline.diff32
-rw-r--r--tests/mir-opt/inline/issue_106141.outer.Inline.diff18
-rw-r--r--tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir128
-rw-r--r--tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir128
-rw-r--r--tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.mir20
-rw-r--r--tests/mir-opt/issue_101973.inner.ConstProp.diff16
-rw-r--r--tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir62
-rw-r--r--tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir8
-rw-r--r--tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.mir122
-rw-r--r--tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.mir68
-rw-r--r--tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.mir52
-rw-r--r--tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir40
-rw-r--r--tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.mir74
-rw-r--r--tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.mir132
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.mir210
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.mir250
-rw-r--r--tests/mir-opt/pre-codegen/try_identity.new.PreCodegen.after.mir48
-rw-r--r--tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir18
-rw-r--r--tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.diff7
-rw-r--r--tests/mir-opt/switch_to_self.rs21
-rw-r--r--tests/mir-opt/switch_to_self.test.MatchBranchSimplification.diff19
-rw-r--r--tests/mir-opt/tls_access.main.PreCodegen.after.mir16
-rw-r--r--tests/mir-opt/while_storage.while_loop.PreCodegen.after.mir8
-rw-r--r--tests/rustdoc-gui/search-result-display.goml12
-rw-r--r--tests/rustdoc-gui/source-anchor-scroll.goml8
-rw-r--r--tests/rustdoc-gui/src/extend_css/lib.rs1
-rw-r--r--tests/rustdoc-gui/src/link_to_definition/lib.rs1
-rw-r--r--tests/rustdoc-gui/src/scrape_examples/src/lib.rs1
-rw-r--r--tests/rustdoc-gui/target.goml8
-rw-r--r--tests/rustdoc-ui/intra-doc/issue-110495-suffix-with-space.stderr7
-rw-r--r--tests/rustdoc-ui/intra-doc/weird-syntax.rs140
-rw-r--r--tests/rustdoc-ui/intra-doc/weird-syntax.stderr272
-rw-r--r--tests/rustdoc/reexport-doc-hidden-inside-private.rs16
-rw-r--r--tests/rustdoc/reexport-doc-hidden.rs3
-rw-r--r--tests/rustdoc/reexport-hidden-macro.rs2
-rw-r--r--tests/rustdoc/reexport-of-doc-hidden.rs42
-rw-r--r--tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr2
-rw-r--r--tests/ui/async-await/issue-78115.rs (renamed from tests/ui/issues/issue-78115.rs)0
-rw-r--r--tests/ui/backtrace.rs6
-rw-r--r--tests/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.stderr2
-rw-r--r--tests/ui/borrowck/borrowck-vec-pattern-nesting.rs2
-rw-r--r--tests/ui/borrowck/borrowck-vec-pattern-nesting.stderr18
-rw-r--r--tests/ui/borrowck/issue-45199.rs3
-rw-r--r--tests/ui/borrowck/issue-45199.stderr4
-rw-r--r--tests/ui/closures/2229_closure_analysis/unique-borrows-are-invariant-1.rs18
-rw-r--r--tests/ui/closures/2229_closure_analysis/unique-borrows-are-invariant-1.stderr14
-rw-r--r--tests/ui/closures/2229_closure_analysis/unique-borrows-are-invariant-2.rs31
-rw-r--r--tests/ui/closures/2229_closure_analysis/unique-borrows-are-invariant-2.stderr15
-rw-r--r--tests/ui/coercion/issue-3794.rs (renamed from tests/ui/issues/issue-3794.rs)0
-rw-r--r--tests/ui/coherence/coherence-inherited-subtyping.re.stderr14
-rw-r--r--tests/ui/coherence/coherence-inherited-subtyping.rs2
-rw-r--r--tests/ui/coherence/coherence-inherited-subtyping.stderr (renamed from tests/ui/coherence/coherence-inherited-subtyping.old.stderr)2
-rw-r--r--tests/ui/coinduction/canonicalization-rerun.rs4
-rw-r--r--tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.rs10
-rw-r--r--tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.stderr11
-rw-r--r--tests/ui/const-generics/transmute-fail.stderr8
-rw-r--r--tests/ui/consts/const_cmp_type_id.stderr2
-rw-r--r--tests/ui/consts/issue-16538.mir.stderr (renamed from tests/ui/issues/issue-16538.mir.stderr)0
-rw-r--r--tests/ui/consts/issue-16538.rs (renamed from tests/ui/issues/issue-16538.rs)0
-rw-r--r--tests/ui/consts/issue-16538.thir.stderr (renamed from tests/ui/issues/issue-16538.thir.stderr)0
-rw-r--r--tests/ui/consts/issue-28822.rs (renamed from tests/ui/issues/issue-28822.rs)0
-rw-r--r--tests/ui/consts/issue-29798.rs (renamed from tests/ui/issues/issue-29798.rs)0
-rw-r--r--tests/ui/consts/issue-73976-monomorphic.stderr1
-rw-r--r--tests/ui/deriving/deriving-all-codegen.stdout15
-rw-r--r--tests/ui/editions/edition-raw-pointer-method-2018.rs2
-rw-r--r--tests/ui/editions/edition-raw-pointer-method-2018.stderr2
-rw-r--r--tests/ui/enum-discriminant/issue-50689.rs (renamed from tests/ui/issues/issue-50689.rs)0
-rw-r--r--tests/ui/extern/issue-1251.rs (renamed from tests/ui/issues/issue-1251.rs)0
-rw-r--r--tests/ui/for-loop-while/issue-1257.rs (renamed from tests/ui/issues/issue-1257.rs)0
-rw-r--r--tests/ui/higher-rank-trait-bounds/issue-95230.rs11
-rw-r--r--tests/ui/higher-ranked/higher-lifetime-bounds.rs (renamed from tests/ui/higher-lifetime-bounds.rs)0
-rw-r--r--tests/ui/higher-ranked/higher-lifetime-bounds.stderr (renamed from tests/ui/higher-lifetime-bounds.stderr)0
-rw-r--r--tests/ui/higher-ranked/leak-check-in-selection.rs24
-rw-r--r--tests/ui/higher-ranked/subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr (renamed from tests/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr)0
-rw-r--r--tests/ui/higher-ranked/subtype/hr-subtype.bound_a_vs_free_x.stderr (renamed from tests/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr)0
-rw-r--r--tests/ui/higher-ranked/subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr (renamed from tests/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr)0
-rw-r--r--tests/ui/higher-ranked/subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr (renamed from tests/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr)0
-rw-r--r--tests/ui/higher-ranked/subtype/hr-subtype.free_x_vs_free_y.stderr (renamed from tests/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr)0
-rw-r--r--tests/ui/higher-ranked/subtype/hr-subtype.rs (renamed from tests/ui/hr-subtype/hr-subtype.rs)0
-rw-r--r--tests/ui/higher-ranked/subtype/placeholder-pattern-fail.rs (renamed from tests/ui/hr-subtype/placeholder-pattern-fail.rs)0
-rw-r--r--tests/ui/higher-ranked/subtype/placeholder-pattern-fail.stderr (renamed from tests/ui/hr-subtype/placeholder-pattern-fail.stderr)0
-rw-r--r--tests/ui/higher-ranked/subtype/placeholder-pattern.rs (renamed from tests/ui/hr-subtype/placeholder-pattern.rs)0
-rw-r--r--tests/ui/higher-ranked/subtype/return-static.rs (renamed from tests/ui/hr-subtype/return-static.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/complex.rs (renamed from tests/ui/higher-rank-trait-bounds/complex.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/due-to-where-clause.rs (renamed from tests/ui/higher-rank-trait-bounds/due-to-where-clause.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/due-to-where-clause.stderr (renamed from tests/ui/higher-rank-trait-bounds/due-to-where-clause.stderr)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/fn-ptr.classic.stderr (renamed from tests/ui/higher-rank-trait-bounds/fn-ptr.classic.stderr)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/fn-ptr.rs (renamed from tests/ui/higher-rank-trait-bounds/fn-ptr.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hang-on-deeply-nested-dyn.rs (renamed from tests/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hang-on-deeply-nested-dyn.stderr (renamed from tests/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.stderr)2
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-binder-levels-in-object-types.rs (renamed from tests/ui/higher-rank-trait-bounds/hrtb-binder-levels-in-object-types.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-cache-issue-54302.rs (renamed from tests/ui/higher-rank-trait-bounds/hrtb-cache-issue-54302.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-cache-issue-54302.stderr (renamed from tests/ui/higher-rank-trait-bounds/hrtb-cache-issue-54302.stderr)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.rs (renamed from tests/ui/higher-rank-trait-bounds/hrtb-conflate-regions.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr (renamed from tests/ui/higher-rank-trait-bounds/hrtb-conflate-regions.stderr)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-debruijn-in-receiver.rs (renamed from tests/ui/higher-rank-trait-bounds/hrtb-debruijn-in-receiver.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-debruijn-in-receiver.stderr (renamed from tests/ui/higher-rank-trait-bounds/hrtb-debruijn-in-receiver.stderr)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-debruijn-object-types-in-closures.rs (renamed from tests/ui/higher-rank-trait-bounds/hrtb-debruijn-object-types-in-closures.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-fn.rs (renamed from tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-fn.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-fn.stderr (renamed from tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-fn.stderr)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.rs (renamed from tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-contravariant.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.stderr (renamed from tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-contravariant.stderr)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.rs (renamed from tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-covariant.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.rs (renamed from tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-invariant.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.stderr (renamed from tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-invariant.stderr)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-fn-like-trait-object.rs (renamed from tests/ui/higher-rank-trait-bounds/hrtb-fn-like-trait-object.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-fn-like-trait.rs (renamed from tests/ui/higher-rank-trait-bounds/hrtb-fn-like-trait.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits-transitive.rs (renamed from tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits-transitive.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr (renamed from tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.rs (renamed from tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr (renamed from tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits.stderr)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-identity-fn-borrows.rs (renamed from tests/ui/higher-rank-trait-bounds/hrtb-identity-fn-borrows.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-identity-fn-borrows.stderr (renamed from tests/ui/higher-rank-trait-bounds/hrtb-identity-fn-borrows.stderr)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-just-for-static.rs (renamed from tests/ui/higher-rank-trait-bounds/hrtb-just-for-static.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-just-for-static.stderr (renamed from tests/ui/higher-rank-trait-bounds/hrtb-just-for-static.stderr)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-malformed-lifetime-generics.rs (renamed from tests/ui/higher-rank-trait-bounds/hrtb-malformed-lifetime-generics.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-malformed-lifetime-generics.stderr (renamed from tests/ui/higher-rank-trait-bounds/hrtb-malformed-lifetime-generics.stderr)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-opt-in-copy.rs (renamed from tests/ui/higher-rank-trait-bounds/hrtb-opt-in-copy.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-parse.rs (renamed from tests/ui/higher-rank-trait-bounds/hrtb-parse.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.polonius.stderr (renamed from tests/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.polonius.stderr)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.rs (renamed from tests/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.stderr (renamed from tests/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.stderr)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-precedence-of-plus-where-clause.rs (renamed from tests/ui/higher-rank-trait-bounds/hrtb-precedence-of-plus-where-clause.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-precedence-of-plus.rs (renamed from tests/ui/higher-rank-trait-bounds/hrtb-precedence-of-plus.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-resolve-lifetime.rs (renamed from tests/ui/higher-rank-trait-bounds/hrtb-resolve-lifetime.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-trait-object-paren-notation.rs (renamed from tests/ui/higher-rank-trait-bounds/hrtb-trait-object-paren-notation.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-trait-object-passed-to-closure.rs (renamed from tests/ui/higher-rank-trait-bounds/hrtb-trait-object-passed-to-closure.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-type-outlives.rs (renamed from tests/ui/higher-rank-trait-bounds/hrtb-type-outlives.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-unboxed-closure-trait.rs (renamed from tests/ui/higher-rank-trait-bounds/hrtb-unboxed-closure-trait.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-wrong-kind.rs (renamed from tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-wrong-kind.stderr (renamed from tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/issue-100689.rs (renamed from tests/ui/higher-rank-trait-bounds/issue-100689.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/issue-102899.rs (renamed from tests/ui/higher-rank-trait-bounds/issue-102899.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/issue-30786.rs (renamed from tests/ui/higher-rank-trait-bounds/issue-30786.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/issue-30786.stderr (renamed from tests/ui/higher-rank-trait-bounds/issue-30786.stderr)2
-rw-r--r--tests/ui/higher-ranked/trait-bounds/issue-36139-normalize-closure-sig.rs (renamed from tests/ui/higher-rank-trait-bounds/issue-36139-normalize-closure-sig.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/issue-39292.rs (renamed from tests/ui/higher-rank-trait-bounds/issue-39292.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/issue-42114.rs (renamed from tests/ui/higher-rank-trait-bounds/issue-42114.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/issue-43623.rs (renamed from tests/ui/higher-rank-trait-bounds/issue-43623.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/issue-46989.rs (renamed from tests/ui/higher-rank-trait-bounds/issue-46989.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/issue-46989.stderr (renamed from tests/ui/higher-rank-trait-bounds/issue-46989.stderr)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/issue-57639.rs (renamed from tests/ui/higher-rank-trait-bounds/issue-57639.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/issue-58451.rs (renamed from tests/ui/higher-rank-trait-bounds/issue-58451.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/issue-58451.stderr (renamed from tests/ui/higher-rank-trait-bounds/issue-58451.stderr)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/issue-59311.rs (renamed from tests/ui/higher-rank-trait-bounds/issue-59311.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/issue-59311.stderr (renamed from tests/ui/higher-rank-trait-bounds/issue-59311.stderr)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/issue-60283.rs (renamed from tests/ui/higher-rank-trait-bounds/issue-60283.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/issue-62203-hrtb-ice.rs (renamed from tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/issue-62203-hrtb-ice.stderr (renamed from tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/issue-88446.rs (renamed from tests/ui/higher-rank-trait-bounds/issue-88446.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/issue-88586-hr-self-outlives-in-trait-def.rs (renamed from tests/ui/higher-rank-trait-bounds/issue-88586-hr-self-outlives-in-trait-def.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/issue-90177.rs (renamed from tests/ui/higher-rank-trait-bounds/issue-90177.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/issue-95034.rs (renamed from tests/ui/higher-rank-trait-bounds/issue-95034.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/issue-95230.next.stderr (renamed from tests/ui/higher-rank-trait-bounds/issue-95230.new.stderr)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/issue-95230.rs11
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-44005.rs (renamed from tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-44005.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-56556.rs (renamed from tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-56556.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-1.rs (renamed from tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-2.rs (renamed from tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-2.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.rs (renamed from tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr (renamed from tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.stderr)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-4.rs (renamed from tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-4.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-5.rs (renamed from tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-5.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-6.rs (renamed from tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-6.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-70120.rs (renamed from tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.migrate.stderr (renamed from tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.migrate.stderr)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.rs (renamed from tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr (renamed from tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.stderr)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-74261.rs (renamed from tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-74261.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-76956.rs (renamed from tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-76956.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-80706.rs (renamed from tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80706.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-80956.rs (renamed from tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80956.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-81809.rs (renamed from tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-81809.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-85455.rs (renamed from tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-85455.stderr (renamed from tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89118.rs (renamed from tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89118.stderr (renamed from tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89436.rs (renamed from tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89436.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90612.rs (renamed from tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90612.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90638.rs (renamed from tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90638.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90875.rs (renamed from tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90875.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90950.rs (renamed from tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90950.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90950.stderr (renamed from tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90950.stderr)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution.rs (renamed from tests/ui/higher-rank-trait-bounds/normalize-under-binder/norm-before-method-resolution.rs)0
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution.stderr (renamed from tests/ui/higher-rank-trait-bounds/normalize-under-binder/norm-before-method-resolution.stderr)0
-rw-r--r--tests/ui/impl-trait/autoderef.rs2
-rw-r--r--tests/ui/impl-trait/multiple-defining-usages-in-body.rs12
-rw-r--r--tests/ui/impl-trait/multiple-defining-usages-in-body.stderr26
-rw-r--r--tests/ui/imports/issue-55884-2.rs1
-rw-r--r--tests/ui/imports/issue-55884-2.stderr6
-rw-r--r--tests/ui/issues/issue-17954.stderr2
-rw-r--r--tests/ui/issues/issue-52049.stderr4
-rw-r--r--tests/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr2
-rw-r--r--tests/ui/lint/invalid_from_utf8.rs93
-rw-r--r--tests/ui/lint/invalid_from_utf8.stderr110
-rw-r--r--tests/ui/lint/rfc-2383-lint-reason/root-attribute-confusion.rs7
-rw-r--r--tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.rs1
-rw-r--r--tests/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs85
-rw-r--r--tests/ui/macros/rfc-2011-nicer-assert-messages/all-not-available-cases.rs2
-rw-r--r--tests/ui/macros/rfc-2011-nicer-assert-messages/assert-with-custom-errors-does-not-create-unnecessary-code.rs2
-rw-r--r--tests/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs2
-rw-r--r--tests/ui/macros/rfc-2011-nicer-assert-messages/feature-gate-generic_assert.rs2
-rw-r--r--tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.rs2
-rw-r--r--tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout2
-rw-r--r--tests/ui/methods/call_method_unknown_pointee.rs28
-rw-r--r--tests/ui/methods/call_method_unknown_pointee.stderr27
-rw-r--r--tests/ui/mir/addrof_alignment.rs15
-rw-r--r--tests/ui/mismatched_types/E0053.stderr2
-rw-r--r--tests/ui/mismatched_types/issue-112036.rs7
-rw-r--r--tests/ui/mismatched_types/issue-112036.stderr15
-rw-r--r--tests/ui/offset-of/offset-of-unsized.rs15
-rw-r--r--tests/ui/panics/nested_panic_caught.rs24
-rw-r--r--tests/ui/parser/issues/issue-111148.rs2
-rw-r--r--tests/ui/parser/issues/issue-111148.stderr8
-rw-r--r--tests/ui/parser/typod-const-in-const-param-def.rs16
-rw-r--r--tests/ui/parser/typod-const-in-const-param-def.stderr46
-rw-r--r--tests/ui/pattern/issue-94866.rs (renamed from tests/ui/issue-94866.rs)0
-rw-r--r--tests/ui/pattern/issue-94866.stderr (renamed from tests/ui/issue-94866.stderr)0
-rw-r--r--tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr94
-rw-r--r--tests/ui/pattern/usefulness/empty-match.normal.stderr93
-rw-r--r--tests/ui/pattern/usefulness/empty-match.rs66
-rw-r--r--tests/ui/privacy/issue-111220-2-tuple-struct-fields-projection.rs33
-rw-r--r--tests/ui/privacy/issue-111220-2-tuple-struct-fields-projection.stderr9
-rw-r--r--tests/ui/privacy/issue-111220-tuple-struct-fields.rs46
-rw-r--r--tests/ui/privacy/issue-111220-tuple-struct-fields.stderr21
-rw-r--r--tests/ui/process/process-panic-after-fork.rs2
-rw-r--r--tests/ui/resolve/hidden_glob_reexports.rs52
-rw-r--r--tests/ui/resolve/hidden_glob_reexports.stderr31
-rw-r--r--tests/ui/structs-enums/issue-3008-1.rs (renamed from tests/ui/issues/issue-3008-1.rs)0
-rw-r--r--tests/ui/structs-enums/issue-3008-1.stderr (renamed from tests/ui/issues/issue-3008-1.stderr)0
-rw-r--r--tests/ui/structs-enums/issue-3008-2.rs (renamed from tests/ui/issues/issue-3008-2.rs)0
-rw-r--r--tests/ui/structs-enums/issue-3008-2.stderr (renamed from tests/ui/issues/issue-3008-2.stderr)0
-rw-r--r--tests/ui/structs-enums/issue-3008-3.rs (renamed from tests/ui/issues/issue-3008-3.rs)0
-rw-r--r--tests/ui/structs-enums/issue-3008-3.stderr (renamed from tests/ui/issues/issue-3008-3.stderr)0
-rw-r--r--tests/ui/suggestions/issue-103646.rs11
-rw-r--r--tests/ui/suggestions/issue-103646.stderr21
-rw-r--r--tests/ui/thir-print/thir-flat.stdout2
-rw-r--r--tests/ui/track-diagnostics/track6.stderr2
-rw-r--r--tests/ui/traits/new-solver/leak-check-coinductive-cycle.rs33
-rw-r--r--tests/ui/type-alias-impl-trait/coherence_different_hidden_ty.rs25
-rw-r--r--tests/ui/type-alias-impl-trait/coherence_different_hidden_ty.stderr12
-rw-r--r--tests/ui/type-alias-impl-trait/coherence_generalization.rs2
-rw-r--r--tests/ui/typeck/issue-106929.rs13
-rw-r--r--tests/ui/typeck/issue-106929.stderr15
-rw-r--r--tests/ui/typeck/issue-1871.rs (renamed from tests/ui/issues/issue-1871.rs)0
-rw-r--r--tests/ui/typeck/issue-1871.stderr (renamed from tests/ui/issues/issue-1871.stderr)0
-rw-r--r--tests/ui/typeck/issue-2063-resource.rs (renamed from tests/ui/issues/issue-2063-resource.rs)0
-rw-r--r--tests/ui/typeck/issue-2063.rs (renamed from tests/ui/issues/issue-2063.rs)0
-rw-r--r--tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.rs2
-rw-r--r--tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.stderr2
-rw-r--r--tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr2
-rw-r--r--tests/ui/where-clauses/issue-50825-1.rs (renamed from tests/ui/issues/issue-50825-1.rs)0
-rw-r--r--tests/ui/where-clauses/issue-50825.rs (renamed from tests/ui/issues/issue-50825.rs)0
-rw-r--r--triagebot.toml2
665 files changed, 13919 insertions, 10838 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 0369442f11c..e7aa317ad75 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -272,17 +272,6 @@ dependencies = [
 
 [[package]]
 name = "bstr"
-version = "0.2.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223"
-dependencies = [
- "lazy_static",
- "memchr",
- "regex-automata 0.1.10",
-]
-
-[[package]]
-name = "bstr"
 version = "1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5ffdb39cb703212f3c11973452c2861b972f757b021158f3516ba10f2fa8b2c1"
@@ -417,9 +406,9 @@ version = "0.1.0"
 
 [[package]]
 name = "cc"
-version = "1.0.77"
+version = "1.0.79"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4"
+checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
 
 [[package]]
 name = "cfg-if"
@@ -667,16 +656,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "codespan-reporting"
-version = "0.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
-dependencies = [
- "termcolor",
- "unicode-width",
-]
-
-[[package]]
 name = "collect-license-metadata"
 version = "0.1.0"
 dependencies = [
@@ -842,9 +821,9 @@ dependencies = [
 
 [[package]]
 name = "crossbeam-channel"
-version = "0.5.6"
+version = "0.5.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
+checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
 dependencies = [
  "cfg-if",
  "crossbeam-utils",
@@ -863,14 +842,14 @@ dependencies = [
 
 [[package]]
 name = "crossbeam-epoch"
-version = "0.9.13"
+version = "0.9.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a"
+checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695"
 dependencies = [
  "autocfg",
  "cfg-if",
  "crossbeam-utils",
- "memoffset 0.7.1",
+ "memoffset",
  "scopeguard",
 ]
 
@@ -944,50 +923,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "cxx"
-version = "1.0.94"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f61f1b6389c3fe1c316bf8a4dccc90a38208354b330925bce1f74a6c4756eb93"
-dependencies = [
- "cc",
- "cxxbridge-flags",
- "cxxbridge-macro",
- "link-cplusplus",
-]
-
-[[package]]
-name = "cxx-build"
-version = "1.0.94"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12cee708e8962df2aeb38f594aae5d827c022b6460ac71a7a3e2c3c2aae5a07b"
-dependencies = [
- "cc",
- "codespan-reporting",
- "once_cell",
- "proc-macro2",
- "quote",
- "scratch",
- "syn 2.0.8",
-]
-
-[[package]]
-name = "cxxbridge-flags"
-version = "1.0.94"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7944172ae7e4068c533afbb984114a56c46e9ccddda550499caa222902c7f7bb"
-
-[[package]]
-name = "cxxbridge-macro"
-version = "1.0.94"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.8",
-]
-
-[[package]]
 name = "datafrog"
 version = "2.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1273,7 +1208,7 @@ version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a3cf3a800ff6e860c863ca6d4b16fd999db8b752819c1606884047b73e468535"
 dependencies = [
- "memoffset 0.8.0",
+ "memoffset",
  "rustc_version",
 ]
 
@@ -1548,12 +1483,12 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
 
 [[package]]
 name = "globset"
-version = "0.4.9"
+version = "0.4.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0a1e17342619edbc21a964c2afbeb6c820c6a2560032872f397bb97ea127bd0a"
+checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc"
 dependencies = [
  "aho-corasick",
- "bstr 0.2.17",
+ "bstr",
  "fnv",
  "log",
  "regex",
@@ -1688,12 +1623,11 @@ dependencies = [
 
 [[package]]
 name = "iana-time-zone-haiku"
-version = "0.1.1"
+version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca"
+checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
 dependencies = [
- "cxx",
- "cxx-build",
+ "cc",
 ]
 
 [[package]]
@@ -1780,11 +1714,10 @@ checksum = "c3360c7b59e5ffa2653671fb74b4741a5d343c03f331c0a4aeda42b5c2b0ec7d"
 
 [[package]]
 name = "ignore"
-version = "0.4.18"
+version = "0.4.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "713f1b139373f96a2e0ce3ac931cd01ee973c3c5dd7c40c0c2efe96ad2b6751d"
+checksum = "dbe7873dab538a9a44ad79ede1faf5f30d49f9a5c883ddbab48bce81b64b7492"
 dependencies = [
- "crossbeam-utils",
  "globset",
  "lazy_static",
  "log",
@@ -2036,15 +1969,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "link-cplusplus"
-version = "1.0.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5"
-dependencies = [
- "cc",
-]
-
-[[package]]
 name = "linkchecker"
 version = "0.1.0"
 dependencies = [
@@ -2226,24 +2150,6 @@ dependencies = [
 
 [[package]]
 name = "memoffset"
-version = "0.6.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
-dependencies = [
- "autocfg",
-]
-
-[[package]]
-name = "memoffset"
-version = "0.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
-dependencies = [
- "autocfg",
-]
-
-[[package]]
-name = "memoffset"
 version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1"
@@ -2439,11 +2345,11 @@ checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
 
 [[package]]
 name = "opener"
-version = "0.5.0"
+version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ea3ebcd72a54701f56345f16785a6d3ac2df7e986d273eb4395c0b01db17952"
+checksum = "293c15678e37254c15bd2f092314abb4e51d7fdde05c2021279c12631b54f005"
 dependencies = [
- "bstr 0.2.17",
+ "bstr",
  "winapi",
 ]
 
@@ -4082,7 +3988,7 @@ version = "0.0.0"
 dependencies = [
  "field-offset",
  "measureme",
- "memoffset 0.6.5",
+ "memoffset",
  "rustc-rayon-core",
  "rustc_ast",
  "rustc_data_structures",
@@ -4380,6 +4286,16 @@ dependencies = [
 ]
 
 [[package]]
+name = "rustdoc-gui-test"
+version = "0.1.0"
+dependencies = [
+ "build_helper",
+ "compiletest",
+ "getopts",
+ "walkdir",
+]
+
+[[package]]
 name = "rustdoc-json-types"
 version = "0.1.0"
 dependencies = [
@@ -4522,12 +4438,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
 
 [[package]]
-name = "scratch"
-version = "1.0.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1"
-
-[[package]]
 name = "self_cell"
 version = "0.10.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4972,22 +4882,22 @@ checksum = "aac81b6fd6beb5884b0cf3321b8117e6e5d47ecb6fc89f414cfdcca8b2fe2dd8"
 
 [[package]]
 name = "thiserror"
-version = "1.0.38"
+version = "1.0.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
+checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.38"
+version = "1.0.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
+checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.102",
+ "syn 2.0.8",
 ]
 
 [[package]]
@@ -5225,7 +5135,7 @@ version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "191a442639ea102fa62671026047e51d574bfda44b7fdf32151d7314624c1cd2"
 dependencies = [
- "bstr 1.3.0",
+ "bstr",
  "cargo-platform",
  "cargo_metadata 0.15.3",
  "color-eyre",
diff --git a/Cargo.toml b/Cargo.toml
index 53331e2869f..6e84df5c693 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,4 +1,5 @@
 [workspace]
+resolver = "1"
 members = [
   "compiler/rustc",
   "library/std",
@@ -40,6 +41,7 @@ members = [
   "src/tools/generate-copyright",
   "src/tools/suggest-tests",
   "src/tools/generate-windows-sys",
+  "src/tools/rustdoc-gui-test",
 ]
 
 exclude = [
diff --git a/RELEASES.md b/RELEASES.md
index 85266a17550..fa95df685aa 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,139 @@
+Version 1.70.0 (2023-06-01)
+==========================
+
+<a id="1.70.0-Language"></a>
+
+Language
+--------
+- [Relax ordering rules for `asm!` operands](https://github.com/rust-lang/rust/pull/105798/)
+- [Properly allow macro expanded `format_args` invocations to uses captures](https://github.com/rust-lang/rust/pull/106505/)
+- [Lint ambiguous glob re-exports](https://github.com/rust-lang/rust/pull/107880/)
+- [Perform const and unsafe checking for expressions in `let _ = expr` position.](https://github.com/rust-lang/rust/pull/102256/)
+
+<a id="1.70.0-Compiler"></a>
+
+Compiler
+--------
+- [Extend -Cdebuginfo with new options and named aliases](https://github.com/rust-lang/rust/pull/109808/)
+  This provides a smaller version of debuginfo for cases that only need line number information
+  (`-Cdebuginfo=line-tables-only`), which may eventually become the default for `-Cdebuginfo=1`.
+- [Make `unused_allocation` lint against `Box::new` too](https://github.com/rust-lang/rust/pull/104363/)
+- [Detect uninhabited types early in const eval](https://github.com/rust-lang/rust/pull/109435/)
+- [Switch to LLD as default linker for {arm,thumb}v4t-none-eabi](https://github.com/rust-lang/rust/pull/109721/)
+- [Add tier 3 target `loongarch64-unknown-linux-gnu`](https://github.com/rust-lang/rust/pull/96971)
+- [Add tier 3 target for `i586-pc-nto-qnx700` (QNX Neutrino RTOS, version 7.0)](https://github.com/rust-lang/rust/pull/109173/), 
+- [Insert alignment checks for pointer dereferences as debug assertions](https://github.com/rust-lang/rust/pull/98112)
+  This catches undefined behavior at runtime, and may cause existing code to fail.
+
+Refer to Rust's [platform support page][platform-support-doc]
+for more information on Rust's tiered platform support.
+
+<a id="1.70.0-Libraries"></a>
+
+Libraries
+---------
+- [Document NonZeroXxx layout guarantees](https://github.com/rust-lang/rust/pull/94786/)
+- [Windows: make `Command` prefer non-verbatim paths](https://github.com/rust-lang/rust/pull/96391/)
+- [Implement Default for some alloc/core iterators](https://github.com/rust-lang/rust/pull/99929/)
+- [Fix handling of trailing bare CR in str::lines](https://github.com/rust-lang/rust/pull/100311/)
+- [allow negative numeric literals in `concat!`](https://github.com/rust-lang/rust/pull/106844/)
+- [Add documentation about the memory layout of `Cell`](https://github.com/rust-lang/rust/pull/106921/)
+- [Use `partial_cmp` to implement tuple `lt`/`le`/`ge`/`gt`](https://github.com/rust-lang/rust/pull/108157/)
+- [Stabilize `atomic_as_ptr`](https://github.com/rust-lang/rust/pull/108419/)
+- [Stabilize `nonnull_slice_from_raw_parts`](https://github.com/rust-lang/rust/pull/97506/)
+- [Partial stabilization of `once_cell`](https://github.com/rust-lang/rust/pull/105587/)
+- [Stabilize `nonzero_min_max`](https://github.com/rust-lang/rust/pull/106633/)
+- [Flatten/inline format_args!() and (string and int) literal arguments into format_args!()](https://github.com/rust-lang/rust/pull/106824/)
+- [Stabilize movbe target feature](https://github.com/rust-lang/rust/pull/107711/)
+- [don't splice from files into pipes in io::copy](https://github.com/rust-lang/rust/pull/108283/)
+- [Add a builtin unstable `FnPtr` trait that is implemented for all function pointers](https://github.com/rust-lang/rust/pull/108080/)
+  This extends `Debug`, `Pointer`, `Hash`, `PartialEq`, `Eq`, `PartialOrd`, and `Ord`
+  implementations for function pointers with all ABIs.
+
+<a id="1.70.0-Stabilized-APIs"></a>
+
+Stabilized APIs
+---------------
+
+- [`NonZero*::MIN/MAX`](https://doc.rust-lang.org/stable/std/num/struct.NonZeroI8.html#associatedconstant.MIN)
+- [`BinaryHeap::retain`](https://doc.rust-lang.org/stable/std/collections/struct.BinaryHeap.html#method.retain)
+- [`Default for std::collections::binary_heap::IntoIter`](https://doc.rust-lang.org/stable/std/collections/binary_heap/struct.IntoIter.html)
+- [`Default for std::collections::btree_map::{IntoIter, Iter, IterMut}`](https://doc.rust-lang.org/stable/std/collections/btree_map/struct.IntoIter.html)
+- [`Default for std::collections::btree_map::{IntoKeys, Keys}`](https://doc.rust-lang.org/stable/std/collections/btree_map/struct.IntoKeys.html)
+- [`Default for std::collections::btree_map::{IntoValues, Values}`](https://doc.rust-lang.org/stable/std/collections/btree_map/struct.IntoKeys.html)
+- [`Default for std::collections::btree_map::Range`](https://doc.rust-lang.org/stable/std/collections/btree_map/struct.Range.html)
+- [`Default for std::collections::btree_set::{IntoIter, Iter}`](https://doc.rust-lang.org/stable/std/collections/btree_set/struct.IntoIter.html)
+- [`Default for std::collections::btree_set::Range`](https://doc.rust-lang.org/stable/std/collections/btree_set/struct.Range.html)
+- [`Default for std::collections::linked_list::{IntoIter, Iter, IterMut}`](https://doc.rust-lang.org/stable/alloc/collections/linked_list/struct.IntoIter.html)
+- [`Default for std::vec::IntoIter`](https://doc.rust-lang.org/stable/alloc/vec/struct.IntoIter.html#impl-Default-for-IntoIter%3CT,+A%3E)
+- [`Default for std::iter::Chain`](https://doc.rust-lang.org/stable/std/iter/struct.Chain.html)
+- [`Default for std::iter::Cloned`](https://doc.rust-lang.org/stable/std/iter/struct.Cloned.html)
+- [`Default for std::iter::Copied`](https://doc.rust-lang.org/stable/std/iter/struct.Copied.html)
+- [`Default for std::iter::Enumerate`](https://doc.rust-lang.org/stable/std/iter/struct.Enumerate.html)
+- [`Default for std::iter::Flatten`](https://doc.rust-lang.org/stable/std/iter/struct.Flatten.html)
+- [`Default for std::iter::Fuse`](https://doc.rust-lang.org/stable/std/iter/struct.Fuse.html)
+- [`Default for std::iter::Rev`](https://doc.rust-lang.org/stable/std/iter/struct.Rev.html)
+- [`Default for std::slice::Iter`](https://doc.rust-lang.org/stable/std/slice/struct.Iter.html)
+- [`Default for std::slice::IterMut`](https://doc.rust-lang.org/stable/std/slice/struct.IterMut.html)
+- [`Rc::into_inner`](https://doc.rust-lang.org/stable/alloc/rc/struct.Rc.html#method.into_inner)
+- [`Arc::into_inner`](https://doc.rust-lang.org/stable/alloc/sync/struct.Arc.html#method.into_inner)
+- [`std::cell::OnceCell`](https://doc.rust-lang.org/stable/std/cell/struct.OnceCell.html)
+- [`Option::is_some_and`](https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.is_some_and)
+- [`NonNull::slice_from_raw_parts`](https://doc.rust-lang.org/stable/std/ptr/struct.NonNull.html#method.slice_from_raw_parts)
+- [`Result::is_ok_and`](https://doc.rust-lang.org/stable/std/result/enum.Result.html#method.is_ok_and)
+- [`Result::is_err_and`](https://doc.rust-lang.org/stable/std/result/enum.Result.html#method.is_err_and)
+- [`std::sync::atomic::Atomic*::as_ptr`](https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicU8.html#method.as_ptr)
+- [`std::io::IsTerminal`](https://doc.rust-lang.org/stable/std/io/trait.IsTerminal.html)
+- [`std::os::linux::net::SocketAddrExt`](https://doc.rust-lang.org/stable/std/os/linux/net/trait.SocketAddrExt.html)
+- [`std::os::unix::net::UnixDatagram::bind_addr`](https://doc.rust-lang.org/stable/std/os/unix/net/struct.UnixDatagram.html#method.bind_addr)
+- [`std::os::unix::net::UnixDatagram::connect_addr`](https://doc.rust-lang.org/stable/std/os/unix/net/struct.UnixDatagram.html#method.connect_addr)
+- [`std::os::unix::net::UnixDatagram::send_to_addr`](https://doc.rust-lang.org/stable/std/os/unix/net/struct.UnixDatagram.html#method.send_to_addr)
+- [`std::os::unix::net::UnixListener::bind_addr`](https://doc.rust-lang.org/stable/std/os/unix/net/struct.UnixListener.html#method.bind_addr)
+- [`std::path::Path::as_mut_os_str`](https://doc.rust-lang.org/stable/std/path/struct.Path.html#method.as_mut_os_str)
+- [`std::sync::OnceLock`](https://doc.rust-lang.org/stable/std/sync/struct.OnceLock.html)
+
+<a id="1.70.0-Cargo"></a>
+
+Cargo
+-----
+
+- [Add `CARGO_PKG_README`](https://github.com/rust-lang/cargo/pull/11645/)
+- [Make `sparse` the default protocol for crates.io](https://github.com/rust-lang/cargo/pull/11791/)
+- [Accurately show status when downgrading dependencies](https://github.com/rust-lang/cargo/pull/11839/)
+- [Use registry.default for login/logout](https://github.com/rust-lang/cargo/pull/11949/)
+- [Stabilize `cargo logout`](https://github.com/rust-lang/cargo/pull/11950/)
+
+<a id="1.70.0-Misc"></a>
+
+Misc
+----
+
+- [Stabilize rustdoc `--test-run-directory`](https://github.com/rust-lang/rust/pull/103682/)
+
+<a id="1.70.0-Compatibility-Notes"></a>
+
+Compatibility Notes
+-------------------
+
+- [Prevent stable `libtest` from supporting `-Zunstable-options`](https://github.com/rust-lang/rust/pull/109044/)
+- [Perform const and unsafe checking for expressions in `let _ = expr` position.](https://github.com/rust-lang/rust/pull/102256/)
+- [WebAssembly targets enable `sign-ext` and `mutable-globals` features in codegen](https://github.com/rust-lang/rust/issues/109807)
+  This may cause incompatibility with older execution environments.
+- [Insert alignment checks for pointer dereferences as debug assertions](https://github.com/rust-lang/rust/pull/98112)
+  This catches undefined behavior at runtime, and may cause existing code to fail.
+
+<a id="1.70.0-Internal-Changes"></a>
+
+Internal Changes
+----------------
+
+These changes do not affect any public interfaces of Rust, but they represent
+significant improvements to the performance or internals of rustc and related
+tools.
+
+- [Upgrade to LLVM 16](https://github.com/rust-lang/rust/pull/109474/)
+- [Use SipHash-1-3 instead of SipHash-2-4 for StableHasher](https://github.com/rust-lang/rust/pull/107925/)
+
 Version 1.69.0 (2023-04-20)
 ==========================
 
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index 7ef39f8026b..6646fa9446f 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -11,6 +11,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::Lrc;
 use rustc_macros::HashStable_Generic;
 use rustc_span::symbol::{kw, sym};
+#[cfg_attr(not(bootstrap), allow(hidden_glob_reexports))]
 use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::{self, edition::Edition, Span, DUMMY_SP};
 use std::borrow::Cow;
diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl
index 21b2a3c22fa..f63a9bfcd70 100644
--- a/compiler/rustc_ast_lowering/messages.ftl
+++ b/compiler/rustc_ast_lowering/messages.ftl
@@ -1,99 +1,121 @@
-ast_lowering_generic_type_with_parentheses =
-    parenthesized type parameters may only be used with a `Fn` trait
-    .label = only `Fn` traits may use parentheses
-
-ast_lowering_use_angle_brackets = use angle brackets instead
+ast_lowering_abi_specified_multiple_times =
+    `{$prev_name}` ABI specified multiple times
+    .label = previously specified here
+    .note = these ABIs are equivalent on the current target
 
-ast_lowering_invalid_abi =
-    invalid ABI: found `{$abi}`
-    .label = invalid ABI
-    .note = invoke `{$command}` for a full list of supported calling conventions.
+ast_lowering_arbitrary_expression_in_pattern =
+    arbitrary expressions aren't allowed in patterns
 
-ast_lowering_invalid_abi_suggestion = did you mean
+ast_lowering_argument = argument
 
 ast_lowering_assoc_ty_parentheses =
     parenthesized generic arguments cannot be used in associated type constraints
 
-ast_lowering_remove_parentheses = remove these parentheses
-
-ast_lowering_misplaced_impl_trait =
-    `impl Trait` only allowed in function and inherent method return types, not in {$position}
-
-ast_lowering_misplaced_assoc_ty_binding =
-    associated type bounds are only allowed in where clauses and function signatures, not in {$position}
+ast_lowering_async_generators_not_supported =
+    `async` generators are not yet supported
 
-ast_lowering_underscore_expr_lhs_assign =
-    in expressions, `_` can only be used on the left-hand side of an assignment
-    .label = `_` not allowed here
+ast_lowering_async_non_move_closure_not_supported =
+    `async` non-`move` closures with parameters are not currently supported
+    .help = consider using `let` statements to manually capture variables by reference before entering an `async move` closure
 
-ast_lowering_base_expression_double_dot =
-    base expression required after `..`
-    .label = add a base expression here
+ast_lowering_att_syntax_only_x86 =
+    the `att_syntax` option is only supported on x86
 
 ast_lowering_await_only_in_async_fn_and_blocks =
     `await` is only allowed inside `async` functions and blocks
     .label = only allowed inside `async` functions and blocks
 
-ast_lowering_this_not_async = this is not `async`
+ast_lowering_bad_return_type_notation_inputs =
+    argument types not allowed with return type notation
+    .suggestion = remove the input types
 
-ast_lowering_generator_too_many_parameters =
-    too many parameters for a generator (expected 0 or 1 parameters)
+ast_lowering_bad_return_type_notation_needs_dots =
+    return type notation arguments must be elided with `..`
+    .suggestion = add `..`
+
+ast_lowering_bad_return_type_notation_output =
+    return type not allowed with return type notation
+    .suggestion = remove the return type
+
+ast_lowering_base_expression_double_dot =
+    base expression required after `..`
+    .label = add a base expression here
+
+ast_lowering_clobber_abi_not_supported =
+    `clobber_abi` is not supported on this target
 
 ast_lowering_closure_cannot_be_static = closures cannot be static
 
-ast_lowering_async_non_move_closure_not_supported =
-    `async` non-`move` closures with parameters are not currently supported
-    .help = consider using `let` statements to manually capture variables by reference before entering an `async move` closure
+ast_lowering_does_not_support_modifiers =
+    the `{$class_name}` register class does not support template modifiers
+
+ast_lowering_extra_double_dot =
+    `..` can only be used once per {$ctx} pattern
+    .label = can only be used once per {$ctx} pattern
 
 ast_lowering_functional_record_update_destructuring_assignment =
     functional record updates are not allowed in destructuring assignments
     .suggestion = consider removing the trailing pattern
 
-ast_lowering_async_generators_not_supported =
-    `async` generators are not yet supported
+ast_lowering_generator_too_many_parameters =
+    too many parameters for a generator (expected 0 or 1 parameters)
 
-ast_lowering_inline_asm_unsupported_target =
-    inline assembly is unsupported on this target
+ast_lowering_generic_type_with_parentheses =
+    parenthesized type parameters may only be used with a `Fn` trait
+    .label = only `Fn` traits may use parentheses
 
-ast_lowering_att_syntax_only_x86 =
-    the `att_syntax` option is only supported on x86
+ast_lowering_inclusive_range_with_no_end = inclusive range with no end
 
-ast_lowering_abi_specified_multiple_times =
-    `{$prev_name}` ABI specified multiple times
-    .label = previously specified here
-    .note = these ABIs are equivalent on the current target
+ast_lowering_inline_asm_unsupported_target =
+    inline assembly is unsupported on this target
 
-ast_lowering_clobber_abi_not_supported =
-    `clobber_abi` is not supported on this target
+ast_lowering_invalid_abi =
+    invalid ABI: found `{$abi}`
+    .label = invalid ABI
+    .note = invoke `{$command}` for a full list of supported calling conventions.
 
 ast_lowering_invalid_abi_clobber_abi =
     invalid ABI for `clobber_abi`
     .note = the following ABIs are supported on this target: {$supported_abis}
 
+ast_lowering_invalid_abi_suggestion = did you mean
+
+ast_lowering_invalid_asm_template_modifier_const =
+    asm template modifiers are not allowed for `const` arguments
+
+ast_lowering_invalid_asm_template_modifier_reg_class =
+    invalid asm template modifier for this register class
+
+ast_lowering_invalid_asm_template_modifier_sym =
+    asm template modifiers are not allowed for `sym` arguments
+
 ast_lowering_invalid_register =
     invalid register `{$reg}`: {$error}
 
 ast_lowering_invalid_register_class =
     invalid register class `{$reg_class}`: {$error}
 
-ast_lowering_invalid_asm_template_modifier_reg_class =
-    invalid asm template modifier for this register class
+ast_lowering_misplaced_assoc_ty_binding =
+    associated type bounds are only allowed in where clauses and function signatures, not in {$position}
 
-ast_lowering_argument = argument
+ast_lowering_misplaced_double_dot =
+    `..` patterns are not allowed here
+    .note = only allowed in tuple, tuple struct, and slice patterns
 
-ast_lowering_template_modifier = template modifier
+ast_lowering_misplaced_impl_trait =
+    `impl Trait` only allowed in function and inherent method return types, not in {$position}
 
-ast_lowering_support_modifiers =
-    the `{$class_name}` register class supports the following template modifiers: {$modifiers}
+ast_lowering_misplaced_relax_trait_bound =
+    `?Trait` bounds are only permitted at the point where a type parameter is declared
 
-ast_lowering_does_not_support_modifiers =
-    the `{$class_name}` register class does not support template modifiers
+ast_lowering_not_supported_for_lifetime_binder_async_closure =
+    `for<...>` binders on `async` closures are not currently supported
 
-ast_lowering_invalid_asm_template_modifier_const =
-    asm template modifiers are not allowed for `const` arguments
+ast_lowering_previously_used_here = previously used here
 
-ast_lowering_invalid_asm_template_modifier_sym =
-    asm template modifiers are not allowed for `sym` arguments
+ast_lowering_register1 = register `{$reg1_name}`
+
+ast_lowering_register2 = register `{$reg2_name}`
 
 ast_lowering_register_class_only_clobber =
     register class `{$reg_class_name}` can only be used as a clobber, not as an input or output
@@ -102,9 +124,7 @@ ast_lowering_register_conflict =
     register `{$reg1_name}` conflicts with register `{$reg2_name}`
     .help = use `lateout` instead of `out` to avoid conflict
 
-ast_lowering_register1 = register `{$reg1_name}`
-
-ast_lowering_register2 = register `{$reg2_name}`
+ast_lowering_remove_parentheses = remove these parentheses
 
 ast_lowering_sub_tuple_binding =
     `{$ident_name} @` is not allowed in a {$ctx}
@@ -113,26 +133,12 @@ ast_lowering_sub_tuple_binding =
 
 ast_lowering_sub_tuple_binding_suggestion = if you don't need to use the contents of {$ident}, discard the tuple's remaining fields
 
-ast_lowering_extra_double_dot =
-    `..` can only be used once per {$ctx} pattern
-    .label = can only be used once per {$ctx} pattern
-
-ast_lowering_previously_used_here = previously used here
-
-ast_lowering_misplaced_double_dot =
-    `..` patterns are not allowed here
-    .note = only allowed in tuple, tuple struct, and slice patterns
-
-ast_lowering_misplaced_relax_trait_bound =
-    `?Trait` bounds are only permitted at the point where a type parameter is declared
-
-ast_lowering_not_supported_for_lifetime_binder_async_closure =
-    `for<...>` binders on `async` closures are not currently supported
+ast_lowering_support_modifiers =
+    the `{$class_name}` register class supports the following template modifiers: {$modifiers}
 
-ast_lowering_arbitrary_expression_in_pattern =
-    arbitrary expressions aren't allowed in patterns
+ast_lowering_template_modifier = template modifier
 
-ast_lowering_inclusive_range_with_no_end = inclusive range with no end
+ast_lowering_this_not_async = this is not `async`
 
 ast_lowering_trait_fn_async =
     functions in traits cannot be declared `async`
@@ -140,14 +146,8 @@ ast_lowering_trait_fn_async =
     .note = `async` trait functions are not currently supported
     .note2 = consider using the `async-trait` crate: https://crates.io/crates/async-trait
 
-ast_lowering_bad_return_type_notation_inputs =
-    argument types not allowed with return type notation
-    .suggestion = remove the input types
-
-ast_lowering_bad_return_type_notation_needs_dots =
-    return type notation arguments must be elided with `..`
-    .suggestion = add `..`
+ast_lowering_underscore_expr_lhs_assign =
+    in expressions, `_` can only be used on the left-hand side of an assignment
+    .label = `_` not allowed here
 
-ast_lowering_bad_return_type_notation_output =
-    return type not allowed with return type notation
-    .suggestion = remove the return type
+ast_lowering_use_angle_brackets = use angle brackets instead
diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs
index 941d3179587..d350498bc96 100644
--- a/compiler/rustc_ast_lowering/src/asm.rs
+++ b/compiler/rustc_ast_lowering/src/asm.rs
@@ -44,6 +44,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     | asm::InlineAsmArch::AArch64
                     | asm::InlineAsmArch::RiscV32
                     | asm::InlineAsmArch::RiscV64
+                    | asm::InlineAsmArch::LoongArch64
             );
             if !is_stable && !self.tcx.features().asm_experimental_arch {
                 feature_err(
diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl
index 2f413789e77..2f0ac0c2b19 100644
--- a/compiler/rustc_ast_passes/messages.ftl
+++ b/compiler/rustc_ast_passes/messages.ftl
@@ -1,64 +1,3 @@
-ast_passes_forbidden_let =
-    `let` expressions are not supported here
-    .note = only supported directly in conditions of `if` and `while` expressions
-    .not_supported_or = `||` operators are not supported in let chain expressions
-    .not_supported_parentheses = `let`s wrapped in parentheses are not supported in a context with let chains
-
-ast_passes_forbidden_let_stable =
-    expected expression, found statement (`let`)
-    .note = variable declaration using `let` is a statement
-
-ast_passes_deprecated_where_clause_location =
-    where clause not allowed here
-
-ast_passes_keyword_lifetime =
-    lifetimes cannot use keyword names
-
-ast_passes_invalid_label =
-    invalid label name `{$name}`
-
-ast_passes_visibility_not_permitted =
-    visibility qualifiers are not permitted here
-    .enum_variant = enum variants and their fields always share the visibility of the enum they are in
-    .trait_impl = trait items always share the visibility of their trait
-    .individual_impl_items = place qualifiers on individual impl items instead
-    .individual_foreign_items = place qualifiers on individual foreign items instead
-
-ast_passes_trait_fn_const =
-    functions in traits cannot be declared const
-    .label = functions in traits cannot be const
-
-ast_passes_forbidden_lifetime_bound =
-    lifetime bounds cannot be used in this context
-
-ast_passes_forbidden_non_lifetime_param =
-    only lifetime parameters can be used in this context
-
-ast_passes_fn_param_too_many =
-    function can not have more than {$max_num_args} arguments
-
-ast_passes_fn_param_c_var_args_only =
-    C-variadic function must be declared with at least one named argument
-
-ast_passes_fn_param_c_var_args_not_last =
-    `...` must be the last argument of a C-variadic function
-
-ast_passes_fn_param_doc_comment =
-    documentation comments cannot be applied to function parameters
-    .label = doc comments are not allowed here
-
-ast_passes_fn_param_forbidden_attr =
-    allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
-
-ast_passes_fn_param_forbidden_self =
-    `self` parameter is only allowed in associated functions
-    .label = not semantically valid as function parameter
-    .note = associated functions are those in `impl` or `trait` definitions
-
-ast_passes_forbidden_default =
-    `default` is only allowed on items in trait impls
-    .label = `default` because of this
-
 ast_passes_assoc_const_without_body =
     associated constant in `impl` without body
     .suggestion = provide a definition for the constant
@@ -71,36 +10,73 @@ ast_passes_assoc_type_without_body =
     associated type in `impl` without body
     .suggestion = provide a definition for the type
 
+ast_passes_at_least_one_trait = at least one trait must be specified
+
+ast_passes_auto_generic = auto traits cannot have generic parameters
+    .label = auto trait cannot have generic parameters
+    .suggestion = remove the parameters
+
+ast_passes_auto_items = auto traits cannot have associated items
+    .label = {ast_passes_auto_items}
+    .suggestion = remove these associated items
+
+ast_passes_auto_super_lifetime = auto traits cannot have super traits or lifetime bounds
+    .label = {ast_passes_auto_super_lifetime}
+    .suggestion = remove the super traits or lifetime bounds
+
+ast_passes_bad_c_variadic = only foreign or `unsafe extern "C"` functions may be C-variadic
+
+ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block
+    .cannot_have = cannot have a body
+    .invalid = the invalid body
+    .existing = `extern` blocks define existing foreign {$kind}s and {$kind}s inside of them cannot have a body
+
+ast_passes_bound_in_context = bounds on `type`s in {$ctx} have no effect
+
+ast_passes_const_and_async = functions cannot be both `const` and `async`
+    .const = `const` because of this
+    .async = `async` because of this
+    .label = {""}
+
 ast_passes_const_without_body =
     free constant item without body
     .suggestion = provide a definition for the constant
 
-ast_passes_static_without_body =
-    free static item without body
-    .suggestion = provide a definition for the static
+ast_passes_constraint_on_negative_bound =
+    associated type constraints not allowed on negative bounds
 
-ast_passes_ty_alias_without_body =
-    free type alias without body
-    .suggestion = provide a definition for the type
+ast_passes_deprecated_where_clause_location =
+    where clause not allowed here
 
-ast_passes_fn_without_body =
-    free function without a body
-    .suggestion = provide a definition for the function
+ast_passes_equality_in_where = equality constraints are not yet supported in `where` clauses
+    .label = not supported
+    .suggestion = if `{$ident}` is an associated type you're trying to set, use the associated type binding syntax
+    .suggestion_path = if `{$trait_segment}::{$potential_assoc}` is an associated type you're trying to set, use the associated type binding syntax
+    .note = see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information
 
 ast_passes_extern_block_suggestion = if you meant to declare an externally defined function, use an `extern` block
 
-ast_passes_bound_in_context = bounds on `type`s in {$ctx} have no effect
+ast_passes_extern_fn_qualifiers = functions in `extern` blocks cannot have qualifiers
+    .label = in this `extern` block
+    .suggestion = remove the qualifiers
+
+ast_passes_extern_item_ascii = items in `extern` blocks cannot use non-ascii identifiers
+    .label = in this `extern` block
+    .note = this limitation may be lifted in the future; see issue #83942 <https://github.com/rust-lang/rust/issues/83942> for more information
+
+ast_passes_extern_keyword_link = for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
 
 ast_passes_extern_types_cannot = `type`s inside `extern` blocks cannot have {$descr}
     .suggestion = remove the {$remove_descr}
     .label = `extern` block begins here
 
-ast_passes_extern_keyword_link = for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
+ast_passes_extern_without_abi = extern declarations without an explicit ABI are deprecated
 
-ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block
-    .cannot_have = cannot have a body
-    .invalid = the invalid body
-    .existing = `extern` blocks define existing foreign {$kind}s and {$kind}s inside of them cannot have a body
+ast_passes_feature_on_non_nightly = `#![feature]` may not be used on the {$channel} release channel
+    .suggestion = remove the attribute
+    .stable_since = the feature `{$name}` has been stable since `{$since}` and no longer requires an attribute to enable
+
+ast_passes_fieldless_union = unions cannot have zero fields
 
 ast_passes_fn_body_extern = incorrect function inside `extern` block
     .cannot_have = cannot have a body
@@ -108,35 +84,50 @@ ast_passes_fn_body_extern = incorrect function inside `extern` block
     .help = you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block
     .label = `extern` blocks define existing foreign functions and functions inside of them cannot have a body
 
-ast_passes_extern_fn_qualifiers = functions in `extern` blocks cannot have qualifiers
-    .label = in this `extern` block
-    .suggestion = remove the qualifiers
+ast_passes_fn_param_c_var_args_not_last =
+    `...` must be the last argument of a C-variadic function
 
-ast_passes_extern_item_ascii = items in `extern` blocks cannot use non-ascii identifiers
-    .label = in this `extern` block
-    .note = this limitation may be lifted in the future; see issue #83942 <https://github.com/rust-lang/rust/issues/83942> for more information
+ast_passes_fn_param_c_var_args_only =
+    C-variadic function must be declared with at least one named argument
 
-ast_passes_bad_c_variadic = only foreign or `unsafe extern "C"` functions may be C-variadic
+ast_passes_fn_param_doc_comment =
+    documentation comments cannot be applied to function parameters
+    .label = doc comments are not allowed here
 
-ast_passes_item_underscore = `{$kind}` items in this context need a name
-    .label = `_` is not a valid name for this `{$kind}` item
+ast_passes_fn_param_forbidden_attr =
+    allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
 
-ast_passes_nomangle_ascii = `#[no_mangle]` requires ASCII identifier
+ast_passes_fn_param_forbidden_self =
+    `self` parameter is only allowed in associated functions
+    .label = not semantically valid as function parameter
+    .note = associated functions are those in `impl` or `trait` definitions
 
-ast_passes_module_nonascii = trying to load file for module `{$name}` with non-ascii identifier name
-    .help = consider using the `#[path]` attribute to specify filesystem path
+ast_passes_fn_param_too_many =
+    function can not have more than {$max_num_args} arguments
 
-ast_passes_auto_generic = auto traits cannot have generic parameters
-    .label = auto trait cannot have generic parameters
-    .suggestion = remove the parameters
+ast_passes_fn_without_body =
+    free function without a body
+    .suggestion = provide a definition for the function
 
-ast_passes_auto_super_lifetime = auto traits cannot have super traits or lifetime bounds
-    .label = {ast_passes_auto_super_lifetime}
-    .suggestion = remove the super traits or lifetime bounds
+ast_passes_forbidden_default =
+    `default` is only allowed on items in trait impls
+    .label = `default` because of this
 
-ast_passes_auto_items = auto traits cannot have associated items
-    .label = {ast_passes_auto_items}
-    .suggestion = remove these associated items
+ast_passes_forbidden_let =
+    `let` expressions are not supported here
+    .note = only supported directly in conditions of `if` and `while` expressions
+    .not_supported_or = `||` operators are not supported in let chain expressions
+    .not_supported_parentheses = `let`s wrapped in parentheses are not supported in a context with let chains
+
+ast_passes_forbidden_let_stable =
+    expected expression, found statement (`let`)
+    .note = variable declaration using `let` is a statement
+
+ast_passes_forbidden_lifetime_bound =
+    lifetime bounds cannot be used in this context
+
+ast_passes_forbidden_non_lifetime_param =
+    only lifetime parameters can be used in this context
 
 ast_passes_generic_before_constraints = generic arguments must come before the first constraint
     .constraints = {$constraint_len ->
@@ -156,88 +147,97 @@ ast_passes_generic_before_constraints = generic arguments must come before the f
     *[other] arguments
     }
 
-ast_passes_pattern_in_fn_pointer = patterns aren't allowed in function pointer types
-
-ast_passes_trait_object_single_bound = only a single explicit lifetime bound is permitted
+ast_passes_generic_default_trailing = generic parameters with a default must be trailing
 
 ast_passes_impl_trait_path = `impl Trait` is not allowed in path parameters
 
+ast_passes_incompatible_features = `{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed
+    .help = remove one of these features
+
+ast_passes_inherent_cannot_be = inherent impls cannot be {$annotation}
+    .because = {$annotation} because of this
+    .type = inherent impl for this type
+    .only_trait = only trait implementations may be annotated with {$annotation}
+
+ast_passes_invalid_label =
+    invalid label name `{$name}`
+
+ast_passes_item_underscore = `{$kind}` items in this context need a name
+    .label = `_` is not a valid name for this `{$kind}` item
+
+ast_passes_keyword_lifetime =
+    lifetimes cannot use keyword names
+
+ast_passes_module_nonascii = trying to load file for module `{$name}` with non-ascii identifier name
+    .help = consider using the `#[path]` attribute to specify filesystem path
+
+ast_passes_negative_bound_not_supported =
+    negative bounds are not supported
+
 ast_passes_nested_impl_trait = nested `impl Trait` is not allowed
     .outer = outer `impl Trait`
     .inner = nested `impl Trait` here
 
-ast_passes_at_least_one_trait = at least one trait must be specified
-
-ast_passes_extern_without_abi = extern declarations without an explicit ABI are deprecated
+ast_passes_nested_lifetimes = nested quantification of lifetimes
 
-ast_passes_out_of_order_params = {$param_ord} parameters must be declared prior to {$max_param} parameters
-    .suggestion = reorder the parameters: lifetimes, then consts and types
+ast_passes_nomangle_ascii = `#[no_mangle]` requires ASCII identifier
 
 ast_passes_obsolete_auto = `impl Trait for .. {"{}"}` is an obsolete syntax
     .help = use `auto trait Trait {"{}"}` instead
 
-ast_passes_unsafe_negative_impl = negative impls cannot be unsafe
-    .negative = negative because of this
-    .unsafe = unsafe because of this
+ast_passes_optional_const_exclusive = `~const` and `{$modifier}` are mutually exclusive
 
-ast_passes_inherent_cannot_be = inherent impls cannot be {$annotation}
-    .because = {$annotation} because of this
-    .type = inherent impl for this type
-    .only_trait = only trait implementations may be annotated with {$annotation}
+ast_passes_optional_trait_object = `?Trait` is not permitted in trait object types
 
-ast_passes_unsafe_item = {$kind} cannot be declared unsafe
+ast_passes_optional_trait_supertrait = `?Trait` is not permitted in supertraits
+    .note = traits are `?{$path_str}` by default
 
-ast_passes_fieldless_union = unions cannot have zero fields
+ast_passes_out_of_order_params = {$param_ord} parameters must be declared prior to {$max_param} parameters
+    .suggestion = reorder the parameters: lifetimes, then consts and types
 
-ast_passes_where_after_type_alias = where clauses are not allowed after the type for type aliases
-    .note = see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
+ast_passes_pattern_in_bodiless = patterns aren't allowed in functions without bodies
+    .label = pattern not allowed in function without body
 
-ast_passes_generic_default_trailing = generic parameters with a default must be trailing
+ast_passes_pattern_in_fn_pointer = patterns aren't allowed in function pointer types
 
-ast_passes_nested_lifetimes = nested quantification of lifetimes
+ast_passes_pattern_in_foreign = patterns aren't allowed in foreign function declarations
+    .label = pattern not allowed in foreign function
 
-ast_passes_optional_trait_supertrait = `?Trait` is not permitted in supertraits
-    .note = traits are `?{$path_str}` by default
+ast_passes_show_span = {$msg}
 
-ast_passes_optional_trait_object = `?Trait` is not permitted in trait object types
+ast_passes_stability_outside_std = stability attributes may not be used outside of the standard library
+
+ast_passes_static_without_body =
+    free static item without body
+    .suggestion = provide a definition for the static
 
 ast_passes_tilde_const_disallowed = `~const` is not allowed here
     .trait = trait objects cannot have `~const` trait bounds
     .closure = closures cannot have `~const` trait bounds
     .function = this function is not `const`, so it cannot have `~const` trait bounds
 
-ast_passes_optional_const_exclusive = `~const` and `{$modifier}` are mutually exclusive
-
-ast_passes_const_and_async = functions cannot be both `const` and `async`
-    .const = `const` because of this
-    .async = `async` because of this
-    .label = {""}
-
-ast_passes_pattern_in_foreign = patterns aren't allowed in foreign function declarations
-    .label = pattern not allowed in foreign function
-
-ast_passes_pattern_in_bodiless = patterns aren't allowed in functions without bodies
-    .label = pattern not allowed in function without body
-
-ast_passes_equality_in_where = equality constraints are not yet supported in `where` clauses
-    .label = not supported
-    .suggestion = if `{$ident}` is an associated type you're trying to set, use the associated type binding syntax
-    .suggestion_path = if `{$trait_segment}::{$potential_assoc}` is an associated type you're trying to set, use the associated type binding syntax
-    .note = see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information
+ast_passes_trait_fn_const =
+    functions in traits cannot be declared const
+    .label = functions in traits cannot be const
 
-ast_passes_stability_outside_std = stability attributes may not be used outside of the standard library
+ast_passes_trait_object_single_bound = only a single explicit lifetime bound is permitted
 
-ast_passes_feature_on_non_nightly = `#![feature]` may not be used on the {$channel} release channel
-    .suggestion = remove the attribute
-    .stable_since = the feature `{$name}` has been stable since `{$since}` and no longer requires an attribute to enable
+ast_passes_ty_alias_without_body =
+    free type alias without body
+    .suggestion = provide a definition for the type
 
-ast_passes_incompatible_features = `{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed
-    .help = remove one of these features
+ast_passes_unsafe_item = {$kind} cannot be declared unsafe
 
-ast_passes_show_span = {$msg}
+ast_passes_unsafe_negative_impl = negative impls cannot be unsafe
+    .negative = negative because of this
+    .unsafe = unsafe because of this
 
-ast_passes_negative_bound_not_supported =
-    negative bounds are not supported
+ast_passes_visibility_not_permitted =
+    visibility qualifiers are not permitted here
+    .enum_variant = enum variants and their fields always share the visibility of the enum they are in
+    .trait_impl = trait items always share the visibility of their trait
+    .individual_impl_items = place qualifiers on individual impl items instead
+    .individual_foreign_items = place qualifiers on individual foreign items instead
 
-ast_passes_constraint_on_negative_bound =
-    associated type constraints not allowed on negative bounds
+ast_passes_where_after_type_alias = where clauses are not allowed after the type for type aliases
+    .note = see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
diff --git a/compiler/rustc_attr/messages.ftl b/compiler/rustc_attr/messages.ftl
index a7f8c993d42..e6cbbaf3704 100644
--- a/compiler/rustc_attr/messages.ftl
+++ b/compiler/rustc_attr/messages.ftl
@@ -1,27 +1,38 @@
+attr_cfg_predicate_identifier =
+    `cfg` predicate key must be an identifier
+
+attr_deprecated_item_suggestion =
+    suggestions on deprecated items are unstable
+    .help = add `#![feature(deprecated_suggestion)]` to the crate root
+    .note = see #94785 for more details
+
 attr_expected_one_cfg_pattern =
     expected 1 cfg-pattern
 
-attr_invalid_predicate =
-    invalid predicate `{$predicate}`
+attr_expected_single_version_literal =
+    expected single version literal
 
-attr_multiple_item =
-    multiple '{$item}' items
+attr_expected_version_literal =
+    expected a version literal
+
+attr_expects_feature_list =
+    `{$name}` expects a list of feature names
+
+attr_expects_features =
+    `{$name}` expects feature names
 
 attr_incorrect_meta_item =
     incorrect meta item
 
-attr_unknown_meta_item =
-    unknown meta item '{$item}'
-    .label = expected one of {$expected}
-
-attr_missing_since =
-    missing 'since'
+attr_incorrect_repr_format_align_one_arg =
+    incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses
 
-attr_missing_note =
-    missing 'note'
+attr_incorrect_repr_format_generic =
+    incorrect `repr({$repr_arg})` attribute format
+    .suggestion = use parentheses instead
 
-attr_multiple_stability_levels =
-    multiple stability levels
+attr_incorrect_repr_format_packed_one_or_zero_arg =
+    incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all
 
 attr_invalid_issue_string =
     `issue` must be a non-zero numeric string or "none"
@@ -31,17 +42,15 @@ attr_invalid_issue_string =
     .pos_overflow = number too large to fit in target type
     .neg_overflow = number too small to fit in target type
 
-attr_missing_feature =
-    missing 'feature'
-
-attr_non_ident_feature =
-    'feature' is not an identifier
+attr_invalid_predicate =
+    invalid predicate `{$predicate}`
 
-attr_missing_issue =
-    missing 'issue'
+attr_invalid_repr_align_need_arg =
+    invalid `repr(align)` attribute: `align` needs an argument
+    .suggestion = supply an argument here
 
-attr_incorrect_repr_format_packed_one_or_zero_arg =
-    incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all
+attr_invalid_repr_generic =
+    invalid `repr({$repr_arg})` attribute: {$error_part}
 
 attr_invalid_repr_hint_no_paren =
     invalid representation hint: `{$name}` does not take a parenthesized argument list
@@ -49,59 +58,50 @@ attr_invalid_repr_hint_no_paren =
 attr_invalid_repr_hint_no_value =
     invalid representation hint: `{$name}` does not take a value
 
-attr_unsupported_literal_generic =
-    unsupported literal
-attr_unsupported_literal_cfg_string =
-    literal in `cfg` predicate value must be a string
-attr_unsupported_literal_deprecated_string =
-    literal in `deprecated` value must be a string
-attr_unsupported_literal_deprecated_kv_pair =
-    item in `deprecated` must be a key/value pair
-attr_unsupported_literal_suggestion =
-    consider removing the prefix
+attr_missing_feature =
+    missing 'feature'
 
-attr_invalid_repr_align_need_arg =
-    invalid `repr(align)` attribute: `align` needs an argument
-    .suggestion = supply an argument here
+attr_missing_issue =
+    missing 'issue'
 
-attr_invalid_repr_generic =
-    invalid `repr({$repr_arg})` attribute: {$error_part}
+attr_missing_note =
+    missing 'note'
 
-attr_incorrect_repr_format_align_one_arg =
-    incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses
+attr_missing_since =
+    missing 'since'
 
-attr_incorrect_repr_format_generic =
-    incorrect `repr({$repr_arg})` attribute format
-    .suggestion = use parentheses instead
+attr_multiple_item =
+    multiple '{$item}' items
 
-attr_rustc_promotable_pairing =
-    `rustc_promotable` attribute must be paired with either a `rustc_const_unstable` or a `rustc_const_stable` attribute
+attr_multiple_stability_levels =
+    multiple stability levels
+
+attr_non_ident_feature =
+    'feature' is not an identifier
 
 attr_rustc_allowed_unstable_pairing =
     `rustc_allowed_through_unstable_modules` attribute must be paired with a `stable` attribute
 
-attr_cfg_predicate_identifier =
-    `cfg` predicate key must be an identifier
-
-attr_deprecated_item_suggestion =
-    suggestions on deprecated items are unstable
-    .help = add `#![feature(deprecated_suggestion)]` to the crate root
-    .note = see #94785 for more details
-
-attr_expected_single_version_literal =
-    expected single version literal
-
-attr_expected_version_literal =
-    expected a version literal
-
-attr_expects_feature_list =
-    `{$name}` expects a list of feature names
-
-attr_expects_features =
-    `{$name}` expects feature names
+attr_rustc_promotable_pairing =
+    `rustc_promotable` attribute must be paired with either a `rustc_const_unstable` or a `rustc_const_stable` attribute
 
 attr_soft_no_args =
     `soft` should not have any arguments
 
+attr_unknown_meta_item =
+    unknown meta item '{$item}'
+    .label = expected one of {$expected}
+
 attr_unknown_version_literal =
     unknown version literal format, assuming it refers to a future version
+
+attr_unsupported_literal_cfg_string =
+    literal in `cfg` predicate value must be a string
+attr_unsupported_literal_deprecated_kv_pair =
+    item in `deprecated` must be a key/value pair
+attr_unsupported_literal_deprecated_string =
+    literal in `deprecated` value must be a string
+attr_unsupported_literal_generic =
+    unsupported literal
+attr_unsupported_literal_suggestion =
+    consider removing the prefix
diff --git a/compiler/rustc_borrowck/messages.ftl b/compiler/rustc_borrowck/messages.ftl
index 4a616dc2464..67fdb671742 100644
--- a/compiler/rustc_borrowck/messages.ftl
+++ b/compiler/rustc_borrowck/messages.ftl
@@ -1,188 +1,108 @@
-borrowck_move_unsized =
-    cannot move a value of type `{$ty}`
-    .label = the size of `{$ty}` cannot be statically determined
-
-borrowck_higher_ranked_lifetime_error =
-    higher-ranked lifetime error
-
-borrowck_could_not_prove =
-    could not prove `{$predicate}`
-
-borrowck_could_not_normalize =
-    could not normalize `{$value}`
-
-borrowck_higher_ranked_subtype_error =
-    higher-ranked subtype error
-
-borrowck_generic_does_not_live_long_enough =
-    `{$kind}` does not live long enough
-
-borrowck_move_borrowed =
-    cannot move out of `{$desc}` because it is borrowed
-
-borrowck_var_does_not_need_mut =
-    variable does not need to be mutable
-    .suggestion = remove this `mut`
-
-borrowck_var_cannot_escape_closure =
-    captured variable cannot escape `FnMut` closure body
-    .note = `FnMut` closures only have access to their captured variables while they are executing...
-    .cannot_escape = ...therefore, they cannot allow references to captured variables to escape
-
-borrowck_var_here_defined = variable defined here
-
-borrowck_var_here_captured = variable captured here
-
-borrowck_closure_inferred_mut = inferred to be a `FnMut` closure
-
-borrowck_returned_closure_escaped =
-    returns a closure that contains a reference to a captured variable, which then escapes the closure body
-
-borrowck_returned_async_block_escaped =
-    returns an `async` block that contains a reference to a captured variable, which then escapes the closure body
-
-borrowck_returned_ref_escaped =
-    returns a reference to a captured variable which escapes the closure body
-
-borrowck_lifetime_constraints_error =
-    lifetime may not live long enough
-
-borrowck_returned_lifetime_wrong =
-    {$mir_def_name} was supposed to return data with lifetime `{$outlived_fr_name}` but it is returning data with lifetime `{$fr_name}`
-
-borrowck_returned_lifetime_short =
-    {$category_desc}requires that `{$free_region_name}` must outlive `{$outlived_fr_name}`
-
-borrowck_used_impl_require_static =
-    the used `impl` has a `'static` requirement
-
-borrowck_borrow_due_to_use_generator =
-    borrow occurs due to use in generator
-
-borrowck_use_due_to_use_generator =
-    use occurs due to use in generator
+borrowck_assign_due_to_use_closure =
+    assignment occurs due to use in closure
 
 borrowck_assign_due_to_use_generator =
     assign occurs due to use in generator
 
+borrowck_assign_part_due_to_use_closure =
+    assignment to part occurs due to use in closure
+
 borrowck_assign_part_due_to_use_generator =
     assign to part occurs due to use in generator
 
 borrowck_borrow_due_to_use_closure =
     borrow occurs due to use in closure
 
-borrowck_use_due_to_use_closure =
-    use occurs due to use in closure
+borrowck_borrow_due_to_use_generator =
+    borrow occurs due to use in generator
 
-borrowck_assign_due_to_use_closure =
-    assignment occurs due to use in closure
+borrowck_calling_operator_moves_lhs =
+    calling this operator moves the left-hand side
 
-borrowck_assign_part_due_to_use_closure =
-    assignment to part occurs due to use in closure
+borrowck_cannot_move_when_borrowed =
+    cannot move out of {$place ->
+        [value] value
+        *[other] {$place}
+    } because it is borrowed
+    .label = borrow of {$borrow_place ->
+        [value] value
+        *[other] {$borrow_place}
+    } occurs here
+    .move_label = move out of {$value_place ->
+        [value] value
+        *[other] {$value_place}
+    } occurs here
 
 borrowck_capture_immute =
     capture is immutable because of use here
 
-borrowck_capture_mut =
-    capture is mutable because of use here
-
 borrowck_capture_move =
     capture is moved because of use here
 
-borrowck_var_borrow_by_use_place_in_generator =
-    {$is_single_var ->
-        *[true] borrow occurs
-        [false] borrows occur
-    } due to use of {$place} in generator
-
-borrowck_var_borrow_by_use_place_in_closure =
-    {$is_single_var ->
-        *[true] borrow occurs
-        [false] borrows occur
-    } due to use of {$place} in closure
+borrowck_capture_mut =
+    capture is mutable because of use here
 
-borrowck_var_borrow_by_use_in_generator =
-    borrow occurs due to use in generator
+borrowck_closure_inferred_mut = inferred to be a `FnMut` closure
 
-borrowck_var_borrow_by_use_in_closure =
-    borrow occurs due to use in closure
+borrowck_closure_invoked_twice =
+    closure cannot be invoked more than once because it moves the variable `{$place_name}` out of its environment
 
-borrowck_var_move_by_use_place_in_generator =
-    move occurs due to use of {$place} in generator
+borrowck_closure_moved_twice =
+    closure cannot be moved more than once as it is not `Copy` due to moving the variable `{$place_name}` out of its environment
 
-borrowck_var_move_by_use_place_in_closure =
-    move occurs due to use of {$place} in closure
+borrowck_consider_borrow_type_contents =
+    help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
 
-borrowck_var_move_by_use_in_generator =
-    move occurs due to use in generator
+borrowck_could_not_normalize =
+    could not normalize `{$value}`
 
-borrowck_var_move_by_use_in_closure =
-    move occurs due to use in closure
+borrowck_could_not_prove =
+    could not prove `{$predicate}`
 
-borrowck_partial_var_move_by_use_in_generator =
-    variable {$is_partial ->
-        [true] partially moved
-        *[false] moved
-    } due to use in generator
+borrowck_func_take_self_moved_place =
+    `{$func}` takes ownership of the receiver `self`, which moves {$place_name}
 
-borrowck_partial_var_move_by_use_in_closure =
-    variable {$is_partial ->
-        [true] partially moved
-        *[false] moved
-    } due to use in closure
+borrowck_generic_does_not_live_long_enough =
+    `{$kind}` does not live long enough
 
-borrowck_var_first_borrow_by_use_place_in_generator =
-    first borrow occurs due to use of {$place} in generator
+borrowck_higher_ranked_lifetime_error =
+    higher-ranked lifetime error
 
-borrowck_var_first_borrow_by_use_place_in_closure =
-    first borrow occurs due to use of {$place} in closure
+borrowck_higher_ranked_subtype_error =
+    higher-ranked subtype error
 
-borrowck_var_second_borrow_by_use_place_in_generator =
-    second borrow occurs due to use of {$place} in generator
+borrowck_lifetime_constraints_error =
+    lifetime may not live long enough
 
-borrowck_var_second_borrow_by_use_place_in_closure =
-    second borrow occurs due to use of {$place} in closure
+borrowck_move_borrowed =
+    cannot move out of `{$desc}` because it is borrowed
 
-borrowck_var_mutable_borrow_by_use_place_in_closure =
-    mutable borrow occurs due to use of {$place} in closure
+borrowck_move_out_place_here =
+    {$place} is moved here
 
-borrowck_cannot_move_when_borrowed =
-    cannot move out of {$place ->
-        [value] value
-        *[other] {$place}
-    } because it is borrowed
-    .label = borrow of {$borrow_place ->
-        [value] value
-        *[other] {$borrow_place}
-    } occurs here
-    .move_label = move out of {$value_place ->
-        [value] value
-        *[other] {$value_place}
-    } occurs here
+borrowck_move_unsized =
+    cannot move a value of type `{$ty}`
+    .label = the size of `{$ty}` cannot be statically determined
 
-borrowck_opaque_type_non_generic_param =
-    expected generic {$kind} parameter, found `{$ty}`
-    .label = {STREQ($ty, "'static") ->
-        [true] cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
-        *[other] this generic parameter must be used with a generic {$kind} parameter
-    }
+borrowck_moved_a_fn_once_in_call =
+    this value implements `FnOnce`, which causes it to be moved when called
 
-borrowck_moved_due_to_call =
+borrowck_moved_due_to_await =
     {$place_name} {$is_partial ->
         [true] partially moved
         *[false] moved
     } due to this {$is_loop_message ->
-        [true] call, in previous iteration of loop
-        *[false] call
+        [true] await, in previous iteration of loop
+        *[false] await
     }
 
-borrowck_moved_due_to_usage_in_operator =
+borrowck_moved_due_to_call =
     {$place_name} {$is_partial ->
         [true] partially moved
         *[false] moved
-    } due to usage in {$is_loop_message ->
-        [true] operator, in previous iteration of loop
-        *[false] operator
+    } due to this {$is_loop_message ->
+        [true] call, in previous iteration of loop
+        *[false] call
     }
 
 borrowck_moved_due_to_implicit_into_iter_call =
@@ -203,13 +123,74 @@ borrowck_moved_due_to_method_call =
         *[false] call
     }
 
-borrowck_moved_due_to_await =
+borrowck_moved_due_to_usage_in_operator =
     {$place_name} {$is_partial ->
         [true] partially moved
         *[false] moved
-    } due to this {$is_loop_message ->
-        [true] await, in previous iteration of loop
-        *[false] await
+    } due to usage in {$is_loop_message ->
+        [true] operator, in previous iteration of loop
+        *[false] operator
+    }
+
+borrowck_opaque_type_non_generic_param =
+    expected generic {$kind} parameter, found `{$ty}`
+    .label = {STREQ($ty, "'static") ->
+        [true] cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
+        *[other] this generic parameter must be used with a generic {$kind} parameter
+    }
+
+borrowck_partial_var_move_by_use_in_closure =
+    variable {$is_partial ->
+        [true] partially moved
+        *[false] moved
+    } due to use in closure
+
+borrowck_partial_var_move_by_use_in_generator =
+    variable {$is_partial ->
+        [true] partially moved
+        *[false] moved
+    } due to use in generator
+
+borrowck_returned_async_block_escaped =
+    returns an `async` block that contains a reference to a captured variable, which then escapes the closure body
+
+borrowck_returned_closure_escaped =
+    returns a closure that contains a reference to a captured variable, which then escapes the closure body
+
+borrowck_returned_lifetime_short =
+    {$category_desc}requires that `{$free_region_name}` must outlive `{$outlived_fr_name}`
+
+borrowck_returned_lifetime_wrong =
+    {$mir_def_name} was supposed to return data with lifetime `{$outlived_fr_name}` but it is returning data with lifetime `{$fr_name}`
+
+borrowck_returned_ref_escaped =
+    returns a reference to a captured variable which escapes the closure body
+
+borrowck_suggest_create_freash_reborrow =
+    consider reborrowing the `Pin` instead of moving it
+
+borrowck_suggest_iterate_over_slice =
+    consider iterating over a slice of the `{$ty}`'s content to avoid moving into the `for` loop
+
+borrowck_ty_no_impl_copy =
+    {$is_partial_move ->
+        [true] partial move
+        *[false] move
+    } occurs because {$place} has type `{$ty}`, which does not implement the `Copy` trait
+
+borrowck_use_due_to_use_closure =
+    use occurs due to use in closure
+
+borrowck_use_due_to_use_generator =
+    use occurs due to use in generator
+
+borrowck_used_impl_require_static =
+    the used `impl` has a `'static` requirement
+
+borrowck_value_capture_here =
+    value captured {$is_within ->
+        [true] here by generator
+        *[false] here
     }
 
 borrowck_value_moved_here =
@@ -224,41 +205,60 @@ borrowck_value_moved_here =
         *[false] {""}
     }
 
-borrowck_consider_borrow_type_contents =
-    help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
+borrowck_var_borrow_by_use_in_closure =
+    borrow occurs due to use in closure
 
-borrowck_moved_a_fn_once_in_call =
-    this value implements `FnOnce`, which causes it to be moved when called
+borrowck_var_borrow_by_use_in_generator =
+    borrow occurs due to use in generator
 
-borrowck_calling_operator_moves_lhs =
-    calling this operator moves the left-hand side
+borrowck_var_borrow_by_use_place_in_closure =
+    {$is_single_var ->
+        *[true] borrow occurs
+        [false] borrows occur
+    } due to use of {$place} in closure
 
-borrowck_func_take_self_moved_place =
-    `{$func}` takes ownership of the receiver `self`, which moves {$place_name}
+borrowck_var_borrow_by_use_place_in_generator =
+    {$is_single_var ->
+        *[true] borrow occurs
+        [false] borrows occur
+    } due to use of {$place} in generator
 
-borrowck_suggest_iterate_over_slice =
-    consider iterating over a slice of the `{$ty}`'s content to avoid moving into the `for` loop
+borrowck_var_cannot_escape_closure =
+    captured variable cannot escape `FnMut` closure body
+    .note = `FnMut` closures only have access to their captured variables while they are executing...
+    .cannot_escape = ...therefore, they cannot allow references to captured variables to escape
 
-borrowck_suggest_create_freash_reborrow =
-    consider reborrowing the `Pin` instead of moving it
+borrowck_var_does_not_need_mut =
+    variable does not need to be mutable
+    .suggestion = remove this `mut`
 
-borrowck_value_capture_here =
-    value captured {$is_within ->
-        [true] here by generator
-        *[false] here
-    }
+borrowck_var_first_borrow_by_use_place_in_closure =
+    first borrow occurs due to use of {$place} in closure
 
-borrowck_move_out_place_here =
-    {$place} is moved here
+borrowck_var_first_borrow_by_use_place_in_generator =
+    first borrow occurs due to use of {$place} in generator
 
-borrowck_closure_invoked_twice =
-    closure cannot be invoked more than once because it moves the variable `{$place_name}` out of its environment
+borrowck_var_here_captured = variable captured here
 
-borrowck_closure_moved_twice =
-    closure cannot be moved more than once as it is not `Copy` due to moving the variable `{$place_name}` out of its environment
+borrowck_var_here_defined = variable defined here
 
-borrowck_ty_no_impl_copy =
-    {$is_partial_move ->
-        [true] partial move
-        *[false] move
-    } occurs because {$place} has type `{$ty}`, which does not implement the `Copy` trait
+borrowck_var_move_by_use_in_closure =
+    move occurs due to use in closure
+
+borrowck_var_move_by_use_in_generator =
+    move occurs due to use in generator
+
+borrowck_var_move_by_use_place_in_closure =
+    move occurs due to use of {$place} in closure
+
+borrowck_var_move_by_use_place_in_generator =
+    move occurs due to use of {$place} in generator
+
+borrowck_var_mutable_borrow_by_use_place_in_closure =
+    mutable borrow occurs due to use of {$place} in closure
+
+borrowck_var_second_borrow_by_use_place_in_closure =
+    second borrow occurs due to use of {$place} in closure
+
+borrowck_var_second_borrow_by_use_place_in_generator =
+    second borrow occurs due to use of {$place} in generator
diff --git a/compiler/rustc_borrowck/src/def_use.rs b/compiler/rustc_borrowck/src/def_use.rs
index b775739fed2..b719a610e07 100644
--- a/compiler/rustc_borrowck/src/def_use.rs
+++ b/compiler/rustc_borrowck/src/def_use.rs
@@ -50,7 +50,6 @@ pub fn categorize(context: PlaceContext) -> Option<DefUse> {
         PlaceContext::MutatingUse(MutatingUseContext::Borrow) |
         PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow) |
         PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow) |
-        PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow) |
 
         // `PlaceMention` and `AscribeUserType` both evaluate the place, which must not
         // contain dangling references.
diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
index f41795d60a0..cfcf31fce32 100644
--- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
@@ -180,24 +180,25 @@ trait TypeOpInfo<'tcx> {
             return;
         };
 
-        let placeholder_region = tcx.mk_re_placeholder(ty::Placeholder {
-            universe: adjusted_universe.into(),
-            bound: placeholder.bound,
-        });
-
-        let error_region =
-            if let RegionElement::PlaceholderRegion(error_placeholder) = error_element {
-                let adjusted_universe =
-                    error_placeholder.universe.as_u32().checked_sub(base_universe.as_u32());
-                adjusted_universe.map(|adjusted| {
-                    tcx.mk_re_placeholder(ty::Placeholder {
-                        universe: adjusted.into(),
-                        bound: error_placeholder.bound,
-                    })
-                })
-            } else {
-                None
-            };
+        let placeholder_region = ty::Region::new_placeholder(
+            tcx,
+            ty::Placeholder { universe: adjusted_universe.into(), bound: placeholder.bound },
+        );
+
+        let error_region = if let RegionElement::PlaceholderRegion(error_placeholder) =
+            error_element
+        {
+            let adjusted_universe =
+                error_placeholder.universe.as_u32().checked_sub(base_universe.as_u32());
+            adjusted_universe.map(|adjusted| {
+                ty::Region::new_placeholder(
+                    tcx,
+                    ty::Placeholder { universe: adjusted.into(), bound: error_placeholder.bound },
+                )
+            })
+        } else {
+            None
+        };
 
         debug!(?placeholder_region);
 
@@ -390,7 +391,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
         error_region,
         &region_constraints,
         |vid| ocx.infcx.region_var_origin(vid),
-        |vid| ocx.infcx.universe_of_region(ocx.infcx.tcx.mk_re_var(vid)),
+        |vid| ocx.infcx.universe_of_region(ty::Region::new_var(ocx.infcx.tcx, vid)),
     )
 }
 
@@ -411,7 +412,7 @@ fn try_extract_error_from_region_constraints<'tcx>(
                 }
                 // FIXME: Should this check the universe of the var?
                 Constraint::VarSubReg(vid, sup) if sup == placeholder_region => {
-                    Some((infcx.tcx.mk_re_var(vid), cause.clone()))
+                    Some((ty::Region::new_var(infcx.tcx, vid), cause.clone()))
                 }
                 _ => None,
             }
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 04b8174079a..15d73ed732f 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -1635,34 +1635,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             })
     }
 
-    /// Reports StorageDeadOrDrop of `place` conflicts with `borrow`.
-    ///
-    /// Depending on the origin of the StorageDeadOrDrop, this may be
-    /// reported as either a drop or an illegal mutation of a borrowed value.
-    /// The latter is preferred when the this is a drop triggered by a
-    /// reassignment, as it's more user friendly to report a problem with the
-    /// explicit assignment than the implicit drop.
-    #[instrument(level = "debug", skip(self))]
-    pub(crate) fn report_storage_dead_or_drop_of_borrowed(
-        &mut self,
-        location: Location,
-        place_span: (Place<'tcx>, Span),
-        borrow: &BorrowData<'tcx>,
-    ) {
-        // It's sufficient to check the last desugaring as Replace is the last
-        // one to be applied.
-        if let Some(DesugaringKind::Replace) = place_span.1.desugaring_kind() {
-            self.report_illegal_mutation_of_borrowed(location, place_span, borrow)
-        } else {
-            self.report_borrowed_value_does_not_live_long_enough(
-                location,
-                borrow,
-                place_span,
-                Some(WriteKind::StorageDeadOrDrop),
-            )
-        }
-    }
-
     /// This means that some data referenced by `borrow` needs to live
     /// past the point where the StorageDeadOrDrop of `place` occurs.
     /// This is usually interpreted as meaning that `place` has too
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 4bde372c847..d0e17bf5a08 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -641,13 +641,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             let Some(hir::Node::Item(item)) = node else { return; };
             let hir::ItemKind::Fn(.., body_id) = item.kind else { return; };
             let body = self.infcx.tcx.hir().body(body_id);
-            let mut assign_span = span;
-            // Drop desugaring is done at MIR build so it's not in the HIR
-            if let Some(DesugaringKind::Replace) = span.desugaring_kind() {
-                assign_span.remove_mark();
-            }
 
-            let mut v = V { assign_span, err, ty, suggested: false };
+            let mut v = V { assign_span: span, err, ty, suggested: false };
             v.visit_body(body);
             if !v.suggested {
                 err.help(format!(
diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs
index 036391d074d..b2ff25ecb96 100644
--- a/compiler/rustc_borrowck/src/invalidation.rs
+++ b/compiler/rustc_borrowck/src/invalidation.rs
@@ -112,11 +112,13 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
             TerminatorKind::SwitchInt { discr, targets: _ } => {
                 self.consume_operand(location, discr);
             }
-            TerminatorKind::Drop { place: drop_place, target: _, unwind: _ } => {
+            TerminatorKind::Drop { place: drop_place, target: _, unwind: _, replace } => {
+                let write_kind =
+                    if *replace { WriteKind::Replace } else { WriteKind::StorageDeadOrDrop };
                 self.access_place(
                     location,
                     *drop_place,
-                    (AccessDepth::Drop, Write(WriteKind::StorageDeadOrDrop)),
+                    (AccessDepth::Drop, Write(write_kind)),
                     LocalMutationIsAllowed::Yes,
                 );
             }
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 9277a262f97..a53ea100c22 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -685,17 +685,19 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
             TerminatorKind::SwitchInt { discr, targets: _ } => {
                 self.consume_operand(loc, (discr, span), flow_state);
             }
-            TerminatorKind::Drop { place, target: _, unwind: _ } => {
+            TerminatorKind::Drop { place, target: _, unwind: _, replace } => {
                 debug!(
                     "visit_terminator_drop \
                      loc: {:?} term: {:?} place: {:?} span: {:?}",
                     loc, term, place, span
                 );
 
+                let write_kind =
+                    if *replace { WriteKind::Replace } else { WriteKind::StorageDeadOrDrop };
                 self.access_place(
                     loc,
                     (*place, span),
-                    (AccessDepth::Drop, Write(WriteKind::StorageDeadOrDrop)),
+                    (AccessDepth::Drop, Write(write_kind)),
                     LocalMutationIsAllowed::Yes,
                     flow_state,
                 );
@@ -885,6 +887,7 @@ enum ReadKind {
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 enum WriteKind {
     StorageDeadOrDrop,
+    Replace,
     MutableBorrow(BorrowKind),
     Mutate,
     Move,
@@ -1132,13 +1135,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                             this.buffer_error(err);
                         }
                         WriteKind::StorageDeadOrDrop => this
-                            .report_storage_dead_or_drop_of_borrowed(location, place_span, borrow),
+                            .report_borrowed_value_does_not_live_long_enough(
+                                location,
+                                borrow,
+                                place_span,
+                                Some(WriteKind::StorageDeadOrDrop),
+                            ),
                         WriteKind::Mutate => {
                             this.report_illegal_mutation_of_borrowed(location, place_span, borrow)
                         }
                         WriteKind::Move => {
                             this.report_move_out_while_borrowed(location, place_span, borrow)
                         }
+                        WriteKind::Replace => {
+                            this.report_illegal_mutation_of_borrowed(location, place_span, borrow)
+                        }
                     }
                     Control::Break
                 }
@@ -1982,12 +1993,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
             Reservation(
                 WriteKind::Move
+                | WriteKind::Replace
                 | WriteKind::StorageDeadOrDrop
                 | WriteKind::MutableBorrow(BorrowKind::Shared)
                 | WriteKind::MutableBorrow(BorrowKind::Shallow),
             )
             | Write(
                 WriteKind::Move
+                | WriteKind::Replace
                 | WriteKind::StorageDeadOrDrop
                 | WriteKind::MutableBorrow(BorrowKind::Shared)
                 | WriteKind::MutableBorrow(BorrowKind::Shallow),
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index 889acb3acbe..b5014a3f479 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -441,7 +441,7 @@ fn for_each_region_constraint<'tcx>(
         let subject = match req.subject {
             ClosureOutlivesSubject::Region(subject) => format!("{:?}", subject),
             ClosureOutlivesSubject::Ty(ty) => {
-                format!("{:?}", ty.instantiate(tcx, |vid| tcx.mk_re_var(vid)))
+                format!("{:?}", ty.instantiate(tcx, |vid| ty::Region::new_var(tcx, vid)))
             }
         };
         with_msg(format!("where {}: {:?}", subject, req.outlived_free_region,))?;
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 50b246b1478..2a0cb49672b 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -1158,7 +1158,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 .universal_regions_outlived_by(r_scc)
                 .filter(|&u_r| !self.universal_regions.is_local_free_region(u_r))
                 .find(|&u_r| self.eval_equal(u_r, r_vid))
-                .map(|u_r| tcx.mk_re_var(u_r))
+                .map(|u_r| ty::Region::new_var(tcx, u_r))
                 // In the case of a failure, use `ReErased`. We will eventually
                 // return `None` in this case.
                 .unwrap_or(tcx.lifetimes.re_erased)
@@ -1355,7 +1355,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             let vid = self.to_region_vid(r);
             let scc = self.constraint_sccs.scc(vid);
             let repr = self.scc_representatives[scc];
-            tcx.mk_re_var(repr)
+            ty::Region::new_var(tcx, repr)
         })
     }
 
@@ -1779,7 +1779,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             }
 
             // If not, report an error.
-            let member_region = infcx.tcx.mk_re_var(member_region_vid);
+            let member_region = ty::Region::new_var(infcx.tcx, member_region_vid);
             errors_buffer.push(RegionErrorKind::UnexpectedHiddenRegion {
                 span: m_c.definition_span,
                 hidden_ty: m_c.hidden_ty,
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index 7fc89e89a35..33f07c1d8fc 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -92,7 +92,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                     }
                     None => {
                         subst_regions.push(vid);
-                        infcx.tcx.mk_re_error_with_message(
+                        ty::Region::new_error_with_message(
+                            infcx.tcx,
                             concrete_type.span,
                             "opaque type with non-universal region substs",
                         )
diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs
index 95dcc8d4b19..f527eee7bda 100644
--- a/compiler/rustc_borrowck/src/type_check/canonical.rs
+++ b/compiler/rustc_borrowck/src/type_check/canonical.rs
@@ -1,12 +1,12 @@
 use std::fmt;
 
+use rustc_errors::ErrorGuaranteed;
 use rustc_infer::infer::canonical::Canonical;
 use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable};
 use rustc_span::def_id::DefId;
 use rustc_span::Span;
 use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput};
-use rustc_trait_selection::traits::query::{Fallible, NoSolution};
 use rustc_trait_selection::traits::ObligationCause;
 
 use crate::diagnostics::{ToUniverseInfo, UniverseInfo};
@@ -30,14 +30,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         locations: Locations,
         category: ConstraintCategory<'tcx>,
         op: Op,
-    ) -> Fallible<R>
+    ) -> Result<R, ErrorGuaranteed>
     where
         Op: type_op::TypeOp<'tcx, Output = R>,
         Op::ErrorInfo: ToUniverseInfo<'tcx>,
     {
         let old_universe = self.infcx.universe();
 
-        let TypeOpOutput { output, constraints, error_info } = op.fully_perform(self.infcx)?;
+        let TypeOpOutput { output, constraints, error_info } =
+            op.fully_perform(self.infcx, locations.span(self.body))?;
 
         debug!(?output, ?constraints);
 
@@ -135,14 +136,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
     ) {
         let param_env = self.param_env;
         let predicate = predicate.to_predicate(self.tcx());
-        self.fully_perform_op(
+        let _: Result<_, ErrorGuaranteed> = self.fully_perform_op(
             locations,
             category,
             param_env.and(type_op::prove_predicate::ProvePredicate::new(predicate)),
-        )
-        .unwrap_or_else(|NoSolution| {
-            span_mirbug!(self, NoSolution, "could not prove {:?}", predicate);
-        })
+        );
     }
 
     pub(super) fn normalize<T>(&mut self, value: T, location: impl NormalizeLocation) -> T
@@ -163,15 +161,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx,
     {
         let param_env = self.param_env;
-        self.fully_perform_op(
+        let result: Result<_, ErrorGuaranteed> = self.fully_perform_op(
             location.to_locations(),
             category,
             param_env.and(type_op::normalize::Normalize::new(value)),
-        )
-        .unwrap_or_else(|NoSolution| {
-            span_mirbug!(self, NoSolution, "failed to normalize `{:?}`", value);
-            value
-        })
+        );
+        result.unwrap_or(value)
     }
 
     #[instrument(skip(self), level = "debug")]
@@ -181,18 +176,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         user_ty: ty::UserType<'tcx>,
         span: Span,
     ) {
-        self.fully_perform_op(
+        let _: Result<_, ErrorGuaranteed> = self.fully_perform_op(
             Locations::All(span),
             ConstraintCategory::Boring,
             self.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(mir_ty, user_ty)),
-        )
-        .unwrap_or_else(|err| {
-            span_mirbug!(
-                self,
-                span,
-                "ascribe_user_type `{mir_ty:?}=={user_ty:?}` failed with `{err:?}`",
-            );
-        });
+        );
     }
 
     /// *Incorrectly* skips the WF checks we normally do in `ascribe_user_type`.
@@ -219,7 +207,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
 
         let cause = ObligationCause::dummy_with_span(span);
         let param_env = self.param_env;
-        self.fully_perform_op(
+        let _: Result<_, ErrorGuaranteed> = self.fully_perform_op(
             Locations::All(span),
             ConstraintCategory::Boring,
             type_op::custom::CustomTypeOp::new(
@@ -230,13 +218,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 },
                 "ascribe_user_type_skip_wf",
             ),
-        )
-        .unwrap_or_else(|err| {
-            span_mirbug!(
-                self,
-                span,
-                "ascribe_user_type_skip_wf `{mir_ty:?}=={user_ty:?}` failed with `{err:?}`",
-            );
-        });
+        );
     }
 }
diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
index bd01c0b504c..c8ec1257d37 100644
--- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
+++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
@@ -8,7 +8,7 @@ use rustc_infer::infer::InferCtxt;
 use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::traits::query::OutlivesBound;
 use rustc_middle::ty::{self, RegionVid, Ty};
-use rustc_span::Span;
+use rustc_span::{Span, DUMMY_SP};
 use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
 use std::rc::Rc;
 use type_op::TypeOpOutput;
@@ -243,18 +243,11 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
             let TypeOpOutput { output: norm_ty, constraints: constraints_normalize, .. } = self
                 .param_env
                 .and(type_op::normalize::Normalize::new(ty))
-                .fully_perform(self.infcx)
-                .unwrap_or_else(|_| {
-                    let guar = self
-                        .infcx
-                        .tcx
-                        .sess
-                        .delay_span_bug(span, format!("failed to normalize {:?}", ty));
-                    TypeOpOutput {
-                        output: self.infcx.tcx.ty_error(guar),
-                        constraints: None,
-                        error_info: None,
-                    }
+                .fully_perform(self.infcx, span)
+                .unwrap_or_else(|guar| TypeOpOutput {
+                    output: self.infcx.tcx.ty_error(guar),
+                    constraints: None,
+                    error_info: None,
                 });
             if let Some(c) = constraints_normalize {
                 constraints.push(c)
@@ -324,7 +317,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
         let TypeOpOutput { output: bounds, constraints, .. } = self
             .param_env
             .and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty })
-            .fully_perform(self.infcx)
+            .fully_perform(self.infcx, DUMMY_SP)
             .unwrap_or_else(|_| bug!("failed to compute implied bounds {:?}", ty));
         debug!(?bounds, ?constraints);
         self.add_outlives_bounds(bounds);
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
index 9731b10aa99..eb02604b9d9 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
@@ -3,8 +3,9 @@ use rustc_index::bit_set::HybridBitSet;
 use rustc_index::interval::IntervalSet;
 use rustc_infer::infer::canonical::QueryRegionConstraints;
 use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, Local, Location};
+use rustc_middle::traits::query::DropckOutlivesResult;
 use rustc_middle::ty::{Ty, TyCtxt, TypeVisitable, TypeVisitableExt};
-use rustc_trait_selection::traits::query::dropck_outlives::DropckOutlivesResult;
+use rustc_span::DUMMY_SP;
 use rustc_trait_selection::traits::query::type_op::outlives::DropckOutlives;
 use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
 use std::rc::Rc;
@@ -568,10 +569,15 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
     ) -> DropData<'tcx> {
         debug!("compute_drop_data(dropped_ty={:?})", dropped_ty,);
 
-        let param_env = typeck.param_env;
-        let TypeOpOutput { output, constraints, .. } =
-            param_env.and(DropckOutlives::new(dropped_ty)).fully_perform(typeck.infcx).unwrap();
-
-        DropData { dropck_result: output, region_constraint_data: constraints }
+        match typeck
+            .param_env
+            .and(DropckOutlives::new(dropped_ty))
+            .fully_perform(typeck.infcx, DUMMY_SP)
+        {
+            Ok(TypeOpOutput { output, constraints, .. }) => {
+                DropData { dropck_result: output, region_constraint_data: constraints }
+            }
+            Err(_) => DropData { dropck_result: Default::default(), region_constraint_data: None },
+        }
     }
 }
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index cf204cff6b3..3b896f6540c 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -10,6 +10,7 @@ use either::Either;
 use hir::OpaqueTyOrigin;
 use rustc_data_structures::frozen::Frozen;
 use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
+use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
@@ -26,6 +27,7 @@ use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::AssertKind;
 use rustc_middle::mir::*;
+use rustc_middle::traits::query::NoSolution;
 use rustc_middle::ty::adjustment::PointerCast;
 use rustc_middle::ty::cast::CastTy;
 use rustc_middle::ty::subst::{SubstsRef, UserSubsts};
@@ -41,7 +43,7 @@ use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
 use rustc_trait_selection::traits::query::type_op::custom::scrape_region_constraints;
 use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
 use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
-use rustc_trait_selection::traits::query::Fallible;
+
 use rustc_trait_selection::traits::PredicateObligation;
 
 use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
@@ -137,7 +139,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
     upvars: &[Upvar<'tcx>],
     use_polonius: bool,
 ) -> MirTypeckResults<'tcx> {
-    let implicit_region_bound = infcx.tcx.mk_re_var(universal_regions.fr_fn_body);
+    let implicit_region_bound = ty::Region::new_var(infcx.tcx, universal_regions.fr_fn_body);
     let mut constraints = MirTypeckRegionConstraints {
         placeholder_indices: PlaceholderIndices::default(),
         placeholder_index_to_region: IndexVec::default(),
@@ -216,24 +218,22 @@ pub(crate) fn type_check<'mir, 'tcx>(
     let opaque_type_values = opaque_type_values
         .into_iter()
         .map(|(opaque_type_key, decl)| {
-            checker
-                .fully_perform_op(
-                    Locations::All(body.span),
-                    ConstraintCategory::OpaqueType,
-                    CustomTypeOp::new(
-                        |ocx| {
-                            ocx.infcx.register_member_constraints(
-                                param_env,
-                                opaque_type_key,
-                                decl.hidden_type.ty,
-                                decl.hidden_type.span,
-                            );
-                            Ok(())
-                        },
-                        "opaque_type_map",
-                    ),
-                )
-                .unwrap();
+            let _: Result<_, ErrorGuaranteed> = checker.fully_perform_op(
+                Locations::All(body.span),
+                ConstraintCategory::OpaqueType,
+                CustomTypeOp::new(
+                    |ocx| {
+                        ocx.infcx.register_member_constraints(
+                            param_env,
+                            opaque_type_key,
+                            decl.hidden_type.ty,
+                            decl.hidden_type.span,
+                        );
+                        Ok(())
+                    },
+                    "opaque_type_map",
+                ),
+            );
             let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type);
             trace!("finalized opaque type {:?} to {:#?}", opaque_type_key, hidden_type.ty.kind());
             if hidden_type.has_non_region_infer() {
@@ -766,8 +766,8 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
             PlaceContext::MutatingUse(_) => ty::Invariant,
             PlaceContext::NonUse(StorageDead | StorageLive | VarDebugInfo) => ty::Invariant,
             PlaceContext::NonMutatingUse(
-                Inspect | Copy | Move | PlaceMention | SharedBorrow | ShallowBorrow | UniqueBorrow
-                | AddressOf | Projection,
+                Inspect | Copy | Move | PlaceMention | SharedBorrow | ShallowBorrow | AddressOf
+                | Projection,
             ) => ty::Covariant,
             PlaceContext::NonUse(AscribeUserTy(variance)) => variance,
         }
@@ -1134,7 +1134,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         sup: Ty<'tcx>,
         locations: Locations,
         category: ConstraintCategory<'tcx>,
-    ) -> Fallible<()> {
+    ) -> Result<(), NoSolution> {
         // Use this order of parameters because the sup type is usually the
         // "expected" type in diagnostics.
         self.relate_types(sup, ty::Variance::Contravariant, sub, locations, category)
@@ -1147,7 +1147,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         found: Ty<'tcx>,
         locations: Locations,
         category: ConstraintCategory<'tcx>,
-    ) -> Fallible<()> {
+    ) -> Result<(), NoSolution> {
         self.relate_types(expected, ty::Variance::Invariant, found, locations, category)
     }
 
@@ -1159,7 +1159,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         user_ty: &UserTypeProjection,
         locations: Locations,
         category: ConstraintCategory<'tcx>,
-    ) -> Fallible<()> {
+    ) -> Result<(), NoSolution> {
         let annotated_type = self.user_type_annotations[user_ty.base].inferred_ty;
         trace!(?annotated_type);
         let mut curr_projected_ty = PlaceTy::from_ty(annotated_type);
@@ -2755,11 +2755,20 @@ impl<'tcx> TypeOp<'tcx> for InstantiateOpaqueType<'tcx> {
     /// constraints in our `InferCtxt`
     type ErrorInfo = InstantiateOpaqueType<'tcx>;
 
-    fn fully_perform(mut self, infcx: &InferCtxt<'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> {
-        let (mut output, region_constraints) = scrape_region_constraints(infcx, |ocx| {
-            ocx.register_obligations(self.obligations.clone());
-            Ok(())
-        })?;
+    fn fully_perform(
+        mut self,
+        infcx: &InferCtxt<'tcx>,
+        span: Span,
+    ) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed> {
+        let (mut output, region_constraints) = scrape_region_constraints(
+            infcx,
+            |ocx| {
+                ocx.register_obligations(self.obligations.clone());
+                Ok(())
+            },
+            "InstantiateOpaqueType",
+            span,
+        )?;
         self.region_constraints = Some(region_constraints);
         output.error_info = Some(self);
         Ok(output)
diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
index dd1f89e5b91..8c4bfb2c6e0 100644
--- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs
+++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
@@ -1,12 +1,13 @@
+use rustc_errors::ErrorGuaranteed;
 use rustc_infer::infer::nll_relate::{TypeRelating, TypeRelatingDelegate};
 use rustc_infer::infer::NllRegionVariableOrigin;
 use rustc_infer::traits::PredicateObligations;
 use rustc_middle::mir::ConstraintCategory;
+use rustc_middle::traits::query::NoSolution;
 use rustc_middle::ty::relate::TypeRelation;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::symbol::sym;
 use rustc_span::{Span, Symbol};
-use rustc_trait_selection::traits::query::Fallible;
 
 use crate::constraints::OutlivesConstraint;
 use crate::diagnostics::UniverseInfo;
@@ -30,7 +31,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         b: Ty<'tcx>,
         locations: Locations,
         category: ConstraintCategory<'tcx>,
-    ) -> Fallible<()> {
+    ) -> Result<(), NoSolution> {
         TypeRelating::new(
             self.infcx,
             NllTypeRelatingDelegate::new(self, locations, category, UniverseInfo::relate(a, b)),
@@ -47,7 +48,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         b: ty::SubstsRef<'tcx>,
         locations: Locations,
         category: ConstraintCategory<'tcx>,
-    ) -> Fallible<()> {
+    ) -> Result<(), NoSolution> {
         TypeRelating::new(
             self.infcx,
             NllTypeRelatingDelegate::new(self, locations, category, UniverseInfo::other()),
@@ -185,7 +186,7 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
     }
 
     fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
-        match self.type_checker.fully_perform_op(
+        let _: Result<_, ErrorGuaranteed> = self.type_checker.fully_perform_op(
             self.locations,
             self.category,
             InstantiateOpaqueType {
@@ -194,16 +195,6 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
                 base_universe: None,
                 region_constraints: None,
             },
-        ) {
-            Ok(()) => {}
-            Err(_) => {
-                // It's a bit redundant to delay a bug here, but I'd rather
-                // delay more bugs than accidentally not delay a bug at all.
-                self.type_checker.tcx().sess.delay_span_bug(
-                    self.locations.span(self.type_checker.body),
-                    "errors selecting obligation during MIR typeck",
-                );
-            }
-        };
+        );
     }
 }
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index 56f078f2da8..c871703429a 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -500,7 +500,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
                     .next_nll_region_var(FR, || RegionCtxt::Free(Symbol::intern("c-variadic")))
                     .as_var();
 
-                let region = self.infcx.tcx.mk_re_var(reg_vid);
+                let region = ty::Region::new_var(self.infcx.tcx, reg_vid);
                 let va_list_ty =
                     self.infcx.tcx.type_of(va_list_did).subst(self.infcx.tcx, &[region.into()]);
 
@@ -660,7 +660,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
                     var: ty::BoundVar::from_usize(bound_vars.len() - 1),
                     kind: ty::BrEnv,
                 };
-                let env_region = tcx.mk_re_late_bound(ty::INNERMOST, br);
+                let env_region = ty::Region::new_late_bound(tcx, ty::INNERMOST, br);
                 let closure_ty = tcx.closure_env_ty(def_id, substs, env_region).unwrap();
 
                 // The "inputs" of the closure in the
@@ -778,7 +778,8 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> {
     {
         let (value, _map) = self.tcx.replace_late_bound_regions(value, |br| {
             debug!(?br);
-            let liberated_region = self.tcx.mk_re_free(all_outlive_scope.to_def_id(), br.kind);
+            let liberated_region =
+                ty::Region::new_free(self.tcx, all_outlive_scope.to_def_id(), br.kind);
             let region_vid = {
                 let name = match br.kind.get_name() {
                     Some(name) => name,
@@ -889,7 +890,7 @@ impl<'tcx> UniversalRegionIndices<'tcx> {
     where
         T: TypeFoldable<TyCtxt<'tcx>>,
     {
-        tcx.fold_regions(value, |region, _| tcx.mk_re_var(self.to_region_vid(region)))
+        tcx.fold_regions(value, |region, _| ty::Region::new_var(tcx, self.to_region_vid(region)))
     }
 }
 
@@ -929,7 +930,7 @@ fn for_each_late_bound_region_in_item<'tcx>(
 
     for bound_var in tcx.late_bound_vars(tcx.hir().local_def_id_to_hir_id(mir_def_id)) {
         let ty::BoundVariableKind::Region(bound_region) = bound_var else { continue; };
-        let liberated_region = tcx.mk_re_free(mir_def_id.to_def_id(), bound_region);
+        let liberated_region = ty::Region::new_free(tcx, mir_def_id.to_def_id(), bound_region);
         f(liberated_region);
     }
 }
diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl
index 3b458b1d30b..f00cd39cbc8 100644
--- a/compiler/rustc_builtin_macros/messages.ftl
+++ b/compiler/rustc_builtin_macros/messages.ftl
@@ -1,10 +1,50 @@
-builtin_macros_requires_cfg_pattern =
-    macro requires a cfg-pattern as an argument
-    .label = cfg-pattern required
+builtin_macros_alloc_error_must_be_fn = alloc_error_handler must be a function
 
-builtin_macros_expected_one_cfg_pattern = expected 1 cfg-pattern
+builtin_macros_asm_clobber_abi = clobber_abi
+builtin_macros_asm_clobber_no_reg = asm with `clobber_abi` must specify explicit registers for outputs
+builtin_macros_asm_clobber_outputs = generic outputs
 
-builtin_macros_alloc_error_must_be_fn = alloc_error_handler must be a function
+builtin_macros_asm_duplicate_arg = duplicate argument named `{$name}`
+    .label = previously here
+    .arg = duplicate argument
+
+builtin_macros_asm_expected_comma = expected token: `,`
+    .label = expected `,`
+
+builtin_macros_asm_expected_other = expected operand, {$is_global_asm ->
+    [true] options
+    *[false] clobber_abi, options
+    }, or additional template string
+
+builtin_macros_asm_explicit_register_name = explicit register arguments cannot have names
+
+builtin_macros_asm_modifier_invalid = asm template modifier must be a single character
+
+builtin_macros_asm_mutually_exclusive = the `{$opt1}` and `{$opt2}` options are mutually exclusive
+
+builtin_macros_asm_noreturn = asm outputs are not allowed with the `noreturn` option
+
+builtin_macros_asm_opt_already_provided = the `{$symbol}` option was already provided
+    .label = this option was already provided
+    .suggestion = remove this option
+
+builtin_macros_asm_pos_after = positional arguments cannot follow named arguments or explicit register arguments
+    .pos = positional argument
+    .named = named argument
+    .explicit = explicit register argument
+
+builtin_macros_asm_pure_combine = the `pure` option must be combined with either `nomem` or `readonly`
+
+builtin_macros_asm_pure_no_output = asm with the `pure` option must have at least one output
+
+builtin_macros_asm_requires_template = requires at least a template string argument
+
+builtin_macros_asm_sym_no_path = expected a path for argument to `sym`
+
+builtin_macros_asm_underscore_input = _ cannot be used for input operands
+
+builtin_macros_assert_missing_comma = unexpected string literal
+    .suggestion = try adding a comma
 
 builtin_macros_assert_requires_boolean = macro requires a boolean expression as an argument
     .label = boolean expression required
@@ -12,51 +52,50 @@ builtin_macros_assert_requires_boolean = macro requires a boolean expression as
 builtin_macros_assert_requires_expression = macro requires an expression as an argument
     .suggestion = try removing semicolon
 
-builtin_macros_assert_missing_comma = unexpected string literal
-    .suggestion = try adding a comma
+builtin_macros_bad_derive_target = `derive` may only be applied to `struct`s, `enum`s and `union`s
+    .label = not applicable here
+    .label2 = not a `struct`, `enum` or `union`
+
+builtin_macros_cannot_derive_union = this trait cannot be derived for unions
 
-builtin_macros_cfg_accessible_unspecified_path = `cfg_accessible` path is not specified
-builtin_macros_cfg_accessible_multiple_paths = multiple `cfg_accessible` paths are specified
-builtin_macros_cfg_accessible_literal_path = `cfg_accessible` path cannot be a literal
 builtin_macros_cfg_accessible_has_args = `cfg_accessible` path cannot accept arguments
 
 builtin_macros_cfg_accessible_indeterminate = cannot determine whether the path is accessible or not
 
-builtin_macros_concat_bytestr = cannot concatenate a byte string literal
-
-builtin_macros_concat_missing_literal = expected a literal
-    .note = only literals (like `"foo"`, `-42` and `3.14`) can be passed to `concat!()`
+builtin_macros_cfg_accessible_literal_path = `cfg_accessible` path cannot be a literal
+builtin_macros_cfg_accessible_multiple_paths = multiple `cfg_accessible` paths are specified
+builtin_macros_cfg_accessible_unspecified_path = `cfg_accessible` path is not specified
+builtin_macros_concat_bytes_array = cannot concatenate doubly nested array
+    .note = byte strings are treated as arrays of bytes
+    .help = try flattening the array
 
-builtin_macros_concat_bytes_missing_literal = expected a byte literal
-    .note = only byte literals (like `b"foo"`, `b's'` and `[3, 4, 5]`) can be passed to `concat_bytes!()`
+builtin_macros_concat_bytes_bad_repeat = repeat count is not a positive number
 
 builtin_macros_concat_bytes_invalid = cannot concatenate {$lit_kind} literals
     .byte_char = try using a byte character
     .byte_str = try using a byte string
     .number_array = try wrapping the number in an array
 
-builtin_macros_concat_bytes_oob = numeric literal is out of bounds
+builtin_macros_concat_bytes_missing_literal = expected a byte literal
+    .note = only byte literals (like `b"foo"`, `b's'` and `[3, 4, 5]`) can be passed to `concat_bytes!()`
 
 builtin_macros_concat_bytes_non_u8 = numeric literal is not a `u8`
 
-builtin_macros_concat_bytes_array = cannot concatenate doubly nested array
-    .note = byte strings are treated as arrays of bytes
-    .help = try flattening the array
+builtin_macros_concat_bytes_oob = numeric literal is out of bounds
 
-builtin_macros_concat_bytes_bad_repeat = repeat count is not a positive number
+builtin_macros_concat_bytestr = cannot concatenate a byte string literal
+
+builtin_macros_concat_idents_ident_args = `concat_idents!()` requires ident args
 
 builtin_macros_concat_idents_missing_args = `concat_idents!()` takes 1 or more arguments
 builtin_macros_concat_idents_missing_comma = `concat_idents!()` expecting comma
-builtin_macros_concat_idents_ident_args = `concat_idents!()` requires ident args
+builtin_macros_concat_missing_literal = expected a literal
+    .note = only literals (like `"foo"`, `-42` and `3.14`) can be passed to `concat!()`
 
-builtin_macros_bad_derive_target = `derive` may only be applied to `struct`s, `enum`s and `union`s
-    .label = not applicable here
-    .label2 = not a `struct`, `enum` or `union`
+builtin_macros_default_arg = `#[default]` attribute does not accept a value
+    .suggestion = try using `#[default]`
 
-builtin_macros_unexpected_lit = expected path to a trait, found literal
-    .label = not a trait
-    .str_lit = try using `#[derive({$sym})]`
-    .other = for example, write `#[derive(Debug)]` for `Debug`
+builtin_macros_derive_macro_call = `derive` cannot be used on items with type macros
 
 builtin_macros_derive_path_args_list = traits in `#[derive(...)]` don't accept arguments
     .suggestion = remove the arguments
@@ -64,66 +103,38 @@ builtin_macros_derive_path_args_list = traits in `#[derive(...)]` don't accept a
 builtin_macros_derive_path_args_value = traits in `#[derive(...)]` don't accept values
     .suggestion = remove the value
 
-builtin_macros_derive_macro_call = `derive` cannot be used on items with type macros
-
-builtin_macros_cannot_derive_union = this trait cannot be derived for unions
-
-builtin_macros_no_default_variant = no default declared
-    .help = make a unit variant default by placing `#[default]` above it
-    .suggestion = make `{$ident}` default
-
-builtin_macros_multiple_defaults = multiple declared defaults
-    .label = first default
-    .additional = additional default
-    .note = only one variant can be default
-    .suggestion = make `{$ident}` default
-
-builtin_macros_non_unit_default = the `#[default]` attribute may only be used on unit enum variants
-    .help = consider a manual implementation of `Default`
-
-builtin_macros_non_exhaustive_default = default variant must be exhaustive
-    .label = declared `#[non_exhaustive]` here
-    .help = consider a manual implementation of `Default`
-
-builtin_macros_multiple_default_attrs = multiple `#[default]` attributes
-    .note = only one `#[default]` attribute is needed
-    .label = `#[default]` used here
-    .label_again = `#[default]` used again here
-    .help = try removing {$only_one ->
-    [true] this
-    *[false] these
-    }
-
-builtin_macros_default_arg = `#[default]` attribute does not accept a value
-    .suggestion = try using `#[default]`
-
-builtin_macros_env_takes_args = `env!()` takes 1 or 2 arguments
-
 builtin_macros_env_not_defined = environment variable `{$var}` not defined at compile time
     .cargo = Cargo sets build script variables at run time. Use `std::env::var("{$var}")` instead
     .other = use `std::env::var("{$var}")` to read the variable at run time
 
-builtin_macros_format_requires_string = requires at least a format string argument
+builtin_macros_env_takes_args = `env!()` takes 1 or 2 arguments
+
+builtin_macros_expected_one_cfg_pattern = expected 1 cfg-pattern
 
 builtin_macros_format_duplicate_arg = duplicate argument named `{$ident}`
     .label1 = previously here
     .label2 = duplicate argument
 
+builtin_macros_format_no_arg_named = there is no argument named `{$name}`
+    .note = did you intend to capture a variable `{$name}` from the surrounding scope?
+    .note2 = to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro
+
+builtin_macros_format_pos_mismatch = {$n} positional {$n ->
+    [one] argument
+    *[more] arguments
+    } in format string, but {$desc}
+
 builtin_macros_format_positional_after_named = positional arguments cannot follow named arguments
     .label = positional arguments must be before named arguments
     .named_args = named argument
 
+builtin_macros_format_requires_string = requires at least a format string argument
+
 builtin_macros_format_string_invalid = invalid format string: {$desc}
     .label = {$label1} in format string
     .note = {$note}
     .second_label = {$label}
 
-builtin_macros_sugg = consider using a positional formatting argument instead
-
-builtin_macros_format_no_arg_named = there is no argument named `{$name}`
-    .note = did you intend to capture a variable `{$name}` from the surrounding scope?
-    .note2 = to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro
-
 builtin_macros_format_unknown_trait = unknown format trait `{$ty}`
     .note = the only appropriate formatting traits are:
                                             - ``, which uses the `Display` trait
@@ -145,60 +156,49 @@ builtin_macros_format_unused_arg = {$named ->
 builtin_macros_format_unused_args = multiple unused formatting arguments
     .label = multiple missing formatting specifiers
 
-builtin_macros_format_pos_mismatch = {$n} positional {$n ->
-    [one] argument
-    *[more] arguments
-    } in format string, but {$desc}
-
-builtin_macros_test_case_non_item = `#[test_case]` attribute is only allowed on items
-
-builtin_macros_test_bad_fn = {$kind} functions cannot be used for tests
-    .label = `{$kind}` because of this
-
-builtin_macros_asm_explicit_register_name = explicit register arguments cannot have names
-
-builtin_macros_asm_mutually_exclusive = the `{$opt1}` and `{$opt2}` options are mutually exclusive
-
-builtin_macros_asm_pure_combine = the `pure` option must be combined with either `nomem` or `readonly`
-
-builtin_macros_asm_pure_no_output = asm with the `pure` option must have at least one output
-
-builtin_macros_asm_modifier_invalid = asm template modifier must be a single character
-
-builtin_macros_asm_requires_template = requires at least a template string argument
-
-builtin_macros_asm_expected_comma = expected token: `,`
-    .label = expected `,`
+builtin_macros_global_asm_clobber_abi = `clobber_abi` cannot be used with `global_asm!`
 
-builtin_macros_asm_underscore_input = _ cannot be used for input operands
+builtin_macros_multiple_default_attrs = multiple `#[default]` attributes
+    .note = only one `#[default]` attribute is needed
+    .label = `#[default]` used here
+    .label_again = `#[default]` used again here
+    .help = try removing {$only_one ->
+    [true] this
+    *[false] these
+    }
 
-builtin_macros_asm_sym_no_path = expected a path for argument to `sym`
+builtin_macros_multiple_defaults = multiple declared defaults
+    .label = first default
+    .additional = additional default
+    .note = only one variant can be default
+    .suggestion = make `{$ident}` default
 
-builtin_macros_asm_expected_other = expected operand, {$is_global_asm ->
-    [true] options
-    *[false] clobber_abi, options
-    }, or additional template string
+builtin_macros_no_default_variant = no default declared
+    .help = make a unit variant default by placing `#[default]` above it
+    .suggestion = make `{$ident}` default
 
-builtin_macros_asm_duplicate_arg = duplicate argument named `{$name}`
-    .label = previously here
-    .arg = duplicate argument
+builtin_macros_non_exhaustive_default = default variant must be exhaustive
+    .label = declared `#[non_exhaustive]` here
+    .help = consider a manual implementation of `Default`
 
-builtin_macros_asm_pos_after = positional arguments cannot follow named arguments or explicit register arguments
-    .pos = positional argument
-    .named = named argument
-    .explicit = explicit register argument
+builtin_macros_non_unit_default = the `#[default]` attribute may only be used on unit enum variants
+    .help = consider a manual implementation of `Default`
 
-builtin_macros_asm_noreturn = asm outputs are not allowed with the `noreturn` option
+builtin_macros_requires_cfg_pattern =
+    macro requires a cfg-pattern as an argument
+    .label = cfg-pattern required
 
-builtin_macros_global_asm_clobber_abi = `clobber_abi` cannot be used with `global_asm!`
+builtin_macros_sugg = consider using a positional formatting argument instead
 
-builtin_macros_asm_clobber_no_reg = asm with `clobber_abi` must specify explicit registers for outputs
-builtin_macros_asm_clobber_abi = clobber_abi
-builtin_macros_asm_clobber_outputs = generic outputs
+builtin_macros_test_bad_fn = {$kind} functions cannot be used for tests
+    .label = `{$kind}` because of this
 
-builtin_macros_asm_opt_already_provided = the `{$symbol}` option was already provided
-    .label = this option was already provided
-    .suggestion = remove this option
+builtin_macros_test_case_non_item = `#[test_case]` attribute is only allowed on items
 
 builtin_macros_test_runner_invalid = `test_runner` argument must be a path
 builtin_macros_test_runner_nargs = `#![test_runner(..)]` accepts exactly 1 argument
+
+builtin_macros_unexpected_lit = expected path to a trait, found literal
+    .label = not a trait
+    .str_lit = try using `#[derive({$sym})]`
+    .other = for example, write `#[derive(Debug)]` for `Debug`
diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs
index ea830a0ce60..b619e80e15f 100644
--- a/compiler/rustc_builtin_macros/src/assert/context.rs
+++ b/compiler/rustc_builtin_macros/src/assert/context.rs
@@ -233,10 +233,19 @@ impl<'cx, 'a> Context<'cx, 'a> {
             ExprKind::Cast(local_expr, _) => {
                 self.manage_cond_expr(local_expr);
             }
+            ExprKind::If(local_expr, _, _) => {
+                self.manage_cond_expr(local_expr);
+            }
             ExprKind::Index(prefix, suffix) => {
                 self.manage_cond_expr(prefix);
                 self.manage_cond_expr(suffix);
             }
+            ExprKind::Let(_, local_expr, _) => {
+                self.manage_cond_expr(local_expr);
+            }
+            ExprKind::Match(local_expr, _) => {
+                self.manage_cond_expr(local_expr);
+            }
             ExprKind::MethodCall(call) => {
                 for arg in &mut call.args {
                     self.manage_cond_expr(arg);
@@ -295,17 +304,14 @@ impl<'cx, 'a> Context<'cx, 'a> {
             | ExprKind::Continue(_)
             | ExprKind::Err
             | ExprKind::Field(_, _)
-            | ExprKind::FormatArgs(_)
             | ExprKind::ForLoop(_, _, _, _)
-            | ExprKind::If(_, _, _)
+            | ExprKind::FormatArgs(_)
             | ExprKind::IncludedBytes(..)
             | ExprKind::InlineAsm(_)
-            | ExprKind::OffsetOf(_, _)
-            | ExprKind::Let(_, _, _)
             | ExprKind::Lit(_)
             | ExprKind::Loop(_, _, _)
             | ExprKind::MacCall(_)
-            | ExprKind::Match(_, _)
+            | ExprKind::OffsetOf(_, _)
             | ExprKind::Path(_, _)
             | ExprKind::Ret(_)
             | ExprKind::Try(_)
diff --git a/compiler/rustc_builtin_macros/src/compile_error.rs b/compiler/rustc_builtin_macros/src/compile_error.rs
index aeb3bb80045..5efc5a4e3ee 100644
--- a/compiler/rustc_builtin_macros/src/compile_error.rs
+++ b/compiler/rustc_builtin_macros/src/compile_error.rs
@@ -18,7 +18,7 @@ pub fn expand_compile_error<'cx>(
         reason = "diagnostic message is specified by user"
     )]
     #[expect(rustc::untranslatable_diagnostic, reason = "diagnostic message is specified by user")]
-    cx.span_err(sp, var.as_str());
+    cx.span_err(sp, var.to_string());
 
     DummyResult::any(sp)
 }
diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs
index 9883563746e..9ba98d0a5d1 100644
--- a/compiler/rustc_builtin_macros/src/deriving/clone.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs
@@ -68,7 +68,6 @@ pub fn expand_deriving_clone(
         _ => cx.span_bug(span, "`#[derive(Clone)]` on trait item or impl item"),
     }
 
-    let attrs = thin_vec![cx.attr_word(sym::inline, span)];
     let trait_def = TraitDef {
         span,
         path: path_std!(clone::Clone),
@@ -82,7 +81,7 @@ pub fn expand_deriving_clone(
             explicit_self: true,
             nonself_args: Vec::new(),
             ret_ty: Self_,
-            attributes: attrs,
+            attributes: thin_vec![cx.attr_word(sym::inline, span)],
             fieldless_variants_strategy: FieldlessVariantsStrategy::Default,
             combine_substructure: substructure,
         }],
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs
index af971958680..c78a0eb04a0 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs
@@ -18,11 +18,6 @@ pub fn expand_deriving_eq(
     is_const: bool,
 ) {
     let span = cx.with_def_site_ctxt(span);
-    let attrs = thin_vec![
-        cx.attr_word(sym::inline, span),
-        cx.attr_nested_word(sym::doc, sym::hidden, span),
-        cx.attr_word(sym::no_coverage, span)
-    ];
     let trait_def = TraitDef {
         span,
         path: path_std!(cmp::Eq),
@@ -36,7 +31,11 @@ pub fn expand_deriving_eq(
             explicit_self: true,
             nonself_args: vec![],
             ret_ty: Unit,
-            attributes: attrs,
+            attributes: thin_vec![
+                cx.attr_word(sym::inline, span),
+                cx.attr_nested_word(sym::doc, sym::hidden, span),
+                cx.attr_word(sym::no_coverage, span)
+            ],
             fieldless_variants_strategy: FieldlessVariantsStrategy::Unify,
             combine_substructure: combine_substructure(Box::new(|a, b, c| {
                 cs_total_eq_assert(a, b, c)
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs
index cfd36f030a1..4401cf8a9c5 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs
@@ -15,7 +15,6 @@ pub fn expand_deriving_ord(
     push: &mut dyn FnMut(Annotatable),
     is_const: bool,
 ) {
-    let attrs = thin_vec![cx.attr_word(sym::inline, span)];
     let trait_def = TraitDef {
         span,
         path: path_std!(cmp::Ord),
@@ -29,7 +28,7 @@ pub fn expand_deriving_ord(
             explicit_self: true,
             nonself_args: vec![(self_ref(), sym::other)],
             ret_ty: Path(path_std!(cmp::Ordering)),
-            attributes: attrs,
+            attributes: thin_vec![cx.attr_word(sym::inline, span)],
             fieldless_variants_strategy: FieldlessVariantsStrategy::Unify,
             combine_substructure: combine_substructure(Box::new(|a, b, c| cs_cmp(a, b, c))),
         }],
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
index bad47db0de1..a71ecc5db7d 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
@@ -82,14 +82,13 @@ pub fn expand_deriving_partial_eq(
 
     // No need to generate `ne`, the default suffices, and not generating it is
     // faster.
-    let attrs = thin_vec![cx.attr_word(sym::inline, span)];
     let methods = vec![MethodDef {
         name: sym::eq,
         generics: Bounds::empty(),
         explicit_self: true,
         nonself_args: vec![(self_ref(), sym::other)],
         ret_ty: Path(path_local!(bool)),
-        attributes: attrs,
+        attributes: thin_vec![cx.attr_word(sym::inline, span)],
         fieldless_variants_strategy: FieldlessVariantsStrategy::Unify,
         combine_substructure: combine_substructure(Box::new(|a, b, c| cs_eq(a, b, c))),
     }];
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
index 9f46247908d..54b6cb7d713 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
@@ -19,8 +19,6 @@ pub fn expand_deriving_partial_ord(
     let ret_ty =
         Path(Path::new_(pathvec_std!(option::Option), vec![Box::new(ordering_ty)], PathKind::Std));
 
-    let attrs = thin_vec![cx.attr_word(sym::inline, span)];
-
     // Order in which to perform matching
     let tag_then_data = if let Annotatable::Item(item) = item
         && let ItemKind::Enum(def, _) = &item.kind {
@@ -48,7 +46,7 @@ pub fn expand_deriving_partial_ord(
         explicit_self: true,
         nonself_args: vec![(self_ref(), sym::other)],
         ret_ty,
-        attributes: attrs,
+        attributes: thin_vec![cx.attr_word(sym::inline, span)],
         fieldless_variants_strategy: FieldlessVariantsStrategy::Unify,
         combine_substructure: combine_substructure(Box::new(|cx, span, substr| {
             cs_partial_cmp(cx, span, substr, tag_then_data)
diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs
index 33fe98b40e1..07b172bc757 100644
--- a/compiler/rustc_builtin_macros/src/deriving/default.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/default.rs
@@ -20,7 +20,6 @@ pub fn expand_deriving_default(
 ) {
     item.visit_with(&mut DetectNonVariantDefaultAttr { cx });
 
-    let attrs = thin_vec![cx.attr_word(sym::inline, span)];
     let trait_def = TraitDef {
         span,
         path: Path::new(vec![kw::Default, sym::Default]),
@@ -34,7 +33,7 @@ pub fn expand_deriving_default(
             explicit_self: false,
             nonself_args: Vec::new(),
             ret_ty: Self_,
-            attributes: attrs,
+            attributes: thin_vec![cx.attr_word(sym::inline, span)],
             fieldless_variants_strategy: FieldlessVariantsStrategy::Default,
             combine_substructure: combine_substructure(Box::new(|cx, trait_span, substr| {
                 match substr.fields {
diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs
index 4eee573db42..101401f9c85 100644
--- a/compiler/rustc_builtin_macros/src/deriving/hash.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs
@@ -1,7 +1,7 @@
 use crate::deriving::generic::ty::*;
 use crate::deriving::generic::*;
 use crate::deriving::{path_std, pathvec_std};
-use rustc_ast::{AttrVec, MetaItem, Mutability};
+use rustc_ast::{MetaItem, Mutability};
 use rustc_expand::base::{Annotatable, ExtCtxt};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
@@ -33,7 +33,7 @@ pub fn expand_deriving_hash(
             explicit_self: true,
             nonself_args: vec![(Ref(Box::new(Path(arg)), Mutability::Mut), sym::state)],
             ret_ty: Unit,
-            attributes: AttrVec::new(),
+            attributes: thin_vec![cx.attr_word(sym::inline, span)],
             fieldless_variants_strategy: FieldlessVariantsStrategy::Unify,
             combine_substructure: combine_substructure(Box::new(|a, b, c| {
                 hash_substructure(a, b, c)
diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs
index d0d78646009..f1ab279daba 100644
--- a/compiler/rustc_builtin_macros/src/errors.rs
+++ b/compiler/rustc_builtin_macros/src/errors.rs
@@ -377,7 +377,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for EnvNotDefined {
                 rustc::untranslatable_diagnostic,
                 reason = "cannot translate user-provided messages"
             )]
-            handler.struct_diagnostic(msg.as_str())
+            handler.struct_diagnostic(msg.to_string())
         } else {
             handler.struct_diagnostic(crate::fluent_generated::builtin_macros_env_not_defined)
         };
diff --git a/compiler/rustc_codegen_cranelift/Readme.md b/compiler/rustc_codegen_cranelift/Readme.md
index c5222982aa7..26dccf309e1 100644
--- a/compiler/rustc_codegen_cranelift/Readme.md
+++ b/compiler/rustc_codegen_cranelift/Readme.md
@@ -42,6 +42,32 @@ This will build your project with rustc_codegen_cranelift instead of the usual L
 
 For additional ways to use rustc_codegen_cranelift like the JIT mode see [usage.md](docs/usage.md).
 
+## Building and testing with changes in rustc code
+
+This is useful when changing code in `rustc_codegen_cranelift` as part of changing [main Rust repository](https://github.com/rust-lang/rust/).
+This can happen, for example, when you are implementing a new compiler intrinsic.
+
+Instruction below uses `$RustCheckoutDir` as substitute for any folder where you cloned Rust repository.
+
+You need to do this steps to successfully compile and use the cranelift backend with your changes in rustc code:
+
+1. `cd $RustCheckoutDir`
+2. Run `python x.py setup` and choose option for compiler (`b`).
+3. Build compiler and necessary tools: `python x.py build --stage=2 compiler library/std src/tools/rustdoc src/tools/rustfmt`
+   * (Optional) You can also build cargo by adding `src/tools/cargo` to previous command.
+4. Copy exectutable files from `./build/host/stage2-tools/<your hostname triple>/release`
+to `./build/host/stage2/bin/`. Note that you would need to do this every time you rebuilt `rust` repository.
+5. Copy cargo from another toolchain: `cp $(rustup which cargo) .build/<your hostname triple>/stage2/bin/cargo`
+   * Another option is to build it at step 3 and copy with other executables at step 4.
+6. Link your new `rustc` to toolchain: `rustup toolchain link stage2 ./build/host/stage2/`.
+7. (Windows only) compile y.rs: `rustc +stage2 -O y.rs`.
+8. You need to prefix every `./y.rs` (or `y` if you built `y.rs`) command by `rustup run stage2` to make cg_clif use your local changes in rustc.
+
+  * `rustup run stage2 ./y.rs prepare`
+  * `rustup run stage2 ./y.rs build`
+  * (Optional) run tests: `rustup run stage2 ./y.rs test`
+9. Now you can use your cg_clif build to compile other Rust programs, e.g. you can open any Rust crate and run commands like `$RustCheckoutDir/compiler/rustc_codegen_cranelift/dist/cargo-clif build --release`.
+
 ## Configuration
 
 See the documentation on the `BackendConfig` struct in [config.rs](src/config.rs) for all
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 9c6a0fae327..fcfa0b862d4 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -473,7 +473,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
             | TerminatorKind::GeneratorDrop => {
                 bug!("shouldn't exist at codegen {:?}", bb_data.terminator());
             }
-            TerminatorKind::Drop { place, target, unwind: _ } => {
+            TerminatorKind::Drop { place, target, unwind: _, replace: _ } => {
                 let drop_place = codegen_place(fx, *place);
                 crate::abi::codegen_drop(fx, source_info, drop_place);
 
diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs
index 5eaa988dd09..67fd6d793e0 100644
--- a/compiler/rustc_codegen_cranelift/src/common.rs
+++ b/compiler/rustc_codegen_cranelift/src/common.rs
@@ -361,7 +361,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
         self.instance.subst_mir_and_normalize_erasing_regions(
             self.tcx,
             ty::ParamEnv::reveal_all(),
-            ty::EarlyBinder(value),
+            ty::EarlyBinder::bind(value),
         )
     }
 
diff --git a/compiler/rustc_codegen_gcc/messages.ftl b/compiler/rustc_codegen_gcc/messages.ftl
index 0a94a08f8dc..97bc8ef9d1b 100644
--- a/compiler/rustc_codegen_gcc/messages.ftl
+++ b/compiler/rustc_codegen_gcc/messages.ftl
@@ -1,68 +1,68 @@
-codegen_gcc_unwinding_inline_asm =
-    GCC backend does not support unwinding from inline asm
-
-codegen_gcc_lto_not_supported =
-    LTO is not supported. You may get a linker error.
+codegen_gcc_invalid_minimum_alignment =
+    invalid minimum global alignment: {$err}
 
 codegen_gcc_invalid_monomorphization_basic_integer =
     invalid monomorphization of `{$name}` intrinsic: expected basic integer type, found `{$ty}`
 
-codegen_gcc_invalid_monomorphization_invalid_float_vector =
-    invalid monomorphization of `{$name}` intrinsic: unsupported element type `{$elem_ty}` of floating-point vector `{$vec_ty}`
-
-codegen_gcc_invalid_monomorphization_not_float =
-    invalid monomorphization of `{$name}` intrinsic: `{$ty}` is not a floating-point type
-
-codegen_gcc_invalid_monomorphization_unrecognized =
-    invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}`
-
 codegen_gcc_invalid_monomorphization_expected_signed_unsigned =
     invalid monomorphization of `{$name}` intrinsic: expected element type `{$elem_ty}` of vector type `{$vec_ty}` to be a signed or unsigned integer type
 
-codegen_gcc_invalid_monomorphization_unsupported_element =
-    invalid monomorphization of `{$name}` intrinsic: unsupported {$name} from `{$in_ty}` with element `{$elem_ty}` to `{$ret_ty}`
+codegen_gcc_invalid_monomorphization_expected_simd =
+    invalid monomorphization of `{$name}` intrinsic: expected SIMD {$expected_ty} type, found non-SIMD `{$found_ty}`
+
+codegen_gcc_invalid_monomorphization_inserted_type =
+    invalid monomorphization of `{$name}` intrinsic: expected inserted type `{$in_elem}` (element of input `{$in_ty}`), found `{$out_ty}`
 
 codegen_gcc_invalid_monomorphization_invalid_bitmask =
     invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{$ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
 
-codegen_gcc_invalid_monomorphization_simd_shuffle =
-    invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be an array of `u32`, got `{$ty}`
-
-codegen_gcc_invalid_monomorphization_expected_simd =
-    invalid monomorphization of `{$name}` intrinsic: expected SIMD {$expected_ty} type, found non-SIMD `{$found_ty}`
+codegen_gcc_invalid_monomorphization_invalid_float_vector =
+    invalid monomorphization of `{$name}` intrinsic: unsupported element type `{$elem_ty}` of floating-point vector `{$vec_ty}`
 
 codegen_gcc_invalid_monomorphization_mask_type =
     invalid monomorphization of `{$name}` intrinsic: mask element type is `{$ty}`, expected `i_`
 
+codegen_gcc_invalid_monomorphization_mismatched_lengths =
+    invalid monomorphization of `{$name}` intrinsic: mismatched lengths: mask length `{$m_len}` != other vector length `{$v_len}`
+
+codegen_gcc_invalid_monomorphization_not_float =
+    invalid monomorphization of `{$name}` intrinsic: `{$ty}` is not a floating-point type
+
+codegen_gcc_invalid_monomorphization_return_element =
+    invalid monomorphization of `{$name}` intrinsic: expected return element type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` with element type `{$out_ty}`
+
+codegen_gcc_invalid_monomorphization_return_integer_type =
+    invalid monomorphization of `{$name}` intrinsic: expected return type with integer elements, found `{$ret_ty}` with non-integer `{$out_ty}`
+
 codegen_gcc_invalid_monomorphization_return_length =
     invalid monomorphization of `{$name}` intrinsic: expected return type of length {$in_len}, found `{$ret_ty}` with length {$out_len}
 
 codegen_gcc_invalid_monomorphization_return_length_input_type =
     invalid monomorphization of `{$name}` intrinsic: expected return type with length {$in_len} (same as input type `{$in_ty}`), found `{$ret_ty}` with length {$out_len}
 
-codegen_gcc_invalid_monomorphization_return_element =
-    invalid monomorphization of `{$name}` intrinsic: expected return element type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` with element type `{$out_ty}`
-
 codegen_gcc_invalid_monomorphization_return_type =
     invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}`
 
-codegen_gcc_invalid_monomorphization_inserted_type =
-    invalid monomorphization of `{$name}` intrinsic: expected inserted type `{$in_elem}` (element of input `{$in_ty}`), found `{$out_ty}`
-
-codegen_gcc_invalid_monomorphization_return_integer_type =
-    invalid monomorphization of `{$name}` intrinsic: expected return type with integer elements, found `{$ret_ty}` with non-integer `{$out_ty}`
+codegen_gcc_invalid_monomorphization_simd_shuffle =
+    invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be an array of `u32`, got `{$ty}`
 
-codegen_gcc_invalid_monomorphization_mismatched_lengths =
-    invalid monomorphization of `{$name}` intrinsic: mismatched lengths: mask length `{$m_len}` != other vector length `{$v_len}`
+codegen_gcc_invalid_monomorphization_unrecognized =
+    invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}`
 
 codegen_gcc_invalid_monomorphization_unsupported_cast =
     invalid monomorphization of `{$name}` intrinsic: unsupported cast from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}` with element `{$out_elem}`
 
+codegen_gcc_invalid_monomorphization_unsupported_element =
+    invalid monomorphization of `{$name}` intrinsic: unsupported {$name} from `{$in_ty}` with element `{$elem_ty}` to `{$ret_ty}`
+
 codegen_gcc_invalid_monomorphization_unsupported_operation =
     invalid monomorphization of `{$name}` intrinsic: unsupported operation on `{$in_ty}` with element `{$in_elem}`
 
-codegen_gcc_invalid_minimum_alignment =
-    invalid minimum global alignment: {$err}
+codegen_gcc_lto_not_supported =
+    LTO is not supported. You may get a linker error.
 
 codegen_gcc_tied_target_features = the target features {$features} must all be either enabled or disabled together
     .help = add the missing features in a `target_feature` attribute
+
+codegen_gcc_unwinding_inline_asm =
+    GCC backend does not support unwinding from inline asm
diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs
index ac04b61a306..bad87db4732 100644
--- a/compiler/rustc_codegen_gcc/src/common.rs
+++ b/compiler/rustc_codegen_gcc/src/common.rs
@@ -1,17 +1,15 @@
 use gccjit::LValue;
 use gccjit::{RValue, Type, ToRValue};
-use rustc_codegen_ssa::mir::place::PlaceRef;
 use rustc_codegen_ssa::traits::{
     BaseTypeMethods,
     ConstMethods,
-    DerivedTypeMethods,
     MiscMethods,
     StaticMethods,
 };
 use rustc_middle::mir::Mutability;
-use rustc_middle::ty::layout::{TyAndLayout, LayoutOf};
+use rustc_middle::ty::layout::{LayoutOf};
 use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar};
-use rustc_target::abi::{self, HasDataLayout, Pointer, Size};
+use rustc_target::abi::{self, HasDataLayout, Pointer};
 
 use crate::consts::const_alloc_to_gcc;
 use crate::context::CodegenCx;
@@ -240,28 +238,26 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
         const_alloc_to_gcc(self, alloc)
     }
 
-    fn from_const_alloc(&self, layout: TyAndLayout<'tcx>, alloc: ConstAllocation<'tcx>, offset: Size) -> PlaceRef<'tcx, RValue<'gcc>> {
-        assert_eq!(alloc.inner().align, layout.align.abi);
-        let ty = self.type_ptr_to(layout.gcc_type(self));
-        let value =
-            if layout.size == Size::ZERO {
-                let value = self.const_usize(alloc.inner().align.bytes());
-                self.const_bitcast(value, ty)
-            }
-            else {
-                let init = const_alloc_to_gcc(self, alloc);
-                let base_addr = self.static_addr_of(init, alloc.inner().align, None);
-
-                let array = self.const_bitcast(base_addr, self.type_i8p());
-                let value = self.context.new_array_access(None, array, self.const_usize(offset.bytes())).get_address(None);
-                self.const_bitcast(value, ty)
-            };
-        PlaceRef::new_sized(value, layout)
-    }
-
     fn const_ptrcast(&self, val: RValue<'gcc>, ty: Type<'gcc>) -> RValue<'gcc> {
         self.context.new_cast(None, val, ty)
     }
+
+    fn const_bitcast(&self, value: RValue<'gcc>, typ: Type<'gcc>) -> RValue<'gcc> {
+        if value.get_type() == self.bool_type.make_pointer() {
+            if let Some(pointee) = typ.get_pointee() {
+                if pointee.dyncast_vector().is_some() {
+                    panic!()
+                }
+            }
+        }
+        // NOTE: since bitcast makes a value non-constant, don't bitcast if not necessary as some
+        // SIMD builtins require a constant value.
+        self.bitcast_if_needed(value, typ)
+    }
+    
+    fn const_ptr_byte_offset(&self, base_addr: Self::Value, offset: abi::Size) -> Self::Value {
+        self.context.new_array_access(None, base_addr, self.const_usize(offset.bytes())).get_address(None)
+    }
 }
 
 pub trait SignType<'gcc, 'tcx> {
diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs
index 792ab8f890d..873f652e6f1 100644
--- a/compiler/rustc_codegen_gcc/src/consts.rs
+++ b/compiler/rustc_codegen_gcc/src/consts.rs
@@ -1,6 +1,6 @@
 #[cfg(feature = "master")]
 use gccjit::FnAttribute;
-use gccjit::{Function, GlobalKind, LValue, RValue, ToRValue, Type};
+use gccjit::{Function, GlobalKind, LValue, RValue, ToRValue};
 use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods, DerivedTypeMethods, StaticMethods};
 use rustc_middle::span_bug;
 use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
@@ -16,21 +16,6 @@ use crate::context::CodegenCx;
 use crate::errors::InvalidMinimumAlignment;
 use crate::type_of::LayoutGccExt;
 
-impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
-    pub fn const_bitcast(&self, value: RValue<'gcc>, typ: Type<'gcc>) -> RValue<'gcc> {
-        if value.get_type() == self.bool_type.make_pointer() {
-            if let Some(pointee) = typ.get_pointee() {
-                if pointee.dyncast_vector().is_some() {
-                    panic!()
-                }
-            }
-        }
-        // NOTE: since bitcast makes a value non-constant, don't bitcast if not necessary as some
-        // SIMD builtins require a constant value.
-        self.bitcast_if_needed(value, typ)
-    }
-}
-
 fn set_global_alignment<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, gv: LValue<'gcc>, mut align: Align) {
     // The target may require greater alignment for globals than the type does.
     // Note: GCC and Clang also allow `__attribute__((aligned))` on variables,
diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl
index d77634741fb..55622fdb20a 100644
--- a/compiler/rustc_codegen_llvm/messages.ftl
+++ b/compiler/rustc_codegen_llvm/messages.ftl
@@ -1,90 +1,90 @@
-codegen_llvm_unknown_ctarget_feature =
-    unknown feature specified for `-Ctarget-feature`: `{$feature}`
-    .note = it is still passed through to the codegen backend
-    .possible_feature = you might have meant: `{$rust_feature}`
-    .consider_filing_feature_request = consider filing a feature request
+codegen_llvm_copy_bitcode = failed to copy bitcode to object file: {$err}
 
-codegen_llvm_unknown_ctarget_feature_prefix =
-    unknown feature specified for `-Ctarget-feature`: `{$feature}`
-    .note = features must begin with a `+` to enable or `-` to disable it
+codegen_llvm_dlltool_fail_import_library =
+    Dlltool could not create import library: {$stdout}
+    {$stderr}
+
+codegen_llvm_dynamic_linking_with_lto =
+    cannot prefer dynamic linking when performing LTO
+    .note = only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO
+
+codegen_llvm_error_calling_dlltool =
+    Error calling dlltool '{$dlltool_path}': {$error}
 
 codegen_llvm_error_creating_import_library =
     Error creating import library for {$lib_name}: {$error}
 
-codegen_llvm_symbol_already_defined =
-    symbol `{$symbol_name}` is already defined
+codegen_llvm_error_writing_def_file =
+    Error writing .DEF file: {$error}
+
+codegen_llvm_from_llvm_diag = {$message}
 
+codegen_llvm_from_llvm_optimization_diag = {$filename}:{$line}:{$column} {$pass_name} ({$kind}): {$message}
 codegen_llvm_invalid_minimum_alignment =
     invalid minimum global alignment: {$err}
 
-codegen_llvm_sanitizer_memtag_requires_mte =
-    `-Zsanitizer=memtag` requires `-Ctarget-feature=+mte`
-
-codegen_llvm_error_writing_def_file =
-    Error writing .DEF file: {$error}
+codegen_llvm_load_bitcode = failed to load bitcode of module "{$name}"
+codegen_llvm_load_bitcode_with_llvm_err = failed to load bitcode of module "{$name}": {$llvm_err}
 
-codegen_llvm_error_calling_dlltool =
-    Error calling dlltool '{$dlltool_path}': {$error}
+codegen_llvm_lto_bitcode_from_rlib = failed to get bitcode from object file for LTO ({$llvm_err})
 
-codegen_llvm_dlltool_fail_import_library =
-    Dlltool could not create import library: {$stdout}
-    {$stderr}
+codegen_llvm_lto_disallowed = lto can only be run for executables, cdylibs and static library outputs
 
-codegen_llvm_target_feature_disable_or_enable =
-    the target features {$features} must all be either enabled or disabled together
+codegen_llvm_lto_dylib = lto cannot be used for `dylib` crate type without `-Zdylib-lto`
 
 codegen_llvm_missing_features =
     add the missing features in a `target_feature` attribute
 
-codegen_llvm_dynamic_linking_with_lto =
-    cannot prefer dynamic linking when performing LTO
-    .note = only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO
+codegen_llvm_multiple_source_dicompileunit = multiple source DICompileUnits found
+codegen_llvm_multiple_source_dicompileunit_with_llvm_err = multiple source DICompileUnits found: {$llvm_err}
+
+codegen_llvm_parse_bitcode = failed to parse bitcode for LTO module
+codegen_llvm_parse_bitcode_with_llvm_err = failed to parse bitcode for LTO module: {$llvm_err}
 
 codegen_llvm_parse_target_machine_config =
     failed to parse target machine config to target machine: {$error}
 
-codegen_llvm_lto_disallowed = lto can only be run for executables, cdylibs and static library outputs
-
-codegen_llvm_lto_dylib = lto cannot be used for `dylib` crate type without `-Zdylib-lto`
-
-codegen_llvm_lto_bitcode_from_rlib = failed to get bitcode from object file for LTO ({$llvm_err})
-
-codegen_llvm_write_output = could not write output to {$path}
-codegen_llvm_write_output_with_llvm_err = could not write output to {$path}: {$llvm_err}
+codegen_llvm_prepare_thin_lto_context = failed to prepare thin LTO context
+codegen_llvm_prepare_thin_lto_context_with_llvm_err = failed to prepare thin LTO context: {$llvm_err}
 
-codegen_llvm_target_machine = could not create LLVM TargetMachine for triple: {$triple}
-codegen_llvm_target_machine_with_llvm_err = could not create LLVM TargetMachine for triple: {$triple}: {$llvm_err}
+codegen_llvm_prepare_thin_lto_module = failed to prepare thin LTO module
+codegen_llvm_prepare_thin_lto_module_with_llvm_err = failed to prepare thin LTO module: {$llvm_err}
 
 codegen_llvm_run_passes = failed to run LLVM passes
 codegen_llvm_run_passes_with_llvm_err = failed to run LLVM passes: {$llvm_err}
 
+codegen_llvm_sanitizer_memtag_requires_mte =
+    `-Zsanitizer=memtag` requires `-Ctarget-feature=+mte`
+
 codegen_llvm_serialize_module = failed to serialize module {$name}
 codegen_llvm_serialize_module_with_llvm_err = failed to serialize module {$name}: {$llvm_err}
 
-codegen_llvm_write_ir = failed to write LLVM IR to {$path}
-codegen_llvm_write_ir_with_llvm_err = failed to write LLVM IR to {$path}: {$llvm_err}
-
-codegen_llvm_prepare_thin_lto_context = failed to prepare thin LTO context
-codegen_llvm_prepare_thin_lto_context_with_llvm_err = failed to prepare thin LTO context: {$llvm_err}
+codegen_llvm_symbol_already_defined =
+    symbol `{$symbol_name}` is already defined
 
-codegen_llvm_load_bitcode = failed to load bitcode of module "{$name}"
-codegen_llvm_load_bitcode_with_llvm_err = failed to load bitcode of module "{$name}": {$llvm_err}
+codegen_llvm_target_feature_disable_or_enable =
+    the target features {$features} must all be either enabled or disabled together
 
-codegen_llvm_write_thinlto_key = error while writing ThinLTO key data: {$err}
-codegen_llvm_write_thinlto_key_with_llvm_err = error while writing ThinLTO key data: {$err}: {$llvm_err}
+codegen_llvm_target_machine = could not create LLVM TargetMachine for triple: {$triple}
+codegen_llvm_target_machine_with_llvm_err = could not create LLVM TargetMachine for triple: {$triple}: {$llvm_err}
 
-codegen_llvm_multiple_source_dicompileunit = multiple source DICompileUnits found
-codegen_llvm_multiple_source_dicompileunit_with_llvm_err = multiple source DICompileUnits found: {$llvm_err}
+codegen_llvm_unknown_ctarget_feature =
+    unknown feature specified for `-Ctarget-feature`: `{$feature}`
+    .note = it is still passed through to the codegen backend
+    .possible_feature = you might have meant: `{$rust_feature}`
+    .consider_filing_feature_request = consider filing a feature request
 
-codegen_llvm_prepare_thin_lto_module = failed to prepare thin LTO module
-codegen_llvm_prepare_thin_lto_module_with_llvm_err = failed to prepare thin LTO module: {$llvm_err}
+codegen_llvm_unknown_ctarget_feature_prefix =
+    unknown feature specified for `-Ctarget-feature`: `{$feature}`
+    .note = features must begin with a `+` to enable or `-` to disable it
 
-codegen_llvm_parse_bitcode = failed to parse bitcode for LTO module
-codegen_llvm_parse_bitcode_with_llvm_err = failed to parse bitcode for LTO module: {$llvm_err}
+codegen_llvm_write_bytecode = failed to write bytecode to {$path}: {$err}
 
-codegen_llvm_from_llvm_optimization_diag = {$filename}:{$line}:{$column} {$pass_name} ({$kind}): {$message}
-codegen_llvm_from_llvm_diag = {$message}
+codegen_llvm_write_ir = failed to write LLVM IR to {$path}
+codegen_llvm_write_ir_with_llvm_err = failed to write LLVM IR to {$path}: {$llvm_err}
 
-codegen_llvm_write_bytecode = failed to write bytecode to {$path}: {$err}
+codegen_llvm_write_output = could not write output to {$path}
+codegen_llvm_write_output_with_llvm_err = could not write output to {$path}: {$llvm_err}
 
-codegen_llvm_copy_bitcode = failed to copy bitcode to object file: {$err}
+codegen_llvm_write_thinlto_key = error while writing ThinLTO key data: {$err}
+codegen_llvm_write_thinlto_key_with_llvm_err = error while writing ThinLTO key data: {$err}: {$llvm_err}
diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs
index 651d644ebb6..6d00464e0a0 100644
--- a/compiler/rustc_codegen_llvm/src/attributes.rs
+++ b/compiler/rustc_codegen_llvm/src/attributes.rs
@@ -88,6 +88,9 @@ pub fn sanitize_attrs<'ll>(
 
         attrs.push(llvm::AttributeKind::SanitizeMemTag.create_attr(cx.llcx));
     }
+    if enabled.contains(SanitizerSet::SAFESTACK) {
+        attrs.push(llvm::AttributeKind::SanitizeSafeStack.create_attr(cx.llcx));
+    }
     attrs
 }
 
diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs
index 9127fba388b..a3910fef954 100644
--- a/compiler/rustc_codegen_llvm/src/common.rs
+++ b/compiler/rustc_codegen_llvm/src/common.rs
@@ -8,16 +8,15 @@ use crate::type_of::LayoutLlvmExt;
 use crate::value::Value;
 
 use rustc_ast::Mutability;
-use rustc_codegen_ssa::mir::place::PlaceRef;
 use rustc_codegen_ssa::traits::*;
 use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher};
 use rustc_hir::def_id::DefId;
 use rustc_middle::bug;
 use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar};
-use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::cstore::{DllCallingConvention, DllImport, PeImportNameType};
-use rustc_target::abi::{self, AddressSpace, HasDataLayout, Pointer, Size};
+use rustc_target::abi::{self, AddressSpace, HasDataLayout, Pointer};
 use rustc_target::spec::Target;
 
 use libc::{c_char, c_uint};
@@ -307,38 +306,24 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         const_alloc_to_llvm(self, alloc)
     }
 
-    fn from_const_alloc(
-        &self,
-        layout: TyAndLayout<'tcx>,
-        alloc: ConstAllocation<'tcx>,
-        offset: Size,
-    ) -> PlaceRef<'tcx, &'ll Value> {
-        let alloc_align = alloc.inner().align;
-        assert_eq!(alloc_align, layout.align.abi);
-        let llty = self.type_ptr_to(layout.llvm_type(self));
-        let llval = if layout.size == Size::ZERO {
-            let llval = self.const_usize(alloc_align.bytes());
-            unsafe { llvm::LLVMConstIntToPtr(llval, llty) }
-        } else {
-            let init = const_alloc_to_llvm(self, alloc);
-            let base_addr = self.static_addr_of(init, alloc_align, None);
-
-            let llval = unsafe {
-                llvm::LLVMRustConstInBoundsGEP2(
-                    self.type_i8(),
-                    self.const_bitcast(base_addr, self.type_i8p()),
-                    &self.const_usize(offset.bytes()),
-                    1,
-                )
-            };
-            self.const_bitcast(llval, llty)
-        };
-        PlaceRef::new_sized(llval, layout)
-    }
-
     fn const_ptrcast(&self, val: &'ll Value, ty: &'ll Type) -> &'ll Value {
         consts::ptrcast(val, ty)
     }
+
+    fn const_bitcast(&self, val: &'ll Value, ty: &'ll Type) -> &'ll Value {
+        self.const_bitcast(val, ty)
+    }
+
+    fn const_ptr_byte_offset(&self, base_addr: Self::Value, offset: abi::Size) -> Self::Value {
+        unsafe {
+            llvm::LLVMRustConstInBoundsGEP2(
+                self.type_i8(),
+                self.const_bitcast(base_addr, self.type_i8p()),
+                &self.const_usize(offset.bytes()),
+                1,
+            )
+        }
+    }
 }
 
 /// Get the [LLVM type][Type] of a [`Value`].
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs
index 3fff112a020..64961baf272 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs
@@ -93,7 +93,7 @@ fn make_mir_scope<'ll, 'tcx>(
             let callee = cx.tcx.subst_and_normalize_erasing_regions(
                 instance.substs,
                 ty::ParamEnv::reveal_all(),
-                ty::EarlyBinder(callee),
+                ty::EarlyBinder::bind(callee),
             );
             let callee_fn_abi = cx.fn_abi_of_instance(callee, ty::List::empty());
             cx.dbg_scope_fn(callee, callee_fn_abi, None)
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index de93a64c0d6..6ef3418cc5f 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -196,6 +196,7 @@ pub enum AttributeKind {
     AllocSize = 37,
     AllocatedPointer = 38,
     AllocAlign = 39,
+    SanitizeSafeStack = 40,
 }
 
 /// LLVMIntPredicate
diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl
index 375fdec1007..9aa2b2e2b2e 100644
--- a/compiler/rustc_codegen_ssa/messages.ftl
+++ b/compiler/rustc_codegen_ssa/messages.ftl
@@ -1,306 +1,306 @@
-codegen_ssa_lib_def_write_failure = failed to write lib.def file: {$error}
-
-codegen_ssa_version_script_write_failure = failed to write version script: {$error}
+codegen_ssa_L4Bender_exporting_symbols_unimplemented = exporting symbols not implemented yet for L4Bender
 
-codegen_ssa_symbol_file_write_failure = failed to write symbols file: {$error}
+codegen_ssa_add_native_library = failed to add native library {$library_path}: {$error}
 
-codegen_ssa_ld64_unimplemented_modifier = `as-needed` modifier not implemented yet for ld64
+codegen_ssa_apple_sdk_error_sdk_path = failed to get {$sdk_name} SDK path: {$error}
 
-codegen_ssa_linker_unsupported_modifier = `as-needed` modifier not supported for current linker
+codegen_ssa_archive_build_failure =
+    failed to build archive: {$error}
 
-codegen_ssa_L4Bender_exporting_symbols_unimplemented = exporting symbols not implemented yet for L4Bender
+codegen_ssa_atomic_compare_exchange = Atomic compare-exchange intrinsic missing failure memory ordering
 
-codegen_ssa_no_natvis_directory = error enumerating natvis directory: {$error}
+codegen_ssa_check_installed_visual_studio = please ensure that Visual Studio 2017 or later, or Build Tools for Visual Studio were installed with the Visual C++ option.
 
 codegen_ssa_copy_path = could not copy {$from} to {$to}: {$error}
 
 codegen_ssa_copy_path_buf = unable to copy {$source_file} to {$output_path}: {$error}
 
+codegen_ssa_create_temp_dir = couldn't create a temp dir: {$error}
+
+codegen_ssa_erroneous_constant = erroneous constant encountered
+
+codegen_ssa_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
+
+codegen_ssa_extern_funcs_not_found = some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
+
+codegen_ssa_extract_bundled_libs_archive_member = failed to get data from archive member '{$rlib}': {$error}
+codegen_ssa_extract_bundled_libs_convert_name = failed to convert name '{$rlib}': {$error}
+codegen_ssa_extract_bundled_libs_mmap_file = failed to mmap file '{$rlib}': {$error}
+codegen_ssa_extract_bundled_libs_open_file = failed to open file '{$rlib}': {$error}
+codegen_ssa_extract_bundled_libs_parse_archive = failed to parse archive '{$rlib}': {$error}
+codegen_ssa_extract_bundled_libs_read_entry = failed to read entry '{$rlib}': {$error}
+codegen_ssa_extract_bundled_libs_write_file = failed to write file '{$rlib}': {$error}
+
+codegen_ssa_failed_to_write = failed to write {$path}: {$error}
+
 codegen_ssa_ignoring_emit_path = ignoring emit path because multiple .{$extension} files were produced
 
 codegen_ssa_ignoring_output = ignoring -o because multiple .{$extension} files were produced
 
-codegen_ssa_create_temp_dir = couldn't create a temp dir: {$error}
+codegen_ssa_illegal_link_ordinal_format = illegal ordinal format in `link_ordinal`
+    .note = an unsuffixed integer value, e.g., `1`, is expected
 
 codegen_ssa_incompatible_linking_modifiers = link modifiers combination `+bundle,+whole-archive` is unstable when generating rlibs
 
-codegen_ssa_add_native_library = failed to add native library {$library_path}: {$error}
-
-codegen_ssa_multiple_external_func_decl = multiple declarations of external function `{$function}` from library `{$library_name}` have different calling conventions
+codegen_ssa_insufficient_vs_code_product = VS Code is a different product, and is not sufficient.
 
-codegen_ssa_rlib_missing_format = could not find formats for rlibs
+codegen_ssa_invalid_link_ordinal_nargs = incorrect number of arguments to `#[link_ordinal]`
+    .note = the attribute requires exactly one argument
 
-codegen_ssa_rlib_only_rmeta_found = could not find rlib for: `{$crate_name}`, found rmeta (metadata) file
+codegen_ssa_invalid_monomorphization_basic_float_type = invalid monomorphization of `{$name}` intrinsic: expected basic float type, found `{$ty}`
 
-codegen_ssa_rlib_not_found = could not find rlib for: `{$crate_name}`
+codegen_ssa_invalid_monomorphization_basic_integer_type = invalid monomorphization of `{$name}` intrinsic: expected basic integer type, found `{$ty}`
 
-codegen_ssa_rlib_incompatible_dependency_formats = `{$ty1}` and `{$ty2}` do not have equivalent dependency formats (`{$list1}` vs `{$list2}`)
+codegen_ssa_invalid_monomorphization_cannot_return = invalid monomorphization of `{$name}` intrinsic: cannot return `{$ret_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
 
-codegen_ssa_linking_failed = linking with `{$linker_path}` failed: {$exit_status}
+codegen_ssa_invalid_monomorphization_cast_fat_pointer = invalid monomorphization of `{$name}` intrinsic: cannot cast fat pointer `{$ty}`
 
-codegen_ssa_extern_funcs_not_found = some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
+codegen_ssa_invalid_monomorphization_expected_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of second argument `{$second_arg}` to be a pointer to the element type `{$in_elem}` of the first argument `{$in_ty}`, found `{$expected_element}` != `{$mutability} {$in_elem}`
 
-codegen_ssa_specify_libraries_to_link = use the `-l` flag to specify native libraries to link
+codegen_ssa_invalid_monomorphization_expected_pointer = invalid monomorphization of `{$name}` intrinsic: expected pointer, got `{$ty}`
 
-codegen_ssa_use_cargo_directive = use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#cargorustc-link-libkindname)
+codegen_ssa_invalid_monomorphization_expected_return_type = invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_ty}`, found `{$ret_ty}`
 
-codegen_ssa_thorin_read_input_failure = failed to read input file
+codegen_ssa_invalid_monomorphization_expected_usize = invalid monomorphization of `{$name}` intrinsic: expected `usize`, got `{$ty}`
 
-codegen_ssa_thorin_parse_input_file_kind = failed to parse input file kind
+codegen_ssa_invalid_monomorphization_expected_vector_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of vector type `{$vector_type}` to be a signed or unsigned integer type
 
-codegen_ssa_thorin_parse_input_object_file = failed to parse input object file
+codegen_ssa_invalid_monomorphization_float_to_int_unchecked = invalid monomorphization of `float_to_int_unchecked` intrinsic: expected basic float type, found `{$ty}`
 
-codegen_ssa_thorin_parse_input_archive_file = failed to parse input archive file
+codegen_ssa_invalid_monomorphization_floating_point_type = invalid monomorphization of `{$name}` intrinsic: `{$in_ty}` is not a floating-point type
 
-codegen_ssa_thorin_parse_archive_member = failed to parse archive member
+codegen_ssa_invalid_monomorphization_floating_point_vector = invalid monomorphization of `{$name}` intrinsic: unsupported element type `{$f_ty}` of floating-point vector `{$in_ty}`
 
-codegen_ssa_thorin_invalid_input_kind = input is not an archive or elf object
+codegen_ssa_invalid_monomorphization_inserted_type = invalid monomorphization of `{$name}` intrinsic: expected inserted type `{$in_elem}` (element of input `{$in_ty}`), found `{$out_ty}`
 
-codegen_ssa_thorin_decompress_data = failed to decompress compressed section
+codegen_ssa_invalid_monomorphization_invalid_bitmask = invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{$mask_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
 
-codegen_ssa_thorin_section_without_name = section without name at offset {$offset}
+codegen_ssa_invalid_monomorphization_mask_type = invalid monomorphization of `{$name}` intrinsic: mask element type is `{$ty}`, expected `i_`
 
-codegen_ssa_thorin_relocation_with_invalid_symbol = relocation with invalid symbol for section `{$section}` at offset {$offset}
+codegen_ssa_invalid_monomorphization_mismatched_lengths = invalid monomorphization of `{$name}` intrinsic: mismatched lengths: mask length `{$m_len}` != other vector length `{$v_len}`
 
-codegen_ssa_thorin_multiple_relocations = multiple relocations for section `{$section}` at offset {$offset}
+codegen_ssa_invalid_monomorphization_return_element = invalid monomorphization of `{$name}` intrinsic: expected return element type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` with element type `{$out_ty}`
 
-codegen_ssa_thorin_unsupported_relocation = unsupported relocation for section {$section} at offset {$offset}
+codegen_ssa_invalid_monomorphization_return_integer_type = invalid monomorphization of `{$name}` intrinsic: expected return type with integer elements, found `{$ret_ty}` with non-integer `{$out_ty}`
 
-codegen_ssa_thorin_missing_dwo_name = missing path attribute to DWARF object ({$id})
+codegen_ssa_invalid_monomorphization_return_length = invalid monomorphization of `{$name}` intrinsic: expected return type of length {$in_len}, found `{$ret_ty}` with length {$out_len}
 
-codegen_ssa_thorin_no_compilation_units = input object has no compilation units
+codegen_ssa_invalid_monomorphization_return_length_input_type = invalid monomorphization of `{$name}` intrinsic: expected return type with length {$in_len} (same as input type `{$in_ty}`), found `{$ret_ty}` with length {$out_len}
 
-codegen_ssa_thorin_no_die = no top-level debugging information entry in compilation/type unit
+codegen_ssa_invalid_monomorphization_return_type = invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}`
 
-codegen_ssa_thorin_top_level_die_not_unit = top-level debugging information entry is not a compilation/type unit
+codegen_ssa_invalid_monomorphization_second_argument_length = invalid monomorphization of `{$name}` intrinsic: expected second argument with length {$in_len} (same as input type `{$in_ty}`), found `{$arg_ty}` with length {$out_len}
 
-codegen_ssa_thorin_missing_required_section = input object missing required section `{$section}`
+codegen_ssa_invalid_monomorphization_shuffle_index_not_constant = invalid monomorphization of `{$name}` intrinsic: shuffle index #{$arg_idx} is not a constant
 
-codegen_ssa_thorin_parse_unit_abbreviations = failed to parse unit abbreviations
+codegen_ssa_invalid_monomorphization_shuffle_index_out_of_bounds = invalid monomorphization of `{$name}` intrinsic: shuffle index #{$arg_idx} is out of bounds (limit {$total_len})
 
-codegen_ssa_thorin_parse_unit_attribute = failed to parse unit attribute
+codegen_ssa_invalid_monomorphization_simd_argument = invalid monomorphization of `{$name}` intrinsic: expected SIMD argument type, found non-SIMD `{$ty}`
 
-codegen_ssa_thorin_parse_unit_header = failed to parse unit header
+codegen_ssa_invalid_monomorphization_simd_first = invalid monomorphization of `{$name}` intrinsic: expected SIMD first type, found non-SIMD `{$ty}`
 
-codegen_ssa_thorin_parse_unit = failed to parse unit
+codegen_ssa_invalid_monomorphization_simd_input = invalid monomorphization of `{$name}` intrinsic: expected SIMD input type, found non-SIMD `{$ty}`
 
-codegen_ssa_thorin_incompatible_index_version = incompatible `{$section}` index version: found version {$actual}, expected version {$format}
+codegen_ssa_invalid_monomorphization_simd_return = invalid monomorphization of `{$name}` intrinsic: expected SIMD return type, found non-SIMD `{$ty}`
 
-codegen_ssa_thorin_offset_at_index = read offset at index {$index} of `.debug_str_offsets.dwo` section
+codegen_ssa_invalid_monomorphization_simd_second = invalid monomorphization of `{$name}` intrinsic: expected SIMD second type, found non-SIMD `{$ty}`
 
-codegen_ssa_thorin_str_at_offset = read string at offset {$offset} of `.debug_str.dwo` section
+codegen_ssa_invalid_monomorphization_simd_shuffle = invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be an array of `u32`, got `{$ty}`
 
-codegen_ssa_thorin_parse_index = failed to parse `{$section}` index section
+codegen_ssa_invalid_monomorphization_simd_third = invalid monomorphization of `{$name}` intrinsic: expected SIMD third type, found non-SIMD `{$ty}`
 
-codegen_ssa_thorin_unit_not_in_index = unit {$unit} from input package is not in its index
+codegen_ssa_invalid_monomorphization_third_arg_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of third argument `{$third_arg}` to be a signed integer type
 
-codegen_ssa_thorin_row_not_in_index = row {$row} found in index's hash table not present in index
+codegen_ssa_invalid_monomorphization_third_argument_length = invalid monomorphization of `{$name}` intrinsic: expected third argument with length {$in_len} (same as input type `{$in_ty}`), found `{$arg_ty}` with length {$out_len}
 
-codegen_ssa_thorin_section_not_in_row = section not found in unit's row in index
+codegen_ssa_invalid_monomorphization_unrecognized_intrinsic = invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}`
 
-codegen_ssa_thorin_empty_unit = unit {$unit} in input DWARF object with no data
+codegen_ssa_invalid_monomorphization_unsupported_cast = invalid monomorphization of `{$name}` intrinsic: unsupported cast from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}` with element `{$out_elem}`
 
-codegen_ssa_thorin_multiple_debug_info_section = multiple `.debug_info.dwo` sections
+codegen_ssa_invalid_monomorphization_unsupported_operation = invalid monomorphization of `{$name}` intrinsic: unsupported operation on `{$in_ty}` with element `{$in_elem}`
 
-codegen_ssa_thorin_multiple_debug_types_section = multiple `.debug_types.dwo` sections in a package
+codegen_ssa_invalid_monomorphization_unsupported_symbol = invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}`
 
-codegen_ssa_thorin_not_split_unit = regular compilation unit in object (missing dwo identifier)
+codegen_ssa_invalid_monomorphization_unsupported_symbol_of_size = invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` of size `{$size}` to `{$ret_ty}`
 
-codegen_ssa_thorin_duplicate_unit = duplicate split compilation unit ({$unit})
+codegen_ssa_invalid_monomorphization_vector_argument = invalid monomorphization of `{$name}` intrinsic: vector argument `{$in_ty}`'s element type `{$in_elem}`, expected integer element type
 
-codegen_ssa_thorin_missing_referenced_unit = unit {$unit} referenced by executable was not found
+codegen_ssa_invalid_no_sanitize = invalid argument for `no_sanitize`
+    .note = expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread`
 
-codegen_ssa_thorin_not_output_object_created = no output object was created from inputs
+codegen_ssa_invalid_windows_subsystem = invalid windows subsystem `{$subsystem}`, only `windows` and `console` are allowed
 
-codegen_ssa_thorin_mixed_input_encodings = input objects haved mixed encodings
+codegen_ssa_ld64_unimplemented_modifier = `as-needed` modifier not implemented yet for ld64
 
-codegen_ssa_thorin_io = {$error}
-codegen_ssa_thorin_object_read = {$error}
-codegen_ssa_thorin_object_write = {$error}
-codegen_ssa_thorin_gimli_read = {$error}
-codegen_ssa_thorin_gimli_write = {$error}
+codegen_ssa_lib_def_write_failure = failed to write lib.def file: {$error}
 
 codegen_ssa_link_exe_unexpected_error = `link.exe` returned an unexpected error
 
-codegen_ssa_repair_vs_build_tools = the Visual Studio build tools may need to be repaired using the Visual Studio installer
-
-codegen_ssa_missing_cpp_build_tool_component = or a necessary component may be missing from the "C++ build tools" workload
+codegen_ssa_link_script_unavailable = can only use link script when linking with GNU-like linker
 
-codegen_ssa_select_cpp_build_tool_workload = in the Visual Studio installer, ensure the "C++ build tools" workload is selected
+codegen_ssa_link_script_write_failure = failed to write link script to {$path}: {$error}
 
-codegen_ssa_visual_studio_not_installed = you may need to install Visual Studio build tools with the "C++ build tools" workload
+codegen_ssa_linker_file_stem = couldn't extract file stem from specified linker
 
 codegen_ssa_linker_not_found = linker `{$linker_path}` not found
     .note = {$error}
 
-codegen_ssa_unable_to_exe_linker = could not exec the linker `{$linker_path}`
-    .note = {$error}
-    .command_note = {$command_formatted}
+codegen_ssa_linker_unsupported_modifier = `as-needed` modifier not supported for current linker
 
-codegen_ssa_msvc_missing_linker = the msvc targets depend on the msvc linker but `link.exe` was not found
+codegen_ssa_linking_failed = linking with `{$linker_path}` failed: {$exit_status}
 
-codegen_ssa_check_installed_visual_studio = please ensure that Visual Studio 2017 or later, or Build Tools for Visual Studio were installed with the Visual C++ option.
+codegen_ssa_metadata_object_file_write = error writing metadata object file: {$error}
 
-codegen_ssa_insufficient_vs_code_product = VS Code is a different product, and is not sufficient.
+codegen_ssa_missing_cpp_build_tool_component = or a necessary component may be missing from the "C++ build tools" workload
 
-codegen_ssa_processing_dymutil_failed = processing debug info with `dsymutil` failed: {$status}
-    .note = {$output}
+codegen_ssa_missing_memory_ordering = Atomic intrinsic missing memory ordering
 
-codegen_ssa_unable_to_run_dsymutil = unable to run `dsymutil`: {$error}
+codegen_ssa_msvc_missing_linker = the msvc targets depend on the msvc linker but `link.exe` was not found
 
-codegen_ssa_stripping_debug_info_failed = stripping debug info with `{$util}` failed: {$status}
-    .note = {$output}
+codegen_ssa_multiple_external_func_decl = multiple declarations of external function `{$function}` from library `{$library_name}` have different calling conventions
 
-codegen_ssa_unable_to_run = unable to run `{$util}`: {$error}
+codegen_ssa_multiple_main_functions = entry symbol `main` declared multiple times
+    .help = did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead
 
-codegen_ssa_linker_file_stem = couldn't extract file stem from specified linker
+codegen_ssa_no_natvis_directory = error enumerating natvis directory: {$error}
 
-codegen_ssa_static_library_native_artifacts = Link against the following native artifacts when linking against this static library. The order and any duplication can be significant on some platforms.
+codegen_ssa_option_gcc_only = option `-Z gcc-ld` is used even though linker flavor is not gcc
 
-codegen_ssa_link_script_unavailable = can only use link script when linking with GNU-like linker
+codegen_ssa_polymorphic_constant_too_generic = codegen encountered polymorphic constant: TooGeneric
 
-codegen_ssa_link_script_write_failure = failed to write link script to {$path}: {$error}
+codegen_ssa_processing_dymutil_failed = processing debug info with `dsymutil` failed: {$status}
+    .note = {$output}
 
-codegen_ssa_failed_to_write = failed to write {$path}: {$error}
+codegen_ssa_read_file = failed to read file: {$message}
 
-codegen_ssa_unable_to_write_debugger_visualizer = Unable to write debugger visualizer file `{$path}`: {$error}
+codegen_ssa_repair_vs_build_tools = the Visual Studio build tools may need to be repaired using the Visual Studio installer
 
 codegen_ssa_rlib_archive_build_failure = failed to build archive from rlib: {$error}
 
-codegen_ssa_option_gcc_only = option `-Z gcc-ld` is used even though linker flavor is not gcc
-
-codegen_ssa_extract_bundled_libs_open_file = failed to open file '{$rlib}': {$error}
-codegen_ssa_extract_bundled_libs_mmap_file = failed to mmap file '{$rlib}': {$error}
-codegen_ssa_extract_bundled_libs_parse_archive = failed to parse archive '{$rlib}': {$error}
-codegen_ssa_extract_bundled_libs_read_entry = failed to read entry '{$rlib}': {$error}
-codegen_ssa_extract_bundled_libs_archive_member = failed to get data from archive member '{$rlib}': {$error}
-codegen_ssa_extract_bundled_libs_convert_name = failed to convert name '{$rlib}': {$error}
-codegen_ssa_extract_bundled_libs_write_file = failed to write file '{$rlib}': {$error}
-
-codegen_ssa_unsupported_arch = unsupported arch `{$arch}` for os `{$os}`
-
-codegen_ssa_apple_sdk_error_sdk_path = failed to get {$sdk_name} SDK path: {$error}
+codegen_ssa_rlib_incompatible_dependency_formats = `{$ty1}` and `{$ty2}` do not have equivalent dependency formats (`{$list1}` vs `{$list2}`)
 
-codegen_ssa_read_file = failed to read file: {$message}
+codegen_ssa_rlib_missing_format = could not find formats for rlibs
 
-codegen_ssa_unsupported_link_self_contained = option `-C link-self-contained` is not supported on this target
+codegen_ssa_rlib_not_found = could not find rlib for: `{$crate_name}`
 
-codegen_ssa_archive_build_failure =
-    failed to build archive: {$error}
+codegen_ssa_rlib_only_rmeta_found = could not find rlib for: `{$crate_name}`, found rmeta (metadata) file
 
-codegen_ssa_unknown_archive_kind =
-    Don't know how to build archive of type: {$kind}
+codegen_ssa_select_cpp_build_tool_workload = in the Visual Studio installer, ensure the "C++ build tools" workload is selected
 
-codegen_ssa_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
+codegen_ssa_shuffle_indices_evaluation = could not evaluate shuffle_indices at compile time
 
-codegen_ssa_multiple_main_functions = entry symbol `main` declared multiple times
-    .help = did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead
+codegen_ssa_specify_libraries_to_link = use the `-l` flag to specify native libraries to link
 
-codegen_ssa_metadata_object_file_write = error writing metadata object file: {$error}
+codegen_ssa_static_library_native_artifacts = Link against the following native artifacts when linking against this static library. The order and any duplication can be significant on some platforms.
 
-codegen_ssa_invalid_windows_subsystem = invalid windows subsystem `{$subsystem}`, only `windows` and `console` are allowed
+codegen_ssa_stripping_debug_info_failed = stripping debug info with `{$util}` failed: {$status}
+    .note = {$output}
 
-codegen_ssa_erroneous_constant = erroneous constant encountered
+codegen_ssa_symbol_file_write_failure = failed to write symbols file: {$error}
 
-codegen_ssa_shuffle_indices_evaluation = could not evaluate shuffle_indices at compile time
+codegen_ssa_target_feature_safe_trait = `#[target_feature(..)]` cannot be applied to safe trait method
+    .label = cannot be applied to safe trait method
+    .label_def = not an `unsafe` function
 
-codegen_ssa_missing_memory_ordering = Atomic intrinsic missing memory ordering
+codegen_ssa_thorin_decompress_data = failed to decompress compressed section
 
-codegen_ssa_unknown_atomic_ordering = unknown ordering in atomic intrinsic
+codegen_ssa_thorin_duplicate_unit = duplicate split compilation unit ({$unit})
 
-codegen_ssa_atomic_compare_exchange = Atomic compare-exchange intrinsic missing failure memory ordering
+codegen_ssa_thorin_empty_unit = unit {$unit} in input DWARF object with no data
 
-codegen_ssa_unknown_atomic_operation = unknown atomic operation
+codegen_ssa_thorin_gimli_read = {$error}
+codegen_ssa_thorin_gimli_write = {$error}
 
-codegen_ssa_invalid_monomorphization_basic_integer_type = invalid monomorphization of `{$name}` intrinsic: expected basic integer type, found `{$ty}`
+codegen_ssa_thorin_incompatible_index_version = incompatible `{$section}` index version: found version {$actual}, expected version {$format}
 
-codegen_ssa_invalid_monomorphization_basic_float_type = invalid monomorphization of `{$name}` intrinsic: expected basic float type, found `{$ty}`
+codegen_ssa_thorin_invalid_input_kind = input is not an archive or elf object
 
-codegen_ssa_invalid_monomorphization_float_to_int_unchecked = invalid monomorphization of `float_to_int_unchecked` intrinsic: expected basic float type, found `{$ty}`
+codegen_ssa_thorin_io = {$error}
+codegen_ssa_thorin_missing_dwo_name = missing path attribute to DWARF object ({$id})
 
-codegen_ssa_invalid_monomorphization_floating_point_vector = invalid monomorphization of `{$name}` intrinsic: unsupported element type `{$f_ty}` of floating-point vector `{$in_ty}`
+codegen_ssa_thorin_missing_referenced_unit = unit {$unit} referenced by executable was not found
 
-codegen_ssa_invalid_monomorphization_floating_point_type = invalid monomorphization of `{$name}` intrinsic: `{$in_ty}` is not a floating-point type
+codegen_ssa_thorin_missing_required_section = input object missing required section `{$section}`
 
-codegen_ssa_invalid_monomorphization_unrecognized_intrinsic = invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}`
+codegen_ssa_thorin_mixed_input_encodings = input objects haved mixed encodings
 
-codegen_ssa_invalid_monomorphization_simd_argument = invalid monomorphization of `{$name}` intrinsic: expected SIMD argument type, found non-SIMD `{$ty}`
+codegen_ssa_thorin_multiple_debug_info_section = multiple `.debug_info.dwo` sections
 
-codegen_ssa_invalid_monomorphization_simd_input = invalid monomorphization of `{$name}` intrinsic: expected SIMD input type, found non-SIMD `{$ty}`
+codegen_ssa_thorin_multiple_debug_types_section = multiple `.debug_types.dwo` sections in a package
 
-codegen_ssa_invalid_monomorphization_simd_first = invalid monomorphization of `{$name}` intrinsic: expected SIMD first type, found non-SIMD `{$ty}`
+codegen_ssa_thorin_multiple_relocations = multiple relocations for section `{$section}` at offset {$offset}
 
-codegen_ssa_invalid_monomorphization_simd_second = invalid monomorphization of `{$name}` intrinsic: expected SIMD second type, found non-SIMD `{$ty}`
+codegen_ssa_thorin_no_compilation_units = input object has no compilation units
 
-codegen_ssa_invalid_monomorphization_simd_third = invalid monomorphization of `{$name}` intrinsic: expected SIMD third type, found non-SIMD `{$ty}`
+codegen_ssa_thorin_no_die = no top-level debugging information entry in compilation/type unit
 
-codegen_ssa_invalid_monomorphization_simd_return = invalid monomorphization of `{$name}` intrinsic: expected SIMD return type, found non-SIMD `{$ty}`
+codegen_ssa_thorin_not_output_object_created = no output object was created from inputs
 
-codegen_ssa_invalid_monomorphization_invalid_bitmask = invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{$mask_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
+codegen_ssa_thorin_not_split_unit = regular compilation unit in object (missing dwo identifier)
 
-codegen_ssa_polymorphic_constant_too_generic = codegen encountered polymorphic constant: TooGeneric
+codegen_ssa_thorin_object_read = {$error}
+codegen_ssa_thorin_object_write = {$error}
+codegen_ssa_thorin_offset_at_index = read offset at index {$index} of `.debug_str_offsets.dwo` section
 
-codegen_ssa_invalid_monomorphization_return_length_input_type = invalid monomorphization of `{$name}` intrinsic: expected return type with length {$in_len} (same as input type `{$in_ty}`), found `{$ret_ty}` with length {$out_len}
+codegen_ssa_thorin_parse_archive_member = failed to parse archive member
 
-codegen_ssa_invalid_monomorphization_second_argument_length = invalid monomorphization of `{$name}` intrinsic: expected second argument with length {$in_len} (same as input type `{$in_ty}`), found `{$arg_ty}` with length {$out_len}
+codegen_ssa_thorin_parse_index = failed to parse `{$section}` index section
 
-codegen_ssa_invalid_monomorphization_third_argument_length = invalid monomorphization of `{$name}` intrinsic: expected third argument with length {$in_len} (same as input type `{$in_ty}`), found `{$arg_ty}` with length {$out_len}
+codegen_ssa_thorin_parse_input_archive_file = failed to parse input archive file
 
-codegen_ssa_invalid_monomorphization_return_integer_type = invalid monomorphization of `{$name}` intrinsic: expected return type with integer elements, found `{$ret_ty}` with non-integer `{$out_ty}`
+codegen_ssa_thorin_parse_input_file_kind = failed to parse input file kind
 
-codegen_ssa_invalid_monomorphization_simd_shuffle = invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be an array of `u32`, got `{$ty}`
+codegen_ssa_thorin_parse_input_object_file = failed to parse input object file
 
-codegen_ssa_invalid_monomorphization_return_length = invalid monomorphization of `{$name}` intrinsic: expected return type of length {$in_len}, found `{$ret_ty}` with length {$out_len}
+codegen_ssa_thorin_parse_unit = failed to parse unit
 
-codegen_ssa_invalid_monomorphization_return_element = invalid monomorphization of `{$name}` intrinsic: expected return element type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` with element type `{$out_ty}`
+codegen_ssa_thorin_parse_unit_abbreviations = failed to parse unit abbreviations
 
-codegen_ssa_invalid_monomorphization_shuffle_index_not_constant = invalid monomorphization of `{$name}` intrinsic: shuffle index #{$arg_idx} is not a constant
+codegen_ssa_thorin_parse_unit_attribute = failed to parse unit attribute
 
-codegen_ssa_invalid_monomorphization_shuffle_index_out_of_bounds = invalid monomorphization of `{$name}` intrinsic: shuffle index #{$arg_idx} is out of bounds (limit {$total_len})
+codegen_ssa_thorin_parse_unit_header = failed to parse unit header
 
-codegen_ssa_invalid_monomorphization_inserted_type = invalid monomorphization of `{$name}` intrinsic: expected inserted type `{$in_elem}` (element of input `{$in_ty}`), found `{$out_ty}`
+codegen_ssa_thorin_read_input_failure = failed to read input file
 
-codegen_ssa_invalid_monomorphization_return_type = invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}`
+codegen_ssa_thorin_relocation_with_invalid_symbol = relocation with invalid symbol for section `{$section}` at offset {$offset}
 
-codegen_ssa_invalid_monomorphization_expected_return_type = invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_ty}`, found `{$ret_ty}`
+codegen_ssa_thorin_row_not_in_index = row {$row} found in index's hash table not present in index
 
-codegen_ssa_invalid_monomorphization_mismatched_lengths = invalid monomorphization of `{$name}` intrinsic: mismatched lengths: mask length `{$m_len}` != other vector length `{$v_len}`
+codegen_ssa_thorin_section_not_in_row = section not found in unit's row in index
 
-codegen_ssa_invalid_monomorphization_mask_type = invalid monomorphization of `{$name}` intrinsic: mask element type is `{$ty}`, expected `i_`
+codegen_ssa_thorin_section_without_name = section without name at offset {$offset}
 
-codegen_ssa_invalid_monomorphization_vector_argument = invalid monomorphization of `{$name}` intrinsic: vector argument `{$in_ty}`'s element type `{$in_elem}`, expected integer element type
+codegen_ssa_thorin_str_at_offset = read string at offset {$offset} of `.debug_str.dwo` section
 
-codegen_ssa_invalid_monomorphization_cannot_return = invalid monomorphization of `{$name}` intrinsic: cannot return `{$ret_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
+codegen_ssa_thorin_top_level_die_not_unit = top-level debugging information entry is not a compilation/type unit
 
-codegen_ssa_invalid_monomorphization_expected_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of second argument `{$second_arg}` to be a pointer to the element type `{$in_elem}` of the first argument `{$in_ty}`, found `{$expected_element}` != `{$mutability} {$in_elem}`
+codegen_ssa_thorin_unit_not_in_index = unit {$unit} from input package is not in its index
 
-codegen_ssa_invalid_monomorphization_third_arg_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of third argument `{$third_arg}` to be a signed integer type
+codegen_ssa_thorin_unsupported_relocation = unsupported relocation for section {$section} at offset {$offset}
 
-codegen_ssa_invalid_monomorphization_unsupported_symbol_of_size = invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` of size `{$size}` to `{$ret_ty}`
+codegen_ssa_unable_to_exe_linker = could not exec the linker `{$linker_path}`
+    .note = {$error}
+    .command_note = {$command_formatted}
 
-codegen_ssa_invalid_monomorphization_unsupported_symbol = invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}`
+codegen_ssa_unable_to_run = unable to run `{$util}`: {$error}
 
-codegen_ssa_invalid_monomorphization_cast_fat_pointer = invalid monomorphization of `{$name}` intrinsic: cannot cast fat pointer `{$ty}`
+codegen_ssa_unable_to_run_dsymutil = unable to run `dsymutil`: {$error}
 
-codegen_ssa_invalid_monomorphization_expected_pointer = invalid monomorphization of `{$name}` intrinsic: expected pointer, got `{$ty}`
+codegen_ssa_unable_to_write_debugger_visualizer = Unable to write debugger visualizer file `{$path}`: {$error}
 
-codegen_ssa_invalid_monomorphization_expected_usize = invalid monomorphization of `{$name}` intrinsic: expected `usize`, got `{$ty}`
+codegen_ssa_unknown_archive_kind =
+    Don't know how to build archive of type: {$kind}
 
-codegen_ssa_invalid_monomorphization_unsupported_cast = invalid monomorphization of `{$name}` intrinsic: unsupported cast from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}` with element `{$out_elem}`
+codegen_ssa_unknown_atomic_operation = unknown atomic operation
 
-codegen_ssa_invalid_monomorphization_unsupported_operation = invalid monomorphization of `{$name}` intrinsic: unsupported operation on `{$in_ty}` with element `{$in_elem}`
+codegen_ssa_unknown_atomic_ordering = unknown ordering in atomic intrinsic
 
-codegen_ssa_invalid_monomorphization_expected_vector_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of vector type `{$vector_type}` to be a signed or unsigned integer type
+codegen_ssa_unsupported_arch = unsupported arch `{$arch}` for os `{$os}`
 
-codegen_ssa_invalid_no_sanitize = invalid argument for `no_sanitize`
-    .note = expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread`
+codegen_ssa_unsupported_link_self_contained = option `-C link-self-contained` is not supported on this target
 
-codegen_ssa_invalid_link_ordinal_nargs = incorrect number of arguments to `#[link_ordinal]`
-    .note = the attribute requires exactly one argument
+codegen_ssa_use_cargo_directive = use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#cargorustc-link-libkindname)
 
-codegen_ssa_illegal_link_ordinal_format = illegal ordinal format in `link_ordinal`
-    .note = an unsuffixed integer value, e.g., `1`, is expected
+codegen_ssa_version_script_write_failure = failed to write version script: {$error}
 
-codegen_ssa_target_feature_safe_trait = `#[target_feature(..)]` cannot be applied to safe trait method
-    .label = cannot be applied to safe trait method
-    .label_def = not an `unsafe` function
+codegen_ssa_visual_studio_not_installed = you may need to install Visual Studio build tools with the "C++ build tools" workload
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 8a00c42a0e8..bdbd10f8260 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -893,7 +893,7 @@ fn link_natively<'a>(
                     linker_path: &linker_path,
                     exit_status: prog.status,
                     command: &cmd,
-                    escaped_output: &escaped_output,
+                    escaped_output,
                 };
                 sess.diagnostic().emit_err(err);
                 // If MSVC's `link.exe` was expected but the return code
@@ -1188,6 +1188,9 @@ fn add_sanitizer_libraries(sess: &Session, crate_type: CrateType, linker: &mut d
     if sanitizer.contains(SanitizerSet::HWADDRESS) {
         link_sanitizer_runtime(sess, linker, "hwasan");
     }
+    if sanitizer.contains(SanitizerSet::SAFESTACK) {
+        link_sanitizer_runtime(sess, linker, "safestack");
+    }
 }
 
 fn link_sanitizer_runtime(sess: &Session, linker: &mut dyn Linker, name: &str) {
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index 8bf84772f08..ad27b854d59 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -188,6 +188,11 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
     };
 
     let mut file = write::Object::new(binary_format, architecture, endianness);
+    if sess.target.is_like_osx {
+        if let Some(build_version) = macho_object_build_version_for_target(&sess.target) {
+            file.set_macho_build_version(build_version)
+        }
+    }
     let e_flags = match architecture {
         Architecture::Mips => {
             let arch = match sess.target.options.cpu.as_ref() {
@@ -258,6 +263,33 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
     Some(file)
 }
 
+/// Apple's LD, when linking for Mac Catalyst, requires object files to
+/// contain information about what they were built for (LC_BUILD_VERSION):
+/// the platform (macOS/watchOS etc), minimum OS version, and SDK version.
+/// This returns a `MachOBuildVersion` if necessary for the target.
+fn macho_object_build_version_for_target(
+    target: &Target,
+) -> Option<object::write::MachOBuildVersion> {
+    if !target.llvm_target.ends_with("-macabi") {
+        return None;
+    }
+    /// The `object` crate demands "X.Y.Z encoded in nibbles as xxxx.yy.zz"
+    /// e.g. minOS 14.0 = 0x000E0000, or SDK 16.2 = 0x00100200
+    fn pack_version((major, minor): (u32, u32)) -> u32 {
+        (major << 16) | (minor << 8)
+    }
+
+    let platform = object::macho::PLATFORM_MACCATALYST;
+    let min_os = (14, 0);
+    let sdk = (16, 2);
+
+    let mut build_version = object::write::MachOBuildVersion::default();
+    build_version.platform = platform;
+    build_version.minos = pack_version(min_os);
+    build_version.sdk = pack_version(sdk);
+    Some(build_version)
+}
+
 pub enum MetadataPosition {
     First,
     Last,
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index c323372bda4..10e9e5588f6 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -1800,7 +1800,7 @@ impl SharedEmitterMain {
                     handler.emit_diagnostic(&mut d);
                 }
                 Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => {
-                    let msg = msg.strip_prefix("error: ").unwrap_or(&msg);
+                    let msg = msg.strip_prefix("error: ").unwrap_or(&msg).to_string();
 
                     let mut err = match level {
                         Level::Error { lint: false } => sess.struct_err(msg).forget_guarantee(),
diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs
index cf4893b8226..bf37ac69f2d 100644
--- a/compiler/rustc_codegen_ssa/src/errors.rs
+++ b/compiler/rustc_codegen_ssa/src/errors.rs
@@ -336,7 +336,7 @@ pub struct LinkingFailed<'a> {
     pub linker_path: &'a PathBuf,
     pub exit_status: ExitStatus,
     pub command: &'a Command,
-    pub escaped_output: &'a str,
+    pub escaped_output: String,
 }
 
 impl IntoDiagnostic<'_> for LinkingFailed<'_> {
@@ -345,11 +345,13 @@ impl IntoDiagnostic<'_> for LinkingFailed<'_> {
         diag.set_arg("linker_path", format!("{}", self.linker_path.display()));
         diag.set_arg("exit_status", format!("{}", self.exit_status));
 
-        diag.note(format!("{:?}", self.command)).note(self.escaped_output);
+        let contains_undefined_ref = self.escaped_output.contains("undefined reference to");
+
+        diag.note(format!("{:?}", self.command)).note(self.escaped_output.to_string());
 
         // Trying to match an error from OS linkers
         // which by now we have no way to translate.
-        if self.escaped_output.contains("undefined reference to") {
+        if contains_undefined_ref {
             diag.note(fluent::codegen_ssa_extern_funcs_not_found)
                 .note(fluent::codegen_ssa_specify_libraries_to_link)
                 .note(fluent::codegen_ssa_use_cargo_directive);
diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
index 835074806e9..22c1f05974d 100644
--- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
@@ -234,7 +234,6 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
             | PlaceContext::NonMutatingUse(
                 NonMutatingUseContext::Inspect
                 | NonMutatingUseContext::SharedBorrow
-                | NonMutatingUseContext::UniqueBorrow
                 | NonMutatingUseContext::ShallowBorrow
                 | NonMutatingUseContext::AddressOf
                 | NonMutatingUseContext::Projection,
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index d516ac4ebb7..3f0b64b1103 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -1256,7 +1256,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 MergingSucc::False
             }
 
-            mir::TerminatorKind::Drop { place, target, unwind } => {
+            mir::TerminatorKind::Drop { place, target, unwind, replace: _ } => {
                 self.codegen_drop_terminator(helper, bx, place, target, unwind, mergeable_succ())
             }
 
diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs
index 1204c99e533..00414003202 100644
--- a/compiler/rustc_codegen_ssa/src/mir/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs
@@ -111,7 +111,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         self.instance.subst_mir_and_normalize_erasing_regions(
             self.cx.tcx(),
             ty::ParamEnv::reveal_all(),
-            ty::EarlyBinder(value),
+            ty::EarlyBinder::bind(value),
         )
     }
 }
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index 2301c3ef13e..4000c9540ce 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -8,10 +8,10 @@ use crate::traits::*;
 use crate::MemFlags;
 
 use rustc_middle::mir;
-use rustc_middle::mir::interpret::{ConstValue, Pointer, Scalar};
+use rustc_middle::mir::interpret::{alloc_range, ConstValue, Pointer, Scalar};
 use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
 use rustc_middle::ty::Ty;
-use rustc_target::abi::{Abi, Align, Size};
+use rustc_target::abi::{self, Abi, Align, Size};
 
 use std::fmt;
 
@@ -115,13 +115,82 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
                 OperandValue::Pair(a_llval, b_llval)
             }
             ConstValue::ByRef { alloc, offset } => {
-                return bx.load_operand(bx.from_const_alloc(layout, alloc, offset));
+                return Self::from_const_alloc(bx, layout, alloc, offset);
             }
         };
 
         OperandRef { val, layout }
     }
 
+    fn from_const_alloc<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
+        bx: &mut Bx,
+        layout: TyAndLayout<'tcx>,
+        alloc: rustc_middle::mir::interpret::ConstAllocation<'tcx>,
+        offset: Size,
+    ) -> Self {
+        let alloc_align = alloc.inner().align;
+        assert_eq!(alloc_align, layout.align.abi);
+        let ty = bx.type_ptr_to(bx.cx().backend_type(layout));
+
+        let read_scalar = |start, size, s: abi::Scalar, ty| {
+            let val = alloc
+                .0
+                .read_scalar(
+                    bx,
+                    alloc_range(start, size),
+                    /*read_provenance*/ matches!(s.primitive(), abi::Pointer(_)),
+                )
+                .unwrap();
+            bx.scalar_to_backend(val, s, ty)
+        };
+
+        // It may seem like all types with `Scalar` or `ScalarPair` ABI are fair game at this point.
+        // However, `MaybeUninit<u64>` is considered a `Scalar` as far as its layout is concerned --
+        // and yet cannot be represented by an interpreter `Scalar`, since we have to handle the
+        // case where some of the bytes are initialized and others are not. So, we need an extra
+        // check that walks over the type of `mplace` to make sure it is truly correct to treat this
+        // like a `Scalar` (or `ScalarPair`).
+        match layout.abi {
+            Abi::Scalar(s @ abi::Scalar::Initialized { .. }) => {
+                let size = s.size(bx);
+                assert_eq!(size, layout.size, "abi::Scalar size does not match layout size");
+                let val = read_scalar(Size::ZERO, size, s, ty);
+                OperandRef { val: OperandValue::Immediate(val), layout }
+            }
+            Abi::ScalarPair(
+                a @ abi::Scalar::Initialized { .. },
+                b @ abi::Scalar::Initialized { .. },
+            ) => {
+                let (a_size, b_size) = (a.size(bx), b.size(bx));
+                let b_offset = a_size.align_to(b.align(bx).abi);
+                assert!(b_offset.bytes() > 0);
+                let a_val = read_scalar(
+                    Size::ZERO,
+                    a_size,
+                    a,
+                    bx.scalar_pair_element_backend_type(layout, 0, true),
+                );
+                let b_val = read_scalar(
+                    b_offset,
+                    b_size,
+                    b,
+                    bx.scalar_pair_element_backend_type(layout, 1, true),
+                );
+                OperandRef { val: OperandValue::Pair(a_val, b_val), layout }
+            }
+            _ if layout.is_zst() => OperandRef::new_zst(bx, layout),
+            _ => {
+                // Neither a scalar nor scalar pair. Load from a place
+                let init = bx.const_data_from_alloc(alloc);
+                let base_addr = bx.static_addr_of(init, alloc_align, None);
+
+                let llval = bx.const_ptr_byte_offset(base_addr, offset);
+                let llval = bx.const_bitcast(llval, ty);
+                bx.load_operand(PlaceRef::new_sized(llval, layout))
+            }
+        }
+    }
+
     /// Asserts that this operand refers to a scalar and returns
     /// a reference to its value.
     pub fn immediate(self) -> V {
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index 6e7065713b8..0255b660380 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -668,11 +668,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
             mir::Rvalue::NullaryOp(ref null_op, ty) => {
                 let ty = self.monomorphize(ty);
-                assert!(bx.cx().type_is_sized(ty));
                 let layout = bx.cx().layout_of(ty);
                 let val = match null_op {
-                    mir::NullOp::SizeOf => layout.size.bytes(),
-                    mir::NullOp::AlignOf => layout.align.abi.bytes(),
+                    mir::NullOp::SizeOf => {
+                        assert!(bx.cx().type_is_sized(ty));
+                        layout.size.bytes()
+                    }
+                    mir::NullOp::AlignOf => {
+                        assert!(bx.cx().type_is_sized(ty));
+                        layout.align.abi.bytes()
+                    }
                     mir::NullOp::OffsetOf(fields) => {
                         layout.offset_of_subfield(bx.cx(), fields.iter().map(|f| f.index())).bytes()
                     }
diff --git a/compiler/rustc_codegen_ssa/src/traits/consts.rs b/compiler/rustc_codegen_ssa/src/traits/consts.rs
index 61906302779..dc2fc396480 100644
--- a/compiler/rustc_codegen_ssa/src/traits/consts.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/consts.rs
@@ -1,8 +1,6 @@
 use super::BackendTypes;
-use crate::mir::place::PlaceRef;
 use rustc_middle::mir::interpret::{ConstAllocation, Scalar};
-use rustc_middle::ty::layout::TyAndLayout;
-use rustc_target::abi::{self, Size};
+use rustc_target::abi;
 
 pub trait ConstMethods<'tcx>: BackendTypes {
     // Constant constructors
@@ -30,12 +28,8 @@ pub trait ConstMethods<'tcx>: BackendTypes {
     fn const_data_from_alloc(&self, alloc: ConstAllocation<'tcx>) -> Self::Value;
 
     fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, llty: Self::Type) -> Self::Value;
-    fn from_const_alloc(
-        &self,
-        layout: TyAndLayout<'tcx>,
-        alloc: ConstAllocation<'tcx>,
-        offset: Size,
-    ) -> PlaceRef<'tcx, Self::Value>;
 
     fn const_ptrcast(&self, val: Self::Value, ty: Self::Type) -> Self::Value;
+    fn const_bitcast(&self, val: Self::Value, ty: Self::Type) -> Self::Value;
+    fn const_ptr_byte_offset(&self, val: Self::Value, offset: abi::Size) -> Self::Value;
 }
diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl
index f6751df443f..7d56cf0aa07 100644
--- a/compiler/rustc_const_eval/messages.ftl
+++ b/compiler/rustc_const_eval/messages.ftl
@@ -1,40 +1,60 @@
-const_eval_unstable_in_stable =
-    const-stable function cannot use `#[feature({$gate})]`
-    .unstable_sugg = if it is not part of the public API, make this function unstably const
-    .bypass_sugg = otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks
+const_eval_interior_mutability_borrow =
+    cannot borrow here, since the borrowed element may contain interior mutability
 
-const_eval_thread_local_access =
-    thread-local statics cannot be accessed at compile-time
+const_eval_interior_mutable_data_refer =
+    {$kind}s cannot refer to interior mutable data
+    .label = this borrow of an interior mutable value may end up in the final value
+    .help = to fix this, the value can be extracted to a separate `static` item and then referenced
+    .teach_note =
+        A constant containing interior mutable data behind a reference can allow you to modify that data.
+        This would make multiple uses of a constant to be able to see different values and allow circumventing
+        the `Send` and `Sync` requirements for shared mutable data, which is unsound.
 
-const_eval_static_access =
-    {$kind}s cannot refer to statics
-    .help = consider extracting the value of the `static` to a `const`, and referring to that
-    .teach_note = `static` and `const` variables can refer to other `const` variables. A `const` variable, however, cannot refer to a `static` variable.
-    .teach_help = To fix this, the value can be extracted to a `const` and then used.
+const_eval_max_num_nodes_in_const = maximum number of nodes exceeded in constant {$global_const_id}
 
-const_eval_raw_ptr_to_int =
-    pointers cannot be cast to integers during const eval
-    .note = at compile-time, pointers do not have an integer value
-    .note2 = avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
+const_eval_mut_deref =
+    mutation through a reference is not allowed in {$kind}s
+
+const_eval_non_const_fmt_macro_call =
+    cannot call non-const formatting macro in {$kind}s
+
+const_eval_non_const_fn_call =
+    cannot call non-const fn `{$def_path_str}` in {$kind}s
+
+const_eval_panic_non_str = argument to `panic!()` in a const context must have type `&str`
 
 const_eval_raw_ptr_comparison =
     pointers cannot be reliably compared during const eval
     .note = see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
 
-const_eval_panic_non_str = argument to `panic!()` in a const context must have type `&str`
+const_eval_raw_ptr_to_int =
+    pointers cannot be cast to integers during const eval
+    .note = at compile-time, pointers do not have an integer value
+    .note2 = avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
 
-const_eval_mut_deref =
-    mutation through a reference is not allowed in {$kind}s
+const_eval_static_access =
+    {$kind}s cannot refer to statics
+    .help = consider extracting the value of the `static` to a `const`, and referring to that
+    .teach_note = `static` and `const` variables can refer to other `const` variables. A `const` variable, however, cannot refer to a `static` variable.
+    .teach_help = To fix this, the value can be extracted to a `const` and then used.
+
+const_eval_thread_local_access =
+    thread-local statics cannot be accessed at compile-time
 
 const_eval_transient_mut_borrow = mutable references are not allowed in {$kind}s
 
 const_eval_transient_mut_borrow_raw = raw mutable references are not allowed in {$kind}s
 
-const_eval_max_num_nodes_in_const = maximum number of nodes exceeded in constant {$global_const_id}
-
 const_eval_unallowed_fn_pointer_call = function pointer calls are not allowed in {$kind}s
 
-const_eval_unstable_const_fn = `{$def_path}` is not yet stable as a const fn
+const_eval_unallowed_heap_allocations =
+    allocations are not allowed in {$kind}s
+    .label = allocation not allowed in {$kind}s
+    .teach_note =
+        The value of statics and constants must be known at compile time, and they live for the entire lifetime of a program. Creating a boxed value allocates memory on the heap at runtime, and therefore cannot be done at compile time.
+
+const_eval_unallowed_inline_asm =
+    inline assembly is not allowed in {$kind}s
 
 const_eval_unallowed_mutable_refs =
     mutable references are not allowed in the final value of {$kind}s
@@ -60,32 +80,12 @@ const_eval_unallowed_mutable_refs_raw =
 
         If you really want global mutable state, try using static mut or a global UnsafeCell.
 
-const_eval_non_const_fmt_macro_call =
-    cannot call non-const formatting macro in {$kind}s
-
-const_eval_non_const_fn_call =
-    cannot call non-const fn `{$def_path_str}` in {$kind}s
-
 const_eval_unallowed_op_in_const_context =
     {$msg}
 
-const_eval_unallowed_heap_allocations =
-    allocations are not allowed in {$kind}s
-    .label = allocation not allowed in {$kind}s
-    .teach_note =
-        The value of statics and constants must be known at compile time, and they live for the entire lifetime of a program. Creating a boxed value allocates memory on the heap at runtime, and therefore cannot be done at compile time.
-
-const_eval_unallowed_inline_asm =
-    inline assembly is not allowed in {$kind}s
-
-const_eval_interior_mutable_data_refer =
-    {$kind}s cannot refer to interior mutable data
-    .label = this borrow of an interior mutable value may end up in the final value
-    .help = to fix this, the value can be extracted to a separate `static` item and then referenced
-    .teach_note =
-        A constant containing interior mutable data behind a reference can allow you to modify that data.
-        This would make multiple uses of a constant to be able to see different values and allow circumventing
-        the `Send` and `Sync` requirements for shared mutable data, which is unsound.
+const_eval_unstable_const_fn = `{$def_path}` is not yet stable as a const fn
 
-const_eval_interior_mutability_borrow =
-    cannot borrow here, since the borrowed element may contain interior mutability
+const_eval_unstable_in_stable =
+    const-stable function cannot use `#[feature({$gate})]`
+    .unstable_sugg = if it is not part of the public API, make this function unstably const
+    .bypass_sugg = otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index 7e94578003e..91ccdef7215 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -497,7 +497,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             .try_subst_mir_and_normalize_erasing_regions(
                 *self.tcx,
                 self.param_env,
-                ty::EarlyBinder(value),
+                ty::EarlyBinder::bind(value),
             )
             .map_err(|_| err_inval!(TooGeneric))
     }
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index df387920010..586e8f063ee 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -114,7 +114,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 }
             }
 
-            Drop { place, target, unwind } => {
+            Drop { place, target, unwind, replace: _ } => {
                 let frame = self.frame();
                 let ty = place.ty(&frame.body.local_decls, *self.tcx).ty;
                 let ty = self.subst_from_frame_and_normalize_erasing_regions(frame, ty)?;
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index 138bc3eb74a..57d939747aa 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -412,9 +412,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                         BorrowKind::Shallow => {
                             PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow)
                         }
-                        BorrowKind::Unique => {
-                            PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow)
-                        }
+                        BorrowKind::Unique => PlaceContext::MutatingUse(MutatingUseContext::Borrow),
                         BorrowKind::Mut { .. } => {
                             PlaceContext::MutatingUse(MutatingUseContext::Borrow)
                         }
diff --git a/compiler/rustc_data_structures/src/sharded.rs b/compiler/rustc_data_structures/src/sharded.rs
index 7ed70ba1e0f..40cbf14958e 100644
--- a/compiler/rustc_data_structures/src/sharded.rs
+++ b/compiler/rustc_data_structures/src/sharded.rs
@@ -1,4 +1,6 @@
 use crate::fx::{FxHashMap, FxHasher};
+#[cfg(parallel_compiler)]
+use crate::sync::is_dyn_thread_safe;
 use crate::sync::{CacheAligned, Lock, LockGuard};
 use std::borrow::Borrow;
 use std::collections::hash_map::RawEntryMut;
@@ -18,6 +20,11 @@ pub const SHARDS: usize = 1 << SHARD_BITS;
 
 /// An array of cache-line aligned inner locked structures with convenience methods.
 pub struct Sharded<T> {
+    /// This mask is used to ensure that accesses are inbounds of `shards`.
+    /// When dynamic thread safety is off, this field is set to 0 causing only
+    /// a single shard to be used for greater cache efficiency.
+    #[cfg(parallel_compiler)]
+    mask: usize,
     shards: [CacheAligned<Lock<T>>; SHARDS],
 }
 
@@ -31,31 +38,54 @@ impl<T: Default> Default for Sharded<T> {
 impl<T> Sharded<T> {
     #[inline]
     pub fn new(mut value: impl FnMut() -> T) -> Self {
-        Sharded { shards: [(); SHARDS].map(|()| CacheAligned(Lock::new(value()))) }
+        Sharded {
+            #[cfg(parallel_compiler)]
+            mask: if is_dyn_thread_safe() { SHARDS - 1 } else { 0 },
+            shards: [(); SHARDS].map(|()| CacheAligned(Lock::new(value()))),
+        }
+    }
+
+    #[inline(always)]
+    fn mask(&self) -> usize {
+        #[cfg(parallel_compiler)]
+        {
+            if SHARDS == 1 { 0 } else { self.mask }
+        }
+        #[cfg(not(parallel_compiler))]
+        {
+            0
+        }
+    }
+
+    #[inline(always)]
+    fn count(&self) -> usize {
+        // `self.mask` is always one below the used shard count
+        self.mask() + 1
     }
 
     /// The shard is selected by hashing `val` with `FxHasher`.
     #[inline]
     pub fn get_shard_by_value<K: Hash + ?Sized>(&self, val: &K) -> &Lock<T> {
-        if SHARDS == 1 { &self.shards[0].0 } else { self.get_shard_by_hash(make_hash(val)) }
+        self.get_shard_by_hash(if SHARDS == 1 { 0 } else { make_hash(val) })
     }
 
     #[inline]
     pub fn get_shard_by_hash(&self, hash: u64) -> &Lock<T> {
-        &self.shards[get_shard_index_by_hash(hash)].0
+        self.get_shard_by_index(get_shard_hash(hash))
     }
 
     #[inline]
     pub fn get_shard_by_index(&self, i: usize) -> &Lock<T> {
-        &self.shards[i].0
+        // SAFETY: The index get ANDed with the mask, ensuring it is always inbounds.
+        unsafe { &self.shards.get_unchecked(i & self.mask()).0 }
     }
 
     pub fn lock_shards(&self) -> Vec<LockGuard<'_, T>> {
-        (0..SHARDS).map(|i| self.shards[i].0.lock()).collect()
+        (0..self.count()).map(|i| self.get_shard_by_index(i).lock()).collect()
     }
 
     pub fn try_lock_shards(&self) -> Option<Vec<LockGuard<'_, T>>> {
-        (0..SHARDS).map(|i| self.shards[i].0.try_lock()).collect()
+        (0..self.count()).map(|i| self.get_shard_by_index(i).try_lock()).collect()
     }
 }
 
@@ -136,11 +166,9 @@ pub fn make_hash<K: Hash + ?Sized>(val: &K) -> u64 {
 /// `hash` can be computed with any hasher, so long as that hasher is used
 /// consistently for each `Sharded` instance.
 #[inline]
-#[allow(clippy::modulo_one)]
-pub fn get_shard_index_by_hash(hash: u64) -> usize {
+fn get_shard_hash(hash: u64) -> usize {
     let hash_len = mem::size_of::<usize>();
     // Ignore the top 7 bits as hashbrown uses these and get the next SHARD_BITS highest bits.
     // hashbrown also uses the lowest bits, so we can't use those
-    let bits = (hash >> (hash_len * 8 - 7 - SHARD_BITS)) as usize;
-    bits % SHARDS
+    (hash >> (hash_len * 8 - 7 - SHARD_BITS)) as usize
 }
diff --git a/compiler/rustc_driver_impl/messages.ftl b/compiler/rustc_driver_impl/messages.ftl
index f19b1ff6426..22b4ec6b0d1 100644
--- a/compiler/rustc_driver_impl/messages.ftl
+++ b/compiler/rustc_driver_impl/messages.ftl
@@ -1,19 +1,19 @@
-driver_impl_rlink_unable_to_read = failed to read rlink file: `{$err}`
-
-driver_impl_rlink_wrong_file_type = The input does not look like a .rlink file
+driver_impl_ice = the compiler unexpectedly panicked. this is a bug.
+driver_impl_ice_bug_report = we would appreciate a bug report: {$bug_report_url}
+driver_impl_ice_exclude_cargo_defaults = some of the compiler flags provided by cargo are hidden
 
+driver_impl_ice_flags = compiler flags: {$flags}
+driver_impl_ice_version = rustc {$version} running on {$triple}
 driver_impl_rlink_empty_version_number = The input does not contain version number
 
 driver_impl_rlink_encoding_version_mismatch = .rlink file was produced with encoding version `{$version_array}`, but the current version is `{$rlink_version}`
 
+driver_impl_rlink_no_a_file = rlink must be a file
+
 driver_impl_rlink_rustc_version_mismatch = .rlink file was produced by rustc version `{$rustc_version}`, but the current version is `{$current_version}`
 
-driver_impl_rlink_no_a_file = rlink must be a file
+driver_impl_rlink_unable_to_read = failed to read rlink file: `{$err}`
 
-driver_impl_unpretty_dump_fail = pretty-print failed to write `{$path}` due to error `{$err}`
+driver_impl_rlink_wrong_file_type = The input does not look like a .rlink file
 
-driver_impl_ice = the compiler unexpectedly panicked. this is a bug.
-driver_impl_ice_bug_report = we would appreciate a bug report: {$bug_report_url}
-driver_impl_ice_version = rustc {$version} running on {$triple}
-driver_impl_ice_flags = compiler flags: {$flags}
-driver_impl_ice_exclude_cargo_defaults = some of the compiler flags provided by cargo are hidden
+driver_impl_unpretty_dump_fail = pretty-print failed to write `{$path}` due to error `{$err}`
diff --git a/compiler/rustc_driver_impl/src/args.rs b/compiler/rustc_driver_impl/src/args.rs
index a713affa099..eb92ccc17b2 100644
--- a/compiler/rustc_driver_impl/src/args.rs
+++ b/compiler/rustc_driver_impl/src/args.rs
@@ -18,6 +18,9 @@ fn arg_expand(arg: String) -> Result<Vec<String>, Error> {
     }
 }
 
+/// **Note:** This function doesn't interpret argument 0 in any special way.
+/// If this function is intended to be used with command line arguments,
+/// `argv[0]` must be removed prior to calling it manually.
 pub fn arg_expand_all(at_args: &[String]) -> Vec<String> {
     let mut args = Vec::new();
     for arg in at_args {
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 40aa69e5a41..14888cf4d75 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -250,6 +250,16 @@ fn run_compiler(
         Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>,
     >,
 ) -> interface::Result<()> {
+    // Throw away the first argument, the name of the binary.
+    // In case of at_args being empty, as might be the case by
+    // passing empty argument array to execve under some platforms,
+    // just use an empty slice.
+    //
+    // This situation was possible before due to arg_expand_all being
+    // called before removing the argument, enabling a crash by calling
+    // the compiler with @empty_file as argv[0] and no more arguments.
+    let at_args = at_args.get(1..).unwrap_or_default();
+
     let args = args::arg_expand_all(at_args);
 
     let Some(matches) = handle_options(&args) else { return Ok(()) };
@@ -1074,9 +1084,6 @@ fn print_flag_list<T>(
 /// So with all that in mind, the comments below have some more detail about the
 /// contortions done here to get things to work out correctly.
 pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
-    // Throw away the first argument, the name of the binary
-    let args = &args[1..];
-
     if args.is_empty() {
         // user did not write `-v` nor `-Z unstable-options`, so do not
         // include that extra information.
@@ -1251,7 +1258,7 @@ pub fn install_ice_hook(bug_report_url: &'static str, extra_info: fn(&Handler))
         if let Some(msg) = info.payload().downcast_ref::<String>() {
             if msg.starts_with("failed printing to stdout: ") && msg.ends_with("(os error 232)") {
                 // the error code is already going to be reported when the panic unwinds up the stack
-                let _ = early_error_no_abort(ErrorOutputType::default(), msg.as_str());
+                let _ = early_error_no_abort(ErrorOutputType::default(), msg.clone());
                 return;
             }
         };
diff --git a/compiler/rustc_error_codes/src/error_codes/E0133.md b/compiler/rustc_error_codes/src/error_codes/E0133.md
index 1adbcc31356..8ca3f03ce15 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0133.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0133.md
@@ -1,4 +1,4 @@
-Unsafe code was used outside of an unsafe function or block.
+Unsafe code was used outside of an unsafe block.
 
 Erroneous code example:
 
@@ -30,4 +30,21 @@ fn main() {
 
 See the [unsafe section][unsafe-section] of the Book for more details.
 
+#### Unsafe code in functions
+
+Unsafe code is currently accepted in unsafe functions, but that is being phased
+out in favor of requiring unsafe blocks here too.
+
+```
+unsafe fn f() { return; }
+
+unsafe fn g() {
+    f(); // Is accepted, but no longer recommended
+    unsafe { f(); } // Recommended way to write this
+}
+```
+
+Linting against this is controlled via the `unsafe_op_in_unsafe_fn` lint, which
+is `allow` by default but will be upgraded to `warn` in a future edition.
+
 [unsafe-section]: https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html
diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs
index 0accb4ab96f..2a97c4ff7ae 100644
--- a/compiler/rustc_error_messages/src/lib.rs
+++ b/compiler/rustc_error_messages/src/lib.rs
@@ -263,8 +263,7 @@ type FluentId = Cow<'static, str>;
 #[rustc_diagnostic_item = "SubdiagnosticMessage"]
 pub enum SubdiagnosticMessage {
     /// Non-translatable diagnostic message.
-    // FIXME(davidtwco): can a `Cow<'static, str>` be used here?
-    Str(String),
+    Str(Cow<'static, str>),
     /// Translatable message which has already been translated eagerly.
     ///
     /// Some diagnostics have repeated subdiagnostics where the same interpolated variables would
@@ -275,8 +274,7 @@ pub enum SubdiagnosticMessage {
     /// incorrect diagnostics. Eager translation results in translation for a subdiagnostic
     /// happening immediately after the subdiagnostic derive's logic has been run. This variant
     /// stores messages which have been translated eagerly.
-    // FIXME(#100717): can a `Cow<'static, str>` be used here?
-    Eager(String),
+    Eager(Cow<'static, str>),
     /// Identifier of a Fluent message. Instances of this variant are generated by the
     /// `Subdiagnostic` derive.
     FluentIdentifier(FluentId),
@@ -290,17 +288,17 @@ pub enum SubdiagnosticMessage {
 
 impl From<String> for SubdiagnosticMessage {
     fn from(s: String) -> Self {
-        SubdiagnosticMessage::Str(s)
+        SubdiagnosticMessage::Str(Cow::Owned(s))
     }
 }
-impl<'a> From<&'a str> for SubdiagnosticMessage {
-    fn from(s: &'a str) -> Self {
-        SubdiagnosticMessage::Str(s.to_string())
+impl From<&'static str> for SubdiagnosticMessage {
+    fn from(s: &'static str) -> Self {
+        SubdiagnosticMessage::Str(Cow::Borrowed(s))
     }
 }
 impl From<Cow<'static, str>> for SubdiagnosticMessage {
     fn from(s: Cow<'static, str>) -> Self {
-        SubdiagnosticMessage::Str(s.to_string())
+        SubdiagnosticMessage::Str(s)
     }
 }
 
@@ -312,8 +310,7 @@ impl From<Cow<'static, str>> for SubdiagnosticMessage {
 #[rustc_diagnostic_item = "DiagnosticMessage"]
 pub enum DiagnosticMessage {
     /// Non-translatable diagnostic message.
-    // FIXME(#100717): can a `Cow<'static, str>` be used here?
-    Str(String),
+    Str(Cow<'static, str>),
     /// Translatable message which has already been translated eagerly.
     ///
     /// Some diagnostics have repeated subdiagnostics where the same interpolated variables would
@@ -324,8 +321,7 @@ pub enum DiagnosticMessage {
     /// incorrect diagnostics. Eager translation results in translation for a subdiagnostic
     /// happening immediately after the subdiagnostic derive's logic has been run. This variant
     /// stores messages which have been translated eagerly.
-    // FIXME(#100717): can a `Cow<'static, str>` be used here?
-    Eager(String),
+    Eager(Cow<'static, str>),
     /// Identifier for a Fluent message (with optional attribute) corresponding to the diagnostic
     /// message.
     ///
@@ -363,17 +359,17 @@ impl DiagnosticMessage {
 
 impl From<String> for DiagnosticMessage {
     fn from(s: String) -> Self {
-        DiagnosticMessage::Str(s)
+        DiagnosticMessage::Str(Cow::Owned(s))
     }
 }
-impl<'a> From<&'a str> for DiagnosticMessage {
-    fn from(s: &'a str) -> Self {
-        DiagnosticMessage::Str(s.to_string())
+impl From<&'static str> for DiagnosticMessage {
+    fn from(s: &'static str) -> Self {
+        DiagnosticMessage::Str(Cow::Borrowed(s))
     }
 }
 impl From<Cow<'static, str>> for DiagnosticMessage {
     fn from(s: Cow<'static, str>) -> Self {
-        DiagnosticMessage::Str(s.to_string())
+        DiagnosticMessage::Str(s)
     }
 }
 
diff --git a/compiler/rustc_errors/messages.ftl b/compiler/rustc_errors/messages.ftl
index dde1d6c0a81..33709734322 100644
--- a/compiler/rustc_errors/messages.ftl
+++ b/compiler/rustc_errors/messages.ftl
@@ -1,19 +1,19 @@
-errors_target_invalid_address_space =
-    invalid address space `{$addr_space}` for `{$cause}` in "data-layout": {$err}
+errors_target_inconsistent_architecture =
+    inconsistent target specification: "data-layout" claims architecture is {$dl}-endian, while "target-endian" is `{$target}`
 
-errors_target_invalid_bits =
-    invalid {$kind} `{$bit}` for `{$cause}` in "data-layout": {$err}
+errors_target_inconsistent_pointer_width =
+    inconsistent target specification: "data-layout" claims pointers are {$pointer_size}-bit, while "target-pointer-width" is `{$target}`
 
-errors_target_missing_alignment =
-    missing alignment for `{$cause}` in "data-layout"
+errors_target_invalid_address_space =
+    invalid address space `{$addr_space}` for `{$cause}` in "data-layout": {$err}
 
 errors_target_invalid_alignment =
     invalid alignment for `{$cause}` in "data-layout": {$err}
 
-errors_target_inconsistent_architecture =
-    inconsistent target specification: "data-layout" claims architecture is {$dl}-endian, while "target-endian" is `{$target}`
-
-errors_target_inconsistent_pointer_width =
-    inconsistent target specification: "data-layout" claims pointers are {$pointer_size}-bit, while "target-pointer-width" is `{$target}`
+errors_target_invalid_bits =
+    invalid {$kind} `{$bit}` for `{$cause}` in "data-layout": {$err}
 
 errors_target_invalid_bits_size = {$err}
+
+errors_target_missing_alignment =
+    missing alignment for `{$cause}` in "data-layout"
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index 29c692128bc..488f2d67ee5 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -352,14 +352,9 @@ impl Diagnostic {
 
     /// Labels all the given spans with the provided label.
     /// See [`Self::span_label()`] for more information.
-    pub fn span_labels(
-        &mut self,
-        spans: impl IntoIterator<Item = Span>,
-        label: impl AsRef<str>,
-    ) -> &mut Self {
-        let label = label.as_ref();
+    pub fn span_labels(&mut self, spans: impl IntoIterator<Item = Span>, label: &str) -> &mut Self {
         for span in spans {
-            self.span_label(span, label);
+            self.span_label(span, label.to_string());
         }
         self
     }
@@ -394,17 +389,18 @@ impl Diagnostic {
         expected: DiagnosticStyledString,
         found: DiagnosticStyledString,
     ) -> &mut Self {
-        let mut msg: Vec<_> = vec![("required when trying to coerce from type `", Style::NoStyle)];
+        let mut msg: Vec<_> =
+            vec![(Cow::from("required when trying to coerce from type `"), Style::NoStyle)];
         msg.extend(expected.0.iter().map(|x| match *x {
-            StringPart::Normal(ref s) => (s.as_str(), Style::NoStyle),
-            StringPart::Highlighted(ref s) => (s.as_str(), Style::Highlight),
+            StringPart::Normal(ref s) => (Cow::from(s.clone()), Style::NoStyle),
+            StringPart::Highlighted(ref s) => (Cow::from(s.clone()), Style::Highlight),
         }));
-        msg.push(("` to type '", Style::NoStyle));
+        msg.push((Cow::from("` to type '"), Style::NoStyle));
         msg.extend(found.0.iter().map(|x| match *x {
-            StringPart::Normal(ref s) => (s.as_str(), Style::NoStyle),
-            StringPart::Highlighted(ref s) => (s.as_str(), Style::Highlight),
+            StringPart::Normal(ref s) => (Cow::from(s.clone()), Style::NoStyle),
+            StringPart::Highlighted(ref s) => (Cow::from(s.clone()), Style::Highlight),
         }));
-        msg.push(("`", Style::NoStyle));
+        msg.push((Cow::from("`"), Style::NoStyle));
 
         // For now, just attach these as notes
         self.highlighted_note(msg);
diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs
index db97d96fccd..7d9d0c76450 100644
--- a/compiler/rustc_errors/src/diagnostic_builder.rs
+++ b/compiler/rustc_errors/src/diagnostic_builder.rs
@@ -558,7 +558,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
         }
 
         // Take the `Diagnostic` by replacing it with a dummy.
-        let dummy = Diagnostic::new(Level::Allow, DiagnosticMessage::Str("".to_string()));
+        let dummy = Diagnostic::new(Level::Allow, DiagnosticMessage::from(""));
         let diagnostic = std::mem::replace(&mut *self.inner.diagnostic, dummy);
 
         // Disable the ICE on `Drop`.
@@ -627,7 +627,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
     pub fn span_labels(
         &mut self,
         spans: impl IntoIterator<Item = Span>,
-        label: impl AsRef<str>,
+        label: &str,
     ) -> &mut Self);
 
     forward!(pub fn note_expected_found(
@@ -781,8 +781,8 @@ impl Drop for DiagnosticBuilderInner<'_> {
                 if !panicking() {
                     handler.emit_diagnostic(&mut Diagnostic::new(
                         Level::Bug,
-                        DiagnosticMessage::Str(
-                            "the following error was constructed but not emitted".to_string(),
+                        DiagnosticMessage::from(
+                            "the following error was constructed but not emitted",
                         ),
                     ));
                     handler.emit_diagnostic(&mut self.diagnostic);
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index e8cd7eaa60f..d8c997b49a1 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -367,7 +367,7 @@ pub trait Emitter: Translate {
 
                 children.push(SubDiagnostic {
                     level: Level::Note,
-                    message: vec![(DiagnosticMessage::Str(msg), Style::NoStyle)],
+                    message: vec![(DiagnosticMessage::from(msg), Style::NoStyle)],
                     span: MultiSpan::new(),
                     render_span: None,
                 });
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 3dec0d9299c..6c5f3e62454 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -628,7 +628,7 @@ impl Handler {
         message: DiagnosticMessage,
         args: impl Iterator<Item = DiagnosticArg<'a, 'static>>,
     ) -> SubdiagnosticMessage {
-        SubdiagnosticMessage::Eager(self.eagerly_translate_to_string(message, args))
+        SubdiagnosticMessage::Eager(Cow::from(self.eagerly_translate_to_string(message, args)))
     }
 
     /// Translate `message` eagerly with `args` to `String`.
@@ -1450,14 +1450,14 @@ impl HandlerInner {
         self.emit_stashed_diagnostics();
 
         let warnings = match self.deduplicated_warn_count {
-            0 => String::new(),
-            1 => "1 warning emitted".to_string(),
-            count => format!("{count} warnings emitted"),
+            0 => Cow::from(""),
+            1 => Cow::from("1 warning emitted"),
+            count => Cow::from(format!("{count} warnings emitted")),
         };
         let errors = match self.deduplicated_err_count {
-            0 => String::new(),
-            1 => "aborting due to previous error".to_string(),
-            count => format!("aborting due to {count} previous errors"),
+            0 => Cow::from(""),
+            1 => Cow::from("aborting due to previous error"),
+            count => Cow::from(format!("aborting due to {count} previous errors")),
         };
         if self.treat_err_as_bug() {
             return;
diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl
index 70d2718b706..6c7e68246ea 100644
--- a/compiler/rustc_expand/messages.ftl
+++ b/compiler/rustc_expand/messages.ftl
@@ -1,142 +1,142 @@
-expand_explain_doc_comment_outer =
-    outer doc comments expand to `#[doc = "..."]`, which is what this macro attempted to match
-
-expand_explain_doc_comment_inner =
-    inner doc comments expand to `#![doc = "..."]`, which is what this macro attempted to match
-
-expand_expr_repeat_no_syntax_vars =
-    attempted to repeat an expression containing no syntax variables matched as repeating at this depth
-
-expand_must_repeat_once =
-    this must repeat at least once
-
-expand_count_repetition_misplaced =
-    `count` can not be placed inside the inner-most repetition
-
-expand_meta_var_expr_unrecognized_var =
-    variable `{$key}` is not recognized in meta-variable expression
-
-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_arg_not_attributes =
+    second argument must be `attributes`
 
 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_attribute_meta_item =
+    attribute must be a meta item, not a literal
 
-expand_arg_not_attributes =
-    second argument must be `attributes`
+expand_attribute_single_word =
+    attribute must only be a single word
 
 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_cannot_be_name_of_macro =
+    `{$trait_ident}` cannot be a name of {$macro_type} macro
 
-expand_attribute_single_word =
-    attribute must only be a single word
+expand_count_repetition_misplaced =
+    `count` can not be placed inside the inner-most repetition
 
-expand_helper_attribute_name_invalid =
-    `{$name}` cannot be a name of derive helper attribute
+expand_duplicate_matcher_binding = duplicate matcher binding
+    .label = duplicate binding
+    .label2 = previous binding
 
 expand_expected_comma_in_list =
     expected token: `,`
 
-expand_only_one_argument =
-    {$name} takes 1 argument
+expand_explain_doc_comment_inner =
+    inner doc comments expand to `#![doc = "..."]`, which is what this macro attempted to match
 
-expand_takes_no_arguments =
-    {$name} takes no arguments
+expand_explain_doc_comment_outer =
+    outer doc comments expand to `#[doc = "..."]`, which is what this macro attempted to match
+
+expand_expr_repeat_no_syntax_vars =
+    attempted to repeat an expression containing no syntax variables matched as repeating at this depth
 
 expand_feature_included_in_edition =
     the feature `{$feature}` is included in the Rust {$edition} edition
 
+expand_feature_not_allowed =
+    the feature `{$name}` is not in the list of allowed features
+
 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_helper_attribute_name_invalid =
+    `{$name}` cannot be a name of derive helper attribute
 
-expand_malformed_feature_attribute =
-    malformed `feature` attribute input
-    .expected = expected just one word
+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_expr_not_supported =
-    removing an expression is not supported in this position
+expand_invalid_cfg_expected_syntax = expected syntax is
 
+expand_invalid_cfg_multiple_predicates = multiple `cfg` predicates are specified
 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_macro_body_stability =
+    macros cannot have body stability attributes
+    .label = invalid body stability attribute
+    .label2 = body stability attribute affects this macro
 
-expand_wrong_fragment_kind =
-    non-{$kind} macro in {$kind} position: {$name}
+expand_macro_const_stability =
+    macros cannot have const stability attributes
+    .label = invalid const stability attribute
+    .label2 = const stability attribute affects this macro
 
-expand_unsupported_key_value =
-    key-value macro attributes are not supported
+expand_malformed_feature_attribute =
+    malformed `feature` attribute input
+    .expected = expected just one word
 
-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_meta_var_dif_seq_matchers = {$msg}
 
-expand_remove_node_not_supported =
-    removing {$descr} is not supported in this position
+expand_meta_var_expr_unrecognized_var =
+    variable `{$key}` is not recognized in meta-variable expression
 
 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_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_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
 
-expand_trace_macro = trace_macro
+expand_must_repeat_once =
+    this must repeat at least once
+
+expand_not_a_meta_item =
+    not a meta item
+
+expand_only_one_argument =
+    {$name} takes 1 argument
+
+expand_only_one_word =
+    must only be one word
+
+expand_proc_macro_derive_tokens =
+    proc-macro derive produced unparsable tokens
 
 expand_proc_macro_panicked =
     proc macro panicked
     .help = message: {$message}
 
-expand_proc_macro_derive_tokens =
-    proc-macro derive produced unparsable tokens
+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_duplicate_matcher_binding = duplicate matcher binding
-    .label = duplicate binding
-    .label2 = previous binding
+expand_remove_expr_not_supported =
+    removing an expression is not supported in this position
+
+expand_remove_node_not_supported =
+    removing {$descr} is not supported in this position
+
+expand_resolve_relative_path =
+    cannot resolve relative path in non-file source `{$path}`
+
+expand_takes_no_arguments =
+    {$name} takes no arguments
+
+expand_trace_macro = trace_macro
+
+expand_unsupported_key_value =
+    key-value macro attributes are not supported
+
+expand_var_still_repeating =
+    variable '{$ident}' is still repeating at this depth
+
+expand_wrong_fragment_kind =
+    non-{$kind} macro in {$kind} position: {$name}
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 4671adccc54..0d43b30474b 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -1154,7 +1154,7 @@ impl<'a> ExtCtxt<'a> {
         // Fixme: does this result in errors?
         self.expansions.clear();
     }
-    pub fn bug(&self, msg: &str) -> ! {
+    pub fn bug(&self, msg: &'static str) -> ! {
         self.sess.parse_sess.span_diagnostic.bug(msg);
     }
     pub fn trace_macros(&self) -> bool {
@@ -1224,7 +1224,7 @@ pub fn resolve_path(
 pub fn expr_to_spanned_string<'a>(
     cx: &'a mut ExtCtxt<'_>,
     expr: P<ast::Expr>,
-    err_msg: &str,
+    err_msg: &'static str,
 ) -> Result<(Symbol, ast::StrStyle, Span), Option<(DiagnosticBuilder<'a, ErrorGuaranteed>, bool)>> {
     // Perform eager expansion on the expression.
     // We want to be able to handle e.g., `concat!("foo", "bar")`.
@@ -1262,7 +1262,7 @@ pub fn expr_to_spanned_string<'a>(
 pub fn expr_to_string(
     cx: &mut ExtCtxt<'_>,
     expr: P<ast::Expr>,
-    err_msg: &str,
+    err_msg: &'static str,
 ) -> Option<(Symbol, ast::StrStyle)> {
     expr_to_spanned_string(cx, expr, err_msg)
         .map_err(|err| {
diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs
index cb8b4899e48..3593bed2d02 100644
--- a/compiler/rustc_expand/src/mbe/diagnostics.rs
+++ b/compiler/rustc_expand/src/mbe/diagnostics.rs
@@ -170,7 +170,7 @@ impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx,
             }
             Error(err_sp, msg) => {
                 let span = err_sp.substitute_dummy(self.root_span);
-                self.cx.struct_span_err(span, msg.as_str()).emit();
+                self.cx.struct_span_err(span, msg.clone()).emit();
                 self.result = Some(DummyResult::any(span));
             }
             ErrorReported(_) => self.result = Some(DummyResult::any(self.root_span)),
@@ -222,7 +222,7 @@ pub(super) fn emit_frag_parse_err(
     {
         let msg = &e.message[0];
         e.message[0] = (
-            DiagnosticMessage::Str(format!(
+            DiagnosticMessage::from(format!(
                 "macro expansion ends with an incomplete expression: {}",
                 message.replace(", found `<eof>`", ""),
             )),
@@ -313,9 +313,9 @@ pub(super) fn annotate_doc_comment(err: &mut Diagnostic, sm: &SourceMap, span: S
 
 /// Generates an appropriate parsing failure message. For EOF, this is "unexpected end...". For
 /// other tokens, this is "unexpected token...".
-pub(super) fn parse_failure_msg(tok: &Token) -> String {
+pub(super) fn parse_failure_msg(tok: &Token) -> Cow<'static, str> {
     match tok.kind {
-        token::Eof => "unexpected end of macro invocation".to_string(),
-        _ => format!("no rules expected the token `{}`", pprust::token_to_string(tok),),
+        token::Eof => Cow::from("unexpected end of macro invocation"),
+        _ => Cow::from(format!("no rules expected the token `{}`", pprust::token_to_string(tok))),
     }
 }
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 5e5c984a7ea..02d1dfcd113 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -1,77 +1,144 @@
-hir_analysis_unrecognized_atomic_operation =
-    unrecognized atomic operation function: `{$op}`
-    .label = unrecognized atomic operation
+hir_analysis_ambiguous_lifetime_bound =
+    ambiguous lifetime bound, explicit lifetime bound required
 
-hir_analysis_wrong_number_of_generic_arguments_to_intrinsic =
-    intrinsic has wrong number of {$descr} parameters: found {$found}, expected {$expected}
-    .label = expected {$expected} {$descr} {$expected ->
-        [one] parameter
-        *[other] parameters
-    }
+hir_analysis_assoc_type_binding_not_allowed =
+    associated type bindings are not allowed here
+    .label = associated type not allowed here
 
-hir_analysis_unrecognized_intrinsic_function =
-    unrecognized intrinsic function: `{$name}`
-    .label = unrecognized intrinsic
+hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the associated type of a trait with uninferred generic parameters
+    .suggestion = use a fully qualified path with inferred lifetimes
 
-hir_analysis_lifetimes_or_bounds_mismatch_on_trait =
-    lifetime parameters or bounds on {$item_kind} `{$ident}` do not match the trait declaration
-    .label = lifetimes do not match {$item_kind} in trait
-    .generics_label = lifetimes in impl do not match this {$item_kind} in trait
-    .where_label = this `where` clause might not match the one in the trait
-    .bounds_label = this bound might be missing in the impl
+hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion = use a fully qualified path with explicit lifetimes
 
 hir_analysis_async_trait_impl_should_be_async =
     method `{$method_name}` should be async because the method from the trait is async
     .trait_item_label = required because the trait method is async
 
+hir_analysis_auto_deref_reached_recursion_limit = reached the recursion limit while auto-dereferencing `{$ty}`
+    .label = deref recursion limit reached
+    .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
+
+hir_analysis_cannot_capture_late_bound_const_in_anon_const =
+    cannot capture late-bound const parameter in a constant
+    .label = parameter defined here
+
+hir_analysis_cannot_capture_late_bound_ty_in_anon_const =
+    cannot capture late-bound type parameter in a constant
+    .label = parameter defined here
+
+hir_analysis_cast_thin_pointer_to_fat_pointer = cannot cast thin pointer `{$expr_ty}` to fat pointer `{$cast_ty}`
+
+hir_analysis_closure_implicit_hrtb = implicit types in closure signatures are forbidden when `for<...>` is present
+    .label = `for<...>` is here
+
+hir_analysis_const_bound_for_non_const_trait =
+    ~const can only be applied to `#[const_trait]` traits
+
+hir_analysis_const_impl_for_non_const_trait =
+    const `impl` for trait `{$trait_name}` which is not marked with `#[const_trait]`
+    .suggestion = mark `{$trait_name}` as const
+    .note = marking a trait with `#[const_trait]` ensures all default method bodies are `const`
+    .adding = adding a non-const method body in the future would be a breaking change
+
+hir_analysis_const_param_ty_impl_on_non_adt =
+    the trait `ConstParamTy` may not be implemented for this type
+    .label = type is not a structure or enumeration
+
+hir_analysis_const_specialize = cannot specialize on const impl with non-const impl
+
+hir_analysis_copy_impl_on_non_adt =
+    the trait `Copy` cannot be implemented for this type
+    .label = type is not a structure or enumeration
+
+hir_analysis_copy_impl_on_type_with_dtor =
+    the trait `Copy` cannot be implemented for this type; the type has a destructor
+    .label = `Copy` not allowed on types with destructors
+
+hir_analysis_drop_impl_negative = negative `Drop` impls are not supported
+
 hir_analysis_drop_impl_on_wrong_item =
     the `Drop` trait may only be implemented for local structs, enums, and unions
     .label = must be a struct, enum, or union in the current crate
 
+hir_analysis_drop_impl_reservation = reservation `Drop` impls are not supported
+
+hir_analysis_empty_specialization = specialization impl does not specialize any associated items
+    .note = impl is a specialization of this impl
+
+hir_analysis_enum_discriminant_overflowed = enum discriminant overflowed
+    .label = overflowed on value after {$discr}
+    .note = explicitly set `{$item_name} = {$wrapped_discr}` if that is desired outcome
+
+hir_analysis_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
+
 hir_analysis_field_already_declared =
     field `{$field_name}` is already declared
     .label = field already declared
     .previous_decl_label = `{$field_name}` first declared here
 
-hir_analysis_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
+hir_analysis_function_not_found_in_trait = function not found in this trait
 
-hir_analysis_const_param_ty_impl_on_non_adt =
-    the trait `ConstParamTy` may not be implemented for this type
-    .label = type is not a structure or enumeration
+hir_analysis_function_not_have_default_implementation = function doesn't have a default implementation
+    .note = required by this annotation
 
-hir_analysis_ambiguous_lifetime_bound =
-    ambiguous lifetime bound, explicit lifetime bound required
+hir_analysis_functions_names_duplicated = functions names are duplicated
+    .note = all `#[rustc_must_implement_one_of]` arguments must be unique
 
-hir_analysis_assoc_type_binding_not_allowed =
-    associated type bindings are not allowed here
-    .label = associated type not allowed here
+hir_analysis_impl_not_marked_default = `{$ident}` specializes an item from a parent `impl`, but that item is not marked `default`
+    .label = cannot specialize default item `{$ident}`
+    .ok_label = parent `impl` is here
+    .note = to specialize, `{$ident}` in the parent `impl` must be marked `default`
 
-hir_analysis_parenthesized_fn_trait_expansion =
-    parenthesized trait syntax expands to `{$expanded_type}`
+hir_analysis_impl_not_marked_default_err = `{$ident}` specializes an item from a parent `impl`, but that item is not marked `default`
+    .note = parent implementation is in crate `{$cname}`
 
-hir_analysis_typeof_reserved_keyword_used =
-    `typeof` is a reserved keyword but unimplemented
-    .suggestion = consider replacing `typeof(...)` with an actual type
-    .label = reserved keyword
+hir_analysis_invalid_union_field =
+    field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union
+    .note = union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>`
 
-hir_analysis_value_of_associated_struct_already_specified =
-    the value of the associated type `{$item_name}` (from trait `{$def_path}`) is already specified
-    .label = re-bound here
-    .previous_bound_label = `{$item_name}` bound here first
+hir_analysis_invalid_union_field_sugg =
+    wrap the field type in `ManuallyDrop<...>`
 
-hir_analysis_unconstrained_opaque_type = unconstrained opaque type
-    .note = `{$name}` must be used in combination with a concrete type within the same {$what}
+hir_analysis_lifetimes_or_bounds_mismatch_on_trait =
+    lifetime parameters or bounds on {$item_kind} `{$ident}` do not match the trait declaration
+    .label = lifetimes do not match {$item_kind} in trait
+    .generics_label = lifetimes in impl do not match this {$item_kind} in trait
+    .where_label = this `where` clause might not match the one in the trait
+    .bounds_label = this bound might be missing in the impl
+
+hir_analysis_linkage_type =
+    invalid type for variable with `#[linkage]` attribute
+
+hir_analysis_main_function_async = `main` function is not allowed to be `async`
+    .label = `main` function is not allowed to be `async`
+
+hir_analysis_main_function_generic_parameters = `main` function is not allowed to have generic parameters
+    .label = `main` cannot have generic parameters
+
+hir_analysis_main_function_return_type_generic = `main` function return type is not allowed to have generic parameters
 
 hir_analysis_manual_implementation =
     manual implementations of `{$trait_name}` are experimental
     .label = manual implementations of `{$trait_name}` are experimental
     .help = add `#![feature(unboxed_closures)]` to the crate attributes to enable
 
-hir_analysis_substs_on_overridden_impl = could not resolve substs on overridden impl
+hir_analysis_missing_one_of_trait_item = not all trait items implemented, missing one of: `{$missing_items_msg}`
+    .label = missing one of `{$missing_items_msg}` in implementation
+    .note = required because of this annotation
 
-hir_analysis_trait_object_declared_with_no_traits =
-    at least one trait is required for an object type
-    .alias_span = this alias does not contain a trait
+hir_analysis_missing_tilde_const = missing `~const` qualifier for specialization
+
+hir_analysis_missing_trait_item = not all trait items implemented, missing: `{$missing_items_msg}`
+    .label = missing `{$missing_items_msg}` in implementation
+
+hir_analysis_missing_trait_item_label = `{$item}` from trait
+
+hir_analysis_missing_trait_item_suggestion = implement the missing item: `{$snippet}`
+
+hir_analysis_missing_trait_item_unstable = not all trait items implemented, missing: `{$missing_item_name}`
+    .note = default implementation of `{$missing_item_name}` is unstable
+    .some_note = use of unstable library feature '{$feature}': {$r}
+    .none_note = use of unstable library feature '{$feature}'
 
 hir_analysis_missing_type_params =
     the type {$parameterCount ->
@@ -95,98 +162,35 @@ hir_analysis_missing_type_params =
     } to {$parameters}
     .note = because of the default `Self` reference, type parameters must be specified on object types
 
-hir_analysis_copy_impl_on_type_with_dtor =
-    the trait `Copy` cannot be implemented for this type; the type has a destructor
-    .label = `Copy` not allowed on types with destructors
-
 hir_analysis_multiple_relaxed_default_bounds =
     type parameter has more than one relaxed default bound, only one is supported
 
-hir_analysis_copy_impl_on_non_adt =
-    the trait `Copy` cannot be implemented for this type
-    .label = type is not a structure or enumeration
-
-hir_analysis_const_impl_for_non_const_trait =
-    const `impl` for trait `{$trait_name}` which is not marked with `#[const_trait]`
-    .suggestion = mark `{$trait_name}` as const
-    .note = marking a trait with `#[const_trait]` ensures all default method bodies are `const`
-    .adding = adding a non-const method body in the future would be a breaking change
-
-hir_analysis_const_bound_for_non_const_trait =
-    ~const can only be applied to `#[const_trait]` traits
-
-hir_analysis_self_in_impl_self =
-    `Self` is not valid in the self type of an impl block
-    .note = replace `Self` with a different type
-
-hir_analysis_linkage_type =
-    invalid type for variable with `#[linkage]` attribute
-
-hir_analysis_auto_deref_reached_recursion_limit = reached the recursion limit while auto-dereferencing `{$ty}`
-    .label = deref recursion limit reached
-    .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
-
-hir_analysis_where_clause_on_main = `main` function is not allowed to have a `where` clause
-    .label = `main` cannot have a `where` clause
-
-hir_analysis_track_caller_on_main = `main` function is not allowed to be `#[track_caller]`
-    .suggestion = remove this annotation
-
-hir_analysis_target_feature_on_main = `main` function is not allowed to have `#[target_feature]`
-
-hir_analysis_start_not_track_caller = `start` is not allowed to be `#[track_caller]`
-    .label = `start` is not allowed to be `#[track_caller]`
-
-hir_analysis_start_not_target_feature = `start` is not allowed to have `#[target_feature]`
-    .label = `start` is not allowed to have `#[target_feature]`
-
-hir_analysis_start_not_async = `start` is not allowed to be `async`
-    .label = `start` is not allowed to be `async`
-
-hir_analysis_start_function_where = start function is not allowed to have a `where` clause
-    .label = start function cannot have a `where` clause
-
-hir_analysis_start_function_parameters = start function is not allowed to have type parameters
-    .label = start function cannot have type parameters
-
-hir_analysis_main_function_return_type_generic = `main` function return type is not allowed to have generic parameters
+hir_analysis_must_be_name_of_associated_function = must be a name of an associated function
 
-hir_analysis_main_function_async = `main` function is not allowed to be `async`
-    .label = `main` function is not allowed to be `async`
+hir_analysis_must_implement_not_function = not a function
 
-hir_analysis_main_function_generic_parameters = `main` function is not allowed to have generic parameters
-    .label = `main` cannot have generic parameters
+hir_analysis_must_implement_not_function_note = all `#[rustc_must_implement_one_of]` arguments must be associated function names
 
-hir_analysis_variadic_function_compatible_convention = C-variadic function must have a compatible calling convention, like {$conventions}
-    .label = C-variadic function must have a compatible calling convention
+hir_analysis_must_implement_not_function_span_note = required by this annotation
 
-hir_analysis_cannot_capture_late_bound_ty_in_anon_const =
-    cannot capture late-bound type parameter in a constant
-    .label = parameter defined here
+hir_analysis_must_implement_one_of_attribute = the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args
 
-hir_analysis_cannot_capture_late_bound_const_in_anon_const =
-    cannot capture late-bound const parameter in a constant
-    .label = parameter defined here
+hir_analysis_paren_sugar_attribute = the `#[rustc_paren_sugar]` attribute is a temporary means of controlling which traits can use parenthetical notation
+    .help = add `#![feature(unboxed_closures)]` to the crate attributes to use it
 
-hir_analysis_variances_of = {$variances_of}
+hir_analysis_parenthesized_fn_trait_expansion =
+    parenthesized trait syntax expands to `{$expanded_type}`
 
 hir_analysis_pass_to_variadic_function = can't pass `{$ty}` to variadic function
     .suggestion = cast the value to `{$cast_ty}`
     .help = cast the value to `{$cast_ty}`
 
-hir_analysis_cast_thin_pointer_to_fat_pointer = cannot cast thin pointer `{$expr_ty}` to fat pointer `{$cast_ty}`
-
-hir_analysis_invalid_union_field =
-    field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union
-    .note = union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>`
-
-hir_analysis_invalid_union_field_sugg =
-    wrap the field type in `ManuallyDrop<...>`
+hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}
+    .label = not allowed in type signatures
 
-hir_analysis_return_type_notation_on_non_rpitit =
-    return type notation used on function that is not `async` and does not return `impl Trait`
-    .note = function returns `{$ty}`, which is not compatible with associated type return bounds
-    .label = this function must be `async` or return `impl Trait`
+hir_analysis_return_type_notation_conflicting_bound =
+    ambiguous associated function `{$assoc_name}` for `{$ty_name}`
+    .note = `{$assoc_name}` is declared in two supertraits: `{$first_bound}` and `{$second_bound}`
 
 hir_analysis_return_type_notation_equality_bound =
     return type notation is not allowed to use type equality
@@ -194,100 +198,96 @@ hir_analysis_return_type_notation_equality_bound =
 hir_analysis_return_type_notation_missing_method =
     cannot find associated function `{$assoc_name}` for `{$ty_name}`
 
-hir_analysis_return_type_notation_conflicting_bound =
-    ambiguous associated function `{$assoc_name}` for `{$ty_name}`
-    .note = `{$assoc_name}` is declared in two supertraits: `{$first_bound}` and `{$second_bound}`
-
-hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}
-    .label = not allowed in type signatures
-
-hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the associated type of a trait with uninferred generic parameters
-    .suggestion = use a fully qualified path with inferred lifetimes
-
-hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion = use a fully qualified path with explicit lifetimes
-
-hir_analysis_enum_discriminant_overflowed = enum discriminant overflowed
-    .label = overflowed on value after {$discr}
-    .note = explicitly set `{$item_name} = {$wrapped_discr}` if that is desired outcome
-
-hir_analysis_paren_sugar_attribute = the `#[rustc_paren_sugar]` attribute is a temporary means of controlling which traits can use parenthetical notation
-    .help = add `#![feature(unboxed_closures)]` to the crate attributes to use it
-
-hir_analysis_must_implement_one_of_attribute = the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args
-
-hir_analysis_must_be_name_of_associated_function = must be a name of an associated function
+hir_analysis_return_type_notation_on_non_rpitit =
+    return type notation used on function that is not `async` and does not return `impl Trait`
+    .note = function returns `{$ty}`, which is not compatible with associated type return bounds
+    .label = this function must be `async` or return `impl Trait`
 
-hir_analysis_function_not_have_default_implementation = function doesn't have a default implementation
-    .note = required by this annotation
+hir_analysis_self_in_impl_self =
+    `Self` is not valid in the self type of an impl block
+    .note = replace `Self` with a different type
 
-hir_analysis_must_implement_not_function = not a function
+hir_analysis_simd_ffi_highly_experimental = use of SIMD type{$snip} in FFI is highly experimental and may result in invalid code
+    .help = add `#![feature(simd_ffi)]` to the crate attributes to enable
 
-hir_analysis_must_implement_not_function_span_note = required by this annotation
+hir_analysis_specialization_trait = implementing `rustc_specialization_trait` traits is unstable
+    .help = add `#![feature(min_specialization)]` to the crate attributes to enable
 
-hir_analysis_must_implement_not_function_note = all `#[rustc_must_implement_one_of]` arguments must be associated function names
+hir_analysis_start_function_parameters = start function is not allowed to have type parameters
+    .label = start function cannot have type parameters
 
-hir_analysis_function_not_found_in_trait = function not found in this trait
+hir_analysis_start_function_where = start function is not allowed to have a `where` clause
+    .label = start function cannot have a `where` clause
 
-hir_analysis_functions_names_duplicated = functions names are duplicated
-    .note = all `#[rustc_must_implement_one_of]` arguments must be unique
+hir_analysis_start_not_async = `start` is not allowed to be `async`
+    .label = `start` is not allowed to be `async`
 
-hir_analysis_simd_ffi_highly_experimental = use of SIMD type{$snip} in FFI is highly experimental and may result in invalid code
-    .help = add `#![feature(simd_ffi)]` to the crate attributes to enable
+hir_analysis_start_not_target_feature = `start` is not allowed to have `#[target_feature]`
+    .label = `start` is not allowed to have `#[target_feature]`
 
-hir_analysis_impl_not_marked_default = `{$ident}` specializes an item from a parent `impl`, but that item is not marked `default`
-    .label = cannot specialize default item `{$ident}`
-    .ok_label = parent `impl` is here
-    .note = to specialize, `{$ident}` in the parent `impl` must be marked `default`
+hir_analysis_start_not_track_caller = `start` is not allowed to be `#[track_caller]`
+    .label = `start` is not allowed to be `#[track_caller]`
 
-hir_analysis_impl_not_marked_default_err = `{$ident}` specializes an item from a parent `impl`, but that item is not marked `default`
-    .note = parent implementation is in crate `{$cname}`
+hir_analysis_static_specialize = cannot specialize on `'static` lifetime
 
-hir_analysis_missing_trait_item = not all trait items implemented, missing: `{$missing_items_msg}`
-    .label = missing `{$missing_items_msg}` in implementation
+hir_analysis_substs_on_overridden_impl = could not resolve substs on overridden impl
 
-hir_analysis_missing_trait_item_suggestion = implement the missing item: `{$snippet}`
+hir_analysis_target_feature_on_main = `main` function is not allowed to have `#[target_feature]`
 
-hir_analysis_missing_trait_item_label = `{$item}` from trait
+hir_analysis_too_large_static = extern static is too large for the current architecture
 
-hir_analysis_missing_one_of_trait_item = not all trait items implemented, missing one of: `{$missing_items_msg}`
-    .label = missing one of `{$missing_items_msg}` in implementation
-    .note = required because of this annotation
+hir_analysis_track_caller_on_main = `main` function is not allowed to be `#[track_caller]`
+    .suggestion = remove this annotation
 
-hir_analysis_missing_trait_item_unstable = not all trait items implemented, missing: `{$missing_item_name}`
-    .note = default implementation of `{$missing_item_name}` is unstable
-    .some_note = use of unstable library feature '{$feature}': {$r}
-    .none_note = use of unstable library feature '{$feature}'
+hir_analysis_trait_object_declared_with_no_traits =
+    at least one trait is required for an object type
+    .alias_span = this alias does not contain a trait
 
 hir_analysis_transparent_enum_variant = transparent enum needs exactly one variant, but has {$number}
     .label = needs exactly one variant, but has {$number}
     .many_label = too many variants in `{$path}`
     .multi_label = variant here
 
-hir_analysis_transparent_non_zero_sized_enum = the variant of a transparent {$desc} needs at most one non-zero-sized field, but has {$field_count}
+hir_analysis_transparent_non_zero_sized = transparent {$desc} needs at most one non-zero-sized field, but has {$field_count}
     .label = needs at most one non-zero-sized field, but has {$field_count}
     .labels = this field is non-zero-sized
 
-hir_analysis_transparent_non_zero_sized = transparent {$desc} needs at most one non-zero-sized field, but has {$field_count}
+hir_analysis_transparent_non_zero_sized_enum = the variant of a transparent {$desc} needs at most one non-zero-sized field, but has {$field_count}
     .label = needs at most one non-zero-sized field, but has {$field_count}
     .labels = this field is non-zero-sized
 
-hir_analysis_too_large_static = extern static is too large for the current architecture
+hir_analysis_typeof_reserved_keyword_used =
+    `typeof` is a reserved keyword but unimplemented
+    .suggestion = consider replacing `typeof(...)` with an actual type
+    .label = reserved keyword
 
-hir_analysis_specialization_trait = implementing `rustc_specialization_trait` traits is unstable
-    .help = add `#![feature(min_specialization)]` to the crate attributes to enable
+hir_analysis_unconstrained_opaque_type = unconstrained opaque type
+    .note = `{$name}` must be used in combination with a concrete type within the same {$what}
 
-hir_analysis_closure_implicit_hrtb = implicit types in closure signatures are forbidden when `for<...>` is present
-    .label = `for<...>` is here
+hir_analysis_unrecognized_atomic_operation =
+    unrecognized atomic operation function: `{$op}`
+    .label = unrecognized atomic operation
 
-hir_analysis_empty_specialization = specialization impl does not specialize any associated items
-    .note = impl is a specialization of this impl
+hir_analysis_unrecognized_intrinsic_function =
+    unrecognized intrinsic function: `{$name}`
+    .label = unrecognized intrinsic
 
-hir_analysis_const_specialize = cannot specialize on const impl with non-const impl
+hir_analysis_value_of_associated_struct_already_specified =
+    the value of the associated type `{$item_name}` (from trait `{$def_path}`) is already specified
+    .label = re-bound here
+    .previous_bound_label = `{$item_name}` bound here first
 
-hir_analysis_static_specialize = cannot specialize on `'static` lifetime
+hir_analysis_variadic_function_compatible_convention = C-variadic function must have a compatible calling convention, like {$conventions}
+    .label = C-variadic function must have a compatible calling convention
 
-hir_analysis_missing_tilde_const = missing `~const` qualifier for specialization
+hir_analysis_variances_of = {$variances_of}
 
-hir_analysis_drop_impl_negative = negative `Drop` impls are not supported
+hir_analysis_where_clause_on_main = `main` function is not allowed to have a `where` clause
+    .label = `main` cannot have a `where` clause
 
-hir_analysis_drop_impl_reservation = reservation `Drop` impls are not supported
+hir_analysis_wrong_number_of_generic_arguments_to_intrinsic =
+    intrinsic has wrong number of {$descr} parameters: found {$found}, expected {$expected}
+    .label = expected {$expected} {$descr} {$expected ->
+        [one] parameter
+        *[other] parameters
+    }
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 5fb06cf9465..3d78ea9aa9b 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -239,7 +239,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     var: ty::BoundVar::from_u32(index),
                     kind: ty::BrNamed(def_id, name),
                 };
-                tcx.mk_re_late_bound(debruijn, br)
+                ty::Region::new_late_bound(tcx, debruijn, br)
             }
 
             Some(rbv::ResolvedArg::EarlyBound(def_id)) => {
@@ -247,12 +247,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 let item_def_id = tcx.hir().ty_param_owner(def_id.expect_local());
                 let generics = tcx.generics_of(item_def_id);
                 let index = generics.param_def_id_to_index[&def_id];
-                tcx.mk_re_early_bound(ty::EarlyBoundRegion { def_id, index, name })
+                ty::Region::new_early_bound(tcx, ty::EarlyBoundRegion { def_id, index, name })
             }
 
             Some(rbv::ResolvedArg::Free(scope, id)) => {
                 let name = lifetime_name(id.expect_local());
-                tcx.mk_re_free(scope, ty::BrNamed(id, name))
+                ty::Region::new_free(tcx, scope, ty::BrNamed(id, name))
 
                 // (*) -- not late-bound, won't change
             }
@@ -269,7 +269,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     // elision. `resolve_lifetime` should have
                     // reported an error in this case -- but if
                     // not, let's error out.
-                    tcx.mk_re_error_with_message(
+                    ty::Region::new_error_with_message(
+                        tcx,
                         lifetime.ident.span,
                         "unelided lifetime in signature",
                     )
@@ -485,7 +486,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                             debug!(?param, "unelided lifetime in signature");
 
                             // This indicates an illegal lifetime in a non-assoc-trait position
-                            tcx.mk_re_error_with_message(
+                            ty::Region::new_error_with_message(
+                                tcx,
                                 self.span,
                                 "unelided lifetime in signature",
                             )
@@ -1159,7 +1161,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             // those that do.
             self.one_bound_for_assoc_type(
                 || traits::supertraits(tcx, trait_ref),
-                trait_ref.print_only_trait_path(),
+                trait_ref.skip_binder().print_only_trait_name(),
                 binding.item_name,
                 path_span,
                 match binding.kind {
@@ -1219,15 +1221,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             let substs =
                 candidate.skip_binder().substs.extend_to(tcx, assoc_item.def_id, |param, _| {
                     let subst = match param.kind {
-                        GenericParamDefKind::Lifetime => tcx
-                            .mk_re_late_bound(
-                                ty::INNERMOST,
-                                ty::BoundRegion {
-                                    var: ty::BoundVar::from_usize(num_bound_vars),
-                                    kind: ty::BoundRegionKind::BrNamed(param.def_id, param.name),
-                                },
-                            )
-                            .into(),
+                        GenericParamDefKind::Lifetime => ty::Region::new_late_bound(
+                            tcx,
+                            ty::INNERMOST,
+                            ty::BoundRegion {
+                                var: ty::BoundVar::from_usize(num_bound_vars),
+                                kind: ty::BoundRegionKind::BrNamed(param.def_id, param.name),
+                            },
+                        )
+                        .into(),
                         GenericParamDefKind::Type { .. } => tcx
                             .mk_bound(
                                 ty::INNERMOST,
@@ -1278,7 +1280,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             // params (and trait ref's late bound params). This logic is very similar to
             // `Predicate::subst_supertrait`, and it's no coincidence why.
             let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output);
-            let subst_output = ty::EarlyBinder(shifted_output).subst(tcx, substs);
+            let subst_output = ty::EarlyBinder::bind(shifted_output).subst(tcx, substs);
 
             let bound_vars = tcx.late_bound_vars(binding.hir_id);
             ty::Binder::bind_with_vars(subst_output, bound_vars)
@@ -1804,7 +1806,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         } else {
                             err.emit()
                         };
-                        tcx.mk_re_error(e)
+                        ty::Region::new_error(tcx, e)
                     })
                 }
             })
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 8bf1e0e84a4..31b89525f15 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -25,6 +25,7 @@ use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
 use rustc_trait_selection::traits::{
     self, ObligationCause, ObligationCauseCode, ObligationCtxt, Reveal,
 };
+use std::borrow::Cow;
 use std::iter;
 
 /// Checks that a method from an impl conforms to the signature of
@@ -471,7 +472,8 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RemapLateBound<'_, 'tcx> {
 
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         if let ty::ReFree(fr) = *r {
-            self.tcx.mk_re_free(
+            ty::Region::new_free(
+                self.tcx,
                 fr.scope,
                 self.mapping.get(&fr.bound_region).copied().unwrap_or(fr.bound_region),
             )
@@ -684,7 +686,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
                 &cause,
                 hir.get_if_local(impl_m.def_id)
                     .and_then(|node| node.fn_decl())
-                    .map(|decl| (decl.output.span(), "return type in trait".to_owned())),
+                    .map(|decl| (decl.output.span(), Cow::from("return type in trait"))),
                 Some(infer::ValuePairs::Terms(ExpectedFound {
                     expected: trait_return_ty.into(),
                     found: impl_return_ty.into(),
@@ -785,23 +787,23 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
                     }
                     let Some(ty::ReEarlyBound(e)) = map.get(&region.into()).map(|r| r.expect_region().kind())
                     else {
-                        return tcx.mk_re_error_with_message(return_span, "expected ReFree to map to ReEarlyBound")
+                        return ty::Region::new_error_with_message(tcx, return_span, "expected ReFree to map to ReEarlyBound")
                     };
-                    tcx.mk_re_early_bound(ty::EarlyBoundRegion {
+                    ty::Region::new_early_bound(tcx, ty::EarlyBoundRegion {
                         def_id: e.def_id,
                         name: e.name,
                         index: (e.index as usize - num_trait_substs + num_impl_substs) as u32,
                     })
                 });
                 debug!(%ty);
-                collected_tys.insert(def_id, ty::EarlyBinder(ty));
+                collected_tys.insert(def_id, ty::EarlyBinder::bind(ty));
             }
             Err(err) => {
                 let reported = tcx.sess.delay_span_bug(
                     return_span,
                     format!("could not fully resolve: {ty} => {err:?}"),
                 );
-                collected_tys.insert(def_id, ty::EarlyBinder(tcx.ty_error(reported)));
+                collected_tys.insert(def_id, ty::EarlyBinder::bind(tcx.ty_error(reported)));
             }
         }
     }
@@ -901,7 +903,7 @@ fn report_trait_method_mismatch<'tcx>(
             if trait_m.fn_has_self_parameter =>
         {
             let ty = trait_sig.inputs()[0];
-            let sugg = match ExplicitSelf::determine(ty, |_| ty == impl_trait_ref.self_ty()) {
+            let sugg = match ExplicitSelf::determine(ty, |ty| ty == impl_trait_ref.self_ty()) {
                 ExplicitSelf::ByValue => "self".to_owned(),
                 ExplicitSelf::ByReference(_, hir::Mutability::Not) => "&self".to_owned(),
                 ExplicitSelf::ByReference(_, hir::Mutability::Mut) => "&mut self".to_owned(),
@@ -963,7 +965,7 @@ fn report_trait_method_mismatch<'tcx>(
     infcx.err_ctxt().note_type_err(
         &mut diag,
         &cause,
-        trait_err_span.map(|sp| (sp, "type in trait".to_owned())),
+        trait_err_span.map(|sp| (sp, Cow::from("type in trait"))),
         Some(infer::ValuePairs::Sigs(ExpectedFound { expected: trait_sig, found: impl_sig })),
         terr,
         false,
@@ -1731,7 +1733,7 @@ pub(super) fn compare_impl_const_raw(
         infcx.err_ctxt().note_type_err(
             &mut diag,
             &cause,
-            trait_c_span.map(|span| (span, "type in trait".to_owned())),
+            trait_c_span.map(|span| (span, Cow::from("type in trait"))),
             Some(infer::ValuePairs::Terms(ExpectedFound {
                 expected: trait_ty.into(),
                 found: impl_ty.into(),
@@ -1932,7 +1934,8 @@ pub(super) fn check_type_bounds<'tcx>(
                 let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name);
                 let bound_var = ty::BoundVariableKind::Region(kind);
                 bound_vars.push(bound_var);
-                tcx.mk_re_late_bound(
+                ty::Region::new_late_bound(
+                    tcx,
                     ty::INNERMOST,
                     ty::BoundRegion { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind },
                 )
diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs
index e0ba255cc06..13d1abe2a65 100644
--- a/compiler/rustc_hir_analysis/src/check/dropck.rs
+++ b/compiler/rustc_hir_analysis/src/check/dropck.rs
@@ -128,7 +128,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
     // We don't need to normalize this param-env or anything, since we're only
     // substituting it with free params, so no additional param-env normalization
     // can occur on top of what has been done in the param_env query itself.
-    let param_env = ty::EarlyBinder(tcx.param_env(adt_def_id))
+    let param_env = ty::EarlyBinder::bind(tcx.param_env(adt_def_id))
         .subst(tcx, adt_to_impl_substs)
         .with_constness(tcx.constness(drop_impl_def_id));
 
@@ -183,7 +183,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
                 }
                 RegionResolutionError::SubSupConflict(_, _, _, a, _, b, _) => format!("{b}: {a}"),
                 RegionResolutionError::UpperBoundUniverseConflict(a, _, _, _, b) => {
-                    format!("{b}: {a}", a = tcx.mk_re_var(a))
+                    format!("{b}: {a}", a = ty::Region::new_var(tcx, a))
                 }
             };
             guar = Some(
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index e8785235c83..1f18017f00b 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -121,10 +121,11 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: DefId) -> hir
     if has_safe_attr != is_in_list {
         tcx.sess.struct_span_err(
             tcx.def_span(intrinsic_id),
-            DiagnosticMessage::Str(format!(
-                    "intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `{}`",
-                    tcx.item_name(intrinsic_id)
-        ))).emit();
+            DiagnosticMessage::from(format!(
+                "intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `{}`",
+                tcx.item_name(intrinsic_id)
+            )
+        )).emit();
     }
 
     is_in_list
@@ -144,11 +145,13 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
     ]);
     let mk_va_list_ty = |mutbl| {
         tcx.lang_items().va_list().map(|did| {
-            let region = tcx.mk_re_late_bound(
+            let region = ty::Region::new_late_bound(
+                tcx,
                 ty::INNERMOST,
                 ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(None) },
             );
-            let env_region = tcx.mk_re_late_bound(
+            let env_region = ty::Region::new_late_bound(
+                tcx,
                 ty::INNERMOST,
                 ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrEnv },
             );
@@ -392,7 +395,12 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
                 let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(None) };
                 (
                     1,
-                    vec![tcx.mk_imm_ref(tcx.mk_re_late_bound(ty::INNERMOST, br), param(0))],
+                    vec![
+                        tcx.mk_imm_ref(
+                            ty::Region::new_late_bound(tcx, ty::INNERMOST, br),
+                            param(0),
+                        ),
+                    ],
                     tcx.mk_projection(discriminant_def_id, tcx.mk_substs(&[param(0).into()])),
                 )
             }
@@ -442,7 +450,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
 
             sym::raw_eq => {
                 let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(None) };
-                let param_ty = tcx.mk_imm_ref(tcx.mk_re_late_bound(ty::INNERMOST, br), param(0));
+                let param_ty =
+                    tcx.mk_imm_ref(ty::Region::new_late_bound(tcx, ty::INNERMOST, br), param(0));
                 (1, vec![param_ty; 2], tcx.types.bool)
             }
 
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index b403ee96b42..fff417fcb29 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -556,11 +556,14 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
                 // Same for the region. In our example, 'a corresponds
                 // to the 'me parameter.
                 let region_param = gat_generics.param_at(*region_a_idx, tcx);
-                let region_param = tcx.mk_re_early_bound(ty::EarlyBoundRegion {
-                    def_id: region_param.def_id,
-                    index: region_param.index,
-                    name: region_param.name,
-                });
+                let region_param = ty::Region::new_early_bound(
+                    tcx,
+                    ty::EarlyBoundRegion {
+                        def_id: region_param.def_id,
+                        index: region_param.index,
+                        name: region_param.name,
+                    },
+                );
                 // The predicate we expect to see. (In our example,
                 // `Self: 'me`.)
                 let clause = ty::PredicateKind::Clause(ty::Clause::TypeOutlives(
@@ -593,18 +596,24 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
                 debug!("required clause: {region_a} must outlive {region_b}");
                 // Translate into the generic parameters of the GAT.
                 let region_a_param = gat_generics.param_at(*region_a_idx, tcx);
-                let region_a_param = tcx.mk_re_early_bound(ty::EarlyBoundRegion {
-                    def_id: region_a_param.def_id,
-                    index: region_a_param.index,
-                    name: region_a_param.name,
-                });
+                let region_a_param = ty::Region::new_early_bound(
+                    tcx,
+                    ty::EarlyBoundRegion {
+                        def_id: region_a_param.def_id,
+                        index: region_a_param.index,
+                        name: region_a_param.name,
+                    },
+                );
                 // Same for the region.
                 let region_b_param = gat_generics.param_at(*region_b_idx, tcx);
-                let region_b_param = tcx.mk_re_early_bound(ty::EarlyBoundRegion {
-                    def_id: region_b_param.def_id,
-                    index: region_b_param.index,
-                    name: region_b_param.name,
-                });
+                let region_b_param = ty::Region::new_early_bound(
+                    tcx,
+                    ty::EarlyBoundRegion {
+                        def_id: region_b_param.def_id,
+                        index: region_b_param.index,
+                        name: region_b_param.name,
+                    },
+                );
                 // The predicate we expect to see.
                 let clause = ty::PredicateKind::Clause(ty::Clause::RegionOutlives(
                     ty::OutlivesPredicate(region_a_param, region_b_param),
@@ -1398,7 +1407,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
             }
             let mut param_count = CountParams::default();
             let has_region = pred.visit_with(&mut param_count).is_break();
-            let substituted_pred = ty::EarlyBinder(pred).subst(tcx, substs);
+            let substituted_pred = ty::EarlyBinder::bind(pred).subst(tcx, substs);
             // Don't check non-defaulted params, dependent defaults (including lifetimes)
             // or preds with multiple params.
             if substituted_pred.has_non_region_param() || param_count.params.len() > 1 || has_region
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index ca0d5509c57..2f7d465839c 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -440,7 +440,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
                                     self.tcx.replace_late_bound_regions_uncached(
                                         poly_trait_ref,
                                         |_| {
-                                            self.tcx.mk_re_early_bound(ty::EarlyBoundRegion {
+                                            ty::Region::new_early_bound(self.tcx, ty::EarlyBoundRegion {
                                                 def_id: item_def_id,
                                                 index: 0,
                                                 name: Symbol::intern(&lt_name),
@@ -1124,7 +1124,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<ty::PolyFnSig<
             bug!("unexpected sort of node in fn_sig(): {:?}", x);
         }
     };
-    ty::EarlyBinder(output)
+    ty::EarlyBinder::bind(output)
 }
 
 fn infer_return_ty_for_fn_sig<'tcx>(
@@ -1312,7 +1312,7 @@ fn impl_trait_ref(
                 check_impl_constness(tcx, impl_.constness, ast_trait_ref),
             )
         })
-        .map(ty::EarlyBinder)
+        .map(ty::EarlyBinder::bind)
 }
 
 fn check_impl_constness(
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index 948b903e509..b92d561fb86 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -86,7 +86,7 @@ pub(super) fn explicit_item_bounds(
         Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
             let item = tcx.hir().get_by_def_id(opaque_def_id.expect_local()).expect_item();
             let opaque_ty = item.expect_opaque_ty();
-            return ty::EarlyBinder(opaque_type_bounds(
+            return ty::EarlyBinder::bind(opaque_type_bounds(
                 tcx,
                 opaque_def_id.expect_local(),
                 opaque_ty.bounds,
@@ -124,7 +124,7 @@ pub(super) fn explicit_item_bounds(
         }
         _ => bug!("item_bounds called on {:?}", def_id),
     };
-    ty::EarlyBinder(bounds)
+    ty::EarlyBinder::bind(bounds)
 }
 
 pub(super) fn item_bounds(
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index e5b5dae551e..70d950eddd8 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -306,11 +306,14 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
 
             let Some(dup_index) = generics.param_def_id_to_index(tcx, dup_def) else { bug!() };
 
-            let dup_region = tcx.mk_re_early_bound(ty::EarlyBoundRegion {
-                def_id: dup_def,
-                index: dup_index,
-                name: duplicate.name.ident().name,
-            });
+            let dup_region = ty::Region::new_early_bound(
+                tcx,
+                ty::EarlyBoundRegion {
+                    def_id: dup_def,
+                    index: dup_index,
+                    name: duplicate.name.ident().name,
+                },
+            );
             predicates.push((
                 ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::RegionOutlives(
                     ty::OutlivesPredicate(orig_region, dup_region),
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 8e082d3c532..65ab00fda81 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -323,7 +323,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
                 return map[&assoc_item.trait_item_def_id.unwrap()];
             }
             Err(_) => {
-                return ty::EarlyBinder(tcx.ty_error_with_message(
+                return ty::EarlyBinder::bind(tcx.ty_error_with_message(
                     DUMMY_SP,
                     "Could not collect return position impl trait in trait tys",
                 ));
@@ -497,7 +497,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
             bug!("unexpected sort of node in type_of(): {:?}", x);
         }
     };
-    ty::EarlyBinder(output)
+    ty::EarlyBinder::bind(output)
 }
 
 fn infer_placeholder_type<'a>(
diff --git a/compiler/rustc_hir_analysis/src/outlives/explicit.rs b/compiler/rustc_hir_analysis/src/outlives/explicit.rs
index 357deb07b8f..7ce48fe1c01 100644
--- a/compiler/rustc_hir_analysis/src/outlives/explicit.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/explicit.rs
@@ -68,7 +68,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> {
                 }
             }
 
-            ty::EarlyBinder(required_predicates)
+            ty::EarlyBinder::bind(required_predicates)
         })
     }
 }
diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
index 0cd2fc1aa29..71dca918fc5 100644
--- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
@@ -68,12 +68,13 @@ pub(super) fn infer_predicates(
             // Therefore mark `predicates_added` as true and which will ensure
             // we walk the crates again and re-calculate predicates for all
             // items.
-            let item_predicates_len: usize =
-                global_inferred_outlives.get(&item_did.to_def_id()).map_or(0, |p| p.0.len());
+            let item_predicates_len: usize = global_inferred_outlives
+                .get(&item_did.to_def_id())
+                .map_or(0, |p| p.as_ref().skip_binder().len());
             if item_required_predicates.len() > item_predicates_len {
                 predicates_added = true;
                 global_inferred_outlives
-                    .insert(item_did.to_def_id(), ty::EarlyBinder(item_required_predicates));
+                    .insert(item_did.to_def_id(), ty::EarlyBinder::bind(item_required_predicates));
             }
         }
 
@@ -137,7 +138,9 @@ fn insert_required_predicates_to_be_wf<'tcx>(
                 // 'a` holds for `Foo`.
                 debug!("Adt");
                 if let Some(unsubstituted_predicates) = global_inferred_outlives.get(&def.did()) {
-                    for (unsubstituted_predicate, &span) in &unsubstituted_predicates.0 {
+                    for (unsubstituted_predicate, &span) in
+                        unsubstituted_predicates.as_ref().skip_binder()
+                    {
                         // `unsubstituted_predicate` is `U: 'b` in the
                         // example above. So apply the substitution to
                         // get `T: 'a` (or `predicate`):
@@ -251,7 +254,7 @@ fn check_explicit_predicates<'tcx>(
     );
     let explicit_predicates = explicit_map.explicit_predicates_of(tcx, def_id);
 
-    for (outlives_predicate, &span) in &explicit_predicates.0 {
+    for (outlives_predicate, &span) in explicit_predicates.as_ref().skip_binder() {
         debug!("outlives_predicate = {:?}", &outlives_predicate);
 
         // Careful: If we are inferring the effects of a `dyn Trait<..>`
diff --git a/compiler/rustc_hir_analysis/src/outlives/mod.rs b/compiler/rustc_hir_analysis/src/outlives/mod.rs
index a8596c707f3..2106d6ff07d 100644
--- a/compiler/rustc_hir_analysis/src/outlives/mod.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/mod.rs
@@ -98,24 +98,27 @@ fn inferred_outlives_crate(tcx: TyCtxt<'_>, (): ()) -> CratePredicatesMap<'_> {
     let predicates = global_inferred_outlives
         .iter()
         .map(|(&def_id, set)| {
-            let predicates = &*tcx.arena.alloc_from_iter(set.0.iter().filter_map(
-                |(ty::OutlivesPredicate(kind1, region2), &span)| {
-                    match kind1.unpack() {
-                        GenericArgKind::Type(ty1) => Some((
-                            ty::Clause::TypeOutlives(ty::OutlivesPredicate(ty1, *region2)),
-                            span,
-                        )),
-                        GenericArgKind::Lifetime(region1) => Some((
-                            ty::Clause::RegionOutlives(ty::OutlivesPredicate(region1, *region2)),
-                            span,
-                        )),
-                        GenericArgKind::Const(_) => {
-                            // Generic consts don't impose any constraints.
-                            None
+            let predicates =
+                &*tcx.arena.alloc_from_iter(set.as_ref().skip_binder().iter().filter_map(
+                    |(ty::OutlivesPredicate(kind1, region2), &span)| {
+                        match kind1.unpack() {
+                            GenericArgKind::Type(ty1) => Some((
+                                ty::Clause::TypeOutlives(ty::OutlivesPredicate(ty1, *region2)),
+                                span,
+                            )),
+                            GenericArgKind::Lifetime(region1) => Some((
+                                ty::Clause::RegionOutlives(ty::OutlivesPredicate(
+                                    region1, *region2,
+                                )),
+                                span,
+                            )),
+                            GenericArgKind::Const(_) => {
+                                // Generic consts don't impose any constraints.
+                                None
+                            }
                         }
-                    }
-                },
-            ));
+                    },
+                ));
             (def_id, predicates)
         })
         .collect();
diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl
index 4a669e3f8b8..aab432eee57 100644
--- a/compiler/rustc_hir_typeck/messages.ftl
+++ b/compiler/rustc_hir_typeck/messages.ftl
@@ -1,92 +1,94 @@
-hir_typeck_field_multiply_specified_in_initializer =
-    field `{$ident}` specified more than once
-    .label = used more than once
-    .previous_use_label = first use of `{$ident}`
+hir_typeck_add_missing_parentheses_in_range = you must surround the range in parentheses to call its `{$func_name}` function
 
-hir_typeck_functional_record_update_on_non_struct =
-    functional record update syntax requires a struct
+hir_typeck_add_return_type_add = try adding a return type
 
-hir_typeck_return_stmt_outside_of_fn_body =
-    return statement outside of function body
-    .encl_body_label = the return is part of this body...
-    .encl_fn_label = ...not the enclosing function body
+hir_typeck_add_return_type_missing_here = a return type might be missing here
 
-hir_typeck_yield_expr_outside_of_generator =
-    yield expression outside of generator literal
+hir_typeck_address_of_temporary_taken = cannot take address of a temporary
+    .label = temporary value
 
-hir_typeck_struct_expr_non_exhaustive =
-    cannot create non-exhaustive {$what} using struct expression
+hir_typeck_arg_mismatch_indeterminate = argument type mismatch was detected, but rustc had trouble determining where
+    .note = we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new
 
-hir_typeck_method_call_on_unknown_type =
-    the type of this value must be known to call a method on a raw pointer on it
+hir_typeck_candidate_trait_note = `{$trait_name}` defines an item `{$item_name}`{$action_or_ty ->
+    [NONE] {""}
+    [implement] , perhaps you need to implement it
+    *[other] , perhaps you need to restrict type parameter `{$action_or_ty}` with it
+}
 
-hir_typeck_address_of_temporary_taken = cannot take address of a temporary
-    .label = temporary value
+hir_typeck_const_select_must_be_const = this argument must be a `const fn`
+    .help = consult the documentation on `const_eval_select` for more information
 
-hir_typeck_add_return_type_add = try adding a return type
+hir_typeck_const_select_must_be_fn = this argument must be a function item
+    .note = expected a function item, found {$ty}
+    .help = consult the documentation on `const_eval_select` for more information
 
-hir_typeck_add_return_type_missing_here = a return type might be missing here
+hir_typeck_convert_to_str = try converting the passed type into a `&str`
+
+hir_typeck_ctor_is_private = tuple struct constructor `{$def}` is private
 
 hir_typeck_expected_default_return_type = expected `()` because of default return type
 
 hir_typeck_expected_return_type = expected `{$expected}` because of return type
 
-hir_typeck_missing_parentheses_in_range = can't call method `{$method_name}` on type `{$ty_str}`
+hir_typeck_field_multiply_specified_in_initializer =
+    field `{$ident}` specified more than once
+    .label = used more than once
+    .previous_use_label = first use of `{$ident}`
 
-hir_typeck_add_missing_parentheses_in_range = you must surround the range in parentheses to call its `{$func_name}` function
+hir_typeck_fru_expr = this expression does not end in a comma...
+hir_typeck_fru_expr2 = ... so this is interpreted as a `..` range expression, instead of functional record update syntax
+hir_typeck_fru_note = this expression may have been misinterpreted as a `..` range expression
+hir_typeck_fru_suggestion =
+    to set the remaining fields{$expr ->
+        [NONE]{""}
+        *[other] {" "}from `{$expr}`
+    }, separate the last named field with a comma
 
-hir_typeck_lang_start_incorrect_number_params = incorrect number of parameters for the `start` lang item
-hir_typeck_lang_start_incorrect_number_params_note_expected_count = the `start` lang item should have four parameters, but found {$found_param_count}
+hir_typeck_functional_record_update_on_non_struct =
+    functional record update syntax requires a struct
 
+hir_typeck_help_set_edition_cargo = set `edition = "{$edition}"` in `Cargo.toml`
+hir_typeck_help_set_edition_standalone = pass `--edition {$edition}` to `rustc`
 hir_typeck_lang_start_expected_sig_note = the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize`
 
+hir_typeck_lang_start_incorrect_number_params = incorrect number of parameters for the `start` lang item
+hir_typeck_lang_start_incorrect_number_params_note_expected_count = the `start` lang item should have four parameters, but found {$found_param_count}
+
 hir_typeck_lang_start_incorrect_param = parameter {$param_num} of the `start` lang item is incorrect
     .suggestion = change the type from `{$found_ty}` to `{$expected_ty}`
 
 hir_typeck_lang_start_incorrect_ret_ty = the return type of the `start` lang item is incorrect
     .suggestion = change the type from `{$found_ty}` to `{$expected_ty}`
 
-hir_typeck_help_set_edition_cargo = set `edition = "{$edition}"` in `Cargo.toml`
-hir_typeck_help_set_edition_standalone = pass `--edition {$edition}` to `rustc`
-hir_typeck_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide
-
-hir_typeck_convert_to_str = try converting the passed type into a `&str`
+hir_typeck_method_call_on_unknown_raw_pointee =
+    cannot call a method on a raw pointer with an unknown pointee type
 
-hir_typeck_op_trait_generic_params = `{$method_name}` must not have any generic parameters
+hir_typeck_missing_parentheses_in_range = can't call method `{$method_name}` on type `{$ty_str}`
 
-hir_typeck_fru_note = this expression may have been misinterpreted as a `..` range expression
-hir_typeck_fru_expr = this expression does not end in a comma...
-hir_typeck_fru_expr2 = ... so this is interpreted as a `..` range expression, instead of functional record update syntax
-hir_typeck_fru_suggestion =
-    to set the remaining fields{$expr ->
-        [NONE]{""}
-        *[other] {" "}from `{$expr}`
-    }, separate the last named field with a comma
+hir_typeck_no_associated_item = no {$item_kind} named `{$item_name}` found for {$ty_prefix} `{$ty_str}`{$trait_missing_method ->
+    [true] {""}
+    *[other] {" "}in the current scope
+}
 
-hir_typeck_const_select_must_be_const = this argument must be a `const fn`
-    .help = consult the documentation on `const_eval_select` for more information
+hir_typeck_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide
 
-hir_typeck_const_select_must_be_fn = this argument must be a function item
-    .note = expected a function item, found {$ty}
-    .help = consult the documentation on `const_eval_select` for more information
+hir_typeck_op_trait_generic_params = `{$method_name}` must not have any generic parameters
 
-hir_typeck_union_pat_multiple_fields = union patterns should have exactly one field
-hir_typeck_union_pat_dotdot = `..` cannot be used in union patterns
+hir_typeck_return_stmt_outside_of_fn_body =
+    return statement outside of function body
+    .encl_body_label = the return is part of this body...
+    .encl_fn_label = ...not the enclosing function body
 
-hir_typeck_arg_mismatch_indeterminate = argument type mismatch was detected, but rustc had trouble determining where
-    .note = we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new
+hir_typeck_struct_expr_non_exhaustive =
+    cannot create non-exhaustive {$what} using struct expression
 
 hir_typeck_suggest_boxing_note = for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
 
 hir_typeck_suggest_boxing_when_appropriate = store this in the heap by calling `Box::new`
 
-hir_typeck_no_associated_item = no {$item_kind} named `{$item_name}` found for {$ty_prefix} `{$ty_str}`{$trait_missing_method ->
-    [true] {""}
-    *[other] {" "}in the current scope
-}
+hir_typeck_union_pat_dotdot = `..` cannot be used in union patterns
 
-hir_typeck_candidate_trait_note = `{$trait_name}` defines an item `{$item_name}`{$action_or_ty ->
-    [NONE] {""}
-    [implement] , perhaps you need to implement it
-    *[other] , perhaps you need to restrict type parameter `{$action_or_ty}` with it
-}
+hir_typeck_union_pat_multiple_fields = union patterns should have exactly one field
+hir_typeck_yield_expr_outside_of_generator =
+    yield expression outside of generator literal
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index 655ab94eb48..4389ad6ef26 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -420,20 +420,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         .steal_diagnostic(segment.ident.span, StashKey::CallIntoMethod)
                 {
                     // Try suggesting `foo(a)` -> `a.foo()` if possible.
-                    if let Some(ty) =
-                        self.suggest_call_as_method(
-                            &mut diag,
-                            segment,
-                            arg_exprs,
-                            call_expr,
-                            expected
-                        )
-                    {
-                        diag.emit();
-                        return ty;
-                    } else {
-                        diag.emit();
-                    }
+                    self.suggest_call_as_method(
+                        &mut diag,
+                        segment,
+                        arg_exprs,
+                        call_expr,
+                        expected
+                    );
+                    diag.emit();
                 }
 
                 let err = self.report_invalid_callee(call_expr, callee_expr, callee_ty, arg_exprs);
@@ -496,9 +490,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         arg_exprs: &'tcx [hir::Expr<'tcx>],
         call_expr: &'tcx hir::Expr<'tcx>,
         expected: Expectation<'tcx>,
-    ) -> Option<Ty<'tcx>> {
+    ) {
         if let [callee_expr, rest @ ..] = arg_exprs {
-            let callee_ty = self.typeck_results.borrow().expr_ty_adjusted_opt(callee_expr)?;
+            let Some(callee_ty) = self.typeck_results.borrow().expr_ty_adjusted_opt(callee_expr) else {
+                return;
+            };
 
             // First, do a probe with `IsSuggestion(true)` to avoid emitting
             // any strange errors. If it's successful, then we'll do a true
@@ -513,7 +509,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 ProbeScope::AllTraits,
                 expected.only_has_type(self),
             ) else {
-                return None;
+                return;
             };
 
             let pick = self.confirm_method(
@@ -525,7 +521,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 segment,
             );
             if pick.illegal_sized_bound.is_some() {
-                return None;
+                return;
             }
 
             let up_to_rcvr_span = segment.ident.span.until(callee_expr.span);
@@ -567,22 +563,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     sugg,
                     Applicability::MaybeIncorrect,
                 );
-
-                // Let's check the method fully now
-                let return_ty = self.check_method_argument_types(
-                    segment.ident.span,
-                    call_expr,
-                    Ok(pick.callee),
-                    rest,
-                    TupleArgumentsFlag::DontTupleArguments,
-                    expected,
-                );
-
-                return Some(return_ty);
             }
         }
-
-        None
     }
 
     fn report_invalid_callee(
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 08c4082e885..905781ec8f5 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -62,6 +62,7 @@ use rustc_span::{self, BytePos, DesugaringKind, Span};
 use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::infer::InferCtxtExt as _;
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
+use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
 use rustc_trait_selection::traits::{
     self, NormalizeExt, ObligationCause, ObligationCauseCode, ObligationCtxt,
 };
@@ -144,12 +145,28 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         debug!("unify(a: {:?}, b: {:?}, use_lub: {})", a, b, self.use_lub);
         self.commit_if_ok(|_| {
             let at = self.at(&self.cause, self.fcx.param_env);
-            if self.use_lub {
+
+            let res = if self.use_lub {
                 at.lub(DefineOpaqueTypes::Yes, b, a)
             } else {
                 at.sup(DefineOpaqueTypes::Yes, b, a)
                     .map(|InferOk { value: (), obligations }| InferOk { value: a, obligations })
+            };
+
+            // In the new solver, lazy norm may allow us to shallowly equate
+            // more types, but we emit possibly impossible-to-satisfy obligations.
+            // Filter these cases out to make sure our coercion is more accurate.
+            if self.tcx.trait_solver_next() {
+                if let Ok(res) = &res {
+                    for obligation in &res.obligations {
+                        if !self.predicate_may_hold(&obligation) {
+                            return Err(TypeError::Mismatch);
+                        }
+                    }
+                }
             }
+
+            res
         })
     }
 
@@ -791,6 +808,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         G: FnOnce(Ty<'tcx>) -> Vec<Adjustment<'tcx>>,
     {
         self.commit_if_ok(|snapshot| {
+            let outer_universe = self.infcx.universe();
+
             let result = if let ty::FnPtr(fn_ty_b) = b.kind()
                 && let (hir::Unsafety::Normal, hir::Unsafety::Unsafe) =
                     (fn_ty_a.unsafety(), fn_ty_b.unsafety())
@@ -807,7 +826,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
             // want the coerced type to be the actual supertype of these two,
             // but for now, we want to just error to ensure we don't lock
             // ourselves into a specific behavior with NLL.
-            self.leak_check(false, snapshot)?;
+            self.leak_check(outer_universe, Some(snapshot))?;
 
             result
         })
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index 102a313067f..4222205c841 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -49,8 +49,8 @@ pub struct StructExprNonExhaustive {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_typeck_method_call_on_unknown_type, code = "E0699")]
-pub struct MethodCallOnUnknownType {
+#[diag(hir_typeck_method_call_on_unknown_raw_pointee, code = "E0699")]
+pub struct MethodCallOnUnknownRawPointee {
     #[primary_span]
     pub span: Span,
 }
@@ -319,3 +319,11 @@ pub struct CandidateTraitNote {
     pub item_name: Ident,
     pub action_or_ty: String,
 }
+
+#[derive(Diagnostic)]
+#[diag(hir_typeck_ctor_is_private, code = "E0603")]
+pub struct CtorIsPrivate {
+    #[primary_span]
+    pub span: Span,
+    pub def: String,
+}
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 2fdcd09b9a2..38ddb7e7604 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -1,4 +1,5 @@
 use crate::callee::{self, DeferredCallResolution};
+use crate::errors::CtorIsPrivate;
 use crate::method::{self, MethodCallee, SelfSource};
 use crate::rvalue_scopes;
 use crate::{BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy, RawTy};
@@ -1207,6 +1208,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             match ty.normalized.ty_adt_def() {
                 Some(adt_def) if adt_def.has_ctor() => {
                     let (ctor_kind, ctor_def_id) = adt_def.non_enum_variant().ctor.unwrap();
+                    // Check the visibility of the ctor.
+                    let vis = tcx.visibility(ctor_def_id);
+                    if !vis.is_accessible_from(tcx.parent_module(hir_id).to_def_id(), tcx) {
+                        tcx.sess
+                            .emit_err(CtorIsPrivate { span, def: tcx.def_path_str(adt_def.did()) });
+                    }
                     let new_res = Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id);
                     let user_substs = Self::user_substs_for_adt(ty);
                     user_self_ty = user_substs.user_self_ty;
@@ -1379,7 +1386,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // the referenced item.
         let ty = tcx.type_of(def_id);
         assert!(!substs.has_escaping_bound_vars());
-        assert!(!ty.0.has_escaping_bound_vars());
+        assert!(!ty.skip_binder().has_escaping_bound_vars());
         let ty_substituted = self.normalize(span, ty.subst(tcx, substs));
 
         if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty {
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
index 019fb86f55c..fb28233bfb1 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
@@ -122,7 +122,7 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
 
                     self.fcx
                         .need_type_info_err_in_generator(self.kind, span, unresolved_term)
-                        .span_note(yield_data.span, &*note)
+                        .span_note(yield_data.span, note)
                         .emit();
                 }
             } else {
@@ -269,7 +269,7 @@ pub fn resolve_interior<'a, 'tcx>(
                     },
                     _ => mk_bound_region(ty::BrAnon(None)),
                 };
-                let r = fcx.tcx.mk_re_late_bound(current_depth, br);
+                let r = ty::Region::new_late_bound(fcx.tcx, current_depth, br);
                 r
             });
             captured_tys.insert(ty).then(|| {
@@ -295,7 +295,11 @@ pub fn resolve_interior<'a, 'tcx>(
                     let var = ty::BoundVar::from_usize(bound_vars.len());
                     bound_vars.push(ty::BoundVariableKind::Region(kind));
                     counter += 1;
-                    fcx.tcx.mk_re_late_bound(ty::INNERMOST, ty::BoundRegion { var, kind })
+                    ty::Region::new_late_bound(
+                        fcx.tcx,
+                        ty::INNERMOST,
+                        ty::BoundRegion { var, kind },
+                    )
                 },
                 types: &mut |b| bug!("unexpected bound ty in binder: {b:?}"),
                 consts: &mut |b, ty| bug!("unexpected bound ct in binder: {b:?} {ty}"),
@@ -686,7 +690,7 @@ fn check_must_not_suspend_def(
                 // Add optional reason note
                 if let Some(note) = attr.value_str() {
                     // FIXME(guswynn): consider formatting this better
-                    lint.span_note(data.source_span, note.as_str());
+                    lint.span_note(data.source_span, note.to_string());
                 }
 
                 // Add some quick suggestions on what to do
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index ba21edea30b..9f3d35a77dc 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -3,7 +3,7 @@ use super::CandidateSource;
 use super::MethodError;
 use super::NoMatchData;
 
-use crate::errors::MethodCallOnUnknownType;
+use crate::errors::MethodCallOnUnknownRawPointee;
 use crate::FnCtxt;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
@@ -438,7 +438,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // so we do a future-compat lint here for the 2015 edition
                 // (see https://github.com/rust-lang/rust/issues/46906)
                 if self.tcx.sess.rust_2018() {
-                    self.tcx.sess.emit_err(MethodCallOnUnknownType { span });
+                    self.tcx.sess.emit_err(MethodCallOnUnknownRawPointee { span });
                 } else {
                     self.tcx.struct_span_lint_hir(
                         lint::builtin::TYVAR_BEHIND_RAW_POINTER,
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 8555c20204a..9ee967dc7a9 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -473,6 +473,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let mut custom_span_label = false;
 
         let static_candidates = &mut no_match_data.static_candidates;
+
+        // `static_candidates` may have same candidates appended by
+        // inherent and extension, which may result in incorrect
+        // diagnostic.
+        static_candidates.dedup();
+
         if !static_candidates.is_empty() {
             err.note(
                 "found the following associated functions; to be used as methods, \
diff --git a/compiler/rustc_incremental/messages.ftl b/compiler/rustc_incremental/messages.ftl
index b760620e3d4..9fa4e0fb27c 100644
--- a/compiler/rustc_incremental/messages.ftl
+++ b/compiler/rustc_incremental/messages.ftl
@@ -1,118 +1,118 @@
-incremental_unrecognized_depnode = unrecognized `DepNode` variant: {$name}
+incremental_assert_loaded =
+    we asserted that an existing incremental cache directory should be successfully loaded, but it was not
 
-incremental_missing_depnode = missing `DepNode` variant
+incremental_assert_not_loaded =
+    we asserted that the incremental cache should not be loaded, but it was loaded
 
-incremental_missing_if_this_changed = no `#[rustc_if_this_changed]` annotation detected
+incremental_assertion_auto =
+    `except` specified DepNodes that can not be affected for "{$name}": "{$e}"
 
-incremental_no_path = no path from `{$source}` to `{$target}`
+incremental_associated_value_expected = expected an associated value
 
-incremental_ok = OK
+incremental_associated_value_expected_for = associated value expected for `{$ident}`
 
-incremental_unknown_reuse_kind = unknown cgu-reuse-kind `{$kind}` specified
+incremental_canonicalize_path = incremental compilation: error canonicalizing path `{$path}`: {$err}
 
-incremental_missing_query_depgraph =
-    found CGU-reuse attribute but `-Zquery-dep-graph` was not specified
+incremental_cargo_help_1 =
+    incremental compilation can be disabled by setting the environment variable CARGO_INCREMENTAL=0 (see https://doc.rust-lang.org/cargo/reference/profiles.html#incremental)
+incremental_cargo_help_2 =
+    the entire build directory can be changed to a different filesystem by setting the environment variable CARGO_TARGET_DIR to a different path (see https://doc.rust-lang.org/cargo/reference/config.html#buildtarget-dir)
 
-incremental_malformed_cgu_name =
-    found malformed codegen unit name `{$user_path}`. codegen units names must always start with the name of the crate (`{$crate_name}` in this case).
+incremental_copy_workproduct_to_cache =
+    error copying object file `{$from}` to incremental directory as `{$to}`: {$err}
 
-incremental_no_module_named =
-    no module named `{$user_path}` (mangled: {$cgu_name}). available modules: {$cgu_names}
+incremental_create_dep_graph = failed to create dependency graph at `{$path}`: {$err}
 
-incremental_field_associated_value_expected = associated value expected for `{$name}`
+incremental_create_incr_comp_dir =
+    could not create incremental compilation {$tag} directory `{$path}`: {$err}
 
-incremental_no_field = no field `{$name}`
+incremental_create_lock =
+    incremental compilation: could not create session directory lock file: {$lock_err}
+incremental_create_new = failed to create {$name} at `{$path}`: {$err}
 
-incremental_assertion_auto =
-    `except` specified DepNodes that can not be affected for "{$name}": "{$e}"
+incremental_decode_incr_cache = could not decode incremental cache: {$err}
 
-incremental_undefined_clean_dirty_assertions_item =
-    clean/dirty auto-assertions not yet defined for Node::Item.node={$kind}
+incremental_delete_full = error deleting incremental compilation session directory `{$path}`: {$err}
 
-incremental_undefined_clean_dirty_assertions =
-    clean/dirty auto-assertions not yet defined for {$kind}
+incremental_delete_incompatible =
+    failed to delete invalidated or incompatible incremental compilation session directory contents `{$path}`: {$err}
 
-incremental_repeated_depnode_label = dep-node label `{$label}` is repeated
+incremental_delete_lock =
+    error deleting lock file for incremental compilation session directory `{$path}`: {$err}
 
-incremental_unrecognized_depnode_label = dep-node label `{$label}` not recognized
+incremental_delete_old = unable to delete old {$name} at `{$path}`: {$err}
 
-incremental_not_dirty = `{$dep_node_str}` should be dirty but is not
+incremental_delete_partial = failed to delete partly initialized session dir `{$path}`: {$err}
 
-incremental_not_clean = `{$dep_node_str}` should be clean but is not
+incremental_delete_workproduct = file-system error deleting outdated file `{$path}`: {$err}
 
-incremental_not_loaded = `{$dep_node_str}` should have been loaded from disk but it was not
+incremental_field_associated_value_expected = associated value expected for `{$name}`
 
-incremental_unknown_item = unknown item `{$name}`
+incremental_finalize = error finalizing incremental compilation session directory `{$path}`: {$err}
 
-incremental_no_cfg = no cfg attribute
+incremental_finalized_gc_failed =
+    failed to garbage collect finalized incremental compilation session directory `{$path}`: {$err}
 
-incremental_associated_value_expected_for = associated value expected for `{$ident}`
+incremental_hard_link_failed =
+    hard linking files in the incremental compilation cache failed. copying files instead. consider moving the cache directory to a file system which supports hard linking in session dir `{$path}`
 
-incremental_associated_value_expected = expected an associated value
+incremental_invalid_gc_failed =
+    failed to garbage collect invalid incremental compilation session directory `{$path}`: {$err}
 
-incremental_unchecked_clean = found unchecked `#[rustc_clean]` attribute
+incremental_load_dep_graph = could not load dep-graph from `{$path}`: {$err}
 
-incremental_delete_old = unable to delete old {$name} at `{$path}`: {$err}
+incremental_lock_unsupported =
+    the filesystem for the incremental path at {$session_dir} does not appear to support locking, consider changing the incremental path to a filesystem that supports locking or disable incremental compilation
+incremental_malformed_cgu_name =
+    found malformed codegen unit name `{$user_path}`. codegen units names must always start with the name of the crate (`{$crate_name}` in this case).
 
-incremental_create_new = failed to create {$name} at `{$path}`: {$err}
+incremental_missing_depnode = missing `DepNode` variant
 
-incremental_write_new = failed to write {$name} to `{$path}`: {$err}
+incremental_missing_if_this_changed = no `#[rustc_if_this_changed]` annotation detected
 
-incremental_canonicalize_path = incremental compilation: error canonicalizing path `{$path}`: {$err}
+incremental_missing_query_depgraph =
+    found CGU-reuse attribute but `-Zquery-dep-graph` was not specified
 
-incremental_create_incr_comp_dir =
-    could not create incremental compilation {$tag} directory `{$path}`: {$err}
+incremental_move_dep_graph = failed to move dependency graph from `{$from}` to `{$to}`: {$err}
 
-incremental_create_lock =
-    incremental compilation: could not create session directory lock file: {$lock_err}
-incremental_lock_unsupported =
-    the filesystem for the incremental path at {$session_dir} does not appear to support locking, consider changing the incremental path to a filesystem that supports locking or disable incremental compilation
-incremental_cargo_help_1 =
-    incremental compilation can be disabled by setting the environment variable CARGO_INCREMENTAL=0 (see https://doc.rust-lang.org/cargo/reference/profiles.html#incremental)
-incremental_cargo_help_2 =
-    the entire build directory can be changed to a different filesystem by setting the environment variable CARGO_TARGET_DIR to a different path (see https://doc.rust-lang.org/cargo/reference/config.html#buildtarget-dir)
+incremental_no_cfg = no cfg attribute
 
-incremental_delete_lock =
-    error deleting lock file for incremental compilation session directory `{$path}`: {$err}
+incremental_no_field = no field `{$name}`
 
-incremental_hard_link_failed =
-    hard linking files in the incremental compilation cache failed. copying files instead. consider moving the cache directory to a file system which supports hard linking in session dir `{$path}`
+incremental_no_module_named =
+    no module named `{$user_path}` (mangled: {$cgu_name}). available modules: {$cgu_names}
 
-incremental_delete_partial = failed to delete partly initialized session dir `{$path}`: {$err}
+incremental_no_path = no path from `{$source}` to `{$target}`
 
-incremental_delete_full = error deleting incremental compilation session directory `{$path}`: {$err}
+incremental_not_clean = `{$dep_node_str}` should be clean but is not
 
-incremental_finalize = error finalizing incremental compilation session directory `{$path}`: {$err}
+incremental_not_dirty = `{$dep_node_str}` should be dirty but is not
 
-incremental_invalid_gc_failed =
-    failed to garbage collect invalid incremental compilation session directory `{$path}`: {$err}
+incremental_not_loaded = `{$dep_node_str}` should have been loaded from disk but it was not
 
-incremental_finalized_gc_failed =
-    failed to garbage collect finalized incremental compilation session directory `{$path}`: {$err}
+incremental_ok = OK
+
+incremental_repeated_depnode_label = dep-node label `{$label}` is repeated
 
 incremental_session_gc_failed =
     failed to garbage collect incremental compilation session directory `{$path}`: {$err}
 
-incremental_assert_not_loaded =
-    we asserted that the incremental cache should not be loaded, but it was loaded
-
-incremental_assert_loaded =
-    we asserted that an existing incremental cache directory should be successfully loaded, but it was not
+incremental_unchecked_clean = found unchecked `#[rustc_clean]` attribute
 
-incremental_delete_incompatible =
-    failed to delete invalidated or incompatible incremental compilation session directory contents `{$path}`: {$err}
+incremental_undefined_clean_dirty_assertions =
+    clean/dirty auto-assertions not yet defined for {$kind}
 
-incremental_load_dep_graph = could not load dep-graph from `{$path}`: {$err}
+incremental_undefined_clean_dirty_assertions_item =
+    clean/dirty auto-assertions not yet defined for Node::Item.node={$kind}
 
-incremental_decode_incr_cache = could not decode incremental cache: {$err}
+incremental_unknown_item = unknown item `{$name}`
 
-incremental_write_dep_graph = failed to write dependency graph to `{$path}`: {$err}
+incremental_unknown_reuse_kind = unknown cgu-reuse-kind `{$kind}` specified
 
-incremental_move_dep_graph = failed to move dependency graph from `{$from}` to `{$to}`: {$err}
+incremental_unrecognized_depnode = unrecognized `DepNode` variant: {$name}
 
-incremental_create_dep_graph = failed to create dependency graph at `{$path}`: {$err}
+incremental_unrecognized_depnode_label = dep-node label `{$label}` not recognized
 
-incremental_copy_workproduct_to_cache =
-    error copying object file `{$from}` to incremental directory as `{$to}`: {$err}
+incremental_write_dep_graph = failed to write dependency graph to `{$path}`: {$err}
 
-incremental_delete_workproduct = file-system error deleting outdated file `{$path}`: {$err}
+incremental_write_new = failed to write {$name} to `{$path}`: {$err}
diff --git a/compiler/rustc_infer/messages.ftl b/compiler/rustc_infer/messages.ftl
index fdc4ff0896f..f44c4a7c1e3 100644
--- a/compiler/rustc_infer/messages.ftl
+++ b/compiler/rustc_infer/messages.ftl
@@ -1,285 +1,72 @@
-infer_opaque_hidden_type =
-    opaque type's hidden type cannot be another opaque type from the same scope
-    .label = one of the two opaque types used here has to be outside its defining scope
-    .opaque_type = opaque type whose hidden type is being assigned
-    .hidden_type = opaque type being used as hidden type
-
-infer_type_annotations_needed = {$source_kind ->
-    [closure] type annotations needed for the closure `{$source_name}`
-    [normal] type annotations needed for `{$source_name}`
-    *[other] type annotations needed
-}
-    .label = type must be known at this point
-
-infer_label_bad = {$bad_kind ->
-    *[other] cannot infer type
-    [more_info] cannot infer {$prefix_kind ->
-        *[type] type for {$prefix}
-        [const_with_param] the value of const parameter
-        [const] the value of the constant
-    } `{$name}`{$has_parent ->
-        [true] {" "}declared on the {$parent_prefix} `{$parent_name}`
-        *[false] {""}
-    }
-}
-
-infer_source_kind_subdiag_let = {$kind ->
-    [with_pattern] consider giving `{$name}` an explicit type
-    [closure] consider giving this closure parameter an explicit type
-    *[other] consider giving this pattern a type
-}{$x_kind ->
-    [has_name] , where the {$prefix_kind ->
-        *[type] type for {$prefix}
-        [const_with_param] value of const parameter
-        [const] value of the constant
-    } `{$arg_name}` is specified
-    [underscore] , where the placeholders `_` are specified
-    *[empty] {""}
-}
-
-infer_source_kind_subdiag_generic_label =
-    cannot infer {$is_type ->
-    [true] type
-    *[false] the value
-    } of the {$is_type ->
-    [true] type
-    *[false] const
-    } {$parent_exists ->
-    [true] parameter `{$param_name}` declared on the {$parent_prefix} `{$parent_name}`
-    *[false] parameter {$param_name}
-    }
-
-infer_source_kind_subdiag_generic_suggestion =
-    consider specifying the generic {$arg_count ->
-    [one] argument
-    *[other] arguments
-    }
-
-infer_source_kind_fully_qualified =
-    try using a fully qualified path to specify the expected types
-
-infer_source_kind_closure_return =
-    try giving this closure an explicit return type
-
-# generator_kind  may need to be translated
-infer_need_type_info_in_generator =
-    type inside {$generator_kind ->
-    [async_block] `async` block
-    [async_closure] `async` closure
-    [async_fn] `async fn` body
-    *[generator] generator
-    } must be known in this context
-
-
-infer_subtype = ...so that the {$requirement ->
-    [method_compat] method type is compatible with trait
-    [type_compat] associated type is compatible with trait
-    [const_compat] const is compatible with trait
-    [expr_assignable] expression is assignable
-    [if_else_different] `if` and `else` have incompatible types
-    [no_else] `if` missing an `else` returns `()`
-    [fn_main_correct_type] `main` function has the correct type
-    [fn_start_correct_type] `#[start]` function has the correct type
-    [intrinsic_correct_type] intrinsic has the correct type
-    [method_correct_type] method receiver has the correct type
-    *[other] types are compatible
-}
-infer_subtype_2 = ...so that {$requirement ->
-    [method_compat] method type is compatible with trait
-    [type_compat] associated type is compatible with trait
-    [const_compat] const is compatible with trait
-    [expr_assignable] expression is assignable
-    [if_else_different] `if` and `else` have incompatible types
-    [no_else] `if` missing an `else` returns `()`
-    [fn_main_correct_type] `main` function has the correct type
-    [fn_start_correct_type] `#[start]` function has the correct type
-    [intrinsic_correct_type] intrinsic has the correct type
-    [method_correct_type] method receiver has the correct type
-    *[other] types are compatible
-}
-
-infer_reborrow = ...so that reference does not outlive borrowed content
-infer_reborrow_upvar = ...so that closure can access `{$name}`
-infer_relate_object_bound = ...so that it can be closed over into an object
-infer_reference_outlives_referent = ...so that the reference type `{$name}` does not outlive the data it points at
-infer_relate_param_bound = ...so that the type `{$name}` will meet its required lifetime bounds{$continues ->
-    [true] ...
+infer_actual_impl_expl_but_actually_implemented_for_ty = ...but `{$trait_path}` is actually implemented for the type `{$ty}`{$has_lifetime ->
+    [true] , for some specific lifetime `'{$lifetime}`
     *[false] {""}
 }
-infer_relate_param_bound_2 = ...that is required by this bound
-infer_relate_region_param_bound = ...so that the declared lifetime parameter bounds are satisfied
-infer_compare_impl_item_obligation = ...so that the definition in impl matches the definition from the trait
-infer_ascribe_user_type_prove_predicate = ...so that the where clause holds
-
-infer_nothing = {""}
-
-infer_lifetime_mismatch = lifetime mismatch
-
-infer_declared_different = this parameter and the return type are declared with different lifetimes...
-infer_data_returned = ...but data{$label_var1_exists ->
-    [true] {" "}from `{$label_var1}`
-    *[false] {""}
-} is returned here
-
-infer_data_lifetime_flow = ...but data with one lifetime flows into the other here
-infer_declared_multiple = this type is declared with multiple lifetimes...
-infer_types_declared_different = these two types are declared with different lifetimes...
-infer_data_flows = ...but data{$label_var1_exists ->
-    [true] {" "}from `{$label_var1}`
-    *[false] -> {""}
-} flows{$label_var2_exists ->
-    [true] {" "}into `{$label_var2}`
-    *[false] -> {""}
-} here
-
-infer_lifetime_param_suggestion = consider introducing a named lifetime parameter{$is_impl ->
-    [true] {" "}and update trait if needed
+infer_actual_impl_expl_but_actually_implements_trait = ...but it actually implements `{$trait_path}`{$has_lifetime ->
+    [true] , for some specific lifetime `'{$lifetime}`
     *[false] {""}
 }
-infer_lifetime_param_suggestion_elided = each elided lifetime in input position becomes a distinct lifetime
-
-infer_region_explanation = {$pref_kind ->
-    *[should_not_happen] [{$pref_kind}]
-    [ref_valid_for] ...the reference is valid for
-    [content_valid_for] ...but the borrowed content is only valid for
-    [type_obj_valid_for] object type is valid for
-    [source_pointer_valid_for] source pointer is only valid for
-    [type_satisfy] type must satisfy
-    [type_outlive] type must outlive
-    [lf_param_instantiated_with] lifetime parameter instantiated with
-    [lf_param_must_outlive] but lifetime parameter must outlive
-    [lf_instantiated_with] lifetime instantiated with
-    [lf_must_outlive] but lifetime must outlive
-    [pointer_valid_for] the pointer is valid for
-    [data_valid_for] but the referenced data is only valid for
-    [empty] {""}
-}{$pref_kind ->
-    [empty] {""}
-    *[other] {" "}
-}{$desc_kind ->
-    *[should_not_happen] [{$desc_kind}]
-    [restatic] the static lifetime
-    [revar] lifetime {$desc_arg}
-    [as_defined] the lifetime `{$desc_arg}` as defined here
-    [as_defined_anon] the anonymous lifetime as defined here
-    [defined_here] the anonymous lifetime defined here
-    [defined_here_reg] the lifetime `{$desc_arg}` as defined here
-}{$suff_kind ->
-    *[should_not_happen] [{$suff_kind}]
-    [empty]{""}
-    [continues] ...
-    [req_by_binding] {" "}as required by this binding
+infer_actual_impl_expl_but_actually_ty_implements = ...but `{$ty}` actually implements `{$trait_path}`{$has_lifetime ->
+    [true] , for some specific lifetime `'{$lifetime}`
+    *[false] {""}
 }
 
-infer_outlives_content = lifetime of reference outlives lifetime of borrowed content...
-infer_outlives_bound = lifetime of the source pointer does not outlive lifetime bound of the object type
-infer_fulfill_req_lifetime = the type `{$ty}` does not fulfill the required lifetime
-infer_lf_bound_not_satisfied = lifetime bound not satisfied
-infer_borrowed_too_long = a value of type `{$ty}` is borrowed for too long
-infer_ref_longer_than_data = in type `{$ty}`, reference has a longer lifetime than the data it references
-
-infer_mismatched_static_lifetime = incompatible lifetime on type
-infer_does_not_outlive_static_from_impl = ...does not necessarily outlive the static lifetime introduced by the compatible `impl`
-infer_implicit_static_lifetime_note = this has an implicit `'static` lifetime requirement
-infer_implicit_static_lifetime_suggestion = consider relaxing the implicit `'static` requirement
-infer_msl_introduces_static = introduces a `'static` lifetime requirement
-infer_msl_unmet_req = because this has an unmet lifetime requirement
-infer_msl_trait_note = this has an implicit `'static` lifetime requirement
-infer_msl_trait_sugg = consider relaxing the implicit `'static` requirement
-infer_suggest_add_let_for_letchains = consider adding `let`
-
-infer_explicit_lifetime_required_with_ident = explicit lifetime required in the type of `{$simple_ident}`
-    .label = lifetime `{$named}` required
-
-infer_explicit_lifetime_required_with_param_type = explicit lifetime required in parameter type
-    .label = lifetime `{$named}` required
-
-infer_explicit_lifetime_required_sugg_with_ident = add explicit lifetime `{$named}` to the type of `{$simple_ident}`
-
-infer_explicit_lifetime_required_sugg_with_param_type = add explicit lifetime `{$named}` to type
-
-infer_actual_impl_expl_expected_signature_two = {$leading_ellipsis ->
-    [true] ...
-    *[false] {""}
-}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
-infer_actual_impl_expl_expected_signature_any = {$leading_ellipsis ->
+infer_actual_impl_expl_expected_other_any = {$leading_ellipsis ->
     [true] ...
     *[false] {""}
-}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...
-infer_actual_impl_expl_expected_signature_some = {$leading_ellipsis ->
+}`{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...
+infer_actual_impl_expl_expected_other_nothing = {$leading_ellipsis ->
     [true] ...
     *[false] {""}
-}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`...
-infer_actual_impl_expl_expected_signature_nothing = {$leading_ellipsis ->
+}`{$ty_or_sig}` must implement `{$trait_path}`
+
+infer_actual_impl_expl_expected_other_some = {$leading_ellipsis ->
     [true] ...
     *[false] {""}
-}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`
-infer_actual_impl_expl_expected_passive_two = {$leading_ellipsis ->
+}`{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`...
+infer_actual_impl_expl_expected_other_two = {$leading_ellipsis ->
     [true] ...
     *[false] {""}
-}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
+}`{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
 infer_actual_impl_expl_expected_passive_any = {$leading_ellipsis ->
     [true] ...
     *[false] {""}
 }`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any lifetime `'{$lifetime_1}`...
-infer_actual_impl_expl_expected_passive_some = {$leading_ellipsis ->
-    [true] ...
-    *[false] {""}
-}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for some specific lifetime `'{$lifetime_1}`...
 infer_actual_impl_expl_expected_passive_nothing = {$leading_ellipsis ->
     [true] ...
     *[false] {""}
 }`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`
-infer_actual_impl_expl_expected_other_two = {$leading_ellipsis ->
+infer_actual_impl_expl_expected_passive_some = {$leading_ellipsis ->
     [true] ...
     *[false] {""}
-}`{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
-infer_actual_impl_expl_expected_other_any = {$leading_ellipsis ->
+}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for some specific lifetime `'{$lifetime_1}`...
+infer_actual_impl_expl_expected_passive_two = {$leading_ellipsis ->
     [true] ...
     *[false] {""}
-}`{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...
-infer_actual_impl_expl_expected_other_some = {$leading_ellipsis ->
+}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
+infer_actual_impl_expl_expected_signature_any = {$leading_ellipsis ->
     [true] ...
     *[false] {""}
-}`{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`...
-infer_actual_impl_expl_expected_other_nothing = {$leading_ellipsis ->
+}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...
+infer_actual_impl_expl_expected_signature_nothing = {$leading_ellipsis ->
     [true] ...
     *[false] {""}
-}`{$ty_or_sig}` must implement `{$trait_path}`
-
-infer_actual_impl_expl_but_actually_implements_trait = ...but it actually implements `{$trait_path}`{$has_lifetime ->
-    [true] , for some specific lifetime `'{$lifetime}`
-    *[false] {""}
-}
-infer_actual_impl_expl_but_actually_implemented_for_ty = ...but `{$trait_path}` is actually implemented for the type `{$ty}`{$has_lifetime ->
-    [true] , for some specific lifetime `'{$lifetime}`
+}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`
+infer_actual_impl_expl_expected_signature_some = {$leading_ellipsis ->
+    [true] ...
     *[false] {""}
-}
-infer_actual_impl_expl_but_actually_ty_implements = ...but `{$ty}` actually implements `{$trait_path}`{$has_lifetime ->
-    [true] , for some specific lifetime `'{$lifetime}`
+}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`...
+infer_actual_impl_expl_expected_signature_two = {$leading_ellipsis ->
+    [true] ...
     *[false] {""}
-}
-
-infer_trait_placeholder_mismatch = implementation of `{$trait_def_id}` is not general enough
-    .label_satisfy = doesn't satisfy where-clause
-    .label_where = due to a where-clause on `{$def_id}`...
-    .label_dup = implementation of `{$trait_def_id}` is not general enough
-
-infer_trait_impl_diff = `impl` item signature doesn't match `trait` item signature
-    .found = found `{$found}`
-    .expected = expected `{$expected}`
-    .expected_found = expected signature `{$expected}`
-               {"   "}found signature `{$found}`
-
-infer_tid_rel_help = verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output
-infer_tid_consider_borrowing = consider borrowing this type parameter in the trait
-infer_tid_param_help = the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
+}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
+infer_ascribe_user_type_prove_predicate = ...so that the where clause holds
 
-infer_dtcs_has_lifetime_req_label = this has an implicit `'static` lifetime requirement
-infer_dtcs_introduces_requirement = calling this method introduces the `impl`'s `'static` requirement
-infer_dtcs_has_req_note = the used `impl` has a `'static` requirement
-infer_dtcs_suggestion = consider relaxing the implicit `'static` requirement
+infer_await_both_futures = consider `await`ing on both `Future`s
+infer_await_future = consider `await`ing on the `Future`
+infer_await_note = calling an async function returns a future
 
+infer_borrowed_too_long = a value of type `{$ty}` is borrowed for too long
 infer_but_calling_introduces = {$has_param_name ->
     [true] `{$param_name}`
     *[false] `fn` parameter
@@ -314,6 +101,77 @@ infer_but_needs_to_satisfy = {$has_param_name ->
     .used_here = ...is used here...
     .introduced_by_bound = `'static` lifetime requirement introduced by this bound
 
+infer_compare_impl_item_obligation = ...so that the definition in impl matches the definition from the trait
+infer_consider_specifying_length = consider specifying the actual array length
+infer_data_flows = ...but data{$label_var1_exists ->
+    [true] {" "}from `{$label_var1}`
+    *[false] -> {""}
+} flows{$label_var2_exists ->
+    [true] {" "}into `{$label_var2}`
+    *[false] -> {""}
+} here
+
+infer_data_lifetime_flow = ...but data with one lifetime flows into the other here
+infer_data_returned = ...but data{$label_var1_exists ->
+    [true] {" "}from `{$label_var1}`
+    *[false] {""}
+} is returned here
+
+infer_declared_different = this parameter and the return type are declared with different lifetimes...
+infer_declared_multiple = this type is declared with multiple lifetimes...
+infer_does_not_outlive_static_from_impl = ...does not necessarily outlive the static lifetime introduced by the compatible `impl`
+infer_dtcs_has_lifetime_req_label = this has an implicit `'static` lifetime requirement
+infer_dtcs_has_req_note = the used `impl` has a `'static` requirement
+infer_dtcs_introduces_requirement = calling this method introduces the `impl`'s `'static` requirement
+infer_dtcs_suggestion = consider relaxing the implicit `'static` requirement
+
+infer_explicit_lifetime_required_sugg_with_ident = add explicit lifetime `{$named}` to the type of `{$simple_ident}`
+
+infer_explicit_lifetime_required_sugg_with_param_type = add explicit lifetime `{$named}` to type
+
+infer_explicit_lifetime_required_with_ident = explicit lifetime required in the type of `{$simple_ident}`
+    .label = lifetime `{$named}` required
+
+infer_explicit_lifetime_required_with_param_type = explicit lifetime required in parameter type
+    .label = lifetime `{$named}` required
+
+infer_fn_consider_casting = consider casting the fn item to a fn pointer: `{$casting}`
+
+infer_fn_uniq_types = different fn items have unique types, even if their signatures are the same
+infer_fps_cast = consider casting to a fn pointer
+infer_fps_cast_both = consider casting both fn items to fn pointers using `as {$expected_sig}`
+
+infer_fps_items_are_distinct = fn items are distinct from fn pointers
+infer_fps_remove_ref = consider removing the reference
+infer_fps_use_ref = consider using a reference
+infer_fulfill_req_lifetime = the type `{$ty}` does not fulfill the required lifetime
+infer_implicit_static_lifetime_note = this has an implicit `'static` lifetime requirement
+infer_implicit_static_lifetime_suggestion = consider relaxing the implicit `'static` requirement
+infer_label_bad = {$bad_kind ->
+    *[other] cannot infer type
+    [more_info] cannot infer {$prefix_kind ->
+        *[type] type for {$prefix}
+        [const_with_param] the value of const parameter
+        [const] the value of the constant
+    } `{$name}`{$has_parent ->
+        [true] {" "}declared on the {$parent_prefix} `{$parent_name}`
+        *[false] {""}
+    }
+}
+
+infer_lf_bound_not_satisfied = lifetime bound not satisfied
+infer_lifetime_mismatch = lifetime mismatch
+
+infer_lifetime_param_suggestion = consider introducing a named lifetime parameter{$is_impl ->
+    [true] {" "}and update trait if needed
+    *[false] {""}
+}
+infer_lifetime_param_suggestion_elided = each elided lifetime in input position becomes a distinct lifetime
+
+infer_meant_byte_literal = if you meant to write a byte literal, prefix with `b`
+infer_meant_char_literal = if you meant to write a `char` literal, use single quotes
+infer_meant_str_literal = if you meant to write a `str` literal, use double quotes
+infer_mismatched_static_lifetime = incompatible lifetime on type
 infer_more_targeted = {$has_param_name ->
     [true] `{$param_name}`
     *[false] `fn` parameter
@@ -322,72 +180,215 @@ infer_more_targeted = {$has_param_name ->
     *[false] an anonymous lifetime `'_`
 } but calling `{$ident}` introduces an implicit `'static` lifetime requirement
 
-infer_ril_introduced_here = `'static` requirement introduced here
-infer_ril_introduced_by = requirement introduced by this return type
-infer_ril_because_of = because of this returned expression
-infer_ril_static_introduced_by = "`'static` lifetime requirement introduced by the return type
+infer_msl_introduces_static = introduces a `'static` lifetime requirement
+infer_msl_trait_note = this has an implicit `'static` lifetime requirement
+infer_msl_trait_sugg = consider relaxing the implicit `'static` requirement
+infer_msl_unmet_req = because this has an unmet lifetime requirement
+infer_need_type_info_in_generator =
+    type inside {$generator_kind ->
+    [async_block] `async` block
+    [async_closure] `async` closure
+    [async_fn] `async fn` body
+    *[generator] generator
+    } must be known in this context
 
-infer_where_remove = remove the `where` clause
-infer_where_copy_predicates = copy the `where` clause predicates from the trait
 
-infer_srs_remove_and_box = consider removing this semicolon and boxing the expressions
-infer_srs_remove = consider removing this semicolon
-infer_srs_add = consider returning the local binding `{$ident}`
-infer_srs_add_one = consider returning one of these bindings
+infer_nothing = {""}
 
-infer_await_both_futures = consider `await`ing on both `Future`s
-infer_await_future = consider `await`ing on the `Future`
-infer_await_note = calling an async function returns a future
+infer_oc_cant_coerce = cannot coerce intrinsics to function pointers
+infer_oc_closure_selfref = closure/generator type that references itself
+infer_oc_const_compat = const not compatible with trait
+infer_oc_fn_main_correct_type = `main` function has wrong type
+infer_oc_fn_start_correct_type = `#[start]` function has wrong type
+infer_oc_generic = mismatched types
 
+infer_oc_if_else_different = `if` and `else` have incompatible types
+infer_oc_intrinsic_correct_type = intrinsic has wrong type
+infer_oc_match_compat = `match` arms have incompatible types
+infer_oc_method_compat = method not compatible with trait
+infer_oc_method_correct_type = mismatched `self` parameter type
+infer_oc_no_diverge = `else` clause of `let...else` does not diverge
+infer_oc_no_else = `if` may be missing an `else` clause
+infer_oc_try_compat = `?` operator has incompatible types
+infer_oc_type_compat = type not compatible with trait
+infer_opaque_captures_lifetime = hidden type for `{$opaque_ty}` captures lifetime that does not appear in bounds
+    .label = opaque type defined here
+
+infer_opaque_hidden_type =
+    opaque type's hidden type cannot be another opaque type from the same scope
+    .label = one of the two opaque types used here has to be outside its defining scope
+    .opaque_type = opaque type whose hidden type is being assigned
+    .hidden_type = opaque type being used as hidden type
+
+infer_outlives_bound = lifetime of the source pointer does not outlive lifetime bound of the object type
+infer_outlives_content = lifetime of reference outlives lifetime of borrowed content...
 infer_prlf_defined_with_sub = the lifetime `{$sub_symbol}` defined here...
 infer_prlf_defined_without_sub = the lifetime defined here...
-infer_prlf_must_outlive_with_sup = ...must outlive the lifetime `{$sup_symbol}` defined here
-infer_prlf_must_outlive_without_sup = ...must outlive the lifetime defined here
 infer_prlf_known_limitation = this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
 
-infer_opaque_captures_lifetime = hidden type for `{$opaque_ty}` captures lifetime that does not appear in bounds
-    .label = opaque type defined here
+infer_prlf_must_outlive_with_sup = ...must outlive the lifetime `{$sup_symbol}` defined here
+infer_prlf_must_outlive_without_sup = ...must outlive the lifetime defined here
+infer_reborrow = ...so that reference does not outlive borrowed content
+infer_reborrow_upvar = ...so that closure can access `{$name}`
+infer_ref_longer_than_data = in type `{$ty}`, reference has a longer lifetime than the data it references
 
-infer_fps_use_ref = consider using a reference
-infer_fps_remove_ref = consider removing the reference
-infer_fps_cast = consider casting to a fn pointer
-infer_fps_items_are_distinct = fn items are distinct from fn pointers
-infer_fps_cast_both = consider casting both fn items to fn pointers using `as {$expected_sig}`
+infer_reference_outlives_referent = ...so that the reference type `{$name}` does not outlive the data it points at
+infer_region_explanation = {$pref_kind ->
+    *[should_not_happen] [{$pref_kind}]
+    [ref_valid_for] ...the reference is valid for
+    [content_valid_for] ...but the borrowed content is only valid for
+    [type_obj_valid_for] object type is valid for
+    [source_pointer_valid_for] source pointer is only valid for
+    [type_satisfy] type must satisfy
+    [type_outlive] type must outlive
+    [lf_param_instantiated_with] lifetime parameter instantiated with
+    [lf_param_must_outlive] but lifetime parameter must outlive
+    [lf_instantiated_with] lifetime instantiated with
+    [lf_must_outlive] but lifetime must outlive
+    [pointer_valid_for] the pointer is valid for
+    [data_valid_for] but the referenced data is only valid for
+    [empty] {""}
+}{$pref_kind ->
+    [empty] {""}
+    *[other] {" "}
+}{$desc_kind ->
+    *[should_not_happen] [{$desc_kind}]
+    [restatic] the static lifetime
+    [revar] lifetime {$desc_arg}
+    [as_defined] the lifetime `{$desc_arg}` as defined here
+    [as_defined_anon] the anonymous lifetime as defined here
+    [defined_here] the anonymous lifetime defined here
+    [defined_here_reg] the lifetime `{$desc_arg}` as defined here
+}{$suff_kind ->
+    *[should_not_happen] [{$suff_kind}]
+    [empty]{""}
+    [continues] ...
+    [req_by_binding] {" "}as required by this binding
+}
 
-infer_fn_uniq_types = different fn items have unique types, even if their signatures are the same
-infer_fn_consider_casting = consider casting the fn item to a fn pointer: `{$casting}`
+infer_relate_object_bound = ...so that it can be closed over into an object
+infer_relate_param_bound = ...so that the type `{$name}` will meet its required lifetime bounds{$continues ->
+    [true] ...
+    *[false] {""}
+}
+infer_relate_param_bound_2 = ...that is required by this bound
+infer_relate_region_param_bound = ...so that the declared lifetime parameter bounds are satisfied
+infer_ril_because_of = because of this returned expression
+infer_ril_introduced_by = requirement introduced by this return type
+infer_ril_introduced_here = `'static` requirement introduced here
+infer_ril_static_introduced_by = "`'static` lifetime requirement introduced by the return type
 
 infer_sarwa_option = you can convert from `&Option<T>` to `Option<&T>` using `.as_ref()`
 infer_sarwa_result = you can convert from `&Result<T, E>` to `Result<&T, &E>` using `.as_ref()`
 
-infer_suggest_accessing_field = you might have meant to use field `{$name}` whose type is `{$ty}`
+infer_sbfrit_box_return_expr = if you change the return type to expect trait objects, box the returned expressions
 
 infer_sbfrit_change_return_type = you could change the return type to be a boxed trait object
-infer_sbfrit_box_return_expr = if you change the return type to expect trait objects, box the returned expressions
+infer_source_kind_closure_return =
+    try giving this closure an explicit return type
 
-infer_stp_wrap_one = try wrapping the pattern in `{$variant}`
+# generator_kind  may need to be translated
+infer_source_kind_fully_qualified =
+    try using a fully qualified path to specify the expected types
+
+infer_source_kind_subdiag_generic_label =
+    cannot infer {$is_type ->
+    [true] type
+    *[false] the value
+    } of the {$is_type ->
+    [true] type
+    *[false] const
+    } {$parent_exists ->
+    [true] parameter `{$param_name}` declared on the {$parent_prefix} `{$parent_name}`
+    *[false] parameter {$param_name}
+    }
+
+infer_source_kind_subdiag_generic_suggestion =
+    consider specifying the generic {$arg_count ->
+    [one] argument
+    *[other] arguments
+    }
+
+infer_source_kind_subdiag_let = {$kind ->
+    [with_pattern] consider giving `{$name}` an explicit type
+    [closure] consider giving this closure parameter an explicit type
+    *[other] consider giving this pattern a type
+}{$x_kind ->
+    [has_name] , where the {$prefix_kind ->
+        *[type] type for {$prefix}
+        [const_with_param] value of const parameter
+        [const] value of the constant
+    } `{$arg_name}` is specified
+    [underscore] , where the placeholders `_` are specified
+    *[empty] {""}
+}
+
+infer_srs_add = consider returning the local binding `{$ident}`
+infer_srs_add_one = consider returning one of these bindings
+
+infer_srs_remove = consider removing this semicolon
+infer_srs_remove_and_box = consider removing this semicolon and boxing the expressions
 infer_stp_wrap_many = try wrapping the pattern in a variant of `{$path}`
 
-infer_tuple_trailing_comma = use a trailing comma to create a tuple with one element
+infer_stp_wrap_one = try wrapping the pattern in `{$variant}`
+infer_subtype = ...so that the {$requirement ->
+    [method_compat] method type is compatible with trait
+    [type_compat] associated type is compatible with trait
+    [const_compat] const is compatible with trait
+    [expr_assignable] expression is assignable
+    [if_else_different] `if` and `else` have incompatible types
+    [no_else] `if` missing an `else` returns `()`
+    [fn_main_correct_type] `main` function has the correct type
+    [fn_start_correct_type] `#[start]` function has the correct type
+    [intrinsic_correct_type] intrinsic has the correct type
+    [method_correct_type] method receiver has the correct type
+    *[other] types are compatible
+}
+infer_subtype_2 = ...so that {$requirement ->
+    [method_compat] method type is compatible with trait
+    [type_compat] associated type is compatible with trait
+    [const_compat] const is compatible with trait
+    [expr_assignable] expression is assignable
+    [if_else_different] `if` and `else` have incompatible types
+    [no_else] `if` missing an `else` returns `()`
+    [fn_main_correct_type] `main` function has the correct type
+    [fn_start_correct_type] `#[start]` function has the correct type
+    [intrinsic_correct_type] intrinsic has the correct type
+    [method_correct_type] method receiver has the correct type
+    *[other] types are compatible
+}
 
-infer_oc_method_compat = method not compatible with trait
-infer_oc_type_compat = type not compatible with trait
-infer_oc_const_compat = const not compatible with trait
-infer_oc_try_compat = `?` operator has incompatible types
-infer_oc_match_compat = `match` arms have incompatible types
-infer_oc_if_else_different = `if` and `else` have incompatible types
-infer_oc_no_else = `if` may be missing an `else` clause
-infer_oc_no_diverge = `else` clause of `let...else` does not diverge
-infer_oc_fn_main_correct_type = `main` function has wrong type
-infer_oc_fn_start_correct_type = `#[start]` function has wrong type
-infer_oc_intrinsic_correct_type = intrinsic has wrong type
-infer_oc_method_correct_type = mismatched `self` parameter type
-infer_oc_closure_selfref = closure/generator type that references itself
-infer_oc_cant_coerce = cannot coerce intrinsics to function pointers
-infer_oc_generic = mismatched types
+infer_suggest_accessing_field = you might have meant to use field `{$name}` whose type is `{$ty}`
+
+infer_suggest_add_let_for_letchains = consider adding `let`
+
+infer_tid_consider_borrowing = consider borrowing this type parameter in the trait
+infer_tid_param_help = the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
+
+infer_tid_rel_help = verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output
+infer_trait_impl_diff = `impl` item signature doesn't match `trait` item signature
+    .found = found `{$found}`
+    .expected = expected `{$expected}`
+    .expected_found = expected signature `{$expected}`
+               {"   "}found signature `{$found}`
+
+infer_trait_placeholder_mismatch = implementation of `{$trait_def_id}` is not general enough
+    .label_satisfy = doesn't satisfy where-clause
+    .label_where = due to a where-clause on `{$def_id}`...
+    .label_dup = implementation of `{$trait_def_id}` is not general enough
 
-infer_meant_byte_literal = if you meant to write a byte literal, prefix with `b`
-infer_meant_char_literal = if you meant to write a `char` literal, use single quotes
-infer_meant_str_literal = if you meant to write a `str` literal, use double quotes
-infer_consider_specifying_length = consider specifying the actual array length
 infer_try_cannot_convert = `?` operator cannot convert from `{$found}` to `{$expected}`
+
+infer_tuple_trailing_comma = use a trailing comma to create a tuple with one element
+
+infer_type_annotations_needed = {$source_kind ->
+    [closure] type annotations needed for the closure `{$source_name}`
+    [normal] type annotations needed for `{$source_name}`
+    *[other] type annotations needed
+}
+    .label = type must be known at this point
+
+infer_types_declared_different = these two types are declared with different lifetimes...
+infer_where_copy_predicates = copy the `where` clause predicates from the trait
+
+infer_where_remove = remove the `where` clause
diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs
index 0c8854e962a..6b2dd0a2b4f 100644
--- a/compiler/rustc_infer/src/infer/at.rs
+++ b/compiler/rustc_infer/src/infer/at.rs
@@ -70,8 +70,8 @@ impl<'tcx> InferCtxt<'tcx> {
             tcx: self.tcx,
             defining_use_anchor: self.defining_use_anchor,
             considering_regions: self.considering_regions,
+            skip_leak_check: self.skip_leak_check,
             inner: self.inner.clone(),
-            skip_leak_check: self.skip_leak_check.clone(),
             lexical_region_resolutions: self.lexical_region_resolutions.clone(),
             selection_cache: self.selection_cache.clone(),
             evaluation_cache: self.evaluation_cache.clone(),
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index 427d05c8b4d..bf53a73f398 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -771,7 +771,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
     ) -> ty::Region<'tcx> {
         let var = self.canonical_var(info, r.into());
         let br = ty::BoundRegion { var, kind: ty::BrAnon(None) };
-        self.interner().mk_re_late_bound(self.binder_index, br)
+        ty::Region::new_late_bound(self.interner(), self.binder_index, br)
     }
 
     /// Given a type variable `ty_var` of the given kind, first check
diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs
index 2abdd5b0aec..c8c318c3f02 100644
--- a/compiler/rustc_infer/src/infer/canonical/mod.rs
+++ b/compiler/rustc_infer/src/infer/canonical/mod.rs
@@ -141,7 +141,7 @@ impl<'tcx> InferCtxt<'tcx> {
             CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion { universe, bound }) => {
                 let universe_mapped = universe_map(universe);
                 let placeholder_mapped = ty::PlaceholderRegion { universe: universe_mapped, bound };
-                self.tcx.mk_re_placeholder(placeholder_mapped).into()
+                ty::Region::new_placeholder(self.tcx, placeholder_mapped).into()
             }
 
             CanonicalVarKind::Const(ui, ty) => self
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index de9afbbcaab..2cf8d8c702d 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -15,7 +15,7 @@ use crate::infer::canonical::{
 use crate::infer::nll_relate::{TypeRelating, TypeRelatingDelegate};
 use crate::infer::region_constraints::{Constraint, RegionConstraintData};
 use crate::infer::{DefineOpaqueTypes, InferCtxt, InferOk, InferResult, NllRegionVariableOrigin};
-use crate::traits::query::{Fallible, NoSolution};
+use crate::traits::query::NoSolution;
 use crate::traits::{Obligation, ObligationCause, PredicateObligation};
 use crate::traits::{PredicateObligations, TraitEngine, TraitEngineExt};
 use rustc_data_structures::captures::Captures;
@@ -57,7 +57,7 @@ impl<'tcx> InferCtxt<'tcx> {
         inference_vars: CanonicalVarValues<'tcx>,
         answer: T,
         fulfill_cx: &mut dyn TraitEngine<'tcx>,
-    ) -> Fallible<CanonicalQueryResponse<'tcx, T>>
+    ) -> Result<CanonicalQueryResponse<'tcx, T>, NoSolution>
     where
         T: Debug + TypeFoldable<TyCtxt<'tcx>>,
         Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>,
@@ -668,14 +668,15 @@ pub fn make_query_region_constraints<'tcx>(
             let constraint = match *k {
                 // Swap regions because we are going from sub (<=) to outlives
                 // (>=).
-                Constraint::VarSubVar(v1, v2) => {
-                    ty::OutlivesPredicate(tcx.mk_re_var(v2).into(), tcx.mk_re_var(v1))
-                }
+                Constraint::VarSubVar(v1, v2) => ty::OutlivesPredicate(
+                    ty::Region::new_var(tcx, v2).into(),
+                    ty::Region::new_var(tcx, v1),
+                ),
                 Constraint::VarSubReg(v1, r2) => {
-                    ty::OutlivesPredicate(r2.into(), tcx.mk_re_var(v1))
+                    ty::OutlivesPredicate(r2.into(), ty::Region::new_var(tcx, v1))
                 }
                 Constraint::RegSubVar(r1, v2) => {
-                    ty::OutlivesPredicate(tcx.mk_re_var(v2).into(), r1)
+                    ty::OutlivesPredicate(ty::Region::new_var(tcx, v2).into(), r1)
                 }
                 Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r2.into(), r1),
             };
@@ -719,7 +720,7 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> {
     }
 
     fn next_placeholder_region(&mut self, placeholder: ty::PlaceholderRegion) -> ty::Region<'tcx> {
-        self.infcx.tcx.mk_re_placeholder(placeholder)
+        ty::Region::new_placeholder(self.infcx.tcx, placeholder)
     }
 
     fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 35c05e80bad..f8a253c8949 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -76,6 +76,7 @@ use rustc_middle::ty::{
 };
 use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span};
 use rustc_target::spec::abi;
+use std::borrow::Cow;
 use std::ops::{ControlFlow, Deref};
 use std::path::PathBuf;
 use std::{cmp, fmt, iter};
@@ -1470,7 +1471,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         &self,
         diag: &mut Diagnostic,
         cause: &ObligationCause<'tcx>,
-        secondary_span: Option<(Span, String)>,
+        secondary_span: Option<(Span, Cow<'static, str>)>,
         mut values: Option<ValuePairs<'tcx>>,
         terr: TypeError<'tcx>,
         swap_secondary_and_primary: bool,
@@ -1629,7 +1630,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             }
         };
 
-        let mut label_or_note = |span: Span, msg: &str| {
+        let mut label_or_note = |span: Span, msg: Cow<'static, str>| {
             if (prefer_label && is_simple_error) || &[span] == diag.span.primary_spans() {
                 diag.span_label(span, msg);
             } else {
@@ -1643,15 +1644,15 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     ..
                 })) = values
                 {
-                    format!("expected this to be `{}`", expected)
+                    Cow::from(format!("expected this to be `{}`", expected))
                 } else {
-                    terr.to_string(self.tcx).to_string()
+                    terr.to_string(self.tcx)
                 };
-                label_or_note(sp, &terr);
-                label_or_note(span, &msg);
+                label_or_note(sp, terr);
+                label_or_note(span, msg);
             } else {
-                label_or_note(span, &terr.to_string(self.tcx));
-                label_or_note(sp, &msg);
+                label_or_note(span, terr.to_string(self.tcx));
+                label_or_note(sp, msg);
             }
         } else {
             if let Some(values) = values
@@ -1663,12 +1664,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 let expected = with_forced_trimmed_paths!(e.sort_string(self.tcx));
                 let found = with_forced_trimmed_paths!(f.sort_string(self.tcx));
                 if expected == found {
-                    label_or_note(span, &terr.to_string(self.tcx));
+                    label_or_note(span, terr.to_string(self.tcx));
                 } else {
-                    label_or_note(span, &format!("expected {expected}, found {found}"));
+                    label_or_note(span, Cow::from(format!("expected {expected}, found {found}")));
                 }
             } else {
-                label_or_note(span, &terr.to_string(self.tcx));
+                label_or_note(span, terr.to_string(self.tcx));
             }
         }
 
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
index c9c1f0aeaac..0b3bc1ce6b3 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
@@ -79,7 +79,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
                 sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
                 _,
             )) => self.try_report_trait_placeholder_mismatch(
-                Some(self.tcx().mk_re_var(*vid)),
+                Some(ty::Region::new_var(self.tcx(), *vid)),
                 cause,
                 Some(*sub_placeholder),
                 Some(*sup_placeholder),
@@ -95,7 +95,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
                 _,
                 _,
             )) => self.try_report_trait_placeholder_mismatch(
-                Some(self.tcx().mk_re_var(*vid)),
+                Some(ty::Region::new_var(self.tcx(), *vid)),
                 cause,
                 Some(*sub_placeholder),
                 None,
@@ -111,7 +111,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
                 sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
                 _,
             )) => self.try_report_trait_placeholder_mismatch(
-                Some(self.tcx().mk_re_var(*vid)),
+                Some(ty::Region::new_var(self.tcx(), *vid)),
                 cause,
                 None,
                 Some(*sup_placeholder),
@@ -127,7 +127,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
                 sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
                 _,
             )) => self.try_report_trait_placeholder_mismatch(
-                Some(self.tcx().mk_re_var(*vid)),
+                Some(ty::Region::new_var(self.tcx(), *vid)),
                 cause,
                 None,
                 Some(*sup_placeholder),
@@ -141,7 +141,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
                 SubregionOrigin::Subtype(box TypeTrace { cause, values }),
                 sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
             )) => self.try_report_trait_placeholder_mismatch(
-                Some(self.tcx().mk_re_var(*vid)),
+                Some(ty::Region::new_var(self.tcx(), *vid)),
                 cause,
                 None,
                 Some(*sup_placeholder),
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
index 421eb807a14..d1f110472c9 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
@@ -234,13 +234,13 @@ impl<T> Trait<T> for X {
                         );
                     }
                     (_, ty::Alias(ty::Projection | ty::Inherent, proj_ty)) if !tcx.is_impl_trait_in_trait(proj_ty.def_id) => {
-                        let msg = format!(
+                        let msg = || format!(
                             "consider constraining the associated type `{}` to `{}`",
                             values.found, values.expected,
                         );
                         if !(self.suggest_constraining_opaque_associated_type(
                             diag,
-                            &msg,
+                            msg,
                             proj_ty,
                             values.expected,
                         ) || self.suggest_constraint(
@@ -250,7 +250,7 @@ impl<T> Trait<T> for X {
                             proj_ty,
                             values.expected,
                         )) {
-                            diag.help(msg);
+                            diag.help(msg());
                             diag.note(
                                 "for more information, visit \
                                 https://doc.rust-lang.org/book/ch19-03-advanced-traits.html",
@@ -308,7 +308,7 @@ impl<T> Trait<T> for X {
     fn suggest_constraint(
         &self,
         diag: &mut Diagnostic,
-        msg: &str,
+        msg: impl Fn() -> String,
         body_owner_def_id: DefId,
         proj_ty: &ty::AliasTy<'tcx>,
         ty: Ty<'tcx>,
@@ -340,7 +340,7 @@ impl<T> Trait<T> for X {
                         assoc,
                         assoc_substs,
                         ty,
-                        msg,
+                        &msg,
                         false,
                     ) {
                         return true;
@@ -374,10 +374,12 @@ impl<T> Trait<T> for X {
     ) {
         let tcx = self.tcx;
 
-        let msg = format!(
-            "consider constraining the associated type `{}` to `{}`",
-            values.expected, values.found
-        );
+        let msg = || {
+            format!(
+                "consider constraining the associated type `{}` to `{}`",
+                values.expected, values.found
+            )
+        };
         let body_owner = tcx.hir().get_if_local(body_owner_def_id);
         let current_method_ident = body_owner.and_then(|n| n.ident()).map(|i| i.name);
 
@@ -428,10 +430,11 @@ impl<T> Trait<T> for X {
             if callable_scope {
                 diag.help(format!(
                     "{} or calling a method that returns `{}`",
-                    msg, values.expected
+                    msg(),
+                    values.expected
                 ));
             } else {
-                diag.help(msg);
+                diag.help(msg());
             }
             diag.note(
                 "for more information, visit \
@@ -463,7 +466,7 @@ fn foo(&self) -> Self::T { String::new() }
     fn suggest_constraining_opaque_associated_type(
         &self,
         diag: &mut Diagnostic,
-        msg: &str,
+        msg: impl Fn() -> String,
         proj_ty: &ty::AliasTy<'tcx>,
         ty: Ty<'tcx>,
     ) -> bool {
@@ -635,7 +638,7 @@ fn foo(&self) -> Self::T { String::new() }
         assoc: ty::AssocItem,
         assoc_substs: &[ty::GenericArg<'tcx>],
         ty: Ty<'tcx>,
-        msg: &str,
+        msg: impl Fn() -> String,
         is_bound_surely_present: bool,
     ) -> bool {
         // FIXME: we would want to call `resolve_vars_if_possible` on `ty` before suggesting.
@@ -678,7 +681,7 @@ fn foo(&self) -> Self::T { String::new() }
         assoc: ty::AssocItem,
         assoc_substs: &[ty::GenericArg<'tcx>],
         ty: Ty<'tcx>,
-        msg: &str,
+        msg: impl Fn() -> String,
     ) -> bool {
         let tcx = self.tcx;
 
@@ -693,7 +696,7 @@ fn foo(&self) -> Self::T { String::new() }
                 let item_args = self.format_generic_args(assoc_substs);
                 (span.shrink_to_hi(), format!("<{}{} = {}>", assoc.ident(tcx), item_args, ty))
             };
-            diag.span_suggestion_verbose(span, msg, sugg, MaybeIncorrect);
+            diag.span_suggestion_verbose(span, msg(), sugg, MaybeIncorrect);
             return true;
         }
         false
diff --git a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
index c304cd25c9c..974bc2f1153 100644
--- a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
+++ b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
@@ -82,8 +82,10 @@ impl<'tcx> InferCtxt<'tcx> {
 
         let delegate = FnMutDelegate {
             regions: &mut |br: ty::BoundRegion| {
-                self.tcx
-                    .mk_re_placeholder(ty::PlaceholderRegion { universe: next_universe, bound: br })
+                ty::Region::new_placeholder(
+                    self.tcx,
+                    ty::PlaceholderRegion { universe: next_universe, bound: br },
+                )
             },
             types: &mut |bound_ty: ty::BoundTy| {
                 self.tcx.mk_placeholder(ty::PlaceholderType {
@@ -103,13 +105,15 @@ impl<'tcx> InferCtxt<'tcx> {
         self.tcx.replace_bound_vars_uncached(binder, delegate)
     }
 
-    /// See [RegionConstraintCollector::leak_check][1].
+    /// See [RegionConstraintCollector::leak_check][1]. We only check placeholder
+    /// leaking into `outer_universe`, i.e. placeholders which cannot be named by that
+    /// universe.
     ///
     /// [1]: crate::infer::region_constraints::RegionConstraintCollector::leak_check
     pub fn leak_check(
         &self,
-        overly_polymorphic: bool,
-        snapshot: &CombinedSnapshot<'tcx>,
+        outer_universe: ty::UniverseIndex,
+        only_consider_snapshot: Option<&CombinedSnapshot<'tcx>>,
     ) -> RelateResult<'tcx, ()> {
         // If the user gave `-Zno-leak-check`, or we have been
         // configured to skip the leak check, then skip the leak check
@@ -117,15 +121,15 @@ impl<'tcx> InferCtxt<'tcx> {
         // subtyping errors that it would have caught will now be
         // caught later on, during region checking. However, we
         // continue to use it for a transition period.
-        if self.tcx.sess.opts.unstable_opts.no_leak_check || self.skip_leak_check.get() {
+        if self.tcx.sess.opts.unstable_opts.no_leak_check || self.skip_leak_check {
             return Ok(());
         }
 
         self.inner.borrow_mut().unwrap_region_constraints().leak_check(
             self.tcx,
-            overly_polymorphic,
+            outer_universe,
             self.universe(),
-            snapshot,
+            only_consider_snapshot,
         )
     }
 }
diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
index 8482ae2aa38..485e34fe2bf 100644
--- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
+++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
@@ -347,7 +347,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
                     // name the placeholder, then the placeholder is
                     // larger; otherwise, the only ancestor is `'static`.
                     Err(placeholder) if empty_ui.can_name(placeholder.universe) => {
-                        self.tcx().mk_re_placeholder(placeholder)
+                        ty::Region::new_placeholder(self.tcx(), placeholder)
                     }
                     Err(_) => self.tcx().lifetimes.re_static,
                 };
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index cd99fc31212..447d4c9f84b 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -251,14 +251,13 @@ pub struct InferCtxt<'tcx> {
     /// solving is left to borrowck instead.
     pub considering_regions: bool,
 
-    pub inner: RefCell<InferCtxtInner<'tcx>>,
-
     /// If set, this flag causes us to skip the 'leak check' during
     /// higher-ranked subtyping operations. This flag is a temporary one used
     /// to manage the removal of the leak-check: for the time being, we still run the
-    /// leak-check, but we issue warnings. This flag can only be set to true
-    /// when entering a snapshot.
-    skip_leak_check: Cell<bool>,
+    /// leak-check, but we issue warnings.
+    skip_leak_check: bool,
+
+    pub inner: RefCell<InferCtxtInner<'tcx>>,
 
     /// Once region inference is done, the values for each variable.
     lexical_region_resolutions: RefCell<Option<LexicalRegionResolutions<'tcx>>>,
@@ -543,6 +542,7 @@ pub struct InferCtxtBuilder<'tcx> {
     tcx: TyCtxt<'tcx>,
     defining_use_anchor: DefiningAnchor,
     considering_regions: bool,
+    skip_leak_check: bool,
     /// Whether we are in coherence mode.
     intercrate: bool,
 }
@@ -557,6 +557,7 @@ impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> {
             tcx: self,
             defining_use_anchor: DefiningAnchor::Error,
             considering_regions: true,
+            skip_leak_check: false,
             intercrate: false,
         }
     }
@@ -584,6 +585,11 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
         self
     }
 
+    pub fn skip_leak_check(mut self, skip_leak_check: bool) -> Self {
+        self.skip_leak_check = skip_leak_check;
+        self
+    }
+
     /// Given a canonical value `C` as a starting point, create an
     /// inference context that contains each of the bound values
     /// within instantiated as a fresh variable. The `f` closure is
@@ -605,11 +611,18 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
     }
 
     pub fn build(&mut self) -> InferCtxt<'tcx> {
-        let InferCtxtBuilder { tcx, defining_use_anchor, considering_regions, intercrate } = *self;
+        let InferCtxtBuilder {
+            tcx,
+            defining_use_anchor,
+            considering_regions,
+            skip_leak_check,
+            intercrate,
+        } = *self;
         InferCtxt {
             tcx,
             defining_use_anchor,
             considering_regions,
+            skip_leak_check,
             inner: RefCell::new(InferCtxtInner::new()),
             lexical_region_resolutions: RefCell::new(None),
             selection_cache: Default::default(),
@@ -619,7 +632,6 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
             tainted_by_errors: Cell::new(None),
             err_count_on_creation: tcx.sess.err_count(),
             in_snapshot: Cell::new(false),
-            skip_leak_check: Cell::new(false),
             universe: Cell::new(ty::UniverseIndex::ROOT),
             intercrate,
         }
@@ -815,32 +827,9 @@ impl<'tcx> InferCtxt<'tcx> {
         r
     }
 
-    /// If `should_skip` is true, then execute `f` then unroll any bindings it creates.
-    #[instrument(skip(self, f), level = "debug")]
-    pub fn probe_maybe_skip_leak_check<R, F>(&self, should_skip: bool, f: F) -> R
-    where
-        F: FnOnce(&CombinedSnapshot<'tcx>) -> R,
-    {
-        let snapshot = self.start_snapshot();
-        let was_skip_leak_check = self.skip_leak_check.get();
-        if should_skip {
-            self.skip_leak_check.set(true);
-        }
-        let r = f(&snapshot);
-        self.rollback_to("probe", snapshot);
-        self.skip_leak_check.set(was_skip_leak_check);
-        r
-    }
-
-    /// Scan the constraints produced since `snapshot` began and returns:
-    ///
-    /// - `None` -- if none of them involves "region outlives" constraints.
-    /// - `Some(true)` -- if there are `'a: 'b` constraints where `'a` or `'b` is a placeholder.
-    /// - `Some(false)` -- if there are `'a: 'b` constraints but none involve placeholders.
-    pub fn region_constraints_added_in_snapshot(
-        &self,
-        snapshot: &CombinedSnapshot<'tcx>,
-    ) -> Option<bool> {
+    /// Scan the constraints produced since `snapshot` and check whether
+    /// we added any region constraints.
+    pub fn region_constraints_added_in_snapshot(&self, snapshot: &CombinedSnapshot<'tcx>) -> bool {
         self.inner
             .borrow_mut()
             .unwrap_region_constraints()
@@ -1065,7 +1054,7 @@ impl<'tcx> InferCtxt<'tcx> {
     ) -> ty::Region<'tcx> {
         let region_var =
             self.inner.borrow_mut().unwrap_region_constraints().new_region_var(universe, origin);
-        self.tcx.mk_re_var(region_var)
+        ty::Region::new_var(self.tcx, region_var)
     }
 
     /// Return the universe that the region `r` was created in. For
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index 9d5ec228d82..105a3f08c82 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -533,17 +533,29 @@ impl<'tcx> InferCtxt<'tcx> {
         // these are the same span, but not in cases like `-> (impl
         // Foo, impl Bar)`.
         let span = cause.span;
-        let prev = self.inner.borrow_mut().opaque_types().register(
-            opaque_type_key,
-            OpaqueHiddenType { ty: hidden_ty, span },
-            origin,
-        );
-        let mut obligations = if let Some(prev) = prev {
-            self.at(&cause, param_env)
-                .eq_exp(DefineOpaqueTypes::Yes, a_is_expected, prev, hidden_ty)?
-                .obligations
+        let mut obligations = if self.intercrate {
+            // During intercrate we do not define opaque types but instead always
+            // force ambiguity unless the hidden type is known to not implement
+            // our trait.
+            vec![traits::Obligation::new(
+                self.tcx,
+                cause.clone(),
+                param_env,
+                ty::PredicateKind::Ambiguous,
+            )]
         } else {
-            Vec::new()
+            let prev = self.inner.borrow_mut().opaque_types().register(
+                opaque_type_key,
+                OpaqueHiddenType { ty: hidden_ty, span },
+                origin,
+            );
+            if let Some(prev) = prev {
+                self.at(&cause, param_env)
+                    .eq_exp(DefineOpaqueTypes::Yes, a_is_expected, prev, hidden_ty)?
+                    .obligations
+            } else {
+                Vec::new()
+            }
         };
 
         self.add_item_bounds_for_hidden_type(
diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs
index c2bf0f3db25..59ae2ce6c60 100644
--- a/compiler/rustc_infer/src/infer/outlives/verify.rs
+++ b/compiler/rustc_infer/src/infer/outlives/verify.rs
@@ -293,7 +293,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
     ) -> impl Iterator<Item = ty::Region<'tcx>> {
         let tcx = self.tcx;
         let bounds = tcx.item_bounds(alias_ty.def_id);
-        trace!("{:#?}", bounds.0);
+        trace!("{:#?}", bounds.skip_binder());
         bounds
             .subst_iter(tcx, alias_ty.substs)
             .filter_map(|p| p.to_opt_type_outlives())
diff --git a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
index 89cfc9ea3d1..dd65f66ccd1 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
@@ -3,7 +3,6 @@ use crate::infer::CombinedSnapshot;
 use rustc_data_structures::{
     fx::FxIndexMap,
     graph::{scc::Sccs, vec_graph::VecGraph},
-    undo_log::UndoLogs,
 };
 use rustc_index::Idx;
 use rustc_middle::ty::error::TypeError;
@@ -13,7 +12,9 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
     /// Searches new universes created during `snapshot`, looking for
     /// placeholders that may "leak" out from the universes they are contained
     /// in. If any leaking placeholders are found, then an `Err` is returned
-    /// (typically leading to the snapshot being reversed).
+    /// (typically leading to the snapshot being reversed). This algorithm
+    /// only looks at placeholders which cannot be named by `outer_universe`,
+    /// as this is the universe we're currently checking for a leak.
     ///
     /// The leak check *used* to be the only way we had to handle higher-ranked
     /// obligations. Now that we have integrated universes into the region
@@ -55,6 +56,12 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
     ///   * if they must also be equal to a placeholder P, and U cannot name P, report an error, as that
     ///     indicates `P: R` and `R` is in an incompatible universe
     ///
+    /// To improve performance and for the old trait solver caching to be sound, this takes
+    /// an optional snapshot in which case we only look at region constraints added in that
+    /// snapshot. If we were to not do that the `leak_check` during evaluation can rely on
+    /// region constraints added outside of that evaluation. As that is not reflected in the
+    /// cache key this would be unsound.
+    ///
     /// # Historical note
     ///
     /// Older variants of the leak check used to report errors for these
@@ -62,36 +69,21 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
     ///
     /// * R: P1, even if R cannot name P1, because R = 'static is a valid sol'n
     /// * R: P1, R: P2, as above
+    #[instrument(level = "debug", skip(self, tcx, only_consider_snapshot), ret)]
     pub fn leak_check(
         &mut self,
         tcx: TyCtxt<'tcx>,
-        overly_polymorphic: bool,
+        outer_universe: ty::UniverseIndex,
         max_universe: ty::UniverseIndex,
-        snapshot: &CombinedSnapshot<'tcx>,
+        only_consider_snapshot: Option<&CombinedSnapshot<'tcx>>,
     ) -> RelateResult<'tcx, ()> {
-        debug!(
-            "leak_check(max_universe={:?}, snapshot.universe={:?}, overly_polymorphic={:?})",
-            max_universe, snapshot.universe, overly_polymorphic
-        );
-
-        assert!(UndoLogs::<super::UndoLog<'_>>::in_snapshot(&self.undo_log));
-
-        let universe_at_start_of_snapshot = snapshot.universe;
-        if universe_at_start_of_snapshot == max_universe {
+        if outer_universe == max_universe {
             return Ok(());
         }
 
-        let mini_graph =
-            &MiniGraph::new(tcx, self.undo_log.region_constraints(), &self.storage.data.verifys);
+        let mini_graph = &MiniGraph::new(tcx, &self, only_consider_snapshot);
 
-        let mut leak_check = LeakCheck::new(
-            tcx,
-            universe_at_start_of_snapshot,
-            max_universe,
-            overly_polymorphic,
-            mini_graph,
-            self,
-        );
+        let mut leak_check = LeakCheck::new(tcx, outer_universe, max_universe, mini_graph, self);
         leak_check.assign_placeholder_values()?;
         leak_check.propagate_scc_value()?;
         Ok(())
@@ -100,9 +92,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
 
 struct LeakCheck<'me, 'tcx> {
     tcx: TyCtxt<'tcx>,
-    universe_at_start_of_snapshot: ty::UniverseIndex,
-    /// Only used when reporting region errors.
-    overly_polymorphic: bool,
+    outer_universe: ty::UniverseIndex,
     mini_graph: &'me MiniGraph<'tcx>,
     rcc: &'me RegionConstraintCollector<'me, 'tcx>,
 
@@ -130,17 +120,15 @@ struct LeakCheck<'me, 'tcx> {
 impl<'me, 'tcx> LeakCheck<'me, 'tcx> {
     fn new(
         tcx: TyCtxt<'tcx>,
-        universe_at_start_of_snapshot: ty::UniverseIndex,
+        outer_universe: ty::UniverseIndex,
         max_universe: ty::UniverseIndex,
-        overly_polymorphic: bool,
         mini_graph: &'me MiniGraph<'tcx>,
         rcc: &'me RegionConstraintCollector<'me, 'tcx>,
     ) -> Self {
         let dummy_scc_universe = SccUniverse { universe: max_universe, region: None };
         Self {
             tcx,
-            universe_at_start_of_snapshot,
-            overly_polymorphic,
+            outer_universe,
             mini_graph,
             rcc,
             scc_placeholders: IndexVec::from_elem_n(None, mini_graph.sccs.num_sccs()),
@@ -165,7 +153,7 @@ impl<'me, 'tcx> LeakCheck<'me, 'tcx> {
 
             // Detect those SCCs that directly contain a placeholder
             if let ty::RePlaceholder(placeholder) = **region {
-                if self.universe_at_start_of_snapshot.cannot_name(placeholder.universe) {
+                if self.outer_universe.cannot_name(placeholder.universe) {
                     self.assign_scc_value(scc, placeholder)?;
                 }
             }
@@ -280,7 +268,7 @@ impl<'me, 'tcx> LeakCheck<'me, 'tcx> {
         placeholder1: ty::PlaceholderRegion,
         placeholder2: ty::PlaceholderRegion,
     ) -> TypeError<'tcx> {
-        self.error(placeholder1, self.tcx.mk_re_placeholder(placeholder2))
+        self.error(placeholder1, ty::Region::new_placeholder(self.tcx, placeholder2))
     }
 
     fn error(
@@ -289,11 +277,7 @@ impl<'me, 'tcx> LeakCheck<'me, 'tcx> {
         other_region: ty::Region<'tcx>,
     ) -> TypeError<'tcx> {
         debug!("error: placeholder={:?}, other_region={:?}", placeholder, other_region);
-        if self.overly_polymorphic {
-            TypeError::RegionsOverlyPolymorphic(placeholder.bound.kind, other_region)
-        } else {
-            TypeError::RegionsInsufficientlyPolymorphic(placeholder.bound.kind, other_region)
-        }
+        TypeError::RegionsInsufficientlyPolymorphic(placeholder.bound.kind, other_region)
     }
 }
 
@@ -379,56 +363,70 @@ struct MiniGraph<'tcx> {
 }
 
 impl<'tcx> MiniGraph<'tcx> {
-    fn new<'a>(
+    fn new(
         tcx: TyCtxt<'tcx>,
-        undo_log: impl Iterator<Item = &'a UndoLog<'tcx>>,
-        verifys: &[Verify<'tcx>],
-    ) -> Self
-    where
-        'tcx: 'a,
-    {
+        region_constraints: &RegionConstraintCollector<'_, 'tcx>,
+        only_consider_snapshot: Option<&CombinedSnapshot<'tcx>>,
+    ) -> Self {
         let mut nodes = FxIndexMap::default();
         let mut edges = Vec::new();
 
         // Note that if `R2: R1`, we get a callback `r1, r2`, so `target` is first parameter.
-        Self::iterate_undo_log(tcx, undo_log, verifys, |target, source| {
-            let source_node = Self::add_node(&mut nodes, source);
-            let target_node = Self::add_node(&mut nodes, target);
-            edges.push((source_node, target_node));
-        });
+        Self::iterate_region_constraints(
+            tcx,
+            region_constraints,
+            only_consider_snapshot,
+            |target, source| {
+                let source_node = Self::add_node(&mut nodes, source);
+                let target_node = Self::add_node(&mut nodes, target);
+                edges.push((source_node, target_node));
+            },
+        );
         let graph = VecGraph::new(nodes.len(), edges);
         let sccs = Sccs::new(&graph);
         Self { nodes, sccs }
     }
 
     /// Invokes `each_edge(R1, R2)` for each edge where `R2: R1`
-    fn iterate_undo_log<'a>(
+    fn iterate_region_constraints(
         tcx: TyCtxt<'tcx>,
-        undo_log: impl Iterator<Item = &'a UndoLog<'tcx>>,
-        verifys: &[Verify<'tcx>],
+        region_constraints: &RegionConstraintCollector<'_, 'tcx>,
+        only_consider_snapshot: Option<&CombinedSnapshot<'tcx>>,
         mut each_edge: impl FnMut(ty::Region<'tcx>, ty::Region<'tcx>),
-    ) where
-        'tcx: 'a,
-    {
-        for undo_entry in undo_log {
-            match undo_entry {
-                &AddConstraint(Constraint::VarSubVar(a, b)) => {
-                    each_edge(tcx.mk_re_var(a), tcx.mk_re_var(b));
-                }
-                &AddConstraint(Constraint::RegSubVar(a, b)) => {
-                    each_edge(a, tcx.mk_re_var(b));
-                }
-                &AddConstraint(Constraint::VarSubReg(a, b)) => {
-                    each_edge(tcx.mk_re_var(a), b);
-                }
-                &AddConstraint(Constraint::RegSubReg(a, b)) => {
-                    each_edge(a, b);
+    ) {
+        let mut each_constraint = |constraint| match constraint {
+            &Constraint::VarSubVar(a, b) => {
+                each_edge(ty::Region::new_var(tcx, a), ty::Region::new_var(tcx, b));
+            }
+            &Constraint::RegSubVar(a, b) => {
+                each_edge(a, ty::Region::new_var(tcx, b));
+            }
+            &Constraint::VarSubReg(a, b) => {
+                each_edge(ty::Region::new_var(tcx, a), b);
+            }
+            &Constraint::RegSubReg(a, b) => {
+                each_edge(a, b);
+            }
+        };
+
+        if let Some(snapshot) = only_consider_snapshot {
+            for undo_entry in
+                region_constraints.undo_log.region_constraints_in_snapshot(&snapshot.undo_snapshot)
+            {
+                match undo_entry {
+                    AddConstraint(constraint) => {
+                        each_constraint(constraint);
+                    }
+                    &AddVerify(i) => span_bug!(
+                        region_constraints.data().verifys[i].origin.span(),
+                        "we never add verifications while doing higher-ranked things",
+                    ),
+                    &AddCombination(..) | &AddVar(..) => {}
                 }
-                &AddVerify(i) => span_bug!(
-                    verifys[i].origin.span(),
-                    "we never add verifications while doing higher-ranked things",
-                ),
-                &AddCombination(..) | &AddVar(..) => {}
+            }
+        } else {
+            for (constraint, _origin) in &region_constraints.data().constraints {
+                each_constraint(constraint)
             }
         }
     }
diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
index c7a307b89e4..613da8a0b45 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
@@ -400,7 +400,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
         data
     }
 
-    pub(super) fn data(&self) -> &RegionConstraintData<'tcx> {
+    pub fn data(&self) -> &RegionConstraintData<'tcx> {
         &self.data
     }
 
@@ -610,13 +610,13 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
         let resolved = ut
             .probe_value(root_vid)
             .get_value_ignoring_universes()
-            .unwrap_or_else(|| tcx.mk_re_var(root_vid));
+            .unwrap_or_else(|| ty::Region::new_var(tcx, root_vid));
 
         // Don't resolve a variable to a region that it cannot name.
         if self.var_universe(vid).can_name(self.universe(resolved)) {
             resolved
         } else {
-            tcx.mk_re_var(vid)
+            ty::Region::new_var(tcx, vid)
         }
     }
 
@@ -637,7 +637,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
     ) -> Region<'tcx> {
         let vars = TwoRegions { a, b };
         if let Some(&c) = self.combine_map(t).get(&vars) {
-            return tcx.mk_re_var(c);
+            return ty::Region::new_var(tcx, c);
         }
         let a_universe = self.universe(a);
         let b_universe = self.universe(b);
@@ -645,7 +645,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
         let c = self.new_region_var(c_universe, MiscVariable(origin.span()));
         self.combine_map(t).insert(vars, c);
         self.undo_log.push(AddCombination(t, vars));
-        let new_r = tcx.mk_re_var(c);
+        let new_r = ty::Region::new_var(tcx, c);
         for old_r in [a, b] {
             match t {
                 Glb => self.make_subregion(origin.clone(), new_r, old_r),
@@ -683,15 +683,10 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
     }
 
     /// See `InferCtxt::region_constraints_added_in_snapshot`.
-    pub fn region_constraints_added_in_snapshot(&self, mark: &Snapshot<'tcx>) -> Option<bool> {
+    pub fn region_constraints_added_in_snapshot(&self, mark: &Snapshot<'tcx>) -> bool {
         self.undo_log
             .region_constraints_in_snapshot(mark)
-            .map(|&elt| match elt {
-                AddConstraint(constraint) => Some(constraint.involves_placeholders()),
-                _ => None,
-            })
-            .max()
-            .unwrap_or(None)
+            .any(|&elt| matches!(elt, AddConstraint(_)))
     }
 
     #[inline]
diff --git a/compiler/rustc_infer/src/infer/undo_log.rs b/compiler/rustc_infer/src/infer/undo_log.rs
index 955c54e8515..25d06b21ec8 100644
--- a/compiler/rustc_infer/src/infer/undo_log.rs
+++ b/compiler/rustc_infer/src/infer/undo_log.rs
@@ -138,11 +138,9 @@ impl<'tcx> InferCtxtInner<'tcx> {
         }
 
         if self.undo_log.num_open_snapshots == 1 {
-            // The root snapshot. It's safe to clear the undo log because
-            // there's no snapshot further out that we might need to roll back
-            // to.
+            // After the root snapshot the undo log should be empty.
             assert!(snapshot.undo_len == 0);
-            self.undo_log.logs.clear();
+            assert!(self.undo_log.logs.is_empty());
         }
 
         self.undo_log.num_open_snapshots -= 1;
@@ -183,15 +181,6 @@ impl<'tcx> InferCtxtUndoLogs<'tcx> {
         self.logs[s.undo_len..].iter().any(|log| matches!(log, UndoLog::OpaqueTypes(..)))
     }
 
-    pub(crate) fn region_constraints(
-        &self,
-    ) -> impl Iterator<Item = &'_ region_constraints::UndoLog<'tcx>> + Clone {
-        self.logs.iter().filter_map(|log| match log {
-            UndoLog::RegionConstraintCollector(log) => Some(log),
-            _ => None,
-        })
-    }
-
     fn assert_open_snapshot(&self, snapshot: &Snapshot<'tcx>) {
         // Failures here may indicate a failure to follow a stack discipline.
         assert!(self.logs.len() >= snapshot.undo_len);
diff --git a/compiler/rustc_interface/messages.ftl b/compiler/rustc_interface/messages.ftl
index 37994899a20..be1a75f020b 100644
--- a/compiler/rustc_interface/messages.ftl
+++ b/compiler/rustc_interface/messages.ftl
@@ -1,33 +1,43 @@
-interface_ferris_identifier =
-    Ferris cannot be used as an identifier
-    .suggestion = try using their name instead
+interface_cant_emit_mir =
+    could not emit MIR: {$error}
 
 interface_emoji_identifier =
     identifiers cannot contain emoji: `{$ident}`
 
-interface_mixed_bin_crate =
-    cannot mix `bin` crate type with others
-
-interface_mixed_proc_macro_crate =
-    cannot mix `proc-macro` crate type with others
-
 interface_error_writing_dependencies =
     error writing dependencies to `{$path}`: {$error}
 
-interface_input_file_would_be_overwritten =
-    the input file "{$path}" would be overwritten by the generated executable
+interface_failed_writing_file =
+    failed to write file {$path}: {$error}"
+
+interface_ferris_identifier =
+    Ferris cannot be used as an identifier
+    .suggestion = try using their name instead
 
 interface_generated_file_conflicts_with_directory =
     the generated executable for the input file "{$input_path}" conflicts with the existing directory "{$dir_path}"
 
-interface_temps_dir_error =
-    failed to find or create the directory specified by `--temps-dir`
+interface_ignoring_extra_filename = ignoring -C extra-filename flag due to -o flag
+
+interface_ignoring_out_dir = ignoring --out-dir flag due to -o flag
+
+interface_input_file_would_be_overwritten =
+    the input file "{$path}" would be overwritten by the generated executable
+
+interface_mixed_bin_crate =
+    cannot mix `bin` crate type with others
+
+interface_mixed_proc_macro_crate =
+    cannot mix `proc-macro` crate type with others
+
+interface_multiple_output_types_adaption =
+    due to multiple output types requested, the explicitly specified output file name will be adapted for each output type
 
 interface_out_dir_error =
     failed to find or create the directory specified by `--out-dir`
 
-interface_cant_emit_mir =
-    could not emit MIR: {$error}
+interface_proc_macro_crate_panic_abort =
+    building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic
 
 interface_rustc_error_fatal =
     fatal error triggered by #[rustc_error]
@@ -35,18 +45,8 @@ interface_rustc_error_fatal =
 interface_rustc_error_unexpected_annotation =
     unexpected annotation used with `#[rustc_error(...)]`!
 
-interface_failed_writing_file =
-    failed to write file {$path}: {$error}"
-
-interface_proc_macro_crate_panic_abort =
-    building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic
+interface_temps_dir_error =
+    failed to find or create the directory specified by `--temps-dir`
 
 interface_unsupported_crate_type_for_target =
     dropping unsupported crate type `{$crate_type}` for target `{$target_triple}`
-
-interface_multiple_output_types_adaption =
-    due to multiple output types requested, the explicitly specified output file name will be adapted for each output type
-
-interface_ignoring_extra_filename = ignoring -C extra-filename flag due to -o flag
-
-interface_ignoring_out_dir = ignoring --out-dir flag due to -o flag
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index e1658d3ff82..e707ac41a05 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -5,6 +5,202 @@ lint_array_into_iter =
     .use_explicit_into_iter_suggestion =
         or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
 
+lint_atomic_ordering_fence = memory fences cannot have `Relaxed` ordering
+    .help = consider using ordering modes `Acquire`, `Release`, `AcqRel` or `SeqCst`
+
+lint_atomic_ordering_invalid = `{$method}`'s failure ordering may not be `Release` or `AcqRel`, since a failed `{$method}` does not result in a write
+    .label = invalid failure ordering
+    .help = consider using `Acquire` or `Relaxed` failure ordering instead
+
+lint_atomic_ordering_load = atomic loads cannot have `Release` or `AcqRel` ordering
+    .help = consider using ordering modes `Acquire`, `SeqCst` or `Relaxed`
+
+lint_atomic_ordering_store = atomic stores cannot have `Acquire` or `AcqRel` ordering
+    .help = consider using ordering modes `Release`, `SeqCst` or `Relaxed`
+
+lint_bad_attribute_argument = bad attribute argument
+
+lint_bad_opt_access = {$msg}
+
+lint_builtin_allow_internal_unsafe =
+    `allow_internal_unsafe` allows defining macros using unsafe without triggering the `unsafe_code` lint at their call site
+
+lint_builtin_anonymous_params = anonymous parameters are deprecated and will be removed in the next edition
+    .suggestion = try naming the parameter or explicitly ignoring it
+
+lint_builtin_asm_labels = avoid using named labels in inline assembly
+
+lint_builtin_box_pointers = type uses owned (Box type) pointers: {$ty}
+
+lint_builtin_clashing_extern_diff_name = `{$this}` redeclares `{$orig}` with a different signature
+    .previous_decl_label = `{$orig}` previously declared here
+    .mismatch_label = this signature doesn't match the previous declaration
+
+lint_builtin_clashing_extern_same_name = `{$this}` redeclared with a different signature
+    .previous_decl_label = `{$orig}` previously declared here
+    .mismatch_label = this signature doesn't match the previous declaration
+lint_builtin_const_no_mangle = const items should never be `#[no_mangle]`
+    .suggestion = try a static value
+
+lint_builtin_decl_unsafe_fn = declaration of an `unsafe` function
+lint_builtin_decl_unsafe_method = declaration of an `unsafe` method
+lint_builtin_deprecated_attr_default_suggestion = remove this attribute
+
+lint_builtin_deprecated_attr_link = use of deprecated attribute `{$name}`: {$reason}. See {$link}
+    .msg_suggestion = {$msg}
+    .default_suggestion = remove this attribute
+lint_builtin_deprecated_attr_used = use of deprecated attribute `{$name}`: no longer used.
+lint_builtin_deref_nullptr = dereferencing a null pointer
+    .label = this code causes undefined behavior when executed
+
+lint_builtin_ellipsis_inclusive_range_patterns = `...` range patterns are deprecated
+    .suggestion = use `..=` for an inclusive range
+
+lint_builtin_explicit_outlives = outlives requirements can be inferred
+    .suggestion = remove {$count ->
+        [one] this bound
+        *[other] these bounds
+    }
+
+lint_builtin_export_name_fn = declaration of a function with `export_name`
+lint_builtin_export_name_method = declaration of a method with `export_name`
+
+lint_builtin_export_name_static = declaration of a static with `export_name`
+lint_builtin_impl_unsafe_method = implementation of an `unsafe` method
+
+lint_builtin_incomplete_features = the feature `{$name}` is incomplete and may not be safe to use and/or cause compiler crashes
+    .note = see issue #{$n} <https://github.com/rust-lang/rust/issues/{$n}> for more information
+    .help = consider using `min_{$name}` instead, which is more stable and complete
+
+lint_builtin_keyword_idents = `{$kw}` is a keyword in the {$next} edition
+    .suggestion = you can use a raw identifier to stay compatible
+
+lint_builtin_link_section_fn = declaration of a function with `link_section`
+
+lint_builtin_link_section_static = declaration of a static with `link_section`
+
+lint_builtin_missing_copy_impl = type could implement `Copy`; consider adding `impl Copy`
+
+lint_builtin_missing_debug_impl =
+    type does not implement `{$debug}`; consider adding `#[derive(Debug)]` or a manual implementation
+
+lint_builtin_missing_doc = missing documentation for {$article} {$desc}
+
+lint_builtin_mutable_transmutes =
+    transmuting &T to &mut T is undefined behavior, even if the reference is unused, consider instead using an UnsafeCell
+
+lint_builtin_no_mangle_fn = declaration of a `no_mangle` function
+lint_builtin_no_mangle_generic = functions generic over types or consts must be mangled
+    .suggestion = remove this attribute
+
+lint_builtin_no_mangle_method = declaration of a `no_mangle` method
+lint_builtin_no_mangle_static = declaration of a `no_mangle` static
+lint_builtin_non_shorthand_field_patterns = the `{$ident}:` in this pattern is redundant
+    .suggestion = use shorthand field pattern
+
+lint_builtin_overridden_symbol_name =
+    the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them
+
+lint_builtin_overridden_symbol_section =
+    the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them
+
+lint_builtin_special_module_name_used_lib = found module declaration for lib.rs
+    .note = lib.rs is the root of this crate's library target
+    .help = to refer to it from other targets, use the library's name as the path
+
+lint_builtin_special_module_name_used_main = found module declaration for main.rs
+    .note = a binary crate cannot be used as library
+
+lint_builtin_trivial_bounds = {$predicate_kind_name} bound {$predicate} does not depend on any type or lifetime parameters
+
+lint_builtin_type_alias_bounds_help = use fully disambiguated paths (i.e., `<T as Trait>::Assoc`) to refer to associated types in type aliases
+
+lint_builtin_type_alias_generic_bounds = bounds on generic parameters are not enforced in type aliases
+    .suggestion = the bound will not be checked when the type alias is used, and should be removed
+
+lint_builtin_type_alias_where_clause = where clauses are not enforced in type aliases
+    .suggestion = the clause will not be checked when the type alias is used, and should be removed
+
+lint_builtin_unexpected_cli_config_name = unexpected `{$name}` as condition name
+    .help = was set with `--cfg` but isn't in the `--check-cfg` expected names
+
+lint_builtin_unexpected_cli_config_value = unexpected condition value `{$value}` for condition name `{$name}`
+    .help = was set with `--cfg` but isn't in the `--check-cfg` expected values
+
+lint_builtin_unnameable_test_items = cannot test inner items
+
+lint_builtin_unpermitted_type_init_label = this code causes undefined behavior when executed
+lint_builtin_unpermitted_type_init_label_suggestion = help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+
+lint_builtin_unpermitted_type_init_uninit = the type `{$ty}` does not permit being left uninitialized
+
+lint_builtin_unpermitted_type_init_zeroed = the type `{$ty}` does not permit zero-initialization
+lint_builtin_unreachable_pub = unreachable `pub` {$what}
+    .suggestion = consider restricting its visibility
+    .help = or consider exporting it for use by other crates
+
+lint_builtin_unsafe_block = usage of an `unsafe` block
+
+lint_builtin_unsafe_impl = implementation of an `unsafe` trait
+
+lint_builtin_unsafe_trait = declaration of an `unsafe` trait
+
+lint_builtin_unstable_features = unstable feature
+
+lint_builtin_unused_doc_comment = unused doc comment
+    .label = rustdoc does not generate documentation for {$kind}
+    .plain_help = use `//` for a plain comment
+    .block_help = use `/* */` for a plain comment
+
+lint_builtin_while_true = denote infinite loops with `loop {"{"} ... {"}"}`
+    .suggestion = use `loop`
+
+lint_check_name_deprecated = lint name `{$lint_name}` is deprecated and does not have an effect anymore. Use: {$new_name}
+
+lint_check_name_unknown = unknown lint: `{$lint_name}`
+    .help = did you mean: `{$suggestion}`
+
+lint_check_name_unknown_tool = unknown lint tool: `{$tool_name}`
+
+lint_check_name_warning = {$msg}
+
+lint_command_line_source = `forbid` lint level was set on command line
+
+lint_confusable_identifier_pair = identifier pair considered confusable between `{$existing_sym}` and `{$sym}`
+    .label = this is where the previous identifier occurred
+
+lint_cstring_ptr = getting the inner pointer of a temporary `CString`
+    .as_ptr_label = this pointer will be invalid
+    .unwrap_label = this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
+    .note = pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
+    .help = for more information, see https://doc.rust-lang.org/reference/destructors.html
+
+lint_default_hash_types = prefer `{$preferred}` over `{$used}`, it has better performance
+    .note = a `use rustc_data_structures::fx::{$preferred}` may be necessary
+
+lint_default_source = `forbid` lint level is the default for {$id}
+
+lint_deprecated_lint_name =
+    lint name `{$name}` is deprecated and may not have an effect in the future.
+    .suggestion = change it to
+
+lint_diag_out_of_impl =
+    diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls
+
+lint_drop_glue =
+    types that do not implement `Drop` can still have drop glue, consider instead using `{$needs_drop}` to detect whether a type is trivially dropped
+
+lint_drop_trait_constraints =
+    bounds on `{$predicate}` are most likely incorrect, consider instead using `{$needs_drop}` to detect whether a type can be trivially dropped
+
+lint_dropping_copy_types = calls to `std::mem::drop` with a value that implements `Copy` does nothing
+    .label = argument has type `{$arg_ty}`
+    .note = use `let _ = ...` to ignore the expression or result
+
+lint_dropping_references = calls to `std::mem::drop` with a reference instead of an owned value does nothing
+    .label = argument has type `{$arg_ty}`
+    .note = use `let _ = ...` to ignore the expression or result
+
 lint_enum_intrinsics_mem_discriminant =
     the return value of `mem::discriminant` is unspecified when called with a non-enum type
     .note = the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `{$ty_param}`, which is not an enum.
@@ -24,49 +220,12 @@ lint_for_loops_over_fallibles =
     .use_while_let = to check pattern in a loop use `while let`
     .use_question_mark = consider unwrapping the `Result` with `?` to iterate over its contents
 
-lint_map_unit_fn = `Iterator::map` call that discard the iterator's values
-    .note = `Iterator::map`, like many of the methods on `Iterator`, gets executed lazily, meaning that its effects won't be visible until it is iterated
-    .function_label = this function returns `()`, which is likely not what you wanted
-    .argument_label = called `Iterator::map` with callable that returns `()`
-    .map_label = after this call to map, the resulting iterator is `impl Iterator<Item = ()>`, which means the only information carried by the iterator is the number of items
-    .suggestion = you might have meant to use `Iterator::for_each`
-
-lint_non_binding_let_on_sync_lock =
-    non-binding let on a synchronization lock
-
-lint_non_binding_let_on_drop_type =
-    non-binding let on a type that implements `Drop`
-
-lint_non_binding_let_suggestion =
-    consider binding to an unused variable to avoid immediately dropping the value
-
-lint_non_binding_let_multi_suggestion =
-    consider immediately dropping the value
-
-lint_deprecated_lint_name =
-    lint name `{$name}` is deprecated and may not have an effect in the future.
-    .suggestion = change it to
-
-lint_renamed_or_removed_lint = {$msg}
-    .suggestion = use the new name
-
-lint_suspicious_double_ref_op =
-    using `.{$call}()` on a double reference, which returns `{$ty}` instead of {$op ->
-        *[should_not_happen] [{$op}]
-        [deref] dereferencing
-        [borrow] borrowing
-        [clone] cloning
-    } the inner type
-
-lint_unknown_lint =
-    unknown lint: `{$name}`
-    .suggestion = did you mean
-
-lint_ignored_unless_crate_specified = {$level}({$name}) is ignored unless specified at crate level
-
-lint_unknown_gated_lint =
-    unknown lint: `{$name}`
-    .note = the `{$name}` lint is unstable
+lint_forgetting_copy_types = calls to `std::mem::forget` with a value that implements `Copy` does nothing
+    .label = argument has type `{$arg_ty}`
+    .note = use `let _ = ...` to ignore the expression or result
+lint_forgetting_references = calls to `std::mem::forget` with a reference instead of an owned value does nothing
+    .label = argument has type `{$arg_ty}`
+    .note = use `let _ = ...` to ignore the expression or result
 
 lint_hidden_unicode_codepoints = unicode codepoint changing visible direction of text present in {$label}
     .label = this {$label} contains {$count ->
@@ -81,56 +240,119 @@ lint_hidden_unicode_codepoints = unicode codepoint changing visible direction of
     .suggestion_escape = if you want to keep them but make them visible in your source code, you can escape them
     .no_suggestion_note_escape = if you want to keep them but make them visible in your source code, you can escape them: {$escaped}
 
-lint_default_hash_types = prefer `{$preferred}` over `{$used}`, it has better performance
-    .note = a `use rustc_data_structures::fx::{$preferred}` may be necessary
+lint_identifier_non_ascii_char = identifier contains non-ASCII characters
 
-lint_query_instability = using `{$query}` can result in unstable query results
-    .note = if you believe this case to be fine, allow this lint and add a comment explaining your rationale
+lint_identifier_uncommon_codepoints = identifier contains uncommon Unicode codepoints
 
-lint_tykind_kind = usage of `ty::TyKind::<kind>`
-    .suggestion = try using `ty::<kind>` directly
+lint_ignored_unless_crate_specified = {$level}({$name}) is ignored unless specified at crate level
 
-lint_tykind = usage of `ty::TyKind`
-    .help = try using `Ty` instead
+lint_improper_ctypes = `extern` {$desc} uses type `{$ty}`, which is not FFI-safe
+    .label = not FFI-safe
+    .note = the type is defined here
 
-lint_ty_qualified = usage of qualified `ty::{$ty}`
-    .suggestion = try importing it and using it unqualified
+lint_improper_ctypes_128bit = 128-bit integers don't currently have a known stable ABI
 
-lint_lintpass_by_hand = implementing `LintPass` by hand
-    .help = try using `declare_lint_pass!` or `impl_lint_pass!` instead
+lint_improper_ctypes_array_help = consider passing a pointer to the array
 
-lint_non_existent_doc_keyword = found non-existing keyword `{$keyword}` used in `#[doc(keyword = "...")]`
-    .help = only existing keywords are allowed in core/std
+lint_improper_ctypes_array_reason = passing raw arrays by value is not FFI-safe
+lint_improper_ctypes_box = box cannot be represented as a single pointer
 
-lint_diag_out_of_impl =
-    diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls
+lint_improper_ctypes_char_help = consider using `u32` or `libc::wchar_t` instead
 
-lint_untranslatable_diag = diagnostics should be created using translatable messages
+lint_improper_ctypes_char_reason = the `char` type has no C equivalent
+lint_improper_ctypes_dyn = trait objects have no C equivalent
 
-lint_trivial_untranslatable_diag = diagnostic with static strings only
+lint_improper_ctypes_enum_phantomdata = this enum contains a PhantomData field
 
-lint_bad_opt_access = {$msg}
+lint_improper_ctypes_enum_repr_help =
+    consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
 
-lint_cstring_ptr = getting the inner pointer of a temporary `CString`
-    .as_ptr_label = this pointer will be invalid
-    .unwrap_label = this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
-    .note = pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
-    .help = for more information, see https://doc.rust-lang.org/reference/destructors.html
+lint_improper_ctypes_enum_repr_reason = enum has no representation hint
+lint_improper_ctypes_fnptr_help = consider using an `extern fn(...) -> ...` function pointer instead
 
-lint_multiple_supertrait_upcastable = `{$ident}` is object-safe and has multiple supertraits
+lint_improper_ctypes_fnptr_reason = this function pointer has Rust-specific calling convention
+lint_improper_ctypes_non_exhaustive = this enum is non-exhaustive
+lint_improper_ctypes_non_exhaustive_variant = this enum has non-exhaustive variants
 
-lint_identifier_non_ascii_char = identifier contains non-ASCII characters
+lint_improper_ctypes_only_phantomdata = composed only of `PhantomData`
 
-lint_identifier_uncommon_codepoints = identifier contains uncommon Unicode codepoints
+lint_improper_ctypes_opaque = opaque types have no C equivalent
 
-lint_confusable_identifier_pair = identifier pair considered confusable between `{$existing_sym}` and `{$sym}`
-    .label = this is where the previous identifier occurred
+lint_improper_ctypes_slice_help = consider using a raw pointer instead
+
+lint_improper_ctypes_slice_reason = slices have no C equivalent
+lint_improper_ctypes_str_help = consider using `*const u8` and a length instead
+
+lint_improper_ctypes_str_reason = string slices have no C equivalent
+lint_improper_ctypes_struct_fieldless_help = consider adding a member to this struct
+
+lint_improper_ctypes_struct_fieldless_reason = this struct has no fields
+lint_improper_ctypes_struct_layout_help = consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
+
+lint_improper_ctypes_struct_layout_reason = this struct has unspecified layout
+lint_improper_ctypes_struct_non_exhaustive = this struct is non-exhaustive
+lint_improper_ctypes_struct_zst = this struct contains only zero-sized fields
+
+lint_improper_ctypes_tuple_help = consider using a struct instead
+
+lint_improper_ctypes_tuple_reason = tuples have unspecified layout
+lint_improper_ctypes_union_fieldless_help = consider adding a member to this union
+
+lint_improper_ctypes_union_fieldless_reason = this union has no fields
+lint_improper_ctypes_union_layout_help = consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this union
+
+lint_improper_ctypes_union_layout_reason = this union has unspecified layout
+lint_improper_ctypes_union_non_exhaustive = this union is non-exhaustive
+
+# FIXME: we should ordinalize $valid_up_to when we add support for doing so
+lint_invalid_from_utf8_checked = calls to `{$method}` with a invalid literal always return an error
+    .label = the literal was valid UTF-8 up to the {$valid_up_to} bytes
+
+# FIXME: we should ordinalize $valid_up_to when we add support for doing so
+lint_invalid_from_utf8_unchecked = calls to `{$method}` with a invalid literal are undefined behavior
+    .label = the literal was valid UTF-8 up to the {$valid_up_to} bytes
+
+lint_lintpass_by_hand = implementing `LintPass` by hand
+    .help = try using `declare_lint_pass!` or `impl_lint_pass!` instead
+
+lint_malformed_attribute = malformed lint attribute input
+
+lint_map_unit_fn = `Iterator::map` call that discard the iterator's values
+    .note = `Iterator::map`, like many of the methods on `Iterator`, gets executed lazily, meaning that its effects won't be visible until it is iterated
+    .function_label = this function returns `()`, which is likely not what you wanted
+    .argument_label = called `Iterator::map` with callable that returns `()`
+    .map_label = after this call to map, the resulting iterator is `impl Iterator<Item = ()>`, which means the only information carried by the iterator is the number of items
+    .suggestion = you might have meant to use `Iterator::for_each`
 
 lint_mixed_script_confusables =
     the usage of Script Group `{$set}` in this crate consists solely of mixed script confusables
     .includes_note = the usage includes {$includes}
     .note = please recheck to make sure their usages are indeed what you want
 
+lint_multiple_supertrait_upcastable = `{$ident}` is object-safe and has multiple supertraits
+
+lint_node_source = `forbid` level set here
+    .note = {$reason}
+
+lint_non_binding_let_multi_suggestion =
+    consider immediately dropping the value
+
+lint_non_binding_let_on_drop_type =
+    non-binding let on a type that implements `Drop`
+
+lint_non_binding_let_on_sync_lock =
+    non-binding let on a synchronization lock
+
+lint_non_binding_let_suggestion =
+    consider binding to an unused variable to avoid immediately dropping the value
+
+lint_non_camel_case_type = {$sort} `{$name}` should have an upper camel case name
+    .suggestion = convert the identifier to upper camel case
+    .label = should have an UpperCamelCase name
+
+lint_non_existent_doc_keyword = found non-existing keyword `{$keyword}` used in `#[doc(keyword = "...")]`
+    .help = only existing keywords are allowed in core/std
+
 lint_non_fmt_panic = panic message is not a string literal
     .note = this usage of `{$name}!()` is deprecated; it will be a hard error in Rust 2021
     .more_info_note = for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
@@ -144,6 +366,14 @@ lint_non_fmt_panic = panic message is not a string literal
         *[false] use
     } std::panic::panic_any instead
 
+lint_non_fmt_panic_braces =
+    panic message contains {$count ->
+        [one] a brace
+        *[other] braces
+    }
+    .note = this message is not used as a format string, but will be in Rust 2021
+    .suggestion = add a "{"{"}{"}"}" format string to use the message literally
+
 lint_non_fmt_panic_unused =
     panic message contains {$count ->
         [one] an unused
@@ -159,18 +389,6 @@ lint_non_fmt_panic_unused =
     }
     .add_fmt_suggestion = or add a "{"{"}{"}"}" format string to use the message literally
 
-lint_non_fmt_panic_braces =
-    panic message contains {$count ->
-        [one] a brace
-        *[other] braces
-    }
-    .note = this message is not used as a format string, but will be in Rust 2021
-    .suggestion = add a "{"{"}{"}"}" format string to use the message literally
-
-lint_non_camel_case_type = {$sort} `{$name}` should have an upper camel case name
-    .suggestion = convert the identifier to upper camel case
-    .label = should have an UpperCamelCase name
-
 lint_non_snake_case = {$sort} `{$name}` should have a snake case name
     .rename_or_convert_suggestion = rename the identifier or convert it to a snake case raw identifier
     .cannot_convert_note = `{$sc}` cannot be used as a raw identifier
@@ -187,29 +405,13 @@ lint_noop_method_call = call to `.{$method}()` on a reference in this situation
     .label = unnecessary method call
     .note = the type `{$receiver_ty}` which `{$method}` is being called on is the same as the type returned from `{$method}`, so the method call does not do anything and can be removed
 
-lint_pass_by_value = passing `{$ty}` by reference
-    .suggestion = try passing by value
-
-lint_redundant_semicolons =
-    unnecessary trailing {$multiple ->
-        [true] semicolons
-        *[false] semicolon
-    }
-    .suggestion = remove {$multiple ->
-        [true] these semicolons
-        *[false] this semicolon
-    }
-
-lint_drop_trait_constraints =
-    bounds on `{$predicate}` are most likely incorrect, consider instead using `{$needs_drop}` to detect whether a type can be trivially dropped
-
-lint_drop_glue =
-    types that do not implement `Drop` can still have drop glue, consider instead using `{$needs_drop}` to detect whether a type is trivially dropped
-
-lint_range_endpoint_out_of_range = range endpoint is out of range for `{$ty}`
+lint_only_cast_u8_to_char = only `u8` can be cast into `char`
+    .suggestion = use a `char` literal instead
 
-lint_range_use_inclusive_range = use an inclusive range instead
+lint_opaque_hidden_inferred_bound = opaque type `{$ty}` does not satisfy its associated type bounds
+    .specifically = this associated type bound is unsatisfied for `{$proj_ty}`
 
+lint_opaque_hidden_inferred_bound_sugg = add this bound
 
 lint_overflowing_bin_hex = literal out of range for `{$ty}`
     .negative_note = the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}`
@@ -222,96 +424,92 @@ lint_overflowing_int = literal out of range for `{$ty}`
     .note = the literal `{$lit}` does not fit into the type `{$ty}` whose range is `{$min}..={$max}`
     .help = consider using the type `{$suggestion_ty}` instead
 
-lint_only_cast_u8_to_char = only `u8` can be cast into `char`
-    .suggestion = use a `char` literal instead
-
-lint_overflowing_uint = literal out of range for `{$ty}`
-    .note = the literal `{$lit}` does not fit into the type `{$ty}` whose range is `{$min}..={$max}`
-
 lint_overflowing_literal = literal out of range for `{$ty}`
     .note = the literal `{$lit}` does not fit into the type `{$ty}` and will be converted to `{$ty}::INFINITY`
 
-lint_unused_comparisons = comparison is useless due to type limits
-
-lint_improper_ctypes = `extern` {$desc} uses type `{$ty}`, which is not FFI-safe
-    .label = not FFI-safe
-    .note = the type is defined here
-
-lint_improper_ctypes_opaque = opaque types have no C equivalent
+lint_overflowing_uint = literal out of range for `{$ty}`
+    .note = the literal `{$lit}` does not fit into the type `{$ty}` whose range is `{$min}..={$max}`
 
-lint_improper_ctypes_fnptr_reason = this function pointer has Rust-specific calling convention
-lint_improper_ctypes_fnptr_help = consider using an `extern fn(...) -> ...` function pointer instead
+lint_overruled_attribute = {$lint_level}({$lint_source}) incompatible with previous forbid
+    .label = overruled by previous forbid
 
-lint_improper_ctypes_tuple_reason = tuples have unspecified layout
-lint_improper_ctypes_tuple_help = consider using a struct instead
+lint_pass_by_value = passing `{$ty}` by reference
+    .suggestion = try passing by value
 
-lint_improper_ctypes_str_reason = string slices have no C equivalent
-lint_improper_ctypes_str_help = consider using `*const u8` and a length instead
+lint_path_statement_drop = path statement drops value
+    .suggestion = use `drop` to clarify the intent
 
-lint_improper_ctypes_dyn = trait objects have no C equivalent
+lint_path_statement_no_effect = path statement with no effect
 
-lint_improper_ctypes_slice_reason = slices have no C equivalent
-lint_improper_ctypes_slice_help = consider using a raw pointer instead
+lint_query_instability = using `{$query}` can result in unstable query results
+    .note = if you believe this case to be fine, allow this lint and add a comment explaining your rationale
 
-lint_improper_ctypes_128bit = 128-bit integers don't currently have a known stable ABI
+lint_range_endpoint_out_of_range = range endpoint is out of range for `{$ty}`
 
-lint_improper_ctypes_char_reason = the `char` type has no C equivalent
-lint_improper_ctypes_char_help = consider using `u32` or `libc::wchar_t` instead
+lint_range_use_inclusive_range = use an inclusive range instead
 
-lint_improper_ctypes_non_exhaustive = this enum is non-exhaustive
-lint_improper_ctypes_non_exhaustive_variant = this enum has non-exhaustive variants
 
-lint_improper_ctypes_enum_repr_reason = enum has no representation hint
-lint_improper_ctypes_enum_repr_help =
-    consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+lint_reason_must_be_string_literal = reason must be a string literal
 
-lint_improper_ctypes_struct_fieldless_reason = this struct has no fields
-lint_improper_ctypes_struct_fieldless_help = consider adding a member to this struct
+lint_reason_must_come_last = reason in lint attribute must come last
 
-lint_improper_ctypes_union_fieldless_reason = this union has no fields
-lint_improper_ctypes_union_fieldless_help = consider adding a member to this union
+lint_redundant_semicolons =
+    unnecessary trailing {$multiple ->
+        [true] semicolons
+        *[false] semicolon
+    }
+    .suggestion = remove {$multiple ->
+        [true] these semicolons
+        *[false] this semicolon
+    }
 
-lint_improper_ctypes_struct_non_exhaustive = this struct is non-exhaustive
-lint_improper_ctypes_union_non_exhaustive = this union is non-exhaustive
+lint_renamed_or_removed_lint = {$msg}
+    .suggestion = use the new name
 
-lint_improper_ctypes_struct_layout_reason = this struct has unspecified layout
-lint_improper_ctypes_struct_layout_help = consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
+lint_requested_level = requested on the command line with `{$level} {$lint_name}`
 
-lint_improper_ctypes_union_layout_reason = this union has unspecified layout
-lint_improper_ctypes_union_layout_help = consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this union
+lint_supertrait_as_deref_target = `{$t}` implements `Deref` with supertrait `{$target_principal}` as target
+    .label = target type is set here
 
-lint_improper_ctypes_box = box cannot be represented as a single pointer
+lint_suspicious_double_ref_op =
+    using `.{$call}()` on a double reference, which returns `{$ty}` instead of {$op ->
+        *[should_not_happen] [{$op}]
+        [deref] dereferencing
+        [borrow] borrowing
+        [clone] cloning
+    } the inner type
 
-lint_improper_ctypes_enum_phantomdata = this enum contains a PhantomData field
+lint_trivial_untranslatable_diag = diagnostic with static strings only
 
-lint_improper_ctypes_struct_zst = this struct contains only zero-sized fields
+lint_ty_qualified = usage of qualified `ty::{$ty}`
+    .suggestion = try importing it and using it unqualified
 
-lint_improper_ctypes_array_reason = passing raw arrays by value is not FFI-safe
-lint_improper_ctypes_array_help = consider passing a pointer to the array
+lint_tykind = usage of `ty::TyKind`
+    .help = try using `Ty` instead
 
-lint_improper_ctypes_only_phantomdata = composed only of `PhantomData`
+lint_tykind_kind = usage of `ty::TyKind::<kind>`
+    .suggestion = try using `ty::<kind>` directly
 
-lint_variant_size_differences =
-    enum variant is more than three times larger ({$largest} bytes) than the next largest
+lint_ungated_async_fn_track_caller = `#[track_caller]` on async functions is a no-op
+     .label = this function will not propagate the caller location
 
-lint_atomic_ordering_load = atomic loads cannot have `Release` or `AcqRel` ordering
-    .help = consider using ordering modes `Acquire`, `SeqCst` or `Relaxed`
+lint_unknown_gated_lint =
+    unknown lint: `{$name}`
+    .note = the `{$name}` lint is unstable
 
-lint_atomic_ordering_store = atomic stores cannot have `Acquire` or `AcqRel` ordering
-    .help = consider using ordering modes `Release`, `SeqCst` or `Relaxed`
+lint_unknown_lint =
+    unknown lint: `{$name}`
+    .suggestion = did you mean
 
-lint_atomic_ordering_fence = memory fences cannot have `Relaxed` ordering
-    .help = consider using ordering modes `Acquire`, `Release`, `AcqRel` or `SeqCst`
+lint_unknown_tool_in_scoped_lint = unknown tool name `{$tool_name}` found in scoped lint: `{$tool_name}::{$lint_name}`
+    .help = add `#![register_tool({$tool_name})]` to the crate root
 
-lint_atomic_ordering_invalid = `{$method}`'s failure ordering may not be `Release` or `AcqRel`, since a failed `{$method}` does not result in a write
-    .label = invalid failure ordering
-    .help = consider using `Acquire` or `Relaxed` failure ordering instead
+lint_unsupported_group = `{$lint_group}` lint group is not supported with ´--force-warn´
 
-lint_unused_op = unused {$op} that must be used
-    .label = the {$op} produces a value
-    .suggestion = use `let _ = ...` to ignore the resulting value
+lint_untranslatable_diag = diagnostics should be created using translatable messages
 
-lint_unused_result = unused result of type `{$ty}`
+lint_unused_allocation = unnecessary allocation, use `&` instead
+lint_unused_allocation_mut = unnecessary allocation, use `&mut` instead
 
 lint_unused_closure =
     unused {$pre}{$count ->
@@ -320,219 +518,28 @@ lint_unused_closure =
     }{$post} that must be used
     .note = closures are lazy and do nothing unless called
 
-lint_unused_generator =
-    unused {$pre}{$count ->
-        [one] generator
-        *[other] generator
-    }{$post} that must be used
-    .note = generators are lazy and do nothing unless resumed
+lint_unused_comparisons = comparison is useless due to type limits
 
 lint_unused_def = unused {$pre}`{$def}`{$post} that must be used
     .suggestion = use `let _ = ...` to ignore the resulting value
 
-lint_path_statement_drop = path statement drops value
-    .suggestion = use `drop` to clarify the intent
-
-lint_path_statement_no_effect = path statement with no effect
-
 lint_unused_delim = unnecessary {$delim} around {$item}
     .suggestion = remove these {$delim}
 
-lint_unused_import_braces = braces around {$node} is unnecessary
-
-lint_unused_allocation = unnecessary allocation, use `&` instead
-lint_unused_allocation_mut = unnecessary allocation, use `&mut` instead
-
-lint_builtin_while_true = denote infinite loops with `loop {"{"} ... {"}"}`
-    .suggestion = use `loop`
-
-lint_builtin_box_pointers = type uses owned (Box type) pointers: {$ty}
-
-lint_builtin_non_shorthand_field_patterns = the `{$ident}:` in this pattern is redundant
-    .suggestion = use shorthand field pattern
-
-lint_builtin_overridden_symbol_name =
-    the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them
-
-lint_builtin_overridden_symbol_section =
-    the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them
-
-lint_builtin_allow_internal_unsafe =
-    `allow_internal_unsafe` allows defining macros using unsafe without triggering the `unsafe_code` lint at their call site
-
-lint_builtin_unsafe_block = usage of an `unsafe` block
-
-lint_builtin_unsafe_trait = declaration of an `unsafe` trait
-
-lint_builtin_unsafe_impl = implementation of an `unsafe` trait
-
-lint_builtin_no_mangle_fn = declaration of a `no_mangle` function
-lint_builtin_export_name_fn = declaration of a function with `export_name`
-lint_builtin_link_section_fn = declaration of a function with `link_section`
-
-lint_builtin_no_mangle_static = declaration of a `no_mangle` static
-lint_builtin_export_name_static = declaration of a static with `export_name`
-lint_builtin_link_section_static = declaration of a static with `link_section`
-
-lint_builtin_no_mangle_method = declaration of a `no_mangle` method
-lint_builtin_export_name_method = declaration of a method with `export_name`
-
-lint_builtin_decl_unsafe_fn = declaration of an `unsafe` function
-lint_builtin_decl_unsafe_method = declaration of an `unsafe` method
-lint_builtin_impl_unsafe_method = implementation of an `unsafe` method
-
-lint_builtin_missing_doc = missing documentation for {$article} {$desc}
-
-lint_builtin_missing_copy_impl = type could implement `Copy`; consider adding `impl Copy`
-
-lint_builtin_missing_debug_impl =
-    type does not implement `{$debug}`; consider adding `#[derive(Debug)]` or a manual implementation
-
-lint_builtin_anonymous_params = anonymous parameters are deprecated and will be removed in the next edition
-    .suggestion = try naming the parameter or explicitly ignoring it
-
-lint_builtin_deprecated_attr_link = use of deprecated attribute `{$name}`: {$reason}. See {$link}
-    .msg_suggestion = {$msg}
-    .default_suggestion = remove this attribute
-lint_builtin_deprecated_attr_used = use of deprecated attribute `{$name}`: no longer used.
-lint_builtin_deprecated_attr_default_suggestion = remove this attribute
-
-lint_builtin_unused_doc_comment = unused doc comment
-    .label = rustdoc does not generate documentation for {$kind}
-    .plain_help = use `//` for a plain comment
-    .block_help = use `/* */` for a plain comment
-
-lint_builtin_no_mangle_generic = functions generic over types or consts must be mangled
-    .suggestion = remove this attribute
-
-lint_builtin_const_no_mangle = const items should never be `#[no_mangle]`
-    .suggestion = try a static value
-
-lint_builtin_mutable_transmutes =
-    transmuting &T to &mut T is undefined behavior, even if the reference is unused, consider instead using an UnsafeCell
-
-lint_builtin_unstable_features = unstable feature
-
-lint_ungated_async_fn_track_caller = `#[track_caller]` on async functions is a no-op
-     .label = this function will not propagate the caller location
-
-lint_builtin_unreachable_pub = unreachable `pub` {$what}
-    .suggestion = consider restricting its visibility
-    .help = or consider exporting it for use by other crates
-
-lint_builtin_unexpected_cli_config_name = unexpected `{$name}` as condition name
-    .help = was set with `--cfg` but isn't in the `--check-cfg` expected names
-
-lint_builtin_unexpected_cli_config_value = unexpected condition value `{$value}` for condition name `{$name}`
-    .help = was set with `--cfg` but isn't in the `--check-cfg` expected values
-
-lint_builtin_type_alias_bounds_help = use fully disambiguated paths (i.e., `<T as Trait>::Assoc`) to refer to associated types in type aliases
-
-lint_builtin_type_alias_where_clause = where clauses are not enforced in type aliases
-    .suggestion = the clause will not be checked when the type alias is used, and should be removed
-
-lint_builtin_type_alias_generic_bounds = bounds on generic parameters are not enforced in type aliases
-    .suggestion = the bound will not be checked when the type alias is used, and should be removed
-
-lint_builtin_trivial_bounds = {$predicate_kind_name} bound {$predicate} does not depend on any type or lifetime parameters
-
-lint_builtin_ellipsis_inclusive_range_patterns = `...` range patterns are deprecated
-    .suggestion = use `..=` for an inclusive range
-
-lint_builtin_unnameable_test_items = cannot test inner items
-
-lint_builtin_keyword_idents = `{$kw}` is a keyword in the {$next} edition
-    .suggestion = you can use a raw identifier to stay compatible
-
-lint_builtin_explicit_outlives = outlives requirements can be inferred
-    .suggestion = remove {$count ->
-        [one] this bound
-        *[other] these bounds
-    }
-
-lint_builtin_incomplete_features = the feature `{$name}` is incomplete and may not be safe to use and/or cause compiler crashes
-    .note = see issue #{$n} <https://github.com/rust-lang/rust/issues/{$n}> for more information
-    .help = consider using `min_{$name}` instead, which is more stable and complete
-
-lint_builtin_unpermitted_type_init_zeroed = the type `{$ty}` does not permit zero-initialization
-lint_builtin_unpermitted_type_init_uninit = the type `{$ty}` does not permit being left uninitialized
-
-lint_builtin_unpermitted_type_init_label = this code causes undefined behavior when executed
-lint_builtin_unpermitted_type_init_label_suggestion = help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
-
-lint_builtin_clashing_extern_same_name = `{$this}` redeclared with a different signature
-    .previous_decl_label = `{$orig}` previously declared here
-    .mismatch_label = this signature doesn't match the previous declaration
-lint_builtin_clashing_extern_diff_name = `{$this}` redeclares `{$orig}` with a different signature
-    .previous_decl_label = `{$orig}` previously declared here
-    .mismatch_label = this signature doesn't match the previous declaration
-
-lint_builtin_deref_nullptr = dereferencing a null pointer
-    .label = this code causes undefined behavior when executed
-
-lint_builtin_asm_labels = avoid using named labels in inline assembly
-
-lint_builtin_special_module_name_used_lib = found module declaration for lib.rs
-    .note = lib.rs is the root of this crate's library target
-    .help = to refer to it from other targets, use the library's name as the path
-
-lint_builtin_special_module_name_used_main = found module declaration for main.rs
-    .note = a binary crate cannot be used as library
-
-lint_supertrait_as_deref_target = `{$t}` implements `Deref` with supertrait `{$target_principal}` as target
-    .label = target type is set here
-
-lint_overruled_attribute = {$lint_level}({$lint_source}) incompatible with previous forbid
-    .label = overruled by previous forbid
-
-lint_default_source = `forbid` lint level is the default for {$id}
-
-lint_node_source = `forbid` level set here
-    .note = {$reason}
-
-lint_command_line_source = `forbid` lint level was set on command line
-
-lint_malformed_attribute = malformed lint attribute input
-
-lint_bad_attribute_argument = bad attribute argument
-
-lint_reason_must_be_string_literal = reason must be a string literal
-
-lint_reason_must_come_last = reason in lint attribute must come last
-
-lint_unknown_tool_in_scoped_lint = unknown tool name `{$tool_name}` found in scoped lint: `{$tool_name}::{$lint_name}`
-    .help = add `#![register_tool({$tool_name})]` to the crate root
-
-lint_unsupported_group = `{$lint_group}` lint group is not supported with ´--force-warn´
-
-lint_requested_level = requested on the command line with `{$level} {$lint_name}`
-
-lint_check_name_unknown = unknown lint: `{$lint_name}`
-    .help = did you mean: `{$suggestion}`
-
-lint_check_name_unknown_tool = unknown lint tool: `{$tool_name}`
-
-lint_check_name_warning = {$msg}
-
-lint_check_name_deprecated = lint name `{$lint_name}` is deprecated and does not have an effect anymore. Use: {$new_name}
-
-lint_opaque_hidden_inferred_bound = opaque type `{$ty}` does not satisfy its associated type bounds
-    .specifically = this associated type bound is unsatisfied for `{$proj_ty}`
-
-lint_opaque_hidden_inferred_bound_sugg = add this bound
+lint_unused_generator =
+    unused {$pre}{$count ->
+        [one] generator
+        *[other] generator
+    }{$post} that must be used
+    .note = generators are lazy and do nothing unless resumed
 
-lint_dropping_references = calls to `std::mem::drop` with a reference instead of an owned value does nothing
-    .label = argument has type `{$arg_ty}`
-    .note = use `let _ = ...` to ignore the expression or result
+lint_unused_import_braces = braces around {$node} is unnecessary
 
-lint_dropping_copy_types = calls to `std::mem::drop` with a value that implements `Copy` does nothing
-    .label = argument has type `{$arg_ty}`
-    .note = use `let _ = ...` to ignore the expression or result
+lint_unused_op = unused {$op} that must be used
+    .label = the {$op} produces a value
+    .suggestion = use `let _ = ...` to ignore the resulting value
 
-lint_forgetting_references = calls to `std::mem::forget` with a reference instead of an owned value does nothing
-    .label = argument has type `{$arg_ty}`
-    .note = use `let _ = ...` to ignore the expression or result
+lint_unused_result = unused result of type `{$ty}`
 
-lint_forgetting_copy_types = calls to `std::mem::forget` with a value that implements `Copy` does nothing
-    .label = argument has type `{$arg_ty}`
-    .note = use `let _ = ...` to ignore the expression or result
+lint_variant_size_differences =
+    enum variant is more than three times larger ({$largest} bytes) than the next largest
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 1d0c43e95e0..947530a1b65 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -952,6 +952,10 @@ pub trait LintContext: Sized {
                     db.span_label(first_reexport_span, format!("the name `{}` in the {} namespace is first re-exported here", name, namespace));
                     db.span_label(duplicate_reexport_span, format!("but the name `{}` in the {} namespace is also re-exported here", name, namespace));
                 }
+                BuiltinLintDiagnostics::HiddenGlobReexports { name, namespace, glob_reexport_span, private_item_span } => {
+                    db.span_label(glob_reexport_span, format!("the name `{}` in the {} namespace is supposed to be publicly re-exported here", name, namespace));
+                    db.span_label(private_item_span, "but the private item here shadows it");
+                }
             }
             // Rewrap `db`, and pass control to the user.
             decorate(db)
diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs
index bbae3d368f4..68167487a1b 100644
--- a/compiler/rustc_lint/src/errors.rs
+++ b/compiler/rustc_lint/src/errors.rs
@@ -39,7 +39,7 @@ impl AddToDiagnostic for OverruledAttributeSub {
                 diag.span_label(span, fluent::lint_node_source);
                 if let Some(rationale) = reason {
                     #[allow(rustc::untranslatable_diagnostic)]
-                    diag.note(rationale.as_str());
+                    diag.note(rationale.to_string());
                 }
             }
             OverruledAttributeSub::CommandLineSource => {
diff --git a/compiler/rustc_lint/src/invalid_from_utf8.rs b/compiler/rustc_lint/src/invalid_from_utf8.rs
new file mode 100644
index 00000000000..3291286ad67
--- /dev/null
+++ b/compiler/rustc_lint/src/invalid_from_utf8.rs
@@ -0,0 +1,118 @@
+use std::str::Utf8Error;
+
+use rustc_ast::{BorrowKind, LitKind};
+use rustc_hir::{Expr, ExprKind};
+use rustc_span::source_map::Spanned;
+use rustc_span::sym;
+
+use crate::lints::InvalidFromUtf8Diag;
+use crate::{LateContext, LateLintPass, LintContext};
+
+declare_lint! {
+    /// The `invalid_from_utf8_unchecked` lint checks for calls to
+    /// `std::str::from_utf8_unchecked` and `std::str::from_utf8_unchecked_mut`
+    /// with an invalid UTF-8 literal.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,compile_fail
+    /// # #[allow(unused)]
+    /// unsafe {
+    ///     std::str::from_utf8_unchecked(b"Ru\x82st");
+    /// }
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Creating such a `str` would result in undefined behavior as per documentation
+    /// for `std::str::from_utf8_unchecked` and `std::str::from_utf8_unchecked_mut`.
+    pub INVALID_FROM_UTF8_UNCHECKED,
+    Deny,
+    "using a non UTF-8 literal in `std::str::from_utf8_unchecked`"
+}
+
+declare_lint! {
+    /// The `invalid_from_utf8` lint checks for calls to
+    /// `std::str::from_utf8` and `std::str::from_utf8_mut`
+    /// with an invalid UTF-8 literal.
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// # #[allow(unused)]
+    /// std::str::from_utf8(b"Ru\x82st");
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Trying to create such a `str` would always return an error as per documentation
+    /// for `std::str::from_utf8` and `std::str::from_utf8_mut`.
+    pub INVALID_FROM_UTF8,
+    Warn,
+    "using a non UTF-8 literal in `std::str::from_utf8`"
+}
+
+declare_lint_pass!(InvalidFromUtf8 => [INVALID_FROM_UTF8_UNCHECKED, INVALID_FROM_UTF8]);
+
+impl<'tcx> LateLintPass<'tcx> for InvalidFromUtf8 {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
+        if let ExprKind::Call(path, [arg]) = expr.kind
+            && let ExprKind::Path(ref qpath) = path.kind
+            && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
+            && let Some(diag_item) = cx.tcx.get_diagnostic_name(def_id)
+            && [sym::str_from_utf8, sym::str_from_utf8_mut,
+                sym::str_from_utf8_unchecked, sym::str_from_utf8_unchecked_mut].contains(&diag_item)
+        {
+            let lint = |utf8_error: Utf8Error| {
+                let label = arg.span;
+                let method = diag_item.as_str().strip_prefix("str_").unwrap();
+                let method = format!("std::str::{method}");
+                let valid_up_to = utf8_error.valid_up_to();
+                let is_unchecked_variant = diag_item.as_str().contains("unchecked");
+
+                cx.emit_spanned_lint(
+                    if is_unchecked_variant { INVALID_FROM_UTF8_UNCHECKED } else { INVALID_FROM_UTF8 },
+                    expr.span,
+                    if is_unchecked_variant {
+                        InvalidFromUtf8Diag::Unchecked { method,  valid_up_to, label }
+                    } else {
+                        InvalidFromUtf8Diag::Checked { method,  valid_up_to, label }
+                    }
+                )
+            };
+
+            match &arg.kind {
+                ExprKind::Lit(Spanned { node: lit, .. }) => {
+                    if let LitKind::ByteStr(bytes, _) = &lit
+                        && let Err(utf8_error) = std::str::from_utf8(bytes)
+                    {
+                        lint(utf8_error);
+                    }
+                },
+                ExprKind::AddrOf(BorrowKind::Ref, _, Expr { kind: ExprKind::Array(args), .. }) => {
+                    let elements = args.iter().map(|e|{
+                        match &e.kind {
+                            ExprKind::Lit(Spanned { node: lit, .. }) => match lit {
+                                LitKind::Byte(b) => Some(*b),
+                                LitKind::Int(b, _) => Some(*b as u8),
+                                _ => None
+                            }
+                            _ => None
+                        }
+                    }).collect::<Option<Vec<_>>>();
+
+                    if let Some(elements) = elements
+                        && let Err(utf8_error) = std::str::from_utf8(&elements)
+                    {
+                        lint(utf8_error);
+                    }
+                }
+                _ => {}
+            }
+        }
+    }
+}
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index b92ed11f38a..8376835f52c 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -242,7 +242,9 @@ impl LintLevelsProvider for LintLevelQueryMap<'_> {
 
 struct QueryMapExpectationsWrapper<'tcx> {
     tcx: TyCtxt<'tcx>,
+    /// HirId of the currently investigated element.
     cur: HirId,
+    /// Level map for `cur`.
     specs: ShallowLintLevelMap,
     expectations: Vec<(LintExpectationId, LintExpectation)>,
     unstable_to_stable_ids: FxHashMap<LintExpectationId, LintExpectationId>,
@@ -255,11 +257,11 @@ impl LintLevelsProvider for QueryMapExpectationsWrapper<'_> {
         self.specs.specs.get(&self.cur.local_id).unwrap_or(&self.empty)
     }
     fn insert(&mut self, id: LintId, lvl: LevelAndSource) {
-        let specs = self.specs.specs.get_mut_or_insert_default(self.cur.local_id);
-        specs.clear();
-        specs.insert(id, lvl);
+        self.specs.specs.get_mut_or_insert_default(self.cur.local_id).insert(id, lvl);
     }
     fn get_lint_level(&self, lint: &'static Lint, _: &Session) -> LevelAndSource {
+        // We cannot use `tcx.lint_level_at_node` because we want to know in which order the
+        // attributes have been inserted, in particular whether an `expect` follows a `forbid`.
         self.specs.lint_level_id_at_node(self.tcx, LintId::of(lint), self.cur)
     }
     fn push_expectation(&mut self, id: LintExpectationId, expectation: LintExpectation) {
@@ -355,7 +357,9 @@ impl<'tcx> Visitor<'tcx> for LintLevelsBuilder<'_, LintLevelQueryMap<'tcx>> {
 
 impl<'tcx> LintLevelsBuilder<'_, QueryMapExpectationsWrapper<'tcx>> {
     fn add_id(&mut self, hir_id: HirId) {
+        // Change both the `HirId` and the associated specs.
         self.provider.cur = hir_id;
+        self.provider.specs.specs.clear();
         self.add(self.provider.tcx.hir().attrs(hir_id), hir_id == hir::CRATE_HIR_ID, Some(hir_id));
     }
 }
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index dfddfe09ab3..c62109b2986 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -60,6 +60,7 @@ mod expect;
 mod for_loops_over_fallibles;
 pub mod hidden_unicode_codepoints;
 mod internal;
+mod invalid_from_utf8;
 mod late;
 mod let_underscore;
 mod levels;
@@ -102,6 +103,7 @@ use enum_intrinsics_non_enums::EnumIntrinsicsNonEnums;
 use for_loops_over_fallibles::*;
 use hidden_unicode_codepoints::*;
 use internal::*;
+use invalid_from_utf8::*;
 use let_underscore::*;
 use map_unit_fn::*;
 use methods::*;
@@ -207,6 +209,7 @@ late_lint_methods!(
             HardwiredLints: HardwiredLints,
             ImproperCTypesDeclarations: ImproperCTypesDeclarations,
             ImproperCTypesDefinitions: ImproperCTypesDefinitions,
+            InvalidFromUtf8: InvalidFromUtf8,
             VariantSizeDifferences: VariantSizeDifferences,
             BoxPointers: BoxPointers,
             PathStatements: PathStatements,
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index de1c2be2875..746abebeb37 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -699,6 +699,25 @@ pub struct ForgetCopyDiag<'a> {
     pub label: Span,
 }
 
+// invalid_from_utf8.rs
+#[derive(LintDiagnostic)]
+pub enum InvalidFromUtf8Diag {
+    #[diag(lint_invalid_from_utf8_unchecked)]
+    Unchecked {
+        method: String,
+        valid_up_to: usize,
+        #[label]
+        label: Span,
+    },
+    #[diag(lint_invalid_from_utf8_checked)]
+    Checked {
+        method: String,
+        valid_up_to: usize,
+        #[label]
+        label: Span,
+    },
+}
+
 // hidden_unicode_codepoints.rs
 #[derive(LintDiagnostic)]
 #[diag(lint_hidden_unicode_codepoints)]
@@ -1527,7 +1546,7 @@ impl<'a> DecorateLint<'a, ()> for UnusedDef<'_, '_> {
         diag.set_arg("def", self.cx.tcx.def_path_str(self.def_id));
         // check for #[must_use = "..."]
         if let Some(note) = self.note {
-            diag.note(note.as_str());
+            diag.note(note.to_string());
         }
         if let Some(sugg) = self.suggestion {
             diag.subdiagnostic(sugg);
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 6e9dc880a7d..1507087bdd4 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -3272,6 +3272,43 @@ declare_lint! {
     "ambiguous glob re-exports",
 }
 
+declare_lint! {
+    /// The `hidden_glob_reexports` lint detects cases where glob re-export items are shadowed by
+    /// private items.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,compile_fail
+    /// #![deny(hidden_glob_reexports)]
+    ///
+    /// pub mod upstream {
+    ///     mod inner { pub struct Foo {}; pub struct Bar {}; }
+    ///     pub use self::inner::*;
+    ///     struct Foo {} // private item shadows `inner::Foo`
+    /// }
+    ///
+    /// // mod downstream {
+    /// //     fn test() {
+    /// //         let _ = crate::upstream::Foo; // inaccessible
+    /// //     }
+    /// // }
+    ///
+    /// pub fn main() {}
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// This was previously accepted without any errors or warnings but it could silently break a
+    /// crate's downstream user code. If the `struct Foo` was added, `dep::inner::Foo` would
+    /// silently become inaccessible and trigger a "`struct `Foo` is private`" visibility error at
+    /// the downstream use site.
+    pub HIDDEN_GLOB_REEXPORTS,
+    Warn,
+    "name introduced by a private item shadows a name introduced by a public glob re-export",
+}
+
 declare_lint_pass! {
     /// Does nothing as a lint pass, but registers some `Lint`s
     /// that are used by other parts of the compiler.
@@ -3304,6 +3341,7 @@ declare_lint_pass! {
         FORBIDDEN_LINT_GROUPS,
         FUNCTION_ITEM_REFERENCES,
         FUZZY_PROVENANCE_CASTS,
+        HIDDEN_GLOB_REEXPORTS,
         ILL_FORMED_ATTRIBUTE_INPUT,
         ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
         IMPLIED_BOUNDS_ENTAILMENT,
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index e27e322db88..5a5031b7919 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -540,6 +540,16 @@ pub enum BuiltinLintDiagnostics {
         /// Span where the same name is also re-exported.
         duplicate_reexport_span: Span,
     },
+    HiddenGlobReexports {
+        /// The name of the local binding which shadows the glob re-export.
+        name: String,
+        /// The namespace for which the shadowing occurred in.
+        namespace: String,
+        /// The glob reexport that is shadowed by the local binding.
+        glob_reexport_span: Span,
+        /// The local binding that shadows the glob reexport.
+        private_item_span: Span,
+    },
 }
 
 /// Lints that are buffered up early on in the `Session` before the
diff --git a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h
index 05890628378..af6f4d5eaf9 100644
--- a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h
+++ b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h
@@ -96,6 +96,7 @@ enum LLVMRustAttribute {
   AllocatedPointer = 38,
   AllocAlign = 39,
 #endif
+  SanitizeSafeStack = 40,
 };
 
 typedef struct OpaqueRustString *RustStringRef;
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index 49acd71b3e1..ea04899ab68 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -234,6 +234,8 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
   case AllocAlign:
     return Attribute::AllocAlign;
 #endif
+  case SanitizeSafeStack:
+    return Attribute::SafeStack;
   }
   report_fatal_error("bad AttributeKind");
 }
diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl
index 79b8b417257..6d8601b9e2b 100644
--- a/compiler/rustc_metadata/messages.ftl
+++ b/compiler/rustc_metadata/messages.ftl
@@ -1,288 +1,288 @@
-metadata_rlib_required =
-    crate `{$crate_name}` required to be available in rlib format, but was not found in this form
-
-metadata_lib_required =
-    crate `{$crate_name}` required to be available in {$kind} format, but was not found in this form
+metadata_as_needed_compatibility =
+    linking modifier `as-needed` is only compatible with `dylib` and `framework` linking kinds
 
-metadata_rustc_lib_required =
-    crate `{$crate_name}` required to be available in {$kind} format, but was not found in this form
-    .note = only .rmeta files are distributed for `rustc_private` crates other than `rustc_driver`
-    .help = try adding `extern crate rustc_driver;` at the top level of this crate
+metadata_bad_panic_strategy =
+    the linked panic runtime `{$runtime}` is not compiled with this crate's panic strategy `{$strategy}`
 
-metadata_crate_dep_multiple =
-    cannot satisfy dependencies so `{$crate_name}` only shows up once
-    .help = having upstream crates all available in one format will likely make this go away
+metadata_bundle_needs_static =
+    linking modifier `bundle` is only compatible with `static` linking kind
 
-metadata_two_panic_runtimes =
-    cannot link together two panic runtimes: {$prev_name} and {$cur_name}
+metadata_cannot_find_crate =
+    can't find crate for `{$crate_name}`{$add_info}
 
-metadata_bad_panic_strategy =
-    the linked panic runtime `{$runtime}` is not compiled with this crate's panic strategy `{$strategy}`
+metadata_cant_find_crate =
+    can't find crate
 
-metadata_required_panic_strategy =
-    the crate `{$crate_name}` requires panic strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}`
+metadata_compiler_missing_profiler =
+    the compiler may have been built without the profiler runtime
 
-metadata_incompatible_panic_in_drop_strategy =
-    the crate `{$crate_name}` is compiled with the panic-in-drop strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}`
+metadata_conflicting_alloc_error_handler =
+    the `#[alloc_error_handler]` in {$other_crate_name} conflicts with allocation error handler in: {$crate_name}
 
-metadata_multiple_names_in_link =
-    multiple `name` arguments in a single `#[link]` attribute
+metadata_conflicting_global_alloc =
+    the `#[global_allocator]` in {$other_crate_name} conflicts with global allocator in: {$crate_name}
 
-metadata_multiple_kinds_in_link =
-    multiple `kind` arguments in a single `#[link]` attribute
+metadata_consider_building_std =
+    consider building the standard library from source with `cargo build -Zbuild-std`
 
-metadata_link_name_form =
-    link name must be of the form `name = "string"`
+metadata_consider_downloading_target =
+    consider downloading the target with `rustup target add {$locator_triple}`
 
-metadata_link_kind_form =
-    link kind must be of the form `kind = "string"`
+metadata_crate_dep_multiple =
+    cannot satisfy dependencies so `{$crate_name}` only shows up once
+    .help = having upstream crates all available in one format will likely make this go away
 
-metadata_link_modifiers_form =
-    link modifiers must be of the form `modifiers = "string"`
+metadata_crate_location_unknown_type =
+    extern location for {$crate_name} is of an unknown type: {$path}
 
-metadata_link_cfg_form =
-    link cfg must be of the form `cfg(/* predicate */)`
+metadata_crate_not_panic_runtime =
+    the crate `{$crate_name}` is not a panic runtime
 
-metadata_wasm_import_form =
-    wasm import module must be of the form `wasm_import_module = "string"`
+metadata_dl_error =
+    {$err}
 
 metadata_empty_link_name =
     link name must not be empty
     .label = empty link name
 
-metadata_link_framework_apple =
-    link kind `framework` is only supported on Apple targets
+metadata_empty_renaming_target =
+    an empty renaming target was specified for library `{$lib_name}`
 
-metadata_framework_only_windows =
-    link kind `raw-dylib` is only supported on Windows targets
+metadata_extern_location_not_exist =
+    extern location for {$crate_name} does not exist: {$location}
 
-metadata_unknown_link_kind =
-    unknown link kind `{$kind}`, expected one of: static, dylib, framework, raw-dylib
-    .label = unknown link kind
+metadata_extern_location_not_file =
+    extern location for {$crate_name} is not a file: {$location}
 
-metadata_multiple_link_modifiers =
-    multiple `modifiers` arguments in a single `#[link]` attribute
+metadata_fail_create_file_encoder =
+    failed to create file encoder: {$err}
 
-metadata_multiple_cfgs =
-    multiple `cfg` arguments in a single `#[link]` attribute
+metadata_fail_seek_file =
+    failed to seek the file: {$err}
 
-metadata_link_cfg_single_predicate =
-    link cfg must have a single predicate argument
+metadata_fail_write_file =
+    failed to write to the file: {$err}
 
-metadata_multiple_wasm_import =
-    multiple `wasm_import_module` arguments in a single `#[link]` attribute
+metadata_failed_create_encoded_metadata =
+    failed to create encoded metadata from file: {$err}
 
-metadata_unexpected_link_arg =
-    unexpected `#[link]` argument, expected one of: name, kind, modifiers, cfg, wasm_import_module, import_name_type
+metadata_failed_create_file =
+    failed to create the file {$filename}: {$err}
 
-metadata_invalid_link_modifier =
-    invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed
+metadata_failed_create_tempdir =
+    couldn't create a temp dir: {$err}
 
-metadata_multiple_modifiers =
-    multiple `{$modifier}` modifiers in a single `modifiers` argument
+metadata_failed_write_error =
+    failed to write {$filename}: {$err}
 
-metadata_bundle_needs_static =
-    linking modifier `bundle` is only compatible with `static` linking kind
+metadata_found_crate_versions =
+    the following crate versions were found:{$found_crates}
 
-metadata_whole_archive_needs_static =
-    linking modifier `whole-archive` is only compatible with `static` linking kind
+metadata_found_staticlib =
+    found staticlib `{$crate_name}` instead of rlib or dylib{$add_info}
+    .help = please recompile that crate using --crate-type lib
 
-metadata_as_needed_compatibility =
-    linking modifier `as-needed` is only compatible with `dylib` and `framework` linking kinds
+metadata_framework_only_windows =
+    link kind `raw-dylib` is only supported on Windows targets
 
-metadata_unknown_link_modifier =
-    unknown linking modifier `{$modifier}`, expected one of: bundle, verbatim, whole-archive, as-needed
+metadata_global_alloc_required =
+    no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait
+
+metadata_import_name_type_form =
+    import name type must be of the form `import_name_type = "string"`
+
+metadata_import_name_type_raw =
+    import name type can only be used with link kind `raw-dylib`
+
+metadata_import_name_type_x86 =
+    import name type is only supported on x86
+
+metadata_incompatible_panic_in_drop_strategy =
+    the crate `{$crate_name}` is compiled with the panic-in-drop strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}`
+
+metadata_incompatible_rustc =
+    found crate `{$crate_name}` compiled by an incompatible version of rustc{$add_info}
+    .help = please recompile that crate using this compiler ({$rustc_version}) (consider running `cargo clean` first)
 
 metadata_incompatible_wasm_link =
     `wasm_import_module` is incompatible with other arguments in `#[link]` attributes
 
-metadata_link_requires_name =
-    `#[link]` attribute requires a `name = "string"` argument
-    .label = missing `name` argument
+metadata_install_missing_components =
+    maybe you need to install the missing components with: `rustup component add rust-src rustc-dev llvm-tools-preview`
 
-metadata_raw_dylib_no_nul =
-    link name must not contain NUL characters if link kind is `raw-dylib`
+metadata_invalid_link_modifier =
+    invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed
 
-metadata_link_ordinal_raw_dylib =
-    `#[link_ordinal]` is only supported if link kind is `raw-dylib`
+metadata_invalid_meta_files =
+    found invalid metadata files for crate `{$crate_name}`{$add_info}
+
+metadata_lib_filename_form =
+    file name should be lib*.rlib or {$dll_prefix}*{$dll_suffix}
 
 metadata_lib_framework_apple =
     library kind `framework` is only supported on Apple targets
 
-metadata_empty_renaming_target =
-    an empty renaming target was specified for library `{$lib_name}`
+metadata_lib_required =
+    crate `{$crate_name}` required to be available in {$kind} format, but was not found in this form
 
-metadata_renaming_no_link =
-    renaming of the library `{$lib_name}` was specified, however this crate contains no `#[link(...)]` attributes referencing this library
+metadata_link_cfg_form =
+    link cfg must be of the form `cfg(/* predicate */)`
 
-metadata_multiple_renamings =
-    multiple renamings were specified for library `{$lib_name}`
+metadata_link_cfg_single_predicate =
+    link cfg must have a single predicate argument
 
-metadata_no_link_mod_override =
-    overriding linking modifiers from command line is not supported
+metadata_link_framework_apple =
+    link kind `framework` is only supported on Apple targets
 
-metadata_unsupported_abi_i686 =
-    ABI not supported by `#[link(kind = "raw-dylib")]` on i686
+metadata_link_kind_form =
+    link kind must be of the form `kind = "string"`
 
-metadata_unsupported_abi =
-    ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture
+metadata_link_modifiers_form =
+    link modifiers must be of the form `modifiers = "string"`
 
-metadata_fail_create_file_encoder =
-    failed to create file encoder: {$err}
+metadata_link_name_form =
+    link name must be of the form `name = "string"`
 
-metadata_fail_seek_file =
-    failed to seek the file: {$err}
+metadata_link_ordinal_raw_dylib =
+    `#[link_ordinal]` is only supported if link kind is `raw-dylib`
 
-metadata_fail_write_file =
-    failed to write to the file: {$err}
+metadata_link_requires_name =
+    `#[link]` attribute requires a `name = "string"` argument
+    .label = missing `name` argument
 
-metadata_crate_not_panic_runtime =
-    the crate `{$crate_name}` is not a panic runtime
+metadata_missing_native_library =
+    could not find native static library `{$libname}`, perhaps an -L flag is missing?
 
-metadata_no_panic_strategy =
-    the crate `{$crate_name}` does not have the panic strategy `{$strategy}`
+metadata_multiple_candidates =
+    multiple candidates for `{$flavor}` dependency `{$crate_name}` found
 
-metadata_profiler_builtins_needs_core =
-    `profiler_builtins` crate (required by compiler options) is not compatible with crate attribute `#![no_core]`
+metadata_multiple_cfgs =
+    multiple `cfg` arguments in a single `#[link]` attribute
 
-metadata_not_profiler_runtime =
-    the crate `{$crate_name}` is not a profiler runtime
+metadata_multiple_import_name_type =
+    multiple `import_name_type` arguments in a single `#[link]` attribute
 
-metadata_no_multiple_global_alloc =
-    cannot define multiple global allocators
-    .label = cannot define a new global allocator
+metadata_multiple_kinds_in_link =
+    multiple `kind` arguments in a single `#[link]` attribute
 
-metadata_prev_global_alloc =
-    previous global allocator defined here
+metadata_multiple_link_modifiers =
+    multiple `modifiers` arguments in a single `#[link]` attribute
 
-metadata_no_multiple_alloc_error_handler =
-    cannot define multiple allocation error handlers
-    .label = cannot define a new allocation error handler
+metadata_multiple_modifiers =
+    multiple `{$modifier}` modifiers in a single `modifiers` argument
 
-metadata_prev_alloc_error_handler =
-    previous allocation error handler defined here
+metadata_multiple_names_in_link =
+    multiple `name` arguments in a single `#[link]` attribute
 
-metadata_conflicting_global_alloc =
-    the `#[global_allocator]` in {$other_crate_name} conflicts with global allocator in: {$crate_name}
+metadata_multiple_renamings =
+    multiple renamings were specified for library `{$lib_name}`
 
-metadata_conflicting_alloc_error_handler =
-    the `#[alloc_error_handler]` in {$other_crate_name} conflicts with allocation error handler in: {$crate_name}
+metadata_multiple_wasm_import =
+    multiple `wasm_import_module` arguments in a single `#[link]` attribute
 
-metadata_global_alloc_required =
-    no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait
+metadata_newer_crate_version =
+    found possibly newer version of crate `{$crate_name}`{$add_info}
+    .note = perhaps that crate needs to be recompiled?
 
-metadata_no_transitive_needs_dep =
-    the crate `{$crate_name}` cannot depend on a crate that needs {$needs_crate_name}, but it depends on `{$deps_crate_name}`
+metadata_no_crate_with_triple =
+    couldn't find crate `{$crate_name}` with expected target triple {$locator_triple}{$add_info}
 
-metadata_failed_write_error =
-    failed to write {$filename}: {$err}
+metadata_no_dylib_plugin =
+    plugin `{$crate_name}` only found in rlib format, but must be available in dylib format
 
-metadata_missing_native_library =
-    could not find native static library `{$libname}`, perhaps an -L flag is missing?
+metadata_no_link_mod_override =
+    overriding linking modifiers from command line is not supported
 
-metadata_only_provide_library_name = only provide the library name `{$suggested_name}`, not the full filename
+metadata_no_multiple_alloc_error_handler =
+    cannot define multiple allocation error handlers
+    .label = cannot define a new allocation error handler
 
-metadata_failed_create_tempdir =
-    couldn't create a temp dir: {$err}
+metadata_no_multiple_global_alloc =
+    cannot define multiple global allocators
+    .label = cannot define a new global allocator
 
-metadata_failed_create_file =
-    failed to create the file {$filename}: {$err}
+metadata_no_panic_strategy =
+    the crate `{$crate_name}` does not have the panic strategy `{$strategy}`
 
-metadata_failed_create_encoded_metadata =
-    failed to create encoded metadata from file: {$err}
+metadata_no_transitive_needs_dep =
+    the crate `{$crate_name}` cannot depend on a crate that needs {$needs_crate_name}, but it depends on `{$deps_crate_name}`
 
 metadata_non_ascii_name =
     cannot load a crate with a non-ascii name `{$crate_name}`
 
-metadata_extern_location_not_exist =
-    extern location for {$crate_name} does not exist: {$location}
-
-metadata_extern_location_not_file =
-    extern location for {$crate_name} is not a file: {$location}
-
-metadata_multiple_candidates =
-    multiple candidates for `{$flavor}` dependency `{$crate_name}` found
+metadata_not_profiler_runtime =
+    the crate `{$crate_name}` is not a profiler runtime
 
-metadata_symbol_conflicts_current =
-    the current crate is indistinguishable from one of its dependencies: it has the same crate-name `{$crate_name}` and was compiled with the same `-C metadata` arguments. This will result in symbol conflicts between the two.
+metadata_only_provide_library_name = only provide the library name `{$suggested_name}`, not the full filename
 
-metadata_symbol_conflicts_others =
-    found two different crates with name `{$crate_name}` that are not distinguished by differing `-C metadata`. This will result in symbol conflicts between the two.
+metadata_prev_alloc_error_handler =
+    previous allocation error handler defined here
 
-metadata_stable_crate_id_collision =
-    found crates (`{$crate_name0}` and `{$crate_name1}`) with colliding StableCrateId values.
+metadata_prev_global_alloc =
+    previous global allocator defined here
 
-metadata_dl_error =
-    {$err}
+metadata_profiler_builtins_needs_core =
+    `profiler_builtins` crate (required by compiler options) is not compatible with crate attribute `#![no_core]`
 
-metadata_newer_crate_version =
-    found possibly newer version of crate `{$crate_name}`{$add_info}
-    .note = perhaps that crate needs to be recompiled?
+metadata_raw_dylib_no_nul =
+    link name must not contain NUL characters if link kind is `raw-dylib`
 
-metadata_found_crate_versions =
-    the following crate versions were found:{$found_crates}
+metadata_renaming_no_link =
+    renaming of the library `{$lib_name}` was specified, however this crate contains no `#[link(...)]` attributes referencing this library
 
-metadata_no_crate_with_triple =
-    couldn't find crate `{$crate_name}` with expected target triple {$locator_triple}{$add_info}
+metadata_required_panic_strategy =
+    the crate `{$crate_name}` requires panic strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}`
 
-metadata_found_staticlib =
-    found staticlib `{$crate_name}` instead of rlib or dylib{$add_info}
-    .help = please recompile that crate using --crate-type lib
+metadata_rlib_required =
+    crate `{$crate_name}` required to be available in rlib format, but was not found in this form
 
-metadata_incompatible_rustc =
-    found crate `{$crate_name}` compiled by an incompatible version of rustc{$add_info}
-    .help = please recompile that crate using this compiler ({$rustc_version}) (consider running `cargo clean` first)
+metadata_rustc_lib_required =
+    crate `{$crate_name}` required to be available in {$kind} format, but was not found in this form
+    .note = only .rmeta files are distributed for `rustc_private` crates other than `rustc_driver`
+    .help = try adding `extern crate rustc_driver;` at the top level of this crate
 
-metadata_invalid_meta_files =
-    found invalid metadata files for crate `{$crate_name}`{$add_info}
+metadata_stable_crate_id_collision =
+    found crates (`{$crate_name0}` and `{$crate_name1}`) with colliding StableCrateId values.
 
-metadata_cannot_find_crate =
-    can't find crate for `{$crate_name}`{$add_info}
+metadata_std_required =
+    `std` is required by `{$current_crate}` because it does not declare `#![no_std]`
 
-metadata_no_dylib_plugin =
-    plugin `{$crate_name}` only found in rlib format, but must be available in dylib format
+metadata_symbol_conflicts_current =
+    the current crate is indistinguishable from one of its dependencies: it has the same crate-name `{$crate_name}` and was compiled with the same `-C metadata` arguments. This will result in symbol conflicts between the two.
 
-metadata_target_not_installed =
-    the `{$locator_triple}` target may not be installed
+metadata_symbol_conflicts_others =
+    found two different crates with name `{$crate_name}` that are not distinguished by differing `-C metadata`. This will result in symbol conflicts between the two.
 
 metadata_target_no_std_support =
     the `{$locator_triple}` target may not support the standard library
 
-metadata_consider_downloading_target =
-    consider downloading the target with `rustup target add {$locator_triple}`
-
-metadata_std_required =
-    `std` is required by `{$current_crate}` because it does not declare `#![no_std]`
-
-metadata_consider_building_std =
-    consider building the standard library from source with `cargo build -Zbuild-std`
-
-metadata_compiler_missing_profiler =
-    the compiler may have been built without the profiler runtime
+metadata_target_not_installed =
+    the `{$locator_triple}` target may not be installed
 
-metadata_install_missing_components =
-    maybe you need to install the missing components with: `rustup component add rust-src rustc-dev llvm-tools-preview`
+metadata_two_panic_runtimes =
+    cannot link together two panic runtimes: {$prev_name} and {$cur_name}
 
-metadata_cant_find_crate =
-    can't find crate
+metadata_unexpected_link_arg =
+    unexpected `#[link]` argument, expected one of: name, kind, modifiers, cfg, wasm_import_module, import_name_type
 
-metadata_crate_location_unknown_type =
-    extern location for {$crate_name} is of an unknown type: {$path}
+metadata_unknown_import_name_type =
+    unknown import name type `{$import_name_type}`, expected one of: decorated, noprefix, undecorated
 
-metadata_lib_filename_form =
-    file name should be lib*.rlib or {$dll_prefix}*{$dll_suffix}
+metadata_unknown_link_kind =
+    unknown link kind `{$kind}`, expected one of: static, dylib, framework, raw-dylib
+    .label = unknown link kind
 
-metadata_multiple_import_name_type =
-    multiple `import_name_type` arguments in a single `#[link]` attribute
+metadata_unknown_link_modifier =
+    unknown linking modifier `{$modifier}`, expected one of: bundle, verbatim, whole-archive, as-needed
 
-metadata_import_name_type_form =
-    import name type must be of the form `import_name_type = "string"`
+metadata_unsupported_abi =
+    ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture
 
-metadata_import_name_type_x86 =
-    import name type is only supported on x86
+metadata_unsupported_abi_i686 =
+    ABI not supported by `#[link(kind = "raw-dylib")]` on i686
 
-metadata_unknown_import_name_type =
-    unknown import name type `{$import_name_type}`, expected one of: decorated, noprefix, undecorated
+metadata_wasm_import_form =
+    wasm import module must be of the form `wasm_import_module = "string"`
 
-metadata_import_name_type_raw =
-    import name type can only be used with link kind `raw-dylib`
+metadata_whole_archive_needs_static =
+    linking modifier `whole-archive` is only compatible with `static` linking kind
diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs
index ceb348f3469..a89d7b464e2 100644
--- a/compiler/rustc_metadata/src/locator.rs
+++ b/compiler/rustc_metadata/src/locator.rs
@@ -666,31 +666,30 @@ impl<'a> CrateLocator<'a> {
             return None;
         }
 
-        let root = metadata.get_root();
-        if root.is_proc_macro_crate() != self.is_proc_macro {
+        let header = metadata.get_header();
+        if header.is_proc_macro_crate != self.is_proc_macro {
             info!(
                 "Rejecting via proc macro: expected {} got {}",
-                self.is_proc_macro,
-                root.is_proc_macro_crate(),
+                self.is_proc_macro, header.is_proc_macro_crate,
             );
             return None;
         }
 
-        if self.exact_paths.is_empty() && self.crate_name != root.name() {
+        if self.exact_paths.is_empty() && self.crate_name != header.name {
             info!("Rejecting via crate name");
             return None;
         }
 
-        if root.triple() != &self.triple {
-            info!("Rejecting via crate triple: expected {} got {}", self.triple, root.triple());
+        if header.triple != self.triple {
+            info!("Rejecting via crate triple: expected {} got {}", self.triple, header.triple);
             self.crate_rejections.via_triple.push(CrateMismatch {
                 path: libpath.to_path_buf(),
-                got: root.triple().to_string(),
+                got: header.triple.to_string(),
             });
             return None;
         }
 
-        let hash = root.hash();
+        let hash = header.hash;
         if let Some(expected_hash) = self.hash {
             if hash != expected_hash {
                 info!("Rejecting via hash: expected {} got {}", expected_hash, hash);
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index cc4e60cf6ac..09e24e012af 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -74,6 +74,7 @@ pub(crate) struct CrateMetadata {
     blob: MetadataBlob,
 
     // --- Some data pre-decoded from the metadata blob, usually for performance ---
+    /// Data about the top-level items in a crate, as well as various crate-level metadata.
     root: CrateRoot,
     /// Trait impl data.
     /// FIXME: Used only from queries and can use query cache,
@@ -449,7 +450,7 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for SyntaxContext {
                 You need to explicitly pass `(crate_metadata_ref, tcx)` to `decode` instead of just `crate_metadata_ref`.");
         };
 
-        let cname = cdata.root.name;
+        let cname = cdata.root.name();
         rustc_span::hygiene::decode_syntax_context(decoder, &cdata.hygiene_context, |_, id| {
             debug!("SpecializedDecoder<SyntaxContext>: decoding {}", id);
             cdata
@@ -564,7 +565,7 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span {
                 let cnum = u32::decode(decoder);
                 panic!(
                     "Decoding of crate {:?} tried to access proc-macro dep {:?}",
-                    decoder.cdata().root.name,
+                    decoder.cdata().root.header.name,
                     cnum
                 );
             }
@@ -671,6 +672,16 @@ impl MetadataBlob {
             .decode(self)
     }
 
+    pub(crate) fn get_header(&self) -> CrateHeader {
+        let slice = &self.blob()[..];
+        let offset = METADATA_HEADER.len();
+
+        let pos_bytes = slice[offset..][..4].try_into().unwrap();
+        let pos = u32::from_be_bytes(pos_bytes) as usize;
+
+        LazyValue::<CrateHeader>::from_position(NonZeroUsize::new(pos).unwrap()).decode(self)
+    }
+
     pub(crate) fn get_root(&self) -> CrateRoot {
         let slice = &self.blob()[..];
         let offset = METADATA_HEADER.len();
@@ -684,8 +695,8 @@ impl MetadataBlob {
     pub(crate) fn list_crate_metadata(&self, out: &mut dyn io::Write) -> io::Result<()> {
         let root = self.get_root();
         writeln!(out, "Crate info:")?;
-        writeln!(out, "name {}{}", root.name, root.extra_filename)?;
-        writeln!(out, "hash {} stable_crate_id {:?}", root.hash, root.stable_crate_id)?;
+        writeln!(out, "name {}{}", root.name(), root.extra_filename)?;
+        writeln!(out, "hash {} stable_crate_id {:?}", root.hash(), root.stable_crate_id)?;
         writeln!(out, "proc_macro {:?}", root.proc_macro_data.is_some())?;
         writeln!(out, "=External Dependencies=")?;
 
@@ -709,21 +720,17 @@ impl CrateRoot {
     }
 
     pub(crate) fn name(&self) -> Symbol {
-        self.name
+        self.header.name
     }
 
     pub(crate) fn hash(&self) -> Svh {
-        self.hash
+        self.header.hash
     }
 
     pub(crate) fn stable_crate_id(&self) -> StableCrateId {
         self.stable_crate_id
     }
 
-    pub(crate) fn triple(&self) -> &TargetTriple {
-        &self.triple
-    }
-
     pub(crate) fn decode_crate_deps<'a>(
         &self,
         metadata: &'a MetadataBlob,
@@ -794,7 +801,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             bug!(
                 "CrateMetadata::def_kind({:?}): id not found, in crate {:?} with number {}",
                 item_id,
-                self.root.name,
+                self.root.name(),
                 self.cnum,
             )
         })
@@ -851,7 +858,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         } else {
             tcx.arena.alloc_from_iter(lazy.decode((self, tcx)))
         };
-        ty::EarlyBinder(&*output)
+        ty::EarlyBinder::bind(&*output)
     }
 
     fn get_variant(
@@ -1702,11 +1709,11 @@ impl CrateMetadata {
     }
 
     pub(crate) fn name(&self) -> Symbol {
-        self.root.name
+        self.root.header.name
     }
 
     pub(crate) fn hash(&self) -> Svh {
-        self.root.hash
+        self.root.header.hash
     }
 
     fn num_def_ids(&self) -> usize {
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 7425963d30f..3d8991d99b5 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -317,9 +317,9 @@ provide! { tcx, def_id, other, cdata,
     }
     native_libraries => { cdata.get_native_libraries(tcx.sess).collect() }
     foreign_modules => { cdata.get_foreign_modules(tcx.sess).map(|m| (m.def_id, m)).collect() }
-    crate_hash => { cdata.root.hash }
+    crate_hash => { cdata.root.header.hash }
     crate_host_hash => { cdata.host_hash }
-    crate_name => { cdata.root.name }
+    crate_name => { cdata.root.header.name }
 
     extra_filename => { cdata.root.extra_filename.clone() }
 
@@ -581,7 +581,7 @@ impl CrateStore for CStore {
     }
 
     fn crate_name(&self, cnum: CrateNum) -> Symbol {
-        self.get_crate_data(cnum).root.name
+        self.get_crate_data(cnum).root.header.name
     }
 
     fn stable_crate_id(&self, cnum: CrateNum) -> StableCrateId {
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index f067bca4b0b..c673eb5afc7 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -662,10 +662,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         let root = stat!("final", || {
             let attrs = tcx.hir().krate_attrs();
             self.lazy(CrateRoot {
-                name: tcx.crate_name(LOCAL_CRATE),
+                header: CrateHeader {
+                    name: tcx.crate_name(LOCAL_CRATE),
+                    triple: tcx.sess.opts.target_triple.clone(),
+                    hash: tcx.crate_hash(LOCAL_CRATE),
+                    is_proc_macro_crate: proc_macro_data.is_some(),
+                },
                 extra_filename: tcx.sess.opts.cg.extra_filename.clone(),
-                triple: tcx.sess.opts.target_triple.clone(),
-                hash: tcx.crate_hash(LOCAL_CRATE),
                 stable_crate_id: tcx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(),
                 required_panic_strategy: tcx.required_panic_strategy(LOCAL_CRATE),
                 panic_in_drop_strategy: tcx.sess.opts.unstable_opts.panic_in_drop,
@@ -1727,7 +1730,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             ty::Closure(_, substs) => {
                 let constness = self.tcx.constness(def_id.to_def_id());
                 self.tables.constness.set_some(def_id.to_def_id().index, constness);
-                record!(self.tables.fn_sig[def_id.to_def_id()] <- ty::EarlyBinder(substs.as_closure().sig()));
+                record!(self.tables.fn_sig[def_id.to_def_id()] <- ty::EarlyBinder::bind(substs.as_closure().sig()));
             }
 
             _ => bug!("closure that is neither generator nor closure"),
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index 97e67fcf8fd..ce2fe70a8b2 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -56,7 +56,7 @@ pub(crate) fn rustc_version(cfg_version: &'static str) -> String {
 /// Metadata encoding version.
 /// N.B., increment this if you change the format of metadata such that
 /// the rustc version can't be found to compare with `rustc_version()`.
-const METADATA_VERSION: u8 = 7;
+const METADATA_VERSION: u8 = 8;
 
 /// Metadata header which includes `METADATA_VERSION`.
 ///
@@ -199,7 +199,27 @@ pub(crate) struct ProcMacroData {
     macros: LazyArray<DefIndex>,
 }
 
-/// Serialized metadata for a crate.
+/// Serialized crate metadata.
+///
+/// This contains just enough information to determine if we should load the `CrateRoot` or not.
+/// Prefer [`CrateRoot`] whenever possible to avoid ICEs when using `omit-git-hash` locally.
+/// See #76720 for more details.
+///
+/// If you do modify this struct, also bump the [`METADATA_VERSION`] constant.
+#[derive(MetadataEncodable, MetadataDecodable)]
+pub(crate) struct CrateHeader {
+    pub(crate) triple: TargetTriple,
+    pub(crate) hash: Svh,
+    pub(crate) name: Symbol,
+    /// Whether this is the header for a proc-macro crate.
+    ///
+    /// This is separate from [`ProcMacroData`] to avoid having to update [`METADATA_VERSION`] every
+    /// time ProcMacroData changes.
+    pub(crate) is_proc_macro_crate: bool,
+}
+
+/// Serialized `.rmeta` data for a crate.
+///
 /// When compiling a proc-macro crate, we encode many of
 /// the `LazyArray<T>` fields as `Lazy::empty()`. This serves two purposes:
 ///
@@ -217,10 +237,10 @@ pub(crate) struct ProcMacroData {
 /// to being unused.
 #[derive(MetadataEncodable, MetadataDecodable)]
 pub(crate) struct CrateRoot {
-    name: Symbol,
-    triple: TargetTriple,
+    /// A header used to detect if this is the right crate to load.
+    header: CrateHeader,
+
     extra_filename: String,
-    hash: Svh,
     stable_crate_id: StableCrateId,
     required_panic_strategy: Option<PanicStrategy>,
     panic_in_drop_strategy: PanicStrategy,
@@ -465,6 +485,7 @@ trivially_parameterized_over_tcx! {
     RawDefId,
     TraitImpls,
     IncoherentImpls,
+    CrateHeader,
     CrateRoot,
     CrateDep,
     AttrFlags,
diff --git a/compiler/rustc_middle/messages.ftl b/compiler/rustc_middle/messages.ftl
index 64d511c261a..3d581daa925 100644
--- a/compiler/rustc_middle/messages.ftl
+++ b/compiler/rustc_middle/messages.ftl
@@ -1,45 +1,45 @@
+middle_cannot_be_normalized =
+    unable to determine layout for `{$ty}` because `{$failure_ty}` cannot be normalized
+
+middle_conflict_types =
+    this expression supplies two conflicting concrete types for the same opaque type
+
+middle_const_eval_non_int =
+    constant evaluation of enum discriminant resulted in non-integer
+
+middle_const_not_used_in_type_alias =
+    const parameter `{$ct}` is part of concrete type but not used in parameter list for the `impl Trait` type alias
+
+middle_cycle =
+    a cycle occurred during layout computation
+
 middle_drop_check_overflow =
     overflow while adding drop-check rules for {$ty}
     .note = overflowed on {$overflow_ty}
 
+middle_limit_invalid =
+    `limit` must be a non-negative integer
+    .label = {$error_str}
+
 middle_opaque_hidden_type_mismatch =
     concrete type differs from previous defining opaque type use
     .label = expected `{$self_ty}`, got `{$other_ty}`
 
-middle_conflict_types =
-    this expression supplies two conflicting concrete types for the same opaque type
-
 middle_previous_use_here =
     previous use here
 
-middle_limit_invalid =
-    `limit` must be a non-negative integer
-    .label = {$error_str}
-
 middle_recursion_limit_reached =
     reached the recursion limit finding the struct tail for `{$ty}`
     .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]`
 
-middle_const_eval_non_int =
-    constant evaluation of enum discriminant resulted in non-integer
-
-middle_unknown_layout =
-    the type `{$ty}` has an unknown layout
-
-middle_values_too_big =
-    values of the type `{$ty}` are too big for the current architecture
-
-middle_cannot_be_normalized =
-    unable to determine layout for `{$ty}` because `{$failure_ty}` cannot be normalized
-
-middle_cycle =
-    a cycle occurred during layout computation
+middle_requires_lang_item = requires `{$name}` lang_item
 
 middle_strict_coherence_needs_negative_coherence =
     to use `strict_coherence` on this trait, the `with_negative_coherence` feature must be enabled
     .label = due to this attribute
 
-middle_requires_lang_item = requires `{$name}` lang_item
+middle_unknown_layout =
+    the type `{$ty}` has an unknown layout
 
-middle_const_not_used_in_type_alias =
-    const parameter `{$ct}` is part of concrete type but not used in parameter list for the `impl Trait` type alias
+middle_values_too_big =
+    values of the type `{$ty}` are too big for the current architecture
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index 56171314944..29dae67bfca 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -415,7 +415,7 @@ impl<'tcx> CanonicalVarValues<'tcx> {
                                 var: ty::BoundVar::from_usize(i),
                                 kind: ty::BrAnon(None),
                             };
-                            tcx.mk_re_late_bound(ty::INNERMOST, br).into()
+                            ty::Region::new_late_bound(tcx, ty::INNERMOST, br).into()
                         }
                         CanonicalVarKind::Const(_, ty)
                         | CanonicalVarKind::PlaceholderConst(_, ty) => tcx
diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs
index 14343ac1108..caf3fc26039 100644
--- a/compiler/rustc_middle/src/lint.rs
+++ b/compiler/rustc_middle/src/lint.rs
@@ -251,7 +251,7 @@ pub fn explain_lint_level_source(
         }
         LintLevelSource::Node { name: lint_attr_name, span, reason, .. } => {
             if let Some(rationale) = reason {
-                err.note(rationale.as_str());
+                err.note(rationale.to_string());
             }
             err.span_note_once(span, "the lint level is defined here");
             if lint_attr_name.as_str() != name {
diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs
index 6354c0aabde..60844c17e47 100644
--- a/compiler/rustc_middle/src/middle/stability.rs
+++ b/compiler/rustc_middle/src/middle/stability.rs
@@ -104,7 +104,7 @@ pub fn report_unstable(
     suggestion: Option<(Span, String, String, Applicability)>,
     is_soft: bool,
     span: Span,
-    soft_handler: impl FnOnce(&'static Lint, Span, &str),
+    soft_handler: impl FnOnce(&'static Lint, Span, String),
 ) {
     let msg = match reason {
         Some(r) => format!("use of unstable library feature '{}': {}", feature, r),
@@ -112,7 +112,7 @@ pub fn report_unstable(
     };
 
     if is_soft {
-        soft_handler(SOFT_UNSTABLE, span, &msg)
+        soft_handler(SOFT_UNSTABLE, span, msg)
     } else {
         let mut err =
             feature_err_issue(&sess.parse_sess, feature, span, GateIssue::Library(issue), msg);
@@ -225,7 +225,7 @@ pub fn deprecation_message_and_lint(
 
 pub fn early_report_deprecation(
     lint_buffer: &mut LintBuffer,
-    message: &str,
+    message: String,
     suggestion: Option<Symbol>,
     lint: &'static Lint,
     span: Span,
@@ -241,7 +241,7 @@ pub fn early_report_deprecation(
 
 fn late_report_deprecation(
     tcx: TyCtxt<'_>,
-    message: &str,
+    message: String,
     suggestion: Option<Symbol>,
     lint: &'static Lint,
     span: Span,
@@ -396,7 +396,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
                         late_report_deprecation(
                             self,
-                            &deprecation_message(
+                            deprecation_message(
                                 is_in_effect,
                                 depr_attr.since,
                                 depr_attr.note,
@@ -619,7 +619,7 @@ impl<'tcx> TyCtxt<'tcx> {
         allow_unstable: AllowUnstable,
         unmarked: impl FnOnce(Span, DefId),
     ) -> bool {
-        let soft_handler = |lint, span, msg: &_| {
+        let soft_handler = |lint, span, msg: String| {
             self.struct_span_lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, msg, |lint| lint)
         };
         let eval_result =
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 5c71910a955..63cdba7f327 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -476,7 +476,7 @@ impl<'tcx> Body<'tcx> {
     /// Returns the return type; it always return first element from `local_decls` array.
     #[inline]
     pub fn bound_return_ty(&self) -> ty::EarlyBinder<Ty<'tcx>> {
-        ty::EarlyBinder(self.local_decls[RETURN_PLACE].ty)
+        ty::EarlyBinder::bind(self.local_decls[RETURN_PLACE].ty)
     }
 
     /// Gets the location of the terminator for the given block.
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index ff54ec56a29..f31b343c947 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -334,10 +334,7 @@ impl<'tcx> CodegenUnit<'tcx> {
     }
 
     pub fn modify_size_estimate(&mut self, delta: usize) {
-        assert!(self.size_estimate.is_some());
-        if let Some(size_estimate) = self.size_estimate {
-            self.size_estimate = Some(size_estimate + delta);
-        }
+        *self.size_estimate.as_mut().unwrap() += delta;
     }
 
     pub fn contains_item(&self, item: &MonoItem<'tcx>) -> bool {
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index 53fd2dd23a7..a15c419da7a 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -413,7 +413,7 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> {
             ty::ReVar(vid) => {
                 let br =
                     ty::BoundRegion { var: ty::BoundVar::new(vid.index()), kind: ty::BrAnon(None) };
-                tcx.mk_re_late_bound(depth, br)
+                ty::Region::new_late_bound(tcx, depth, br)
             }
             _ => bug!("unexpected region in ClosureOutlivesSubjectTy: {r:?}"),
         });
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 21faf1958e9..3e474c1d377 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -220,6 +220,11 @@ pub enum BorrowKind {
     /// immutable, but not aliasable. This solves the problem. For
     /// simplicity, we don't give users the way to express this
     /// borrow, it's just used when translating closures.
+    ///
+    // FIXME(#112072): This is wrong. Unique borrows are mutable borrows except
+    // that they do not require their pointee to be marked as a mutable.
+    // They should still be treated as mutable borrows in every other way,
+    // e.g. for variance or overlap checking.
     Unique,
 
     /// Data is mutable and not aliasable.
@@ -603,7 +608,11 @@ pub enum TerminatorKind<'tcx> {
     /// > The drop glue is executed if, among all statements executed within this `Body`, an assignment to
     /// > the place or one of its "parents" occurred more recently than a move out of it. This does not
     /// > consider indirect assignments.
-    Drop { place: Place<'tcx>, target: BasicBlock, unwind: UnwindAction },
+    ///
+    /// The `replace` flag indicates whether this terminator was created as part of an assignment.
+    /// This should only be used for diagnostic purposes, and does not have any operational
+    /// meaning.
+    Drop { place: Place<'tcx>, target: BasicBlock, unwind: UnwindAction, replace: bool },
 
     /// Roughly speaking, evaluates the `func` operand and the arguments, and starts execution of
     /// the referred to function. The operand types must match the argument types of the function.
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs
index 2c6126cdd29..561ef371b09 100644
--- a/compiler/rustc_middle/src/mir/terminator.rs
+++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -105,7 +105,7 @@ pub struct Terminator<'tcx> {
     pub kind: TerminatorKind<'tcx>,
 }
 
-pub type Successors<'a> = impl Iterator<Item = BasicBlock> + 'a;
+pub type Successors<'a> = impl DoubleEndedIterator<Item = BasicBlock> + 'a;
 pub type SuccessorsMut<'a> =
     iter::Chain<std::option::IntoIter<&'a mut BasicBlock>, slice::IterMut<'a, BasicBlock>>;
 
diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs
index 7d247eeb656..99ead14139a 100644
--- a/compiler/rustc_middle/src/mir/traversal.rs
+++ b/compiler/rustc_middle/src/mir/traversal.rs
@@ -149,7 +149,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
         //      B     C
         //      |     |
         //      |     |
-        //      D     |
+        //      |     D
         //       \   /
         //        \ /
         //         E
@@ -159,26 +159,26 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
         //
         // When the first call to `traverse_successor` happens, the following happens:
         //
-        //     [(B, [D]),  // `B` taken from the successors of `A`, pushed to the
-        //                 // top of the stack along with the successors of `B`
-        //      (A, [C])]
+        //     [(C, [D]),  // `C` taken from the successors of `A`, pushed to the
+        //                 // top of the stack along with the successors of `C`
+        //      (A, [B])]
         //
-        //     [(D, [E]),  // `D` taken from successors of `B`, pushed to stack
-        //      (B, []),
-        //      (A, [C])]
+        //     [(D, [E]),  // `D` taken from successors of `C`, pushed to stack
+        //      (C, []),
+        //      (A, [B])]
         //
         //     [(E, []),   // `E` taken from successors of `D`, pushed to stack
         //      (D, []),
-        //      (B, []),
-        //      (A, [C])]
+        //      (C, []),
+        //      (A, [B])]
         //
         // Now that the top of the stack has no successors we can traverse, each item will
-        // be popped off during iteration until we get back to `A`. This yields [E, D, B].
+        // be popped off during iteration until we get back to `A`. This yields [E, D, C].
         //
-        // When we yield `B` and call `traverse_successor`, we push `C` to the stack, but
+        // When we yield `C` and call `traverse_successor`, we push `B` to the stack, but
         // since we've already visited `E`, that child isn't added to the stack. The last
-        // two iterations yield `C` and finally `A` for a final traversal of [E, D, B, C, A]
-        while let Some(&mut (_, ref mut iter)) = self.visit_stack.last_mut() && let Some(bb) = iter.next() {
+        // two iterations yield `B` and finally `A` for a final traversal of [E, D, C, B, A]
+        while let Some(&mut (_, ref mut iter)) = self.visit_stack.last_mut() && let Some(bb) = iter.next_back() {
             if self.visited.insert(bb) {
                 if let Some(term) = &self.basic_blocks[bb].terminator {
                     self.visit_stack.push((bb, term.successors()));
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 596dd80bf48..8d44e929afd 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -504,6 +504,7 @@ macro_rules! make_mir_visitor {
                         place,
                         target: _,
                         unwind: _,
+                        replace: _,
                     } => {
                         self.visit_place(
                             place,
@@ -649,8 +650,8 @@ macro_rules! make_mir_visitor {
                             BorrowKind::Shallow => PlaceContext::NonMutatingUse(
                                 NonMutatingUseContext::ShallowBorrow
                             ),
-                            BorrowKind::Unique => PlaceContext::NonMutatingUse(
-                                NonMutatingUseContext::UniqueBorrow
+                            BorrowKind::Unique => PlaceContext::MutatingUse(
+                                MutatingUseContext::Borrow
                             ),
                             BorrowKind::Mut { .. } =>
                                 PlaceContext::MutatingUse(MutatingUseContext::Borrow),
@@ -1264,8 +1265,6 @@ pub enum NonMutatingUseContext {
     SharedBorrow,
     /// Shallow borrow.
     ShallowBorrow,
-    /// Unique borrow.
-    UniqueBorrow,
     /// AddressOf for *const pointer.
     AddressOf,
     /// PlaceMention statement.
@@ -1344,9 +1343,7 @@ impl PlaceContext {
         matches!(
             self,
             PlaceContext::NonMutatingUse(
-                NonMutatingUseContext::SharedBorrow
-                    | NonMutatingUseContext::ShallowBorrow
-                    | NonMutatingUseContext::UniqueBorrow
+                NonMutatingUseContext::SharedBorrow | NonMutatingUseContext::ShallowBorrow
             ) | PlaceContext::MutatingUse(MutatingUseContext::Borrow)
         )
     }
diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs
index c4f8718754f..eae5a280e11 100644
--- a/compiler/rustc_middle/src/traits/query.rs
+++ b/compiler/rustc_middle/src/traits/query.rs
@@ -95,8 +95,6 @@ pub type CanonicalTypeOpNormalizeGoal<'tcx, T> =
 #[derive(Copy, Clone, Debug, HashStable, PartialEq, Eq)]
 pub struct NoSolution;
 
-pub type Fallible<T> = Result<T, NoSolution>;
-
 impl<'tcx> From<TypeError<'tcx>> for NoSolution {
     fn from(_: TypeError<'tcx>) -> NoSolution {
         NoSolution
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs
index 7c5c030c276..e067d2a984f 100644
--- a/compiler/rustc_middle/src/ty/adt.rs
+++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -573,7 +573,7 @@ impl<'tcx> AdtDef<'tcx> {
     /// Due to normalization being eager, this applies even if
     /// the associated type is behind a pointer (e.g., issue #31299).
     pub fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> ty::EarlyBinder<&'tcx [Ty<'tcx>]> {
-        ty::EarlyBinder(tcx.adt_sized_constraint(self.did()))
+        ty::EarlyBinder::bind(tcx.adt_sized_constraint(self.did()))
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index 7fc75674da5..76f52bc34ed 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -264,7 +264,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for mir::Place<'tcx> {
 
 impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Region<'tcx> {
     fn decode(decoder: &mut D) -> Self {
-        decoder.interner().mk_region_from_kind(Decodable::decode(decoder))
+        ty::Region::new_from_kind(decoder.interner(), Decodable::decode(decoder))
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 1a4bd14815f..aecb46556b0 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -254,5 +254,5 @@ pub fn const_param_default(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBind
             "`const_param_default` expected a generic parameter with a constant"
         ),
     };
-    ty::EarlyBinder(Const::from_anon_const(tcx, default_def_id))
+    ty::EarlyBinder::bind(Const::from_anon_const(tcx, default_def_id))
 }
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 2bde55bc4fd..77725f0b3b6 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -115,6 +115,16 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
     type FreeRegion = ty::FreeRegion;
     type RegionVid = ty::RegionVid;
     type PlaceholderRegion = ty::PlaceholderRegion;
+
+    fn ty_and_mut_to_parts(
+        TypeAndMut { ty, mutbl }: TypeAndMut<'tcx>,
+    ) -> (Self::Ty, Self::Mutability) {
+        (ty, mutbl)
+    }
+
+    fn mutability_is_mut(mutbl: Self::Mutability) -> bool {
+        mutbl.is_mut()
+    }
 }
 
 type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>;
@@ -713,30 +723,6 @@ impl<'tcx> TyCtxt<'tcx> {
         self.mk_ty_from_kind(Error(reported))
     }
 
-    /// Constructs a `RegionKind::ReError` lifetime.
-    #[track_caller]
-    pub fn mk_re_error(self, reported: ErrorGuaranteed) -> Region<'tcx> {
-        self.intern_region(ty::ReError(reported))
-    }
-
-    /// Constructs a `RegionKind::ReError` lifetime and registers a `delay_span_bug` to ensure it
-    /// gets used.
-    #[track_caller]
-    pub fn mk_re_error_misc(self) -> Region<'tcx> {
-        self.mk_re_error_with_message(
-            DUMMY_SP,
-            "RegionKind::ReError constructed but no error reported",
-        )
-    }
-
-    /// Constructs a `RegionKind::ReError` lifetime and registers a `delay_span_bug` with the given
-    /// `msg` to ensure it gets used.
-    #[track_caller]
-    pub fn mk_re_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Region<'tcx> {
-        let reported = self.sess.delay_span_bug(span, msg);
-        self.mk_re_error(reported)
-    }
-
     /// Like [TyCtxt::ty_error] but for constants, with current `ErrorGuaranteed`
     #[track_caller]
     pub fn const_error(self, ty: Ty<'tcx>, reported: ErrorGuaranteed) -> Const<'tcx> {
@@ -759,7 +745,7 @@ impl<'tcx> TyCtxt<'tcx> {
         self,
         ty: Ty<'tcx>,
         span: S,
-        msg: &str,
+        msg: &'static str,
     ) -> Const<'tcx> {
         let reported = self.sess.delay_span_bug(span, msg);
         self.mk_const(ty::ConstKind::Error(reported), ty)
@@ -1515,9 +1501,9 @@ macro_rules! direct_interners {
 
 // Functions with a `mk_` prefix are intended for use outside this file and
 // crate. Functions with an `intern_` prefix are intended for use within this
-// file only, and have a corresponding `mk_` function.
+// crate only, and have a corresponding `mk_` function.
 direct_interners! {
-    region: intern_region(RegionKind<'tcx>): Region -> Region<'tcx>,
+    region: pub(crate) intern_region(RegionKind<'tcx>): Region -> Region<'tcx>,
     const_: intern_const(ConstData<'tcx>): Const -> Const<'tcx>,
     const_allocation: pub mk_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>,
     layout: pub mk_layout(LayoutS): Layout -> Layout<'tcx>,
@@ -1992,7 +1978,7 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> GenericArg<'tcx> {
         match param.kind {
             GenericParamDefKind::Lifetime => {
-                self.mk_re_early_bound(param.to_early_bound_region_data()).into()
+                ty::Region::new_early_bound(self, param.to_early_bound_region_data()).into()
             }
             GenericParamDefKind::Type { .. } => self.mk_ty_param(param.index, param.name).into(),
             GenericParamDefKind::Const { .. } => self
@@ -2032,65 +2018,6 @@ impl<'tcx> TyCtxt<'tcx> {
         self.mk_alias(ty::Opaque, self.mk_alias_ty(def_id, substs))
     }
 
-    #[inline]
-    pub fn mk_re_early_bound(self, early_bound_region: ty::EarlyBoundRegion) -> Region<'tcx> {
-        self.intern_region(ty::ReEarlyBound(early_bound_region))
-    }
-
-    #[inline]
-    pub fn mk_re_late_bound(
-        self,
-        debruijn: ty::DebruijnIndex,
-        bound_region: ty::BoundRegion,
-    ) -> Region<'tcx> {
-        // Use a pre-interned one when possible.
-        if let ty::BoundRegion { var, kind: ty::BrAnon(None) } = bound_region
-            && let Some(inner) = self.lifetimes.re_late_bounds.get(debruijn.as_usize())
-            && let Some(re) = inner.get(var.as_usize()).copied()
-        {
-            re
-        } else {
-            self.intern_region(ty::ReLateBound(debruijn, bound_region))
-        }
-    }
-
-    #[inline]
-    pub fn mk_re_free(self, scope: DefId, bound_region: ty::BoundRegionKind) -> Region<'tcx> {
-        self.intern_region(ty::ReFree(ty::FreeRegion { scope, bound_region }))
-    }
-
-    #[inline]
-    pub fn mk_re_var(self, v: ty::RegionVid) -> Region<'tcx> {
-        // Use a pre-interned one when possible.
-        self.lifetimes
-            .re_vars
-            .get(v.as_usize())
-            .copied()
-            .unwrap_or_else(|| self.intern_region(ty::ReVar(v)))
-    }
-
-    #[inline]
-    pub fn mk_re_placeholder(self, placeholder: ty::PlaceholderRegion) -> Region<'tcx> {
-        self.intern_region(ty::RePlaceholder(placeholder))
-    }
-
-    // Avoid this in favour of more specific `mk_re_*` methods, where possible,
-    // to avoid the cost of the `match`.
-    pub fn mk_region_from_kind(self, kind: ty::RegionKind<'tcx>) -> Region<'tcx> {
-        match kind {
-            ty::ReEarlyBound(region) => self.mk_re_early_bound(region),
-            ty::ReLateBound(debruijn, region) => self.mk_re_late_bound(debruijn, region),
-            ty::ReFree(ty::FreeRegion { scope, bound_region }) => {
-                self.mk_re_free(scope, bound_region)
-            }
-            ty::ReStatic => self.lifetimes.re_static,
-            ty::ReVar(vid) => self.mk_re_var(vid),
-            ty::RePlaceholder(region) => self.mk_re_placeholder(region),
-            ty::ReErased => self.lifetimes.re_erased,
-            ty::ReError(reported) => self.mk_re_error(reported),
-        }
-    }
-
     pub fn mk_place_field(self, place: Place<'tcx>, f: FieldIdx, ty: Ty<'tcx>) -> Place<'tcx> {
         self.mk_place_elem(place, PlaceElem::Field(f, ty))
     }
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index 6a29063b80d..9c91b778403 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -1,5 +1,6 @@
 //! Diagnostics related methods for `Ty`.
 
+use std::borrow::Cow;
 use std::ops::ControlFlow;
 
 use crate::ty::{
@@ -384,22 +385,18 @@ pub fn suggest_constraining_type_params<'a>(
 
     if suggestions.len() == 1 {
         let (span, suggestion, msg) = suggestions.pop().unwrap();
-
-        let s;
         let msg = match msg {
             SuggestChangingConstraintsMessage::RestrictBoundFurther => {
-                "consider further restricting this bound"
+                Cow::from("consider further restricting this bound")
             }
             SuggestChangingConstraintsMessage::RestrictType { ty } => {
-                s = format!("consider restricting type parameter `{}`", ty);
-                &s
+                Cow::from(format!("consider restricting type parameter `{}`", ty))
             }
             SuggestChangingConstraintsMessage::RestrictTypeFurther { ty } => {
-                s = format!("consider further restricting type parameter `{}`", ty);
-                &s
+                Cow::from(format!("consider further restricting type parameter `{}`", ty))
             }
             SuggestChangingConstraintsMessage::RemovingQSized => {
-                "consider removing the `?Sized` bound to make the type parameter `Sized`"
+                Cow::from("consider removing the `?Sized` bound to make the type parameter `Sized`")
             }
         };
 
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index 49ab9b79e96..66293f19eef 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -45,7 +45,6 @@ pub enum TypeError<'tcx> {
 
     RegionsDoesNotOutlive(Region<'tcx>, Region<'tcx>),
     RegionsInsufficientlyPolymorphic(BoundRegionKind, Region<'tcx>),
-    RegionsOverlyPolymorphic(BoundRegionKind, Region<'tcx>),
     RegionsPlaceholderMismatch,
 
     Sorts(ExpectedFound<Ty<'tcx>>),
@@ -74,7 +73,6 @@ impl TypeError<'_> {
         match self {
             TypeError::RegionsDoesNotOutlive(_, _)
             | TypeError::RegionsInsufficientlyPolymorphic(_, _)
-            | TypeError::RegionsOverlyPolymorphic(_, _)
             | TypeError::RegionsPlaceholderMismatch => true,
             _ => false,
         }
@@ -98,11 +96,6 @@ impl<'tcx> TypeError<'tcx> {
             }
         }
 
-        let br_string = |br: ty::BoundRegionKind| match br {
-            ty::BrNamed(_, name) => format!(" {}", name),
-            _ => String::new(),
-        };
-
         match self {
             CyclicTy(_) => "cyclic type of infinite size".into(),
             CyclicConst(_) => "encountered a self-referencing constant".into(),
@@ -144,11 +137,6 @@ impl<'tcx> TypeError<'tcx> {
             RegionsInsufficientlyPolymorphic(..) => {
                 "one type is more general than the other".into()
             }
-            RegionsOverlyPolymorphic(br, _) => format!(
-                "expected concrete lifetime, found bound lifetime parameter{}",
-                br_string(br)
-            )
-            .into(),
             RegionsPlaceholderMismatch => "one type is more general than the other".into(),
             ArgumentSorts(values, _) | Sorts(values) => {
                 let expected = values.expected.sort_string(tcx);
@@ -228,7 +216,6 @@ impl<'tcx> TypeError<'tcx> {
             | FieldMisMatch(..)
             | RegionsDoesNotOutlive(..)
             | RegionsInsufficientlyPolymorphic(..)
-            | RegionsOverlyPolymorphic(..)
             | RegionsPlaceholderMismatch
             | Traits(_)
             | ProjectionMismatched(_)
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index 25890eb15cd..149ce29b8d9 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -213,7 +213,7 @@ where
                     // debruijn index. Then we adjust it to the
                     // correct depth.
                     assert_eq!(debruijn1, ty::INNERMOST);
-                    self.tcx.mk_re_late_bound(debruijn, br)
+                    ty::Region::new_late_bound(self.tcx, debruijn, br)
                 } else {
                     region
                 }
@@ -328,7 +328,7 @@ impl<'tcx> TyCtxt<'tcx> {
         T: TypeFoldable<TyCtxt<'tcx>>,
     {
         self.replace_late_bound_regions_uncached(value, |br| {
-            self.mk_re_free(all_outlive_scope, br.kind)
+            ty::Region::new_free(self, all_outlive_scope, br.kind)
         })
     }
 
@@ -341,7 +341,8 @@ impl<'tcx> TyCtxt<'tcx> {
             value,
             FnMutDelegate {
                 regions: &mut |r: ty::BoundRegion| {
-                    self.mk_re_late_bound(
+                    ty::Region::new_late_bound(
+                        self,
                         ty::INNERMOST,
                         ty::BoundRegion { var: shift_bv(r.var), kind: r.kind },
                     )
@@ -383,7 +384,7 @@ impl<'tcx> TyCtxt<'tcx> {
                     .or_insert_with(|| ty::BoundVariableKind::Region(ty::BrAnon(None)))
                     .expect_region();
                 let br = ty::BoundRegion { var, kind };
-                self.tcx.mk_re_late_bound(ty::INNERMOST, br)
+                ty::Region::new_late_bound(self.tcx, ty::INNERMOST, br)
             }
             fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> {
                 let entry = self.map.entry(bt.var);
@@ -451,7 +452,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Shifter<'tcx> {
         match *r {
             ty::ReLateBound(debruijn, br) if debruijn >= self.current_index => {
                 let debruijn = debruijn.shifted_in(self.amount);
-                self.tcx.mk_re_late_bound(debruijn, br)
+                ty::Region::new_late_bound(self.tcx, debruijn, br)
             }
             _ => r,
         }
@@ -492,7 +493,7 @@ pub fn shift_region<'tcx>(
 ) -> ty::Region<'tcx> {
     match *region {
         ty::ReLateBound(debruijn, br) if amount > 0 => {
-            tcx.mk_re_late_bound(debruijn.shifted_in(amount), br)
+            ty::Region::new_late_bound(tcx, debruijn.shifted_in(amount), br)
         }
         _ => region,
     }
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index b0ffe78299d..30f92b91cb7 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -100,7 +100,7 @@ impl GenericParamDef {
         preceding_substs: &[ty::GenericArg<'tcx>],
     ) -> ty::GenericArg<'tcx> {
         match &self.kind {
-            ty::GenericParamDefKind::Lifetime => tcx.mk_re_error_misc().into(),
+            ty::GenericParamDefKind::Lifetime => ty::Region::new_error_misc(tcx).into(),
             ty::GenericParamDefKind::Type { .. } => tcx.ty_error_misc().into(),
             ty::GenericParamDefKind::Const { .. } => {
                 tcx.const_error_misc(tcx.type_of(self.def_id).subst(tcx, preceding_substs)).into()
@@ -343,7 +343,7 @@ impl<'tcx> GenericPredicates<'tcx> {
         substs: SubstsRef<'tcx>,
     ) -> impl Iterator<Item = (Predicate<'tcx>, Span)> + DoubleEndedIterator + ExactSizeIterator
     {
-        EarlyBinder(self.predicates).subst_iter_copied(tcx, substs)
+        EarlyBinder::bind(self.predicates).subst_iter_copied(tcx, substs)
     }
 
     #[instrument(level = "debug", skip(self, tcx))]
@@ -358,7 +358,7 @@ impl<'tcx> GenericPredicates<'tcx> {
         }
         instantiated
             .predicates
-            .extend(self.predicates.iter().map(|(p, _)| EarlyBinder(*p).subst(tcx, substs)));
+            .extend(self.predicates.iter().map(|(p, _)| EarlyBinder::bind(*p).subst(tcx, substs)));
         instantiated.spans.extend(self.predicates.iter().map(|(_, sp)| *sp));
     }
 
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
index ac42d6e0510..d48672b2baa 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
@@ -158,7 +158,7 @@ impl<'tcx> InhabitedPredicate<'tcx> {
     fn subst_opt(self, tcx: TyCtxt<'tcx>, substs: ty::SubstsRef<'tcx>) -> Option<Self> {
         match self {
             Self::ConstIsZero(c) => {
-                let c = ty::EarlyBinder(c).subst(tcx, substs);
+                let c = ty::EarlyBinder::bind(c).subst(tcx, substs);
                 let pred = match c.kind().try_to_target_usize(tcx) {
                     Some(0) => Self::True,
                     Some(1..) => Self::False,
@@ -167,7 +167,7 @@ impl<'tcx> InhabitedPredicate<'tcx> {
                 Some(pred)
             }
             Self::GenericType(t) => {
-                Some(ty::EarlyBinder(t).subst(tcx, substs).inhabited_predicate(tcx))
+                Some(ty::EarlyBinder::bind(t).subst(tcx, substs).inhabited_predicate(tcx))
             }
             Self::And(&[a, b]) => match a.subst_opt(tcx, substs) {
                 None => b.subst_opt(tcx, substs).map(|b| a.and(tcx, b)),
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index a8d0dca37ff..72341e656e2 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -53,7 +53,6 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{ExpnId, ExpnKind, Span};
 use rustc_target::abi::{Align, FieldIdx, Integer, IntegerType, VariantIdx};
 pub use rustc_target::abi::{ReprFlags, ReprOptions};
-use rustc_type_ir::WithCachedTypeInfo;
 pub use subst::*;
 pub use vtable::*;
 
@@ -145,6 +144,7 @@ mod opaque_types;
 mod parameterized;
 mod rvalue_scopes;
 mod structural_impls;
+#[cfg_attr(not(bootstrap), allow(hidden_glob_reexports))]
 mod sty;
 mod typeck_results;
 
@@ -764,7 +764,7 @@ impl<'tcx> Predicate<'tcx> {
         let shifted_pred =
             tcx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder());
         // 2) Self: Bar1<'a, '^0.1> -> T: Bar1<'^0.0, '^0.1>
-        let new = EarlyBinder(shifted_pred).subst(tcx, trait_ref.skip_binder().substs);
+        let new = EarlyBinder::bind(shifted_pred).subst(tcx, trait_ref.skip_binder().substs);
         // 3) ['x] + ['b] -> ['x, 'b]
         let bound_vars =
             tcx.mk_bound_variable_kinds_from_iter(trait_bound_vars.iter().chain(pred_bound_vars));
@@ -1496,7 +1496,7 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
 /// identified by both a universe, as well as a name residing within that universe. Distinct bound
 /// regions/types/consts within the same universe simply have an unknown relationship to one
 /// another.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
 #[derive(HashStable, TyEncodable, TyDecodable)]
 pub struct Placeholder<T> {
     pub universe: UniverseIndex,
diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs
index 1b336b7bfc6..d1ed7be3d2e 100644
--- a/compiler/rustc_middle/src/ty/opaque_types.rs
+++ b/compiler/rustc_middle/src/ty/opaque_types.rs
@@ -141,7 +141,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
                     )
                     .emit();
 
-                self.interner().mk_re_error(e)
+                ty::Region::new_error(self.interner(), e)
             }
         }
     }
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs
index 64e7480e626..2de0a3f75dc 100644
--- a/compiler/rustc_middle/src/ty/print/mod.rs
+++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -123,7 +123,7 @@ pub trait Printer<'tcx>: Sized {
                         impl_trait_ref.map(|i| i.subst(self.tcx(), substs)),
                     )
                 } else {
-                    (self_ty.0, impl_trait_ref.map(|i| i.0))
+                    (self_ty.subst_identity(), impl_trait_ref.map(|i| i.subst_identity()))
                 };
                 self.print_impl_path(def_id, substs, self_ty, impl_trait_ref)
             }
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index a064174e261..6156fdf7eac 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -184,7 +184,7 @@ impl<'tcx> RegionHighlightMode<'tcx> {
 
     /// Convenience wrapper for `highlighting_region`.
     pub fn highlighting_region_vid(&mut self, vid: ty::RegionVid, number: usize) {
-        self.highlighting_region(self.tcx.mk_re_var(vid), number)
+        self.highlighting_region(ty::Region::new_var(self.tcx, vid), number)
     }
 
     /// Returns `Some(n)` with the number to use for the given region, if any.
@@ -685,29 +685,30 @@ pub trait PrettyPrinter<'tcx>:
             }
             ty::FnPtr(ref bare_fn) => p!(print(bare_fn)),
             ty::Infer(infer_ty) => {
-                let verbose = self.should_print_verbose();
+                if self.should_print_verbose() {
+                    p!(write("{:?}", ty.kind()));
+                    return Ok(self);
+                }
+
                 if let ty::TyVar(ty_vid) = infer_ty {
                     if let Some(name) = self.ty_infer_name(ty_vid) {
                         p!(write("{}", name))
                     } else {
-                        if verbose {
-                            p!(write("{:?}", infer_ty))
-                        } else {
-                            p!(write("{}", infer_ty))
-                        }
+                        p!(write("{}", infer_ty))
                     }
                 } else {
-                    if verbose { p!(write("{:?}", infer_ty)) } else { p!(write("{}", infer_ty)) }
+                    p!(write("{}", infer_ty))
                 }
             }
-            ty::Error(_) => p!("[type error]"),
+            ty::Error(_) => p!("{{type error}}"),
             ty::Param(ref param_ty) => p!(print(param_ty)),
             ty::Bound(debruijn, bound_ty) => match bound_ty.kind {
-                ty::BoundTyKind::Anon => debug_bound_var(&mut self, debruijn, bound_ty.var)?,
+                ty::BoundTyKind::Anon => {
+                    rustc_type_ir::debug_bound_var(&mut self, debruijn, bound_ty.var)?
+                }
                 ty::BoundTyKind::Param(_, s) => match self.should_print_verbose() {
-                    true if debruijn == ty::INNERMOST => p!(write("^{}", s)),
-                    true => p!(write("^{}_{}", debruijn.index(), s)),
-                    false => p!(write("{}", s)),
+                    true => p!(write("{:?}", ty.kind())),
+                    false => p!(write("{s}")),
                 },
             },
             ty::Adt(def, substs) => {
@@ -740,10 +741,11 @@ pub trait PrettyPrinter<'tcx>:
                 }
             }
             ty::Placeholder(placeholder) => match placeholder.bound.kind {
-                ty::BoundTyKind::Anon => {
-                    debug_placeholder_var(&mut self, placeholder.universe, placeholder.bound.var)?;
-                }
-                ty::BoundTyKind::Param(_, name) => p!(write("{}", name)),
+                ty::BoundTyKind::Anon => p!(write("{placeholder:?}")),
+                ty::BoundTyKind::Param(_, name) => match self.should_print_verbose() {
+                    true => p!(write("{:?}", ty.kind())),
+                    false => p!(write("{name}")),
+                },
             },
             ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
                 // We use verbose printing in 'NO_QUERIES' mode, to
@@ -1372,15 +1374,13 @@ pub trait PrettyPrinter<'tcx>:
             }
 
             ty::ConstKind::Bound(debruijn, bound_var) => {
-                debug_bound_var(&mut self, debruijn, bound_var)?
+                rustc_type_ir::debug_bound_var(&mut self, debruijn, bound_var)?
             }
-            ty::ConstKind::Placeholder(placeholder) => {
-                debug_placeholder_var(&mut self, placeholder.universe, placeholder.bound)?;
-            },
+            ty::ConstKind::Placeholder(placeholder) => p!(write("{placeholder:?}")),
             // FIXME(generic_const_exprs):
             // write out some legible representation of an abstract const?
-            ty::ConstKind::Expr(_) => p!("[const expr]"),
-            ty::ConstKind::Error(_) => p!("[const error]"),
+            ty::ConstKind::Expr(_) => p!("{{const expr}}"),
+            ty::ConstKind::Error(_) => p!("{{const error}}"),
         };
         Ok(self)
     }
@@ -2303,7 +2303,7 @@ impl<'a, 'tcx> ty::TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> {
         };
         if let ty::ReLateBound(debruijn1, br) = *region {
             assert_eq!(debruijn1, ty::INNERMOST);
-            self.tcx.mk_re_late_bound(self.current_index, br)
+            ty::Region::new_late_bound(self.tcx, self.current_index, br)
         } else {
             region
         }
@@ -2415,7 +2415,8 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
                         if let Some(lt_idx) = lifetime_idx {
                             if lt_idx > binder_level_idx {
                                 let kind = ty::BrNamed(CRATE_DEF_ID.to_def_id(), name);
-                                return tcx.mk_re_late_bound(
+                                return ty::Region::new_late_bound(
+                                    tcx,
                                     ty::INNERMOST,
                                     ty::BoundRegion { var: br.var, kind },
                                 );
@@ -2430,7 +2431,8 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
                         if let Some(lt_idx) = lifetime_idx {
                             if lt_idx > binder_level_idx {
                                 let kind = ty::BrNamed(def_id, name);
-                                return tcx.mk_re_late_bound(
+                                return ty::Region::new_late_bound(
+                                    tcx,
                                     ty::INNERMOST,
                                     ty::BoundRegion { var: br.var, kind },
                                 );
@@ -2443,7 +2445,8 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
                         if let Some(lt_idx) = lifetime_idx {
                             if lt_idx > binder_level_idx {
                                 let kind = br.kind;
-                                return tcx.mk_re_late_bound(
+                                return ty::Region::new_late_bound(
+                                    tcx,
                                     ty::INNERMOST,
                                     ty::BoundRegion { var: br.var, kind },
                                 );
@@ -2458,7 +2461,11 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
                     start_or_continue(&mut self, "for<", ", ");
                     do_continue(&mut self, name);
                 }
-                tcx.mk_re_late_bound(ty::INNERMOST, ty::BoundRegion { var: br.var, kind })
+                ty::Region::new_late_bound(
+                    tcx,
+                    ty::INNERMOST,
+                    ty::BoundRegion { var: br.var, kind },
+                )
             };
             let mut folder = RegionFolder {
                 tcx,
@@ -3065,27 +3072,3 @@ pub struct OpaqueFnEntry<'tcx> {
     fn_trait_ref: Option<ty::PolyTraitRef<'tcx>>,
     return_ty: Option<ty::Binder<'tcx, Term<'tcx>>>,
 }
-
-pub fn debug_bound_var<T: std::fmt::Write>(
-    fmt: &mut T,
-    debruijn: ty::DebruijnIndex,
-    var: ty::BoundVar,
-) -> Result<(), std::fmt::Error> {
-    if debruijn == ty::INNERMOST {
-        write!(fmt, "^{}", var.index())
-    } else {
-        write!(fmt, "^{}_{}", debruijn.index(), var.index())
-    }
-}
-
-pub fn debug_placeholder_var<T: std::fmt::Write>(
-    fmt: &mut T,
-    universe: ty::UniverseIndex,
-    bound: ty::BoundVar,
-) -> Result<(), std::fmt::Error> {
-    if universe == ty::UniverseIndex::ROOT {
-        write!(fmt, "!{}", bound.index())
-    } else {
-        write!(fmt, "!{}_{}", universe.index(), bound.index())
-    }
-}
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 16cb6c91046..a965450d27d 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -88,7 +88,35 @@ impl fmt::Debug for ty::FreeRegion {
 
 impl<'tcx> fmt::Debug for ty::FnSig<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "({:?}; c_variadic: {})->{:?}", self.inputs(), self.c_variadic, self.output())
+        let ty::FnSig { inputs_and_output: _, c_variadic, unsafety, abi } = self;
+
+        write!(f, "{}", unsafety.prefix_str())?;
+        match abi {
+            rustc_target::spec::abi::Abi::Rust => (),
+            abi => write!(f, "extern \"{abi:?}\" ")?,
+        };
+
+        write!(f, "fn(")?;
+        let inputs = self.inputs();
+        match inputs.len() {
+            0 if *c_variadic => write!(f, "...)")?,
+            0 => write!(f, ")")?,
+            _ => {
+                for ty in &self.inputs()[0..(self.inputs().len() - 1)] {
+                    write!(f, "{ty:?}, ")?;
+                }
+                write!(f, "{:?}", self.inputs().last().unwrap())?;
+                if *c_variadic {
+                    write!(f, "...")?;
+                }
+                write!(f, ")")?;
+            }
+        }
+
+        match self.output().kind() {
+            ty::Tuple(list) if list.is_empty() => Ok(()),
+            _ => write!(f, " -> {:?}", self.output()),
+        }
     }
 }
 
@@ -216,20 +244,37 @@ impl<'tcx> fmt::Debug for ty::ConstKind<'tcx> {
         match self {
             Param(param) => write!(f, "{param:?}"),
             Infer(var) => write!(f, "{var:?}"),
-            Bound(debruijn, var) => ty::print::debug_bound_var(f, *debruijn, *var),
-            Placeholder(placeholder) => {
-                ty::print::debug_placeholder_var(f, placeholder.universe, placeholder.bound)
-            }
+            Bound(debruijn, var) => rustc_type_ir::debug_bound_var(f, *debruijn, *var),
+            Placeholder(placeholder) => write!(f, "{placeholder:?}"),
             Unevaluated(uv) => {
                 f.debug_tuple("Unevaluated").field(&uv.substs).field(&uv.def).finish()
             }
             Value(valtree) => write!(f, "{valtree:?}"),
-            Error(_) => write!(f, "[const error]"),
+            Error(_) => write!(f, "{{const error}}"),
             Expr(expr) => write!(f, "{expr:?}"),
         }
     }
 }
 
+impl fmt::Debug for ty::BoundTy {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self.kind {
+            ty::BoundTyKind::Anon => write!(f, "{:?}", self.var),
+            ty::BoundTyKind::Param(_, sym) => write!(f, "{sym:?}"),
+        }
+    }
+}
+
+impl<T: fmt::Debug> fmt::Debug for ty::Placeholder<T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        if self.universe == ty::UniverseIndex::ROOT {
+            write!(f, "!{:?}", self.bound)
+        } else {
+            write!(f, "!{}_{:?}", self.universe.index(), self.bound)
+        }
+    }
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // Atomic structs
 //
@@ -294,6 +339,7 @@ TrivialTypeTraversalAndLiftImpls! {
     crate::ty::AliasRelationDirection,
     crate::ty::Placeholder<crate::ty::BoundRegion>,
     crate::ty::Placeholder<crate::ty::BoundTy>,
+    crate::ty::Placeholder<ty::BoundVar>,
     crate::ty::ClosureKind,
     crate::ty::FreeRegion,
     crate::ty::InferTy,
@@ -310,7 +356,6 @@ TrivialTypeTraversalAndLiftImpls! {
     interpret::Scalar,
     rustc_target::abi::Size,
     ty::BoundVar,
-    ty::Placeholder<ty::BoundVar>,
 }
 
 TrivialTypeTraversalAndLiftImpls! {
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index e6d51c4ec97..d19a7bcde79 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -15,14 +15,14 @@ use hir::def::DefKind;
 use polonius_engine::Atom;
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::intern::Interned;
-use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
+use rustc_errors::{DiagnosticArgValue, ErrorGuaranteed, IntoDiagnosticArg, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::LangItem;
 use rustc_index::Idx;
 use rustc_macros::HashStable;
 use rustc_span::symbol::{kw, sym, Symbol};
-use rustc_span::Span;
+use rustc_span::{Span, DUMMY_SP};
 use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
 use rustc_target::spec::abi::{self, Abi};
 use std::borrow::Cow;
@@ -568,7 +568,7 @@ impl<'tcx> GeneratorSubsts<'tcx> {
         let layout = tcx.generator_layout(def_id).unwrap();
         layout.variant_fields.iter().map(move |variant| {
             variant.iter().map(move |field| {
-                ty::EarlyBinder(layout.field_tys[*field].ty).subst(tcx, self.substs)
+                ty::EarlyBinder::bind(layout.field_tys[*field].ty).subst(tcx, self.substs)
             })
         })
     }
@@ -1459,6 +1459,103 @@ impl ParamConst {
 #[rustc_pass_by_value]
 pub struct Region<'tcx>(pub Interned<'tcx, RegionKind<'tcx>>);
 
+impl<'tcx> Region<'tcx> {
+    #[inline]
+    pub fn new_early_bound(
+        tcx: TyCtxt<'tcx>,
+        early_bound_region: ty::EarlyBoundRegion,
+    ) -> Region<'tcx> {
+        tcx.intern_region(ty::ReEarlyBound(early_bound_region))
+    }
+
+    #[inline]
+    pub fn new_late_bound(
+        tcx: TyCtxt<'tcx>,
+        debruijn: ty::DebruijnIndex,
+        bound_region: ty::BoundRegion,
+    ) -> Region<'tcx> {
+        // Use a pre-interned one when possible.
+        if let ty::BoundRegion { var, kind: ty::BrAnon(None) } = bound_region
+            && let Some(inner) = tcx.lifetimes.re_late_bounds.get(debruijn.as_usize())
+            && let Some(re) = inner.get(var.as_usize()).copied()
+        {
+            re
+        } else {
+            tcx.intern_region(ty::ReLateBound(debruijn, bound_region))
+        }
+    }
+
+    #[inline]
+    pub fn new_free(
+        tcx: TyCtxt<'tcx>,
+        scope: DefId,
+        bound_region: ty::BoundRegionKind,
+    ) -> Region<'tcx> {
+        tcx.intern_region(ty::ReFree(ty::FreeRegion { scope, bound_region }))
+    }
+
+    #[inline]
+    pub fn new_var(tcx: TyCtxt<'tcx>, v: ty::RegionVid) -> Region<'tcx> {
+        // Use a pre-interned one when possible.
+        tcx.lifetimes
+            .re_vars
+            .get(v.as_usize())
+            .copied()
+            .unwrap_or_else(|| tcx.intern_region(ty::ReVar(v)))
+    }
+
+    #[inline]
+    pub fn new_placeholder(tcx: TyCtxt<'tcx>, placeholder: ty::PlaceholderRegion) -> Region<'tcx> {
+        tcx.intern_region(ty::RePlaceholder(placeholder))
+    }
+
+    /// Constructs a `RegionKind::ReError` region.
+    #[track_caller]
+    pub fn new_error(tcx: TyCtxt<'tcx>, reported: ErrorGuaranteed) -> Region<'tcx> {
+        tcx.intern_region(ty::ReError(reported))
+    }
+
+    /// Constructs a `RegionKind::ReError` region and registers a `delay_span_bug` to ensure it
+    /// gets used.
+    #[track_caller]
+    pub fn new_error_misc(tcx: TyCtxt<'tcx>) -> Region<'tcx> {
+        Region::new_error_with_message(
+            tcx,
+            DUMMY_SP,
+            "RegionKind::ReError constructed but no error reported",
+        )
+    }
+
+    /// Constructs a `RegionKind::ReError` region and registers a `delay_span_bug` with the given
+    /// `msg` to ensure it gets used.
+    #[track_caller]
+    pub fn new_error_with_message<S: Into<MultiSpan>>(
+        tcx: TyCtxt<'tcx>,
+        span: S,
+        msg: &'static str,
+    ) -> Region<'tcx> {
+        let reported = tcx.sess.delay_span_bug(span, msg);
+        Region::new_error(tcx, reported)
+    }
+
+    /// Avoid this in favour of more specific `new_*` methods, where possible,
+    /// to avoid the cost of the `match`.
+    pub fn new_from_kind(tcx: TyCtxt<'tcx>, kind: RegionKind<'tcx>) -> Region<'tcx> {
+        match kind {
+            ty::ReEarlyBound(region) => Region::new_early_bound(tcx, region),
+            ty::ReLateBound(debruijn, region) => Region::new_late_bound(tcx, debruijn, region),
+            ty::ReFree(ty::FreeRegion { scope, bound_region }) => {
+                Region::new_free(tcx, scope, bound_region)
+            }
+            ty::ReStatic => tcx.lifetimes.re_static,
+            ty::ReVar(vid) => Region::new_var(tcx, vid),
+            ty::RePlaceholder(region) => Region::new_placeholder(tcx, region),
+            ty::ReErased => tcx.lifetimes.re_erased,
+            ty::ReError(reported) => Region::new_error(tcx, reported),
+        }
+    }
+}
+
 impl<'tcx> Deref for Region<'tcx> {
     type Target = RegionKind<'tcx>;
 
@@ -1511,10 +1608,11 @@ impl Atom for RegionVid {
 
 rustc_index::newtype_index! {
     #[derive(HashStable)]
+    #[debug_format = "{}"]
     pub struct BoundVar {}
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable)]
 pub struct BoundTy {
     pub var: BoundVar,
@@ -2366,7 +2464,7 @@ impl<'tcx> Ty<'tcx> {
 
             ty::Tuple(tys) => tys.iter().all(|ty| ty.is_trivially_sized(tcx)),
 
-            ty::Adt(def, _substs) => def.sized_constraint(tcx).0.is_empty(),
+            ty::Adt(def, _substs) => def.sized_constraint(tcx).skip_binder().is_empty(),
 
             ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => false,
 
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs
index 43f95635ab0..8685a22d9ca 100644
--- a/compiler/rustc_middle/src/ty/subst.rs
+++ b/compiler/rustc_middle/src/ty/subst.rs
@@ -538,13 +538,17 @@ impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>>> TypeVisitable<TyCtxt<'tcx>> for &'tcx
 /// [`subst_identity`](EarlyBinder::subst_identity) or [`skip_binder`](EarlyBinder::skip_binder).
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
 #[derive(Encodable, Decodable, HashStable)]
-pub struct EarlyBinder<T>(pub T);
+pub struct EarlyBinder<T>(T);
 
 /// For early binders, you should first call `subst` before using any visitors.
 impl<'tcx, T> !TypeFoldable<TyCtxt<'tcx>> for ty::EarlyBinder<T> {}
 impl<'tcx, T> !TypeVisitable<TyCtxt<'tcx>> for ty::EarlyBinder<T> {}
 
 impl<T> EarlyBinder<T> {
+    pub fn bind(inner: T) -> EarlyBinder<T> {
+        EarlyBinder(inner)
+    }
+
     pub fn as_ref(&self) -> EarlyBinder<&T> {
         EarlyBinder(&self.0)
     }
@@ -582,6 +586,9 @@ impl<T> EarlyBinder<T> {
     /// arguments of an `FnSig`). Otherwise, consider using
     /// [`subst_identity`](EarlyBinder::subst_identity).
     ///
+    /// To skip the binder on `x: &EarlyBinder<T>` to obtain `&T`, leverage
+    /// [`EarlyBinder::as_ref`](EarlyBinder::as_ref): `x.as_ref().skip_binder()`.
+    ///
     /// See also [`Binder::skip_binder`](super::Binder::skip_binder), which is
     /// the analogous operation on [`super::Binder`].
     pub fn skip_binder(self) -> T {
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index ba05135638e..311f63adc7f 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -709,7 +709,7 @@ impl<'tcx> TyCtxt<'tcx> {
             .as_ref()
             .map_or_else(|| [].iter(), |l| l.field_tys.iter())
             .filter(|decl| !decl.ignore_for_traits)
-            .map(|decl| ty::EarlyBinder(decl.ty))
+            .map(|decl| ty::EarlyBinder::bind(decl.ty))
     }
 
     /// Normalizes all opaque types in the given value, replacing them
diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs
index c62c33d4dfc..a00c77ccbcd 100644
--- a/compiler/rustc_middle/src/values.rs
+++ b/compiler/rustc_middle/src/values.rs
@@ -96,13 +96,13 @@ impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for Representability {
 
 impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for ty::EarlyBinder<Ty<'_>> {
     fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo<DepKind>]) -> Self {
-        ty::EarlyBinder(Ty::from_cycle_error(tcx, cycle))
+        ty::EarlyBinder::bind(Ty::from_cycle_error(tcx, cycle))
     }
 }
 
 impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for ty::EarlyBinder<ty::Binder<'_, ty::FnSig<'_>>> {
     fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo<DepKind>]) -> Self {
-        ty::EarlyBinder(ty::Binder::from_cycle_error(tcx, cycle))
+        ty::EarlyBinder::bind(ty::Binder::from_cycle_error(tcx, cycle))
     }
 }
 
diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl
index 0282492a261..cb265cf2c6a 100644
--- a/compiler/rustc_mir_build/messages.ftl
+++ b/compiler/rustc_mir_build/messages.ftl
@@ -1,62 +1,40 @@
-mir_build_unconditional_recursion = function cannot return without recursing
-    .label = cannot return without recursing
-    .help = a `loop` may express intention better if this is on purpose
-
-mir_build_unconditional_recursion_call_site_label = recursive call site
-
-mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe =
-    call to unsafe function `{$function}` is unsafe and requires unsafe block (error E0133)
-    .note = consult the function's documentation for information on how to avoid undefined behavior
-    .label = call to unsafe function
-
-mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe_nameless =
-    call to unsafe function is unsafe and requires unsafe block (error E0133)
-    .note = consult the function's documentation for information on how to avoid undefined behavior
-    .label = call to unsafe function
-
-mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe =
-    use of inline assembly is unsafe and requires unsafe block (error E0133)
-    .note = inline assembly is entirely unchecked and can cause undefined behavior
-    .label = use of inline assembly
+mir_build_adt_defined_here = `{$ty}` defined here
 
-mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe =
-    initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe
-    block (error E0133)
-    .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
-    .label = initializing type with `rustc_layout_scalar_valid_range` attr
+mir_build_already_borrowed = cannot borrow value as mutable because it is also borrowed as immutable
 
-mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe =
-    use of mutable static is unsafe and requires unsafe block (error E0133)
-    .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
-    .label = use of mutable static
+mir_build_already_mut_borrowed = cannot borrow value as immutable because it is also borrowed as mutable
 
-mir_build_unsafe_op_in_unsafe_fn_extern_static_requires_unsafe =
-    use of extern static is unsafe and requires unsafe block (error E0133)
-    .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
-    .label = use of extern static
+mir_build_assoc_const_in_pattern = associated consts cannot be referenced in patterns
 
-mir_build_unsafe_op_in_unsafe_fn_deref_raw_pointer_requires_unsafe =
-    dereference of raw pointer is unsafe and requires unsafe block (error E0133)
-    .note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
-    .label = dereference of raw pointer
+mir_build_bindings_with_variant_name =
+    pattern binding `{$name}` is named the same as one of the variants of the type `{$ty_path}`
+    .suggestion = to match on the variant, qualify the path
 
-mir_build_unsafe_op_in_unsafe_fn_union_field_requires_unsafe =
-    access to union field is unsafe and requires unsafe block (error E0133)
-    .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior
-    .label = access to union field
+mir_build_borrow = value is borrowed by `{$name}` here
 
-mir_build_unsafe_op_in_unsafe_fn_mutation_of_layout_constrained_field_requires_unsafe =
-    mutation of layout constrained field is unsafe and requires unsafe block (error E0133)
-    .note = mutating layout constrained fields cannot statically be checked for valid values
-    .label = mutation of layout constrained field
+mir_build_borrow_of_layout_constrained_field_requires_unsafe =
+    borrow of layout constrained field with interior mutability is unsafe and requires unsafe block
+    .note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
+    .label = borrow of layout constrained field with interior mutability
 
-mir_build_unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe =
-    borrow of layout constrained field with interior mutability is unsafe and requires unsafe block (error E0133)
+mir_build_borrow_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+    borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block
     .note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
     .label = borrow of layout constrained field with interior mutability
 
-mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe =
-    call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block (error E0133)
+mir_build_borrow_of_moved_value = borrow of moved value
+    .label = value moved into `{$name}` here
+    .occurs_because_label = move occurs because `{$name}` has type `{$ty}` which does not implement the `Copy` trait
+    .value_borrowed_label = value borrowed here after move
+    .suggestion = borrow this binding in the pattern to avoid moving the value
+
+mir_build_call_to_fn_with_requires_unsafe =
+    call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block
+    .note = can only be called if the required target features are available
+    .label = call to function with `#[target_feature]`
+
+mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+    call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe function or block
     .note = can only be called if the required target features are available
     .label = call to function with `#[target_feature]`
 
@@ -70,55 +48,24 @@ mir_build_call_to_unsafe_fn_requires_unsafe_nameless =
     .note = consult the function's documentation for information on how to avoid undefined behavior
     .label = call to unsafe function
 
-mir_build_call_to_unsafe_fn_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
-    call to unsafe function `{$function}` is unsafe and requires unsafe function or block
-    .note = consult the function's documentation for information on how to avoid undefined behavior
-    .label = call to unsafe function
-
 mir_build_call_to_unsafe_fn_requires_unsafe_nameless_unsafe_op_in_unsafe_fn_allowed =
     call to unsafe function is unsafe and requires unsafe function or block
     .note = consult the function's documentation for information on how to avoid undefined behavior
     .label = call to unsafe function
 
-mir_build_inline_assembly_requires_unsafe =
-    use of inline assembly is unsafe and requires unsafe block
-    .note = inline assembly is entirely unchecked and can cause undefined behavior
-    .label = use of inline assembly
-
-mir_build_inline_assembly_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
-    use of inline assembly is unsafe and requires unsafe function or block
-    .note = inline assembly is entirely unchecked and can cause undefined behavior
-    .label = use of inline assembly
-
-mir_build_initializing_type_with_requires_unsafe =
-    initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe block
-    .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
-    .label = initializing type with `rustc_layout_scalar_valid_range` attr
-
-mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
-    initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe function or block
-    .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
-    .label = initializing type with `rustc_layout_scalar_valid_range` attr
+mir_build_call_to_unsafe_fn_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+    call to unsafe function `{$function}` is unsafe and requires unsafe function or block
+    .note = consult the function's documentation for information on how to avoid undefined behavior
+    .label = call to unsafe function
 
-mir_build_mutable_static_requires_unsafe =
-    use of mutable static is unsafe and requires unsafe block
-    .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
-    .label = use of mutable static
+mir_build_confused = missing patterns are not covered because `{$variable}` is interpreted as a constant pattern, not a new variable
 
-mir_build_mutable_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
-    use of mutable static is unsafe and requires unsafe function or block
-    .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
-    .label = use of mutable static
+mir_build_const_param_in_pattern = const parameters cannot be referenced in patterns
 
-mir_build_extern_static_requires_unsafe =
-    use of extern static is unsafe and requires unsafe block
-    .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
-    .label = use of extern static
+mir_build_const_pattern_depends_on_generic_parameter =
+    constant pattern depends on a generic parameter
 
-mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
-    use of extern static is unsafe and requires unsafe function or block
-    .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
-    .label = use of extern static
+mir_build_could_not_eval_const_pattern = could not evaluate constant pattern
 
 mir_build_deref_raw_pointer_requires_unsafe =
     dereference of raw pointer is unsafe and requires unsafe block
@@ -130,117 +77,46 @@ mir_build_deref_raw_pointer_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
     .note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
     .label = dereference of raw pointer
 
-mir_build_union_field_requires_unsafe =
-    access to union field is unsafe and requires unsafe block
-    .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior
-    .label = access to union field
-
-mir_build_union_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
-    access to union field is unsafe and requires unsafe function or block
-    .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior
-    .label = access to union field
-
-mir_build_mutation_of_layout_constrained_field_requires_unsafe =
-    mutation of layout constrained field is unsafe and requires unsafe block
-    .note = mutating layout constrained fields cannot statically be checked for valid values
-    .label = mutation of layout constrained field
-
-mir_build_mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
-    mutation of layout constrained field is unsafe and requires unsafe function or block
-    .note = mutating layout constrained fields cannot statically be checked for valid values
-    .label = mutation of layout constrained field
-
-mir_build_borrow_of_layout_constrained_field_requires_unsafe =
-    borrow of layout constrained field with interior mutability is unsafe and requires unsafe block
-    .note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
-    .label = borrow of layout constrained field with interior mutability
-
-mir_build_borrow_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
-    borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block
-    .note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
-    .label = borrow of layout constrained field with interior mutability
-
-mir_build_call_to_fn_with_requires_unsafe =
-    call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block
-    .note = can only be called if the required target features are available
-    .label = call to function with `#[target_feature]`
-
-mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
-    call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe function or block
-    .note = can only be called if the required target features are available
-    .label = call to function with `#[target_feature]`
-
-mir_build_unused_unsafe = unnecessary `unsafe` block
-    .label = unnecessary `unsafe` block
-
-mir_build_unused_unsafe_enclosing_block_label = because it's nested under this `unsafe` block
-mir_build_unused_unsafe_enclosing_fn_label = because it's nested under this `unsafe` fn
-
-mir_build_non_exhaustive_patterns_type_not_empty = non-exhaustive patterns: type `{$ty}` is non-empty
-    .def_note = `{$peeled_ty}` defined here
-    .type_note = the matched value is of type `{$ty}`
-    .non_exhaustive_type_note = the matched value is of type `{$ty}`, which is marked as non-exhaustive
-    .reference_note = references are always considered inhabited
-    .suggestion = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
-    .help = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
-
-mir_build_static_in_pattern = statics cannot be referenced in patterns
-
-mir_build_assoc_const_in_pattern = associated consts cannot be referenced in patterns
-
-mir_build_const_param_in_pattern = const parameters cannot be referenced in patterns
+mir_build_extern_static_requires_unsafe =
+    use of extern static is unsafe and requires unsafe block
+    .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+    .label = use of extern static
 
-mir_build_non_const_path = runtime values cannot be referenced in patterns
+mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+    use of extern static is unsafe and requires unsafe function or block
+    .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+    .label = use of extern static
 
-mir_build_unreachable_pattern = unreachable pattern
-    .label = unreachable pattern
-    .catchall_label = matches any value
+mir_build_float_pattern = floating-point types cannot be used in patterns
 
-mir_build_const_pattern_depends_on_generic_parameter =
-    constant pattern depends on a generic parameter
+mir_build_indirect_structural_match =
+    to use a constant of type `{$non_sm_ty}` in a pattern, `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]`
 
-mir_build_could_not_eval_const_pattern = could not evaluate constant pattern
+mir_build_inform_irrefutable = `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
 
-mir_build_lower_range_bound_must_be_less_than_or_equal_to_upper =
-    lower range bound must be less than or equal to upper
-    .label = lower bound larger than upper bound
-    .teach_note = When matching against a range, the compiler verifies that the range is non-empty. Range patterns include both end-points, so this is equivalent to requiring the start of the range to be less than or equal to the end of the range.
+mir_build_initializing_type_with_requires_unsafe =
+    initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe block
+    .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
+    .label = initializing type with `rustc_layout_scalar_valid_range` attr
 
-mir_build_literal_in_range_out_of_bounds =
-    literal out of range for `{$ty}`
-    .label = this value doesn't fit in `{$ty}` whose maximum value is `{$max}`
+mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+    initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe function or block
+    .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
+    .label = initializing type with `rustc_layout_scalar_valid_range` attr
 
-mir_build_lower_range_bound_must_be_less_than_upper = lower range bound must be less than upper
+mir_build_inline_assembly_requires_unsafe =
+    use of inline assembly is unsafe and requires unsafe block
+    .note = inline assembly is entirely unchecked and can cause undefined behavior
+    .label = use of inline assembly
 
-mir_build_leading_irrefutable_let_patterns = leading irrefutable {$count ->
-        [one] pattern
-        *[other] patterns
-    } in let chain
-    .note = {$count ->
-        [one] this pattern
-        *[other] these patterns
-    } will always match
-    .help = consider moving {$count ->
-        [one] it
-        *[other] them
-    } outside of the construct
+mir_build_inline_assembly_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+    use of inline assembly is unsafe and requires unsafe function or block
+    .note = inline assembly is entirely unchecked and can cause undefined behavior
+    .label = use of inline assembly
 
-mir_build_trailing_irrefutable_let_patterns = trailing irrefutable {$count ->
-        [one] pattern
-        *[other] patterns
-    } in let chain
-    .note = {$count ->
-        [one] this pattern
-        *[other] these patterns
-    } will always match
-    .help = consider moving {$count ->
-        [one] it
-        *[other] them
-    } into the body
+mir_build_interpreted_as_const = introduce a variable instead
 
-mir_build_bindings_with_variant_name =
-    pattern binding `{$name}` is named the same as one of the variants of the type `{$ty_path}`
-    .suggestion = to match on the variant, qualify the path
+mir_build_invalid_pattern = `{$non_sm_ty}` cannot be used in patterns
 
 mir_build_irrefutable_let_patterns_if_let = irrefutable `if let` {$count ->
         [one] pattern
@@ -282,80 +158,97 @@ mir_build_irrefutable_let_patterns_while_let = irrefutable `while let` {$count -
     } will always match, so the loop will never exit
     .help = consider instead using a `loop {"{"} ... {"}"}` with a `let` inside it
 
-mir_build_borrow_of_moved_value = borrow of moved value
-    .label = value moved into `{$name}` here
-    .occurs_because_label = move occurs because `{$name}` has type `{$ty}` which does not implement the `Copy` trait
-    .value_borrowed_label = value borrowed here after move
-    .suggestion = borrow this binding in the pattern to avoid moving the value
+mir_build_leading_irrefutable_let_patterns = leading irrefutable {$count ->
+        [one] pattern
+        *[other] patterns
+    } in let chain
+    .note = {$count ->
+        [one] this pattern
+        *[other] these patterns
+    } will always match
+    .help = consider moving {$count ->
+        [one] it
+        *[other] them
+    } outside of the construct
 
-mir_build_multiple_mut_borrows = cannot borrow value as mutable more than once at a time
+mir_build_literal_in_range_out_of_bounds =
+    literal out of range for `{$ty}`
+    .label = this value doesn't fit in `{$ty}` whose maximum value is `{$max}`
 
-mir_build_already_borrowed = cannot borrow value as mutable because it is also borrowed as immutable
+mir_build_lower_range_bound_must_be_less_than_or_equal_to_upper =
+    lower range bound must be less than or equal to upper
+    .label = lower bound larger than upper bound
+    .teach_note = When matching against a range, the compiler verifies that the range is non-empty. Range patterns include both end-points, so this is equivalent to requiring the start of the range to be less than or equal to the end of the range.
 
-mir_build_already_mut_borrowed = cannot borrow value as immutable because it is also borrowed as mutable
+mir_build_lower_range_bound_must_be_less_than_upper = lower range bound must be less than upper
 
-mir_build_moved_while_borrowed = cannot move out of value because it is borrowed
+mir_build_more_information = for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
 
-mir_build_mutable_borrow = value is mutably borrowed by `{$name}` here
+mir_build_moved = value is moved into `{$name}` here
 
-mir_build_borrow = value is borrowed by `{$name}` here
+mir_build_moved_while_borrowed = cannot move out of value because it is borrowed
 
-mir_build_moved = value is moved into `{$name}` here
+mir_build_multiple_mut_borrows = cannot borrow value as mutable more than once at a time
 
-mir_build_union_pattern = cannot use unions in constant patterns
+mir_build_mutable_borrow = value is mutably borrowed by `{$name}` here
 
-mir_build_type_not_structural =
-     to use a constant of type `{$non_sm_ty}` in a pattern, `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]`
+mir_build_mutable_static_requires_unsafe =
+    use of mutable static is unsafe and requires unsafe block
+    .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+    .label = use of mutable static
 
-mir_build_unsized_pattern = cannot use unsized non-slice type `{$non_sm_ty}` in constant patterns
+mir_build_mutable_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+    use of mutable static is unsafe and requires unsafe function or block
+    .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+    .label = use of mutable static
 
-mir_build_invalid_pattern = `{$non_sm_ty}` cannot be used in patterns
+mir_build_mutation_of_layout_constrained_field_requires_unsafe =
+    mutation of layout constrained field is unsafe and requires unsafe block
+    .note = mutating layout constrained fields cannot statically be checked for valid values
+    .label = mutation of layout constrained field
 
-mir_build_float_pattern = floating-point types cannot be used in patterns
+mir_build_mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+    mutation of layout constrained field is unsafe and requires unsafe function or block
+    .note = mutating layout constrained fields cannot statically be checked for valid values
+    .label = mutation of layout constrained field
 
-mir_build_pointer_pattern = function pointers and unsized pointers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+mir_build_non_const_path = runtime values cannot be referenced in patterns
 
-mir_build_indirect_structural_match =
-    to use a constant of type `{$non_sm_ty}` in a pattern, `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]`
+mir_build_non_exhaustive_omitted_pattern = some variants are not matched explicitly
+    .help = ensure that all variants are matched explicitly by adding the suggested match arms
+    .note = the matched value is of type `{$scrut_ty}` and the `non_exhaustive_omitted_patterns` attribute was found
+
+mir_build_non_exhaustive_patterns_type_not_empty = non-exhaustive patterns: type `{$ty}` is non-empty
+    .def_note = `{$peeled_ty}` defined here
+    .type_note = the matched value is of type `{$ty}`
+    .non_exhaustive_type_note = the matched value is of type `{$ty}`, which is marked as non-exhaustive
+    .reference_note = references are always considered inhabited
+    .suggestion = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+    .help = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 mir_build_nontrivial_structural_match =
     to use a constant of type `{$non_sm_ty}` in a pattern, the constant's initializer must be trivial or `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]`
 
-mir_build_type_not_structural_tip = the traits must be derived, manual `impl`s are not sufficient
-
-mir_build_type_not_structural_more_info = see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
-
 mir_build_overlapping_range_endpoints = multiple patterns overlap on their endpoints
     .range = ... with this range
     .note = you likely meant to write mutually exclusive ranges
 
-mir_build_non_exhaustive_omitted_pattern = some variants are not matched explicitly
-    .help = ensure that all variants are matched explicitly by adding the suggested match arms
-    .note = the matched value is of type `{$scrut_ty}` and the `non_exhaustive_omitted_patterns` attribute was found
-
-mir_build_uncovered = {$count ->
-        [1] pattern `{$witness_1}`
-        [2] patterns `{$witness_1}` and `{$witness_2}`
-        [3] patterns `{$witness_1}`, `{$witness_2}` and `{$witness_3}`
-        *[other] patterns `{$witness_1}`, `{$witness_2}`, `{$witness_3}` and {$remainder} more
-    } not covered
-
-mir_build_privately_uninhabited = pattern `{$witness_1}` is currently uninhabited, but this variant contains private fields which may become inhabited in the future
-
 mir_build_pattern_not_covered = refutable pattern in {$origin}
     .pattern_ty = the matched value is of type `{$pattern_ty}`
 
-mir_build_inform_irrefutable = `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+mir_build_pointer_pattern = function pointers and unsized pointers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
 
-mir_build_more_information = for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+mir_build_privately_uninhabited = pattern `{$witness_1}` is currently uninhabited, but this variant contains private fields which may become inhabited in the future
 
-mir_build_adt_defined_here = `{$ty}` defined here
+mir_build_rustc_box_attribute_error = `#[rustc_box]` attribute used incorrectly
+    .attributes = no other attributes may be applied
+    .not_box = `#[rustc_box]` may only be applied to a `Box::new()` call
+    .missing_box = `#[rustc_box]` requires the `owned_box` lang item
 
-mir_build_variant_defined_here = not covered
+mir_build_static_in_pattern = statics cannot be referenced in patterns
 
-mir_build_interpreted_as_const = introduce a variable instead
+mir_build_suggest_attempted_int_lit = alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits
 
-mir_build_confused = missing patterns are not covered because `{$variable}` is interpreted as a constant pattern, not a new variable
 
 mir_build_suggest_if_let = you might want to use `if let` to ignore the {$count ->
         [one] variant that isn't
@@ -367,10 +260,117 @@ mir_build_suggest_let_else = you might want to use `let else` to handle the {$co
         *[other] variants that aren't
     } matched
 
-mir_build_suggest_attempted_int_lit = alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits
+mir_build_trailing_irrefutable_let_patterns = trailing irrefutable {$count ->
+        [one] pattern
+        *[other] patterns
+    } in let chain
+    .note = {$count ->
+        [one] this pattern
+        *[other] these patterns
+    } will always match
+    .help = consider moving {$count ->
+        [one] it
+        *[other] them
+    } into the body
 
+mir_build_type_not_structural =
+     to use a constant of type `{$non_sm_ty}` in a pattern, `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]`
 
-mir_build_rustc_box_attribute_error = `#[rustc_box]` attribute used incorrectly
-    .attributes = no other attributes may be applied
-    .not_box = `#[rustc_box]` may only be applied to a `Box::new()` call
-    .missing_box = `#[rustc_box]` requires the `owned_box` lang item
+mir_build_type_not_structural_more_info = see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
+
+mir_build_type_not_structural_tip = the traits must be derived, manual `impl`s are not sufficient
+
+mir_build_unconditional_recursion = function cannot return without recursing
+    .label = cannot return without recursing
+    .help = a `loop` may express intention better if this is on purpose
+
+mir_build_unconditional_recursion_call_site_label = recursive call site
+
+mir_build_uncovered = {$count ->
+        [1] pattern `{$witness_1}`
+        [2] patterns `{$witness_1}` and `{$witness_2}`
+        [3] patterns `{$witness_1}`, `{$witness_2}` and `{$witness_3}`
+        *[other] patterns `{$witness_1}`, `{$witness_2}`, `{$witness_3}` and {$remainder} more
+    } not covered
+
+mir_build_union_field_requires_unsafe =
+    access to union field is unsafe and requires unsafe block
+    .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior
+    .label = access to union field
+
+mir_build_union_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+    access to union field is unsafe and requires unsafe function or block
+    .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior
+    .label = access to union field
+
+mir_build_union_pattern = cannot use unions in constant patterns
+
+mir_build_unreachable_pattern = unreachable pattern
+    .label = unreachable pattern
+    .catchall_label = matches any value
+
+mir_build_unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe =
+    borrow of layout constrained field with interior mutability is unsafe and requires unsafe block (error E0133)
+    .note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
+    .label = borrow of layout constrained field with interior mutability
+
+mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe =
+    call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block (error E0133)
+    .note = can only be called if the required target features are available
+    .label = call to function with `#[target_feature]`
+
+mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe =
+    call to unsafe function `{$function}` is unsafe and requires unsafe block (error E0133)
+    .note = consult the function's documentation for information on how to avoid undefined behavior
+    .label = call to unsafe function
+
+mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe_nameless =
+    call to unsafe function is unsafe and requires unsafe block (error E0133)
+    .note = consult the function's documentation for information on how to avoid undefined behavior
+    .label = call to unsafe function
+
+mir_build_unsafe_op_in_unsafe_fn_deref_raw_pointer_requires_unsafe =
+    dereference of raw pointer is unsafe and requires unsafe block (error E0133)
+    .note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+    .label = dereference of raw pointer
+
+mir_build_unsafe_op_in_unsafe_fn_extern_static_requires_unsafe =
+    use of extern static is unsafe and requires unsafe block (error E0133)
+    .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+    .label = use of extern static
+
+mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe =
+    initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe
+    block (error E0133)
+    .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
+    .label = initializing type with `rustc_layout_scalar_valid_range` attr
+
+mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe =
+    use of inline assembly is unsafe and requires unsafe block (error E0133)
+    .note = inline assembly is entirely unchecked and can cause undefined behavior
+    .label = use of inline assembly
+
+mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe =
+    use of mutable static is unsafe and requires unsafe block (error E0133)
+    .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+    .label = use of mutable static
+
+mir_build_unsafe_op_in_unsafe_fn_mutation_of_layout_constrained_field_requires_unsafe =
+    mutation of layout constrained field is unsafe and requires unsafe block (error E0133)
+    .note = mutating layout constrained fields cannot statically be checked for valid values
+    .label = mutation of layout constrained field
+
+mir_build_unsafe_op_in_unsafe_fn_union_field_requires_unsafe =
+    access to union field is unsafe and requires unsafe block (error E0133)
+    .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior
+    .label = access to union field
+
+mir_build_unsized_pattern = cannot use unsized non-slice type `{$non_sm_ty}` in constant patterns
+
+mir_build_unused_unsafe = unnecessary `unsafe` block
+    .label = unnecessary `unsafe` block
+
+mir_build_unused_unsafe_enclosing_block_label = because it's nested under this `unsafe` block
+mir_build_unused_unsafe_enclosing_fn_label = because it's nested under this `unsafe` fn
+
+mir_build_variant_defined_here = not covered
diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
index b74422708ce..ebf830cb9c1 100644
--- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
+++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
@@ -57,6 +57,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
                     place: self.parse_place(args[0])?,
                     target: self.parse_block(args[1])?,
                     unwind: UnwindAction::Continue,
+                    replace: false,
                 })
             },
             @call("mir_call", args) => {
diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
index bcab4c0d24b..3742d640e3b 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -725,6 +725,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         place: to_drop,
                         target: success,
                         unwind: UnwindAction::Continue,
+                        replace: false,
                     },
                 );
                 this.diverge_from(block);
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index 7331f8ecaa9..7c0fbc6f81c 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -91,7 +91,7 @@ use rustc_middle::middle::region;
 use rustc_middle::mir::*;
 use rustc_middle::thir::{Expr, LintLevel};
 
-use rustc_span::{DesugaringKind, Span, DUMMY_SP};
+use rustc_span::{Span, DUMMY_SP};
 
 #[derive(Debug)]
 pub struct Scopes<'tcx> {
@@ -371,6 +371,7 @@ impl DropTree {
                         // The caller will handle this if needed.
                         unwind: UnwindAction::Terminate,
                         place: drop_data.0.local.into(),
+                        replace: false,
                     };
                     cfg.terminate(block, drop_data.0.source_info, terminator);
                 }
@@ -1128,9 +1129,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         place: Place<'tcx>,
         value: Rvalue<'tcx>,
     ) -> BlockAnd<()> {
-        let span = self.tcx.with_stable_hashing_context(|hcx| {
-            span.mark_with_reason(None, DesugaringKind::Replace, self.tcx.sess.edition(), hcx)
-        });
         let source_info = self.source_info(span);
 
         // create the new block for the assignment
@@ -1148,6 +1146,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 place,
                 target: assign,
                 unwind: UnwindAction::Cleanup(assign_unwind),
+                replace: true,
             },
         );
         self.diverge_from(block);
@@ -1261,6 +1260,7 @@ fn build_scope_drops<'tcx>(
                         place: local.into(),
                         target: next,
                         unwind: UnwindAction::Continue,
+                        replace: false,
                     },
                 );
                 block = next;
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index 463f639defe..d00fb754c64 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -142,7 +142,7 @@ impl<'tcx> Cx<'tcx> {
                     var: ty::BoundVar::from_usize(bound_vars.len() - 1),
                     kind: ty::BrEnv,
                 };
-                let env_region = self.tcx.mk_re_late_bound(ty::INNERMOST, br);
+                let env_region = ty::Region::new_late_bound(self.tcx, ty::INNERMOST, br);
                 let closure_env_ty =
                     self.tcx.closure_env_ty(closure_def_id, closure_substs, env_region).unwrap();
                 let liberated_closure_env_ty = self.tcx.erase_late_bound_regions(
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index c11a4f7229d..1e51cb9aa96 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -491,8 +491,8 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
             AdtDefinedHere { adt_def_span, ty, variants }
         };
 
-        // Emit an extra note if the first uncovered witness is
-        // visibly uninhabited anywhere in the current crate.
+        // Emit an extra note if the first uncovered witness would be uninhabited
+        // if we disregard visibility.
         let witness_1_is_privately_uninhabited =
             if cx.tcx.features().exhaustive_patterns
                 && let Some(witness_1) = witnesses.get(0)
diff --git a/compiler/rustc_mir_dataflow/messages.ftl b/compiler/rustc_mir_dataflow/messages.ftl
index 98854152508..5698367e42b 100644
--- a/compiler/rustc_mir_dataflow/messages.ftl
+++ b/compiler/rustc_mir_dataflow/messages.ftl
@@ -1,29 +1,29 @@
+mir_dataflow_duplicate_values_for =
+    duplicate values for `{$name}`
+
 mir_dataflow_path_must_end_in_filename =
     path must end in a filename
 
-mir_dataflow_unknown_formatter =
-    unknown formatter
+mir_dataflow_peek_argument_not_a_local =
+    rustc_peek: argument was not a local
 
-mir_dataflow_duplicate_values_for =
-    duplicate values for `{$name}`
+mir_dataflow_peek_argument_untracked =
+    rustc_peek: argument untracked
 
-mir_dataflow_requires_an_argument =
-    `{$name}` requires an argument
+mir_dataflow_peek_bit_not_set =
+    rustc_peek: bit not set
 
-mir_dataflow_stop_after_dataflow_ended_compilation =
-    stop_after_dataflow ended compilation
+mir_dataflow_peek_must_be_not_temporary =
+    dataflow::sanity_check cannot feed a non-temp to rustc_peek
 
 mir_dataflow_peek_must_be_place_or_ref_place =
     rustc_peek: argument expression must be either `place` or `&place`
 
-mir_dataflow_peek_must_be_not_temporary =
-    dataflow::sanity_check cannot feed a non-temp to rustc_peek
-
-mir_dataflow_peek_bit_not_set =
-    rustc_peek: bit not set
+mir_dataflow_requires_an_argument =
+    `{$name}` requires an argument
 
-mir_dataflow_peek_argument_not_a_local =
-    rustc_peek: argument was not a local
+mir_dataflow_stop_after_dataflow_ended_compilation =
+    stop_after_dataflow ended compilation
 
-mir_dataflow_peek_argument_untracked =
-    rustc_peek: argument untracked
+mir_dataflow_unknown_formatter =
+    unknown formatter
diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
index 18895072c3b..d615c83d621 100644
--- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
@@ -237,6 +237,7 @@ where
                         place: self.place,
                         target: self.succ,
                         unwind: self.unwind.into_action(),
+                        replace: false,
                     },
                 );
             }
@@ -719,6 +720,7 @@ where
                 place: tcx.mk_place_deref(ptr),
                 target: loop_block,
                 unwind: unwind.into_action(),
+                replace: false,
             },
         );
 
@@ -963,8 +965,12 @@ where
     }
 
     fn drop_block(&mut self, target: BasicBlock, unwind: Unwind) -> BasicBlock {
-        let block =
-            TerminatorKind::Drop { place: self.place, target, unwind: unwind.into_action() };
+        let block = TerminatorKind::Drop {
+            place: self.place,
+            target,
+            unwind: unwind.into_action(),
+            replace: false,
+        };
         self.new_block(unwind, block)
     }
 
diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs
index c8fe1af6674..ba328e78040 100644
--- a/compiler/rustc_mir_dataflow/src/framework/direction.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs
@@ -479,7 +479,7 @@ impl Direction for Forward {
             Goto { target } => propagate(target, exit_state),
 
             Assert { target, unwind, expected: _, msg: _, cond: _ }
-            | Drop { target, unwind, place: _ }
+            | Drop { target, unwind, place: _, replace: _ }
             | FalseUnwind { real_target: target, unwind } => {
                 if let UnwindAction::Cleanup(unwind) = unwind {
                     propagate(unwind, exit_state);
diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs
index aeca0073304..6ae6bdc17d5 100644
--- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs
@@ -199,8 +199,7 @@ impl DefUse {
                 | NonMutatingUseContext::Move
                 | NonMutatingUseContext::PlaceMention
                 | NonMutatingUseContext::ShallowBorrow
-                | NonMutatingUseContext::SharedBorrow
-                | NonMutatingUseContext::UniqueBorrow,
+                | NonMutatingUseContext::SharedBorrow,
             ) => Some(DefUse::Use),
 
             PlaceContext::MutatingUse(MutatingUseContext::Projection)
diff --git a/compiler/rustc_mir_transform/messages.ftl b/compiler/rustc_mir_transform/messages.ftl
index 8c85cb5f76d..b13429d121d 100644
--- a/compiler/rustc_mir_transform/messages.ftl
+++ b/compiler/rustc_mir_transform/messages.ftl
@@ -1,3 +1,8 @@
+mir_transform_arithmetic_overflow = this arithmetic operation will overflow
+mir_transform_call_to_unsafe_label = call to unsafe function
+mir_transform_call_to_unsafe_note = consult the function's documentation for information on how to avoid undefined behavior
+mir_transform_const_defined_here = `const` item defined here
+
 mir_transform_const_modify = attempting to modify a `const` item
     .note = each usage of a `const` item creates a new temporary; the original `const` item will not be modified
 
@@ -6,50 +11,10 @@ mir_transform_const_mut_borrow = taking a mutable reference to a `const` item
     .note2 = the mutable reference will refer to this temporary, not the original `const` item
     .note3 = mutable reference created due to call to this method
 
-mir_transform_const_defined_here = `const` item defined here
-
-mir_transform_unaligned_packed_ref = reference to packed field is unaligned
-    .note = packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses
-    .note_ub = creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
-    .help = copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-
-mir_transform_unused_unsafe = unnecessary `unsafe` block
-    .label = because it's nested under this `unsafe` block
-
-mir_transform_requires_unsafe = {$details} is unsafe and requires unsafe {$op_in_unsafe_fn_allowed ->
-    [true] function or block
-    *[false] block
-    }
-    .not_inherited = items do not inherit unsafety from separate enclosing items
-
-mir_transform_call_to_unsafe_label = call to unsafe function
-mir_transform_call_to_unsafe_note = consult the function's documentation for information on how to avoid undefined behavior
-mir_transform_use_of_asm_label = use of inline assembly
-mir_transform_use_of_asm_note = inline assembly is entirely unchecked and can cause undefined behavior
-mir_transform_initializing_valid_range_label = initializing type with `rustc_layout_scalar_valid_range` attr
-mir_transform_initializing_valid_range_note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
 mir_transform_const_ptr2int_label = cast of pointer to int
 mir_transform_const_ptr2int_note = casting pointers to integers in constants
-mir_transform_use_of_static_mut_label = use of mutable static
-mir_transform_use_of_static_mut_note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
-mir_transform_use_of_extern_static_label = use of extern static
-mir_transform_use_of_extern_static_note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
 mir_transform_deref_ptr_label = dereference of raw pointer
 mir_transform_deref_ptr_note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
-mir_transform_union_access_label = access to union field
-mir_transform_union_access_note = the field may not be properly initialized: using uninitialized data will cause undefined behavior
-mir_transform_mutation_layout_constrained_label = mutation of layout constrained field
-mir_transform_mutation_layout_constrained_note = mutating layout constrained fields cannot statically be checked for valid values
-mir_transform_mutation_layout_constrained_borrow_label = borrow of layout constrained field with interior mutability
-mir_transform_mutation_layout_constrained_borrow_note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
-mir_transform_target_feature_call_label = call to function with `#[target_feature]`
-mir_transform_target_feature_call_note = can only be called if the required target features are available
-
-mir_transform_unsafe_op_in_unsafe_fn = {$details} is unsafe and requires unsafe block (error E0133)
-
-mir_transform_arithmetic_overflow = this arithmetic operation will overflow
-mir_transform_operation_will_panic = this operation will panic at runtime
-
 mir_transform_ffi_unwind_call = call to {$foreign ->
     [true] foreign function
     *[false] function pointer
@@ -58,9 +23,45 @@ mir_transform_ffi_unwind_call = call to {$foreign ->
 mir_transform_fn_item_ref = taking a reference to a function item does not give a function pointer
     .suggestion = cast `{$ident}` to obtain a function pointer
 
+mir_transform_initializing_valid_range_label = initializing type with `rustc_layout_scalar_valid_range` attr
+mir_transform_initializing_valid_range_note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
 mir_transform_must_not_suspend = {$pre}`{$def_path}`{$post} held across a suspend point, but should not be
     .label = the value is held across this suspend point
     .note = {$reason}
     .help = consider using a block (`{"{ ... }"}`) to shrink the value's scope, ending before the suspend point
 
+mir_transform_mutation_layout_constrained_borrow_label = borrow of layout constrained field with interior mutability
+mir_transform_mutation_layout_constrained_borrow_note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
+mir_transform_mutation_layout_constrained_label = mutation of layout constrained field
+mir_transform_mutation_layout_constrained_note = mutating layout constrained fields cannot statically be checked for valid values
+mir_transform_operation_will_panic = this operation will panic at runtime
+
+mir_transform_requires_unsafe = {$details} is unsafe and requires unsafe {$op_in_unsafe_fn_allowed ->
+    [true] function or block
+    *[false] block
+    }
+    .not_inherited = items do not inherit unsafety from separate enclosing items
+
 mir_transform_simd_shuffle_last_const = last argument of `simd_shuffle` is required to be a `const` item
+
+mir_transform_target_feature_call_label = call to function with `#[target_feature]`
+mir_transform_target_feature_call_note = can only be called if the required target features are available
+
+mir_transform_unaligned_packed_ref = reference to packed field is unaligned
+    .note = packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses
+    .note_ub = creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+    .help = copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+mir_transform_union_access_label = access to union field
+mir_transform_union_access_note = the field may not be properly initialized: using uninitialized data will cause undefined behavior
+mir_transform_unsafe_op_in_unsafe_fn = {$details} is unsafe and requires unsafe block (error E0133)
+
+mir_transform_unused_unsafe = unnecessary `unsafe` block
+    .label = because it's nested under this `unsafe` block
+
+mir_transform_use_of_asm_label = use of inline assembly
+mir_transform_use_of_asm_note = inline assembly is entirely unchecked and can cause undefined behavior
+mir_transform_use_of_extern_static_label = use of extern static
+mir_transform_use_of_extern_static_note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+mir_transform_use_of_static_mut_label = use of mutable static
+mir_transform_use_of_static_mut_note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
diff --git a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
index b29ffcc70f9..ef2a0c790e9 100644
--- a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
+++ b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
@@ -80,7 +80,7 @@ fn add_move_for_packed_drop<'tcx>(
     is_cleanup: bool,
 ) {
     debug!("add_move_for_packed_drop({:?} @ {:?})", terminator, loc);
-    let TerminatorKind::Drop { ref place, target, unwind } = terminator.kind else {
+    let TerminatorKind::Drop { ref place, target, unwind, replace } = terminator.kind else {
         unreachable!();
     };
 
@@ -98,6 +98,11 @@ fn add_move_for_packed_drop<'tcx>(
     patch.add_assign(loc, Place::from(temp), Rvalue::Use(Operand::Move(*place)));
     patch.patch_terminator(
         loc.block,
-        TerminatorKind::Drop { place: Place::from(temp), target: storage_dead_block, unwind },
+        TerminatorKind::Drop {
+            place: Place::from(temp),
+            target: storage_dead_block,
+            unwind,
+            replace,
+        },
     );
 }
diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs
index d60184e0ebe..1fe8ea07892 100644
--- a/compiler/rustc_mir_transform/src/check_alignment.rs
+++ b/compiler/rustc_mir_transform/src/check_alignment.rs
@@ -75,6 +75,14 @@ struct PointerFinder<'tcx, 'a> {
 }
 
 impl<'tcx, 'a> Visitor<'tcx> for PointerFinder<'tcx, 'a> {
+    fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
+        if let Rvalue::AddressOf(..) = rvalue {
+            // Ignore dereferences inside of an AddressOf
+            return;
+        }
+        self.super_rvalue(rvalue, location);
+    }
+
     fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) {
         if let PlaceContext::NonUse(_) = context {
             return;
diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs
index a5d18fff89b..1ba1951afde 100644
--- a/compiler/rustc_mir_transform/src/const_prop.rs
+++ b/compiler/rustc_mir_transform/src/const_prop.rs
@@ -772,7 +772,6 @@ impl<'tcx> Visitor<'tcx> for CanConstProp {
             // mutation.
             | NonMutatingUse(NonMutatingUseContext::SharedBorrow)
             | NonMutatingUse(NonMutatingUseContext::ShallowBorrow)
-            | NonMutatingUse(NonMutatingUseContext::UniqueBorrow)
             | NonMutatingUse(NonMutatingUseContext::AddressOf)
             | MutatingUse(MutatingUseContext::Borrow)
             | MutatingUse(MutatingUseContext::AddressOf) => {
diff --git a/compiler/rustc_mir_transform/src/copy_prop.rs b/compiler/rustc_mir_transform/src/copy_prop.rs
index 319f3a79705..3df459dfa79 100644
--- a/compiler/rustc_mir_transform/src/copy_prop.rs
+++ b/compiler/rustc_mir_transform/src/copy_prop.rs
@@ -130,7 +130,6 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> {
             PlaceContext::NonMutatingUse(
                 NonMutatingUseContext::SharedBorrow
                 | NonMutatingUseContext::ShallowBorrow
-                | NonMutatingUseContext::UniqueBorrow
                 | NonMutatingUseContext::AddressOf,
             ) => true,
             // For debuginfo, merging locals is ok.
diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs
index 98e7a519c20..fda0e1023f7 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs
@@ -14,7 +14,7 @@ use rustc_mir_dataflow::un_derefer::UnDerefer;
 use rustc_mir_dataflow::MoveDataParamEnv;
 use rustc_mir_dataflow::{on_all_children_bits, on_all_drop_children_bits};
 use rustc_mir_dataflow::{Analysis, ResultsCursor};
-use rustc_span::{DesugaringKind, Span};
+use rustc_span::Span;
 use rustc_target::abi::{FieldIdx, VariantIdx};
 use std::fmt;
 
@@ -401,7 +401,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
             let terminator = data.terminator();
 
             match terminator.kind {
-                TerminatorKind::Drop { mut place, target, unwind } => {
+                TerminatorKind::Drop { mut place, target, unwind, replace } => {
                     if let Some(new_place) = self.un_derefer.derefer(place.as_ref(), self.body) {
                         place = new_place;
                     }
@@ -434,10 +434,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
                             )
                         }
                         LookupResult::Parent(..) => {
-                            if !matches!(
-                                terminator.source_info.span.desugaring_kind(),
-                                Some(DesugaringKind::Replace),
-                            ) {
+                            if !replace {
                                 self.tcx.sess.delay_span_bug(
                                     terminator.source_info.span,
                                     format!("drop of untracked value {:?}", bb),
diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs
index 5989dbebf2d..b1c9c4acc40 100644
--- a/compiler/rustc_mir_transform/src/function_item_references.rs
+++ b/compiler/rustc_mir_transform/src/function_item_references.rs
@@ -83,7 +83,7 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
                         // If the inner type matches the type bound by `Pointer`
                         if inner_ty == bound_ty {
                             // Do a substitution using the parameters from the callsite
-                            let subst_ty = EarlyBinder(inner_ty).subst(self.tcx, substs_ref);
+                            let subst_ty = EarlyBinder::bind(inner_ty).subst(self.tcx, substs_ref);
                             if let Some((fn_id, fn_substs)) =
                                 FunctionItemRefChecker::is_fn_ref(subst_ty)
                             {
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index 891e446942e..89567ed0ab8 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -1045,7 +1045,10 @@ fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
 
     for (block, block_data) in body.basic_blocks.iter_enumerated() {
         let (target, unwind, source_info) = match block_data.terminator() {
-            Terminator { source_info, kind: TerminatorKind::Drop { place, target, unwind } } => {
+            Terminator {
+                source_info,
+                kind: TerminatorKind::Drop { place, target, unwind, replace: _ },
+            } => {
                 if let Some(local) = place.as_local() {
                     if local == SELF_ARG {
                         (target, unwind, source_info)
@@ -1304,6 +1307,7 @@ fn insert_clean_drop(body: &mut Body<'_>) -> BasicBlock {
         place: Place::from(SELF_ARG),
         target: return_block,
         unwind: UnwindAction::Continue,
+        replace: false,
     };
     let source_info = SourceInfo::outermost(body.span);
 
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 1748b1bf4a0..55b9f084c39 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -192,7 +192,7 @@ impl<'tcx> Inliner<'tcx> {
         let Ok(callee_body) = callsite.callee.try_subst_mir_and_normalize_erasing_regions(
             self.tcx,
             self.param_env,
-            ty::EarlyBinder(callee_body.clone()),
+            ty::EarlyBinder::bind(callee_body.clone()),
         ) else {
             return Err("failed to normalize callee body");
         };
@@ -449,16 +449,16 @@ impl<'tcx> Inliner<'tcx> {
             checker.visit_basic_block_data(bb, blk);
 
             let term = blk.terminator();
-            if let TerminatorKind::Drop { ref place, target, unwind } = term.kind {
+            if let TerminatorKind::Drop { ref place, target, unwind, replace: _ } = term.kind {
                 work_list.push(target);
 
                 // If the place doesn't actually need dropping, treat it like a regular goto.
                 let ty = callsite
                     .callee
-                    .subst_mir(self.tcx, ty::EarlyBinder(&place.ty(callee_body, tcx).ty));
+                    .subst_mir(self.tcx, ty::EarlyBinder::bind(&place.ty(callee_body, tcx).ty));
                 if ty.needs_drop(tcx, self.param_env) && let UnwindAction::Cleanup(unwind) = unwind {
-                        work_list.push(unwind);
-                    }
+                    work_list.push(unwind);
+                }
             } else if callee_attrs.instruction_set != self.codegen_fn_attrs.instruction_set
                 && matches!(term.kind, TerminatorKind::InlineAsm { .. })
             {
@@ -790,7 +790,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
                 // If the place doesn't actually need dropping, treat it like a regular goto.
                 let ty = self
                     .instance
-                    .subst_mir(tcx, ty::EarlyBinder(&place.ty(self.callee_body, tcx).ty));
+                    .subst_mir(tcx, ty::EarlyBinder::bind(&place.ty(self.callee_body, tcx).ty));
                 if ty.needs_drop(tcx, self.param_env) {
                     self.cost += CALL_PENALTY;
                     if let UnwindAction::Cleanup(_) = unwind {
@@ -801,7 +801,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
                 }
             }
             TerminatorKind::Call { func: Operand::Constant(ref f), unwind, .. } => {
-                let fn_ty = self.instance.subst_mir(tcx, ty::EarlyBinder(&f.literal.ty()));
+                let fn_ty = self.instance.subst_mir(tcx, ty::EarlyBinder::bind(&f.literal.ty()));
                 self.cost += if let ty::FnDef(def_id, _) = *fn_ty.kind() && tcx.is_intrinsic(def_id) {
                     // Don't give intrinsics the extra penalty for calls
                     INSTR_COST
diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs
index 1ccf06f6153..8a10445f837 100644
--- a/compiler/rustc_mir_transform/src/inline/cycle.rs
+++ b/compiler/rustc_mir_transform/src/inline/cycle.rs
@@ -47,7 +47,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>(
             let Ok(substs) = caller.try_subst_mir_and_normalize_erasing_regions(
                 tcx,
                 param_env,
-                ty::EarlyBinder(substs),
+                ty::EarlyBinder::bind(substs),
             ) else {
                 trace!(?caller, ?param_env, ?substs, "cannot normalize, skipping");
                 continue;
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 65864dc016f..54c138b6fbd 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -3,6 +3,7 @@
 #![deny(rustc::diagnostic_outside_of_impl)]
 #![feature(box_patterns)]
 #![feature(drain_filter)]
+#![feature(is_sorted)]
 #![feature(let_chains)]
 #![feature(map_try_insert)]
 #![feature(min_specialization)]
@@ -84,6 +85,7 @@ mod match_branches;
 mod multiple_return_terminators;
 mod normalize_array_len;
 mod nrvo;
+mod prettify;
 mod ref_prop;
 mod remove_noop_landing_pads;
 mod remove_storage_markers;
@@ -581,6 +583,9 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             &large_enums::EnumSizeOpt { discrepancy: 128 },
             // Some cleanup necessary at least for LLVM and potentially other codegen backends.
             &add_call_guards::CriticalCallEdges,
+            // Cleanup for human readability, off by default.
+            &prettify::ReorderBasicBlocks,
+            &prettify::ReorderLocals,
             // Dump the end result for testing and debugging purposes.
             &dump_mir::Marker("PreCodegen"),
         ],
diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs
index 59942dc76f9..6eb48498274 100644
--- a/compiler/rustc_mir_transform/src/match_branches.rs
+++ b/compiler/rustc_mir_transform/src/match_branches.rs
@@ -41,7 +41,7 @@ pub struct MatchBranchSimplification;
 
 impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
-        sess.mir_opt_level() >= 3
+        sess.mir_opt_level() >= 1
     }
 
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
@@ -62,7 +62,12 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
                     ..
                 } if targets.iter().len() == 1 => {
                     let (value, target) = targets.iter().next().unwrap();
-                    if target == targets.otherwise() {
+                    // We require that this block and the two possible target blocks all be
+                    // distinct.
+                    if target == targets.otherwise()
+                        || bb_idx == target
+                        || bb_idx == targets.otherwise()
+                    {
                         continue;
                     }
                     (discr, value, target, targets.otherwise())
diff --git a/compiler/rustc_mir_transform/src/prettify.rs b/compiler/rustc_mir_transform/src/prettify.rs
new file mode 100644
index 00000000000..6f46974ea00
--- /dev/null
+++ b/compiler/rustc_mir_transform/src/prettify.rs
@@ -0,0 +1,150 @@
+//! These two passes provide no value to the compiler, so are off at every level.
+//!
+//! However, they can be enabled on the command line
+//! (`-Zmir-enable-passes=+ReorderBasicBlocks,+ReorderLocals`)
+//! to make the MIR easier to read for humans.
+
+use crate::MirPass;
+use rustc_index::{bit_set::BitSet, IndexSlice, IndexVec};
+use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
+use rustc_middle::mir::*;
+use rustc_middle::ty::TyCtxt;
+use rustc_session::Session;
+
+/// Rearranges the basic blocks into a *reverse post-order*.
+///
+/// Thus after this pass, all the successors of a block are later than it in the
+/// `IndexVec`, unless that successor is a back-edge (such as from a loop).
+pub struct ReorderBasicBlocks;
+
+impl<'tcx> MirPass<'tcx> for ReorderBasicBlocks {
+    fn is_enabled(&self, _session: &Session) -> bool {
+        false
+    }
+
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+        let rpo: IndexVec<BasicBlock, BasicBlock> =
+            body.basic_blocks.postorder().iter().copied().rev().collect();
+        if rpo.iter().is_sorted() {
+            return;
+        }
+
+        let mut updater = BasicBlockUpdater { map: rpo.invert_bijective_mapping(), tcx };
+        debug_assert_eq!(updater.map[START_BLOCK], START_BLOCK);
+        updater.visit_body(body);
+
+        permute(body.basic_blocks.as_mut(), &updater.map);
+    }
+}
+
+/// Rearranges the locals into *use* order.
+///
+/// Thus after this pass, a local with a smaller [`Location`] where it was first
+/// assigned or referenced will have a smaller number.
+///
+/// (Does not reorder arguments nor the [`RETURN_PLACE`].)
+pub struct ReorderLocals;
+
+impl<'tcx> MirPass<'tcx> for ReorderLocals {
+    fn is_enabled(&self, _session: &Session) -> bool {
+        false
+    }
+
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+        let mut finder =
+            LocalFinder { map: IndexVec::new(), seen: BitSet::new_empty(body.local_decls.len()) };
+
+        // We can't reorder the return place or the arguments
+        for local in (0..=body.arg_count).map(Local::from_usize) {
+            finder.track(local);
+        }
+
+        for (bb, bbd) in body.basic_blocks.iter_enumerated() {
+            finder.visit_basic_block_data(bb, bbd);
+        }
+
+        // track everything in case there are some locals that we never saw,
+        // such as in non-block things like debug info or in non-uses.
+        for local in body.local_decls.indices() {
+            finder.track(local);
+        }
+
+        if finder.map.iter().is_sorted() {
+            return;
+        }
+
+        let mut updater = LocalUpdater { map: finder.map.invert_bijective_mapping(), tcx };
+
+        for local in (0..=body.arg_count).map(Local::from_usize) {
+            debug_assert_eq!(updater.map[local], local);
+        }
+
+        updater.visit_body_preserves_cfg(body);
+
+        permute(&mut body.local_decls, &updater.map);
+    }
+}
+
+fn permute<I: rustc_index::Idx + Ord, T>(data: &mut IndexVec<I, T>, map: &IndexSlice<I, I>) {
+    // FIXME: It would be nice to have a less-awkward way to apply permutations,
+    // but I don't know one that exists.  `sort_by_cached_key` has logic for it
+    // internally, but not in a way that we're allowed to use here.
+    let mut enumerated: Vec<_> = std::mem::take(data).into_iter_enumerated().collect();
+    enumerated.sort_by_key(|p| map[p.0]);
+    *data = enumerated.into_iter().map(|p| p.1).collect();
+}
+
+struct BasicBlockUpdater<'tcx> {
+    map: IndexVec<BasicBlock, BasicBlock>,
+    tcx: TyCtxt<'tcx>,
+}
+
+impl<'tcx> MutVisitor<'tcx> for BasicBlockUpdater<'tcx> {
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+
+    fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, _location: Location) {
+        for succ in terminator.successors_mut() {
+            *succ = self.map[*succ];
+        }
+    }
+}
+
+struct LocalFinder {
+    map: IndexVec<Local, Local>,
+    seen: BitSet<Local>,
+}
+
+impl LocalFinder {
+    fn track(&mut self, l: Local) {
+        if self.seen.insert(l) {
+            self.map.push(l);
+        }
+    }
+}
+
+impl<'tcx> Visitor<'tcx> for LocalFinder {
+    fn visit_local(&mut self, l: Local, context: PlaceContext, _location: Location) {
+        // Exclude non-uses to keep `StorageLive` from controlling where we put
+        // a `Local`, since it might not actually be assigned until much later.
+        if context.is_use() {
+            self.track(l);
+        }
+    }
+}
+
+struct LocalUpdater<'tcx> {
+    pub map: IndexVec<Local, Local>,
+    pub tcx: TyCtxt<'tcx>,
+}
+
+impl<'tcx> MutVisitor<'tcx> for LocalUpdater<'tcx> {
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+
+    fn visit_local(&mut self, l: &mut Local, _: PlaceContext, _: Location) {
+        *l = self.map[*l];
+    }
+}
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index 7c47d8814db..ae726dea944 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -69,7 +69,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
             // of this function. Is this intentional?
             if let Some(ty::Generator(gen_def_id, substs, _)) = ty.map(Ty::kind) {
                 let body = tcx.optimized_mir(*gen_def_id).generator_drop().unwrap();
-                let body = EarlyBinder(body.clone()).subst(tcx, substs);
+                let body = EarlyBinder::bind(body.clone()).subst(tcx, substs);
                 debug!("make_shim({:?}) = {:?}", instance, body);
                 return body;
             }
@@ -544,6 +544,7 @@ impl<'tcx> CloneShimBuilder<'tcx> {
                     place: dest_field,
                     target: unwind,
                     unwind: UnwindAction::Terminate,
+                    replace: false,
                 },
                 true,
             );
@@ -643,8 +644,11 @@ fn build_call_shim<'tcx>(
     let sig = sig.map_bound(|sig| tcx.erase_late_bound_regions(sig));
 
     assert_eq!(sig_substs.is_some(), !instance.has_polymorphic_mir_body());
-    let mut sig =
-        if let Some(sig_substs) = sig_substs { sig.subst(tcx, &sig_substs) } else { sig.0 };
+    let mut sig = if let Some(sig_substs) = sig_substs {
+        sig.subst(tcx, &sig_substs)
+    } else {
+        sig.skip_binder()
+    };
 
     if let CallKind::Indirect(fnty) = call_kind {
         // `sig` determines our local decls, and thus the callee type in the `Call` terminator. This
@@ -800,6 +804,7 @@ fn build_call_shim<'tcx>(
                 place: rcvr_place(),
                 target: BasicBlock::new(2),
                 unwind: UnwindAction::Continue,
+                replace: false,
             },
             false,
         );
@@ -815,6 +820,7 @@ fn build_call_shim<'tcx>(
                 place: rcvr_place(),
                 target: BasicBlock::new(4),
                 unwind: UnwindAction::Terminate,
+                replace: false,
             },
             true,
         );
diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs
index e8e4246b797..7a0d3a025f3 100644
--- a/compiler/rustc_mir_transform/src/ssa.rs
+++ b/compiler/rustc_mir_transform/src/ssa.rs
@@ -216,7 +216,6 @@ impl<'tcx> Visitor<'tcx> for SsaVisitor<'_> {
             PlaceContext::NonMutatingUse(
                 NonMutatingUseContext::SharedBorrow
                 | NonMutatingUseContext::ShallowBorrow
-                | NonMutatingUseContext::UniqueBorrow
                 | NonMutatingUseContext::AddressOf,
             )
             | PlaceContext::MutatingUse(_) => {
diff --git a/compiler/rustc_monomorphize/messages.ftl b/compiler/rustc_monomorphize/messages.ftl
index 6cea6a603f3..fdd47e6f79b 100644
--- a/compiler/rustc_monomorphize/messages.ftl
+++ b/compiler/rustc_monomorphize/messages.ftl
@@ -1,32 +1,32 @@
-monomorphize_recursion_limit =
-    reached the recursion limit while instantiating `{$shrunk}`
-    .note = `{$def_path_str}` defined here
-
-monomorphize_written_to_path = the full type name has been written to '{$path}'
-
-monomorphize_type_length_limit = reached the type-length limit while instantiating `{$shrunk}`
-
 monomorphize_consider_type_length_limit =
     consider adding a `#![type_length_limit="{$type_length}"]` attribute to your crate
 
-monomorphize_fatal_error = {$error_message}
-
-monomorphize_unknown_partition_strategy = unknown partitioning strategy
+monomorphize_couldnt_dump_mono_stats =
+    unexpected error occurred while dumping monomorphization stats: {$error}
 
-monomorphize_symbol_already_defined = symbol `{$symbol}` is already defined
+monomorphize_encountered_error_while_instantiating =
+    the above error was encountered while instantiating `{$formatted_item}`
 
-monomorphize_unused_generic_params = item has unused generic parameters
+monomorphize_fatal_error = {$error_message}
 
 monomorphize_large_assignments =
     moving {$size} bytes
     .label = value moved from here
     .note = The current maximum size is {$limit}, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
 
-monomorphize_couldnt_dump_mono_stats =
-    unexpected error occurred while dumping monomorphization stats: {$error}
+monomorphize_recursion_limit =
+    reached the recursion limit while instantiating `{$shrunk}`
+    .note = `{$def_path_str}` defined here
 
-monomorphize_encountered_error_while_instantiating =
-    the above error was encountered while instantiating `{$formatted_item}`
+monomorphize_symbol_already_defined = symbol `{$symbol}` is already defined
+
+monomorphize_type_length_limit = reached the type-length limit while instantiating `{$shrunk}`
 
 monomorphize_unknown_cgu_collection_mode =
     unknown codegen-item collection mode '{$mode}', falling back to 'lazy' mode
+
+monomorphize_unknown_partition_strategy = unknown partitioning strategy
+
+monomorphize_unused_generic_params = item has unused generic parameters
+
+monomorphize_written_to_path = the full type name has been written to '{$path}'
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 35b154b7b34..cefa64d27ac 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -677,7 +677,7 @@ impl<'a, 'tcx> MirNeighborCollector<'a, 'tcx> {
         self.instance.subst_mir_and_normalize_erasing_regions(
             self.tcx,
             ty::ParamEnv::reveal_all(),
-            ty::EarlyBinder(value),
+            ty::EarlyBinder::bind(value),
         )
     }
 }
diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs
new file mode 100644
index 00000000000..be9c349c384
--- /dev/null
+++ b/compiler/rustc_monomorphize/src/partitioning.rs
@@ -0,0 +1,1182 @@
+//! Partitioning Codegen Units for Incremental Compilation
+//! ======================================================
+//!
+//! The task of this module is to take the complete set of monomorphizations of
+//! a crate and produce a set of codegen units from it, where a codegen unit
+//! is a named set of (mono-item, linkage) pairs. That is, this module
+//! decides which monomorphization appears in which codegen units with which
+//! linkage. The following paragraphs describe some of the background on the
+//! partitioning scheme.
+//!
+//! The most important opportunity for saving on compilation time with
+//! incremental compilation is to avoid re-codegenning and re-optimizing code.
+//! Since the unit of codegen and optimization for LLVM is "modules" or, how
+//! we call them "codegen units", the particulars of how much time can be saved
+//! by incremental compilation are tightly linked to how the output program is
+//! partitioned into these codegen units prior to passing it to LLVM --
+//! especially because we have to treat codegen units as opaque entities once
+//! they are created: There is no way for us to incrementally update an existing
+//! LLVM module and so we have to build any such module from scratch if it was
+//! affected by some change in the source code.
+//!
+//! From that point of view it would make sense to maximize the number of
+//! codegen units by, for example, putting each function into its own module.
+//! That way only those modules would have to be re-compiled that were actually
+//! affected by some change, minimizing the number of functions that could have
+//! been re-used but just happened to be located in a module that is
+//! re-compiled.
+//!
+//! However, since LLVM optimization does not work across module boundaries,
+//! using such a highly granular partitioning would lead to very slow runtime
+//! code since it would effectively prohibit inlining and other inter-procedure
+//! optimizations. We want to avoid that as much as possible.
+//!
+//! Thus we end up with a trade-off: The bigger the codegen units, the better
+//! LLVM's optimizer can do its work, but also the smaller the compilation time
+//! reduction we get from incremental compilation.
+//!
+//! Ideally, we would create a partitioning such that there are few big codegen
+//! units with few interdependencies between them. For now though, we use the
+//! following heuristic to determine the partitioning:
+//!
+//! - There are two codegen units for every source-level module:
+//! - One for "stable", that is non-generic, code
+//! - One for more "volatile" code, i.e., monomorphized instances of functions
+//!   defined in that module
+//!
+//! In order to see why this heuristic makes sense, let's take a look at when a
+//! codegen unit can get invalidated:
+//!
+//! 1. The most straightforward case is when the BODY of a function or global
+//! changes. Then any codegen unit containing the code for that item has to be
+//! re-compiled. Note that this includes all codegen units where the function
+//! has been inlined.
+//!
+//! 2. The next case is when the SIGNATURE of a function or global changes. In
+//! this case, all codegen units containing a REFERENCE to that item have to be
+//! re-compiled. This is a superset of case 1.
+//!
+//! 3. The final and most subtle case is when a REFERENCE to a generic function
+//! is added or removed somewhere. Even though the definition of the function
+//! might be unchanged, a new REFERENCE might introduce a new monomorphized
+//! instance of this function which has to be placed and compiled somewhere.
+//! Conversely, when removing a REFERENCE, it might have been the last one with
+//! that particular set of generic arguments and thus we have to remove it.
+//!
+//! From the above we see that just using one codegen unit per source-level
+//! module is not such a good idea, since just adding a REFERENCE to some
+//! generic item somewhere else would invalidate everything within the module
+//! containing the generic item. The heuristic above reduces this detrimental
+//! side-effect of references a little by at least not touching the non-generic
+//! code of the module.
+//!
+//! A Note on Inlining
+//! ------------------
+//! As briefly mentioned above, in order for LLVM to be able to inline a
+//! function call, the body of the function has to be available in the LLVM
+//! module where the call is made. This has a few consequences for partitioning:
+//!
+//! - The partitioning algorithm has to take care of placing functions into all
+//!   codegen units where they should be available for inlining. It also has to
+//!   decide on the correct linkage for these functions.
+//!
+//! - The partitioning algorithm has to know which functions are likely to get
+//!   inlined, so it can distribute function instantiations accordingly. Since
+//!   there is no way of knowing for sure which functions LLVM will decide to
+//!   inline in the end, we apply a heuristic here: Only functions marked with
+//!   `#[inline]` are considered for inlining by the partitioner. The current
+//!   implementation will not try to determine if a function is likely to be
+//!   inlined by looking at the functions definition.
+//!
+//! Note though that as a side-effect of creating a codegen units per
+//! source-level module, functions from the same module will be available for
+//! inlining, even when they are not marked `#[inline]`.
+
+use std::cmp;
+use std::collections::hash_map::Entry;
+use std::fs::{self, File};
+use std::io::{BufWriter, Write};
+use std::path::{Path, PathBuf};
+
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::sync;
+use rustc_hir::def::DefKind;
+use rustc_hir::def_id::{DefId, DefIdSet, LOCAL_CRATE};
+use rustc_hir::definitions::DefPathDataName;
+use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
+use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel};
+use rustc_middle::mir;
+use rustc_middle::mir::mono::{
+    CodegenUnit, CodegenUnitNameBuilder, InstantiationMode, Linkage, MonoItem, Visibility,
+};
+use rustc_middle::query::Providers;
+use rustc_middle::ty::print::{characteristic_def_id_of_type, with_no_trimmed_paths};
+use rustc_middle::ty::{self, visit::TypeVisitableExt, InstanceDef, TyCtxt};
+use rustc_session::config::{DumpMonoStatsFormat, SwitchWithOptPath};
+use rustc_span::symbol::Symbol;
+
+use crate::collector::InliningMap;
+use crate::collector::{self, MonoItemCollectionMode};
+use crate::errors::{CouldntDumpMonoStats, SymbolAlreadyDefined, UnknownCguCollectionMode};
+
+struct PartitioningCx<'a, 'tcx> {
+    tcx: TyCtxt<'tcx>,
+    target_cgu_count: usize,
+    inlining_map: &'a InliningMap<'tcx>,
+}
+
+struct PlacedRootMonoItems<'tcx> {
+    codegen_units: Vec<CodegenUnit<'tcx>>,
+    roots: FxHashSet<MonoItem<'tcx>>,
+    internalization_candidates: FxHashSet<MonoItem<'tcx>>,
+}
+
+fn partition<'tcx, I>(
+    tcx: TyCtxt<'tcx>,
+    mono_items: &mut I,
+    max_cgu_count: usize,
+    inlining_map: &InliningMap<'tcx>,
+) -> Vec<CodegenUnit<'tcx>>
+where
+    I: Iterator<Item = MonoItem<'tcx>>,
+{
+    let _prof_timer = tcx.prof.generic_activity("cgu_partitioning");
+
+    let cx = &PartitioningCx { tcx, target_cgu_count: max_cgu_count, inlining_map };
+    // In the first step, we place all regular monomorphizations into their
+    // respective 'home' codegen unit. Regular monomorphizations are all
+    // functions and statics defined in the local crate.
+    let PlacedRootMonoItems { mut codegen_units, roots, internalization_candidates } = {
+        let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_roots");
+        place_root_mono_items(cx, mono_items)
+    };
+
+    for cgu in &mut codegen_units {
+        cgu.create_size_estimate(tcx);
+    }
+
+    debug_dump(tcx, "INITIAL PARTITIONING", &codegen_units);
+
+    // Merge until we have at most `max_cgu_count` codegen units.
+    // `merge_codegen_units` is responsible for updating the CGU size
+    // estimates.
+    {
+        let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_merge_cgus");
+        merge_codegen_units(cx, &mut codegen_units);
+        debug_dump(tcx, "POST MERGING", &codegen_units);
+    }
+
+    // In the next step, we use the inlining map to determine which additional
+    // monomorphizations have to go into each codegen unit. These additional
+    // monomorphizations can be drop-glue, functions from external crates, and
+    // local functions the definition of which is marked with `#[inline]`.
+    let mono_item_placements = {
+        let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_inline_items");
+        place_inlined_mono_items(cx, &mut codegen_units, roots)
+    };
+
+    for cgu in &mut codegen_units {
+        cgu.create_size_estimate(tcx);
+    }
+
+    debug_dump(tcx, "POST INLINING", &codegen_units);
+
+    // Next we try to make as many symbols "internal" as possible, so LLVM has
+    // more freedom to optimize.
+    if !tcx.sess.link_dead_code() {
+        let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_internalize_symbols");
+        internalize_symbols(
+            cx,
+            &mut codegen_units,
+            mono_item_placements,
+            internalization_candidates,
+        );
+    }
+
+    let instrument_dead_code =
+        tcx.sess.instrument_coverage() && !tcx.sess.instrument_coverage_except_unused_functions();
+
+    if instrument_dead_code {
+        assert!(
+            codegen_units.len() > 0,
+            "There must be at least one CGU that code coverage data can be generated in."
+        );
+
+        // Find the smallest CGU that has exported symbols and put the dead
+        // function stubs in that CGU. We look for exported symbols to increase
+        // the likelihood the linker won't throw away the dead functions.
+        // FIXME(#92165): In order to truly resolve this, we need to make sure
+        // the object file (CGU) containing the dead function stubs is included
+        // in the final binary. This will probably require forcing these
+        // function symbols to be included via `-u` or `/include` linker args.
+        let mut cgus: Vec<_> = codegen_units.iter_mut().collect();
+        cgus.sort_by_key(|cgu| cgu.size_estimate());
+
+        let dead_code_cgu =
+            if let Some(cgu) = cgus.into_iter().rev().find(|cgu| {
+                cgu.items().iter().any(|(_, (linkage, _))| *linkage == Linkage::External)
+            }) {
+                cgu
+            } else {
+                // If there are no CGUs that have externally linked items,
+                // then we just pick the first CGU as a fallback.
+                &mut codegen_units[0]
+            };
+        dead_code_cgu.make_code_coverage_dead_code_cgu();
+    }
+
+    // Finally, sort by codegen unit name, so that we get deterministic results.
+    codegen_units.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
+
+    debug_dump(tcx, "FINAL", &codegen_units);
+
+    codegen_units
+}
+
+fn place_root_mono_items<'tcx, I>(
+    cx: &PartitioningCx<'_, 'tcx>,
+    mono_items: &mut I,
+) -> PlacedRootMonoItems<'tcx>
+where
+    I: Iterator<Item = MonoItem<'tcx>>,
+{
+    let mut roots = FxHashSet::default();
+    let mut codegen_units = FxHashMap::default();
+    let is_incremental_build = cx.tcx.sess.opts.incremental.is_some();
+    let mut internalization_candidates = FxHashSet::default();
+
+    // Determine if monomorphizations instantiated in this crate will be made
+    // available to downstream crates. This depends on whether we are in
+    // share-generics mode and whether the current crate can even have
+    // downstream crates.
+    let export_generics =
+        cx.tcx.sess.opts.share_generics() && cx.tcx.local_crate_exports_generics();
+
+    let cgu_name_builder = &mut CodegenUnitNameBuilder::new(cx.tcx);
+    let cgu_name_cache = &mut FxHashMap::default();
+
+    for mono_item in mono_items {
+        match mono_item.instantiation_mode(cx.tcx) {
+            InstantiationMode::GloballyShared { .. } => {}
+            InstantiationMode::LocalCopy => continue,
+        }
+
+        let characteristic_def_id = characteristic_def_id_of_mono_item(cx.tcx, mono_item);
+        let is_volatile = is_incremental_build && mono_item.is_generic_fn();
+
+        let codegen_unit_name = match characteristic_def_id {
+            Some(def_id) => compute_codegen_unit_name(
+                cx.tcx,
+                cgu_name_builder,
+                def_id,
+                is_volatile,
+                cgu_name_cache,
+            ),
+            None => fallback_cgu_name(cgu_name_builder),
+        };
+
+        let codegen_unit = codegen_units
+            .entry(codegen_unit_name)
+            .or_insert_with(|| CodegenUnit::new(codegen_unit_name));
+
+        let mut can_be_internalized = true;
+        let (linkage, visibility) = mono_item_linkage_and_visibility(
+            cx.tcx,
+            &mono_item,
+            &mut can_be_internalized,
+            export_generics,
+        );
+        if visibility == Visibility::Hidden && can_be_internalized {
+            internalization_candidates.insert(mono_item);
+        }
+
+        codegen_unit.items_mut().insert(mono_item, (linkage, visibility));
+        roots.insert(mono_item);
+    }
+
+    // Always ensure we have at least one CGU; otherwise, if we have a
+    // crate with just types (for example), we could wind up with no CGU.
+    if codegen_units.is_empty() {
+        let codegen_unit_name = fallback_cgu_name(cgu_name_builder);
+        codegen_units.insert(codegen_unit_name, CodegenUnit::new(codegen_unit_name));
+    }
+
+    let codegen_units = codegen_units.into_values().collect();
+    PlacedRootMonoItems { codegen_units, roots, internalization_candidates }
+}
+
+fn merge_codegen_units<'tcx>(
+    cx: &PartitioningCx<'_, 'tcx>,
+    codegen_units: &mut Vec<CodegenUnit<'tcx>>,
+) {
+    assert!(cx.target_cgu_count >= 1);
+
+    // Note that at this point in time the `codegen_units` here may not be
+    // in a deterministic order (but we know they're deterministically the
+    // same set). We want this merging to produce a deterministic ordering
+    // of codegen units from the input.
+    //
+    // Due to basically how we've implemented the merging below (merge the
+    // two smallest into each other) we're sure to start off with a
+    // deterministic order (sorted by name). This'll mean that if two cgus
+    // have the same size the stable sort below will keep everything nice
+    // and deterministic.
+    codegen_units.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
+
+    // This map keeps track of what got merged into what.
+    let mut cgu_contents: FxHashMap<Symbol, Vec<Symbol>> =
+        codegen_units.iter().map(|cgu| (cgu.name(), vec![cgu.name()])).collect();
+
+    // Merge the two smallest codegen units until the target size is
+    // reached.
+    while codegen_units.len() > cx.target_cgu_count {
+        // Sort small cgus to the back
+        codegen_units.sort_by_cached_key(|cgu| cmp::Reverse(cgu.size_estimate()));
+        let mut smallest = codegen_units.pop().unwrap();
+        let second_smallest = codegen_units.last_mut().unwrap();
+
+        // Move the mono-items from `smallest` to `second_smallest`
+        second_smallest.modify_size_estimate(smallest.size_estimate());
+        for (k, v) in smallest.items_mut().drain() {
+            second_smallest.items_mut().insert(k, v);
+        }
+
+        // Record that `second_smallest` now contains all the stuff that was
+        // in `smallest` before.
+        let mut consumed_cgu_names = cgu_contents.remove(&smallest.name()).unwrap();
+        cgu_contents.get_mut(&second_smallest.name()).unwrap().append(&mut consumed_cgu_names);
+
+        debug!(
+            "CodegenUnit {} merged into CodegenUnit {}",
+            smallest.name(),
+            second_smallest.name()
+        );
+    }
+
+    let cgu_name_builder = &mut CodegenUnitNameBuilder::new(cx.tcx);
+
+    if cx.tcx.sess.opts.incremental.is_some() {
+        // If we are doing incremental compilation, we want CGU names to
+        // reflect the path of the source level module they correspond to.
+        // For CGUs that contain the code of multiple modules because of the
+        // merging done above, we use a concatenation of the names of all
+        // contained CGUs.
+        let new_cgu_names: FxHashMap<Symbol, String> = cgu_contents
+            .into_iter()
+            // This `filter` makes sure we only update the name of CGUs that
+            // were actually modified by merging.
+            .filter(|(_, cgu_contents)| cgu_contents.len() > 1)
+            .map(|(current_cgu_name, cgu_contents)| {
+                let mut cgu_contents: Vec<&str> = cgu_contents.iter().map(|s| s.as_str()).collect();
+
+                // Sort the names, so things are deterministic and easy to
+                // predict. We are sorting primitive `&str`s here so we can
+                // use unstable sort.
+                cgu_contents.sort_unstable();
+
+                (current_cgu_name, cgu_contents.join("--"))
+            })
+            .collect();
+
+        for cgu in codegen_units.iter_mut() {
+            if let Some(new_cgu_name) = new_cgu_names.get(&cgu.name()) {
+                if cx.tcx.sess.opts.unstable_opts.human_readable_cgu_names {
+                    cgu.set_name(Symbol::intern(&new_cgu_name));
+                } else {
+                    // If we don't require CGU names to be human-readable,
+                    // we use a fixed length hash of the composite CGU name
+                    // instead.
+                    let new_cgu_name = CodegenUnit::mangle_name(&new_cgu_name);
+                    cgu.set_name(Symbol::intern(&new_cgu_name));
+                }
+            }
+        }
+    } else {
+        // If we are compiling non-incrementally we just generate simple CGU
+        // names containing an index.
+        for (index, cgu) in codegen_units.iter_mut().enumerate() {
+            let numbered_codegen_unit_name =
+                cgu_name_builder.build_cgu_name_no_mangle(LOCAL_CRATE, &["cgu"], Some(index));
+            cgu.set_name(numbered_codegen_unit_name);
+        }
+    }
+}
+
+/// For symbol internalization, we need to know whether a symbol/mono-item is
+/// accessed from outside the codegen unit it is defined in. This type is used
+/// to keep track of that.
+#[derive(Clone, PartialEq, Eq, Debug)]
+enum MonoItemPlacement {
+    SingleCgu { cgu_name: Symbol },
+    MultipleCgus,
+}
+
+fn place_inlined_mono_items<'tcx>(
+    cx: &PartitioningCx<'_, 'tcx>,
+    codegen_units: &mut [CodegenUnit<'tcx>],
+    roots: FxHashSet<MonoItem<'tcx>>,
+) -> FxHashMap<MonoItem<'tcx>, MonoItemPlacement> {
+    let mut mono_item_placements = FxHashMap::default();
+
+    let single_codegen_unit = codegen_units.len() == 1;
+
+    for old_codegen_unit in codegen_units.iter_mut() {
+        // Collect all items that need to be available in this codegen unit.
+        let mut reachable = FxHashSet::default();
+        for root in old_codegen_unit.items().keys() {
+            follow_inlining(*root, cx.inlining_map, &mut reachable);
+        }
+
+        let mut new_codegen_unit = CodegenUnit::new(old_codegen_unit.name());
+
+        // Add all monomorphizations that are not already there.
+        for mono_item in reachable {
+            if let Some(linkage) = old_codegen_unit.items().get(&mono_item) {
+                // This is a root, just copy it over.
+                new_codegen_unit.items_mut().insert(mono_item, *linkage);
+            } else {
+                if roots.contains(&mono_item) {
+                    bug!(
+                        "GloballyShared mono-item inlined into other CGU: \
+                          {:?}",
+                        mono_item
+                    );
+                }
+
+                // This is a CGU-private copy.
+                new_codegen_unit
+                    .items_mut()
+                    .insert(mono_item, (Linkage::Internal, Visibility::Default));
+            }
+
+            if !single_codegen_unit {
+                // If there is more than one codegen unit, we need to keep track
+                // in which codegen units each monomorphization is placed.
+                match mono_item_placements.entry(mono_item) {
+                    Entry::Occupied(e) => {
+                        let placement = e.into_mut();
+                        debug_assert!(match *placement {
+                            MonoItemPlacement::SingleCgu { cgu_name } => {
+                                cgu_name != new_codegen_unit.name()
+                            }
+                            MonoItemPlacement::MultipleCgus => true,
+                        });
+                        *placement = MonoItemPlacement::MultipleCgus;
+                    }
+                    Entry::Vacant(e) => {
+                        e.insert(MonoItemPlacement::SingleCgu {
+                            cgu_name: new_codegen_unit.name(),
+                        });
+                    }
+                }
+            }
+        }
+
+        *old_codegen_unit = new_codegen_unit;
+    }
+
+    return mono_item_placements;
+
+    fn follow_inlining<'tcx>(
+        mono_item: MonoItem<'tcx>,
+        inlining_map: &InliningMap<'tcx>,
+        visited: &mut FxHashSet<MonoItem<'tcx>>,
+    ) {
+        if !visited.insert(mono_item) {
+            return;
+        }
+
+        inlining_map.with_inlining_candidates(mono_item, |target| {
+            follow_inlining(target, inlining_map, visited);
+        });
+    }
+}
+
+fn internalize_symbols<'tcx>(
+    cx: &PartitioningCx<'_, 'tcx>,
+    codegen_units: &mut [CodegenUnit<'tcx>],
+    mono_item_placements: FxHashMap<MonoItem<'tcx>, MonoItemPlacement>,
+    internalization_candidates: FxHashSet<MonoItem<'tcx>>,
+) {
+    if codegen_units.len() == 1 {
+        // Fast path for when there is only one codegen unit. In this case we
+        // can internalize all candidates, since there is nowhere else they
+        // could be accessed from.
+        for cgu in codegen_units {
+            for candidate in &internalization_candidates {
+                cgu.items_mut().insert(*candidate, (Linkage::Internal, Visibility::Default));
+            }
+        }
+
+        return;
+    }
+
+    // Build a map from every monomorphization to all the monomorphizations that
+    // reference it.
+    let mut accessor_map: FxHashMap<MonoItem<'tcx>, Vec<MonoItem<'tcx>>> = Default::default();
+    cx.inlining_map.iter_accesses(|accessor, accessees| {
+        for accessee in accessees {
+            accessor_map.entry(*accessee).or_default().push(accessor);
+        }
+    });
+
+    // For each internalization candidates in each codegen unit, check if it is
+    // accessed from outside its defining codegen unit.
+    for cgu in codegen_units {
+        let home_cgu = MonoItemPlacement::SingleCgu { cgu_name: cgu.name() };
+
+        for (accessee, linkage_and_visibility) in cgu.items_mut() {
+            if !internalization_candidates.contains(accessee) {
+                // This item is no candidate for internalizing, so skip it.
+                continue;
+            }
+            debug_assert_eq!(mono_item_placements[accessee], home_cgu);
+
+            if let Some(accessors) = accessor_map.get(accessee) {
+                if accessors
+                    .iter()
+                    .filter_map(|accessor| {
+                        // Some accessors might not have been
+                        // instantiated. We can safely ignore those.
+                        mono_item_placements.get(accessor)
+                    })
+                    .any(|placement| *placement != home_cgu)
+                {
+                    // Found an accessor from another CGU, so skip to the next
+                    // item without marking this one as internal.
+                    continue;
+                }
+            }
+
+            // If we got here, we did not find any accesses from other CGUs,
+            // so it's fine to make this monomorphization internal.
+            *linkage_and_visibility = (Linkage::Internal, Visibility::Default);
+        }
+    }
+}
+
+fn characteristic_def_id_of_mono_item<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    mono_item: MonoItem<'tcx>,
+) -> Option<DefId> {
+    match mono_item {
+        MonoItem::Fn(instance) => {
+            let def_id = match instance.def {
+                ty::InstanceDef::Item(def) => def,
+                ty::InstanceDef::VTableShim(..)
+                | ty::InstanceDef::ReifyShim(..)
+                | ty::InstanceDef::FnPtrShim(..)
+                | ty::InstanceDef::ClosureOnceShim { .. }
+                | ty::InstanceDef::Intrinsic(..)
+                | ty::InstanceDef::DropGlue(..)
+                | ty::InstanceDef::Virtual(..)
+                | ty::InstanceDef::CloneShim(..)
+                | ty::InstanceDef::ThreadLocalShim(..)
+                | ty::InstanceDef::FnPtrAddrShim(..) => return None,
+            };
+
+            // If this is a method, we want to put it into the same module as
+            // its self-type. If the self-type does not provide a characteristic
+            // DefId, we use the location of the impl after all.
+
+            if tcx.trait_of_item(def_id).is_some() {
+                let self_ty = instance.substs.type_at(0);
+                // This is a default implementation of a trait method.
+                return characteristic_def_id_of_type(self_ty).or(Some(def_id));
+            }
+
+            if let Some(impl_def_id) = tcx.impl_of_method(def_id) {
+                if tcx.sess.opts.incremental.is_some()
+                    && tcx.trait_id_of_impl(impl_def_id) == tcx.lang_items().drop_trait()
+                {
+                    // Put `Drop::drop` into the same cgu as `drop_in_place`
+                    // since `drop_in_place` is the only thing that can
+                    // call it.
+                    return None;
+                }
+
+                // When polymorphization is enabled, methods which do not depend on their generic
+                // parameters, but the self-type of their impl block do will fail to normalize.
+                if !tcx.sess.opts.unstable_opts.polymorphize || !instance.has_param() {
+                    // This is a method within an impl, find out what the self-type is:
+                    let impl_self_ty = tcx.subst_and_normalize_erasing_regions(
+                        instance.substs,
+                        ty::ParamEnv::reveal_all(),
+                        tcx.type_of(impl_def_id),
+                    );
+                    if let Some(def_id) = characteristic_def_id_of_type(impl_self_ty) {
+                        return Some(def_id);
+                    }
+                }
+            }
+
+            Some(def_id)
+        }
+        MonoItem::Static(def_id) => Some(def_id),
+        MonoItem::GlobalAsm(item_id) => Some(item_id.owner_id.to_def_id()),
+    }
+}
+
+fn compute_codegen_unit_name(
+    tcx: TyCtxt<'_>,
+    name_builder: &mut CodegenUnitNameBuilder<'_>,
+    def_id: DefId,
+    volatile: bool,
+    cache: &mut CguNameCache,
+) -> Symbol {
+    // Find the innermost module that is not nested within a function.
+    let mut current_def_id = def_id;
+    let mut cgu_def_id = None;
+    // Walk backwards from the item we want to find the module for.
+    loop {
+        if current_def_id.is_crate_root() {
+            if cgu_def_id.is_none() {
+                // If we have not found a module yet, take the crate root.
+                cgu_def_id = Some(def_id.krate.as_def_id());
+            }
+            break;
+        } else if tcx.def_kind(current_def_id) == DefKind::Mod {
+            if cgu_def_id.is_none() {
+                cgu_def_id = Some(current_def_id);
+            }
+        } else {
+            // If we encounter something that is not a module, throw away
+            // any module that we've found so far because we now know that
+            // it is nested within something else.
+            cgu_def_id = None;
+        }
+
+        current_def_id = tcx.parent(current_def_id);
+    }
+
+    let cgu_def_id = cgu_def_id.unwrap();
+
+    *cache.entry((cgu_def_id, volatile)).or_insert_with(|| {
+        let def_path = tcx.def_path(cgu_def_id);
+
+        let components = def_path.data.iter().map(|part| match part.data.name() {
+            DefPathDataName::Named(name) => name,
+            DefPathDataName::Anon { .. } => unreachable!(),
+        });
+
+        let volatile_suffix = volatile.then_some("volatile");
+
+        name_builder.build_cgu_name(def_path.krate, components, volatile_suffix)
+    })
+}
+
+// Anything we can't find a proper codegen unit for goes into this.
+fn fallback_cgu_name(name_builder: &mut CodegenUnitNameBuilder<'_>) -> Symbol {
+    name_builder.build_cgu_name(LOCAL_CRATE, &["fallback"], Some("cgu"))
+}
+
+fn mono_item_linkage_and_visibility<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    mono_item: &MonoItem<'tcx>,
+    can_be_internalized: &mut bool,
+    export_generics: bool,
+) -> (Linkage, Visibility) {
+    if let Some(explicit_linkage) = mono_item.explicit_linkage(tcx) {
+        return (explicit_linkage, Visibility::Default);
+    }
+    let vis = mono_item_visibility(tcx, mono_item, can_be_internalized, export_generics);
+    (Linkage::External, vis)
+}
+
+type CguNameCache = FxHashMap<(DefId, bool), Symbol>;
+
+fn static_visibility<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    can_be_internalized: &mut bool,
+    def_id: DefId,
+) -> Visibility {
+    if tcx.is_reachable_non_generic(def_id) {
+        *can_be_internalized = false;
+        default_visibility(tcx, def_id, false)
+    } else {
+        Visibility::Hidden
+    }
+}
+
+fn mono_item_visibility<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    mono_item: &MonoItem<'tcx>,
+    can_be_internalized: &mut bool,
+    export_generics: bool,
+) -> Visibility {
+    let instance = match mono_item {
+        // This is pretty complicated; see below.
+        MonoItem::Fn(instance) => instance,
+
+        // Misc handling for generics and such, but otherwise:
+        MonoItem::Static(def_id) => return static_visibility(tcx, can_be_internalized, *def_id),
+        MonoItem::GlobalAsm(item_id) => {
+            return static_visibility(tcx, can_be_internalized, item_id.owner_id.to_def_id());
+        }
+    };
+
+    let def_id = match instance.def {
+        InstanceDef::Item(def_id) | InstanceDef::DropGlue(def_id, Some(_)) => def_id,
+
+        // We match the visibility of statics here
+        InstanceDef::ThreadLocalShim(def_id) => {
+            return static_visibility(tcx, can_be_internalized, def_id);
+        }
+
+        // These are all compiler glue and such, never exported, always hidden.
+        InstanceDef::VTableShim(..)
+        | InstanceDef::ReifyShim(..)
+        | InstanceDef::FnPtrShim(..)
+        | InstanceDef::Virtual(..)
+        | InstanceDef::Intrinsic(..)
+        | InstanceDef::ClosureOnceShim { .. }
+        | InstanceDef::DropGlue(..)
+        | InstanceDef::CloneShim(..)
+        | InstanceDef::FnPtrAddrShim(..) => return Visibility::Hidden,
+    };
+
+    // The `start_fn` lang item is actually a monomorphized instance of a
+    // function in the standard library, used for the `main` function. We don't
+    // want to export it so we tag it with `Hidden` visibility but this symbol
+    // is only referenced from the actual `main` symbol which we unfortunately
+    // don't know anything about during partitioning/collection. As a result we
+    // forcibly keep this symbol out of the `internalization_candidates` set.
+    //
+    // FIXME: eventually we don't want to always force this symbol to have
+    //        hidden visibility, it should indeed be a candidate for
+    //        internalization, but we have to understand that it's referenced
+    //        from the `main` symbol we'll generate later.
+    //
+    //        This may be fixable with a new `InstanceDef` perhaps? Unsure!
+    if tcx.lang_items().start_fn() == Some(def_id) {
+        *can_be_internalized = false;
+        return Visibility::Hidden;
+    }
+
+    let is_generic = instance.substs.non_erasable_generics().next().is_some();
+
+    // Upstream `DefId` instances get different handling than local ones.
+    let Some(def_id) = def_id.as_local() else {
+        return if export_generics && is_generic {
+            // If it is an upstream monomorphization and we export generics, we must make
+            // it available to downstream crates.
+            *can_be_internalized = false;
+            default_visibility(tcx, def_id, true)
+        } else {
+            Visibility::Hidden
+        };
+    };
+
+    if is_generic {
+        if export_generics {
+            if tcx.is_unreachable_local_definition(def_id) {
+                // This instance cannot be used from another crate.
+                Visibility::Hidden
+            } else {
+                // This instance might be useful in a downstream crate.
+                *can_be_internalized = false;
+                default_visibility(tcx, def_id.to_def_id(), true)
+            }
+        } else {
+            // We are not exporting generics or the definition is not reachable
+            // for downstream crates, we can internalize its instantiations.
+            Visibility::Hidden
+        }
+    } else {
+        // If this isn't a generic function then we mark this a `Default` if
+        // this is a reachable item, meaning that it's a symbol other crates may
+        // access when they link to us.
+        if tcx.is_reachable_non_generic(def_id.to_def_id()) {
+            *can_be_internalized = false;
+            debug_assert!(!is_generic);
+            return default_visibility(tcx, def_id.to_def_id(), false);
+        }
+
+        // If this isn't reachable then we're gonna tag this with `Hidden`
+        // visibility. In some situations though we'll want to prevent this
+        // symbol from being internalized.
+        //
+        // There's two categories of items here:
+        //
+        // * First is weak lang items. These are basically mechanisms for
+        //   libcore to forward-reference symbols defined later in crates like
+        //   the standard library or `#[panic_handler]` definitions. The
+        //   definition of these weak lang items needs to be referencable by
+        //   libcore, so we're no longer a candidate for internalization.
+        //   Removal of these functions can't be done by LLVM but rather must be
+        //   done by the linker as it's a non-local decision.
+        //
+        // * Second is "std internal symbols". Currently this is primarily used
+        //   for allocator symbols. Allocators are a little weird in their
+        //   implementation, but the idea is that the compiler, at the last
+        //   minute, defines an allocator with an injected object file. The
+        //   `alloc` crate references these symbols (`__rust_alloc`) and the
+        //   definition doesn't get hooked up until a linked crate artifact is
+        //   generated.
+        //
+        //   The symbols synthesized by the compiler (`__rust_alloc`) are thin
+        //   veneers around the actual implementation, some other symbol which
+        //   implements the same ABI. These symbols (things like `__rg_alloc`,
+        //   `__rdl_alloc`, `__rde_alloc`, etc), are all tagged with "std
+        //   internal symbols".
+        //
+        //   The std-internal symbols here **should not show up in a dll as an
+        //   exported interface**, so they return `false` from
+        //   `is_reachable_non_generic` above and we'll give them `Hidden`
+        //   visibility below. Like the weak lang items, though, we can't let
+        //   LLVM internalize them as this decision is left up to the linker to
+        //   omit them, so prevent them from being internalized.
+        let attrs = tcx.codegen_fn_attrs(def_id);
+        if attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
+            *can_be_internalized = false;
+        }
+
+        Visibility::Hidden
+    }
+}
+
+fn default_visibility(tcx: TyCtxt<'_>, id: DefId, is_generic: bool) -> Visibility {
+    if !tcx.sess.target.default_hidden_visibility {
+        return Visibility::Default;
+    }
+
+    // Generic functions never have export-level C.
+    if is_generic {
+        return Visibility::Hidden;
+    }
+
+    // Things with export level C don't get instantiated in
+    // downstream crates.
+    if !id.is_local() {
+        return Visibility::Hidden;
+    }
+
+    // C-export level items remain at `Default`, all other internal
+    // items become `Hidden`.
+    match tcx.reachable_non_generics(id.krate).get(&id) {
+        Some(SymbolExportInfo { level: SymbolExportLevel::C, .. }) => Visibility::Default,
+        _ => Visibility::Hidden,
+    }
+}
+fn debug_dump<'a, 'tcx: 'a>(tcx: TyCtxt<'tcx>, label: &str, cgus: &[CodegenUnit<'tcx>]) {
+    let dump = move || {
+        use std::fmt::Write;
+
+        let num_cgus = cgus.len();
+        let max = cgus.iter().map(|cgu| cgu.size_estimate()).max().unwrap();
+        let min = cgus.iter().map(|cgu| cgu.size_estimate()).min().unwrap();
+        let ratio = max as f64 / min as f64;
+
+        let s = &mut String::new();
+        let _ = writeln!(
+            s,
+            "{label} ({num_cgus} CodegenUnits, max={max}, min={min}, max/min={ratio:.1}):"
+        );
+        for cgu in cgus {
+            let _ =
+                writeln!(s, "CodegenUnit {} estimated size {}:", cgu.name(), cgu.size_estimate());
+
+            for (mono_item, linkage) in cgu.items() {
+                let symbol_name = mono_item.symbol_name(tcx).name;
+                let symbol_hash_start = symbol_name.rfind('h');
+                let symbol_hash = symbol_hash_start.map_or("<no hash>", |i| &symbol_name[i..]);
+
+                let _ = with_no_trimmed_paths!(writeln!(
+                    s,
+                    " - {} [{:?}] [{}] estimated size {}",
+                    mono_item,
+                    linkage,
+                    symbol_hash,
+                    mono_item.size_estimate(tcx)
+                ));
+            }
+
+            let _ = writeln!(s);
+        }
+
+        std::mem::take(s)
+    };
+
+    debug!("{}", dump());
+}
+
+#[inline(never)] // give this a place in the profiler
+fn assert_symbols_are_distinct<'a, 'tcx, I>(tcx: TyCtxt<'tcx>, mono_items: I)
+where
+    I: Iterator<Item = &'a MonoItem<'tcx>>,
+    'tcx: 'a,
+{
+    let _prof_timer = tcx.prof.generic_activity("assert_symbols_are_distinct");
+
+    let mut symbols: Vec<_> =
+        mono_items.map(|mono_item| (mono_item, mono_item.symbol_name(tcx))).collect();
+
+    symbols.sort_by_key(|sym| sym.1);
+
+    for &[(mono_item1, ref sym1), (mono_item2, ref sym2)] in symbols.array_windows() {
+        if sym1 == sym2 {
+            let span1 = mono_item1.local_span(tcx);
+            let span2 = mono_item2.local_span(tcx);
+
+            // Deterministically select one of the spans for error reporting
+            let span = match (span1, span2) {
+                (Some(span1), Some(span2)) => {
+                    Some(if span1.lo().0 > span2.lo().0 { span1 } else { span2 })
+                }
+                (span1, span2) => span1.or(span2),
+            };
+
+            tcx.sess.emit_fatal(SymbolAlreadyDefined { span, symbol: sym1.to_string() });
+        }
+    }
+}
+
+fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> (&DefIdSet, &[CodegenUnit<'_>]) {
+    let collection_mode = match tcx.sess.opts.unstable_opts.print_mono_items {
+        Some(ref s) => {
+            let mode = s.to_lowercase();
+            let mode = mode.trim();
+            if mode == "eager" {
+                MonoItemCollectionMode::Eager
+            } else {
+                if mode != "lazy" {
+                    tcx.sess.emit_warning(UnknownCguCollectionMode { mode });
+                }
+
+                MonoItemCollectionMode::Lazy
+            }
+        }
+        None => {
+            if tcx.sess.link_dead_code() {
+                MonoItemCollectionMode::Eager
+            } else {
+                MonoItemCollectionMode::Lazy
+            }
+        }
+    };
+
+    let (items, inlining_map) = collector::collect_crate_mono_items(tcx, collection_mode);
+
+    tcx.sess.abort_if_errors();
+
+    let (codegen_units, _) = tcx.sess.time("partition_and_assert_distinct_symbols", || {
+        sync::join(
+            || {
+                let mut codegen_units = partition(
+                    tcx,
+                    &mut items.iter().copied(),
+                    tcx.sess.codegen_units(),
+                    &inlining_map,
+                );
+                codegen_units[0].make_primary();
+                &*tcx.arena.alloc_from_iter(codegen_units)
+            },
+            || assert_symbols_are_distinct(tcx, items.iter()),
+        )
+    });
+
+    if tcx.prof.enabled() {
+        // Record CGU size estimates for self-profiling.
+        for cgu in codegen_units {
+            tcx.prof.artifact_size(
+                "codegen_unit_size_estimate",
+                cgu.name().as_str(),
+                cgu.size_estimate() as u64,
+            );
+        }
+    }
+
+    let mono_items: DefIdSet = items
+        .iter()
+        .filter_map(|mono_item| match *mono_item {
+            MonoItem::Fn(ref instance) => Some(instance.def_id()),
+            MonoItem::Static(def_id) => Some(def_id),
+            _ => None,
+        })
+        .collect();
+
+    // Output monomorphization stats per def_id
+    if let SwitchWithOptPath::Enabled(ref path) = tcx.sess.opts.unstable_opts.dump_mono_stats {
+        if let Err(err) =
+            dump_mono_items_stats(tcx, &codegen_units, path, tcx.crate_name(LOCAL_CRATE))
+        {
+            tcx.sess.emit_fatal(CouldntDumpMonoStats { error: err.to_string() });
+        }
+    }
+
+    if tcx.sess.opts.unstable_opts.print_mono_items.is_some() {
+        let mut item_to_cgus: FxHashMap<_, Vec<_>> = Default::default();
+
+        for cgu in codegen_units {
+            for (&mono_item, &linkage) in cgu.items() {
+                item_to_cgus.entry(mono_item).or_default().push((cgu.name(), linkage));
+            }
+        }
+
+        let mut item_keys: Vec<_> = items
+            .iter()
+            .map(|i| {
+                let mut output = with_no_trimmed_paths!(i.to_string());
+                output.push_str(" @@");
+                let mut empty = Vec::new();
+                let cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty);
+                cgus.sort_by_key(|(name, _)| *name);
+                cgus.dedup();
+                for &(ref cgu_name, (linkage, _)) in cgus.iter() {
+                    output.push(' ');
+                    output.push_str(cgu_name.as_str());
+
+                    let linkage_abbrev = match linkage {
+                        Linkage::External => "External",
+                        Linkage::AvailableExternally => "Available",
+                        Linkage::LinkOnceAny => "OnceAny",
+                        Linkage::LinkOnceODR => "OnceODR",
+                        Linkage::WeakAny => "WeakAny",
+                        Linkage::WeakODR => "WeakODR",
+                        Linkage::Appending => "Appending",
+                        Linkage::Internal => "Internal",
+                        Linkage::Private => "Private",
+                        Linkage::ExternalWeak => "ExternalWeak",
+                        Linkage::Common => "Common",
+                    };
+
+                    output.push('[');
+                    output.push_str(linkage_abbrev);
+                    output.push(']');
+                }
+                output
+            })
+            .collect();
+
+        item_keys.sort();
+
+        for item in item_keys {
+            println!("MONO_ITEM {item}");
+        }
+    }
+
+    (tcx.arena.alloc(mono_items), codegen_units)
+}
+
+/// Outputs stats about instantiation counts and estimated size, per `MonoItem`'s
+/// def, to a file in the given output directory.
+fn dump_mono_items_stats<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    codegen_units: &[CodegenUnit<'tcx>],
+    output_directory: &Option<PathBuf>,
+    crate_name: Symbol,
+) -> Result<(), Box<dyn std::error::Error>> {
+    let output_directory = if let Some(ref directory) = output_directory {
+        fs::create_dir_all(directory)?;
+        directory
+    } else {
+        Path::new(".")
+    };
+
+    let format = tcx.sess.opts.unstable_opts.dump_mono_stats_format;
+    let ext = format.extension();
+    let filename = format!("{crate_name}.mono_items.{ext}");
+    let output_path = output_directory.join(&filename);
+    let file = File::create(&output_path)?;
+    let mut file = BufWriter::new(file);
+
+    // Gather instantiated mono items grouped by def_id
+    let mut items_per_def_id: FxHashMap<_, Vec<_>> = Default::default();
+    for cgu in codegen_units {
+        for (&mono_item, _) in cgu.items() {
+            // Avoid variable-sized compiler-generated shims
+            if mono_item.is_user_defined() {
+                items_per_def_id.entry(mono_item.def_id()).or_default().push(mono_item);
+            }
+        }
+    }
+
+    #[derive(serde::Serialize)]
+    struct MonoItem {
+        name: String,
+        instantiation_count: usize,
+        size_estimate: usize,
+        total_estimate: usize,
+    }
+
+    // Output stats sorted by total instantiated size, from heaviest to lightest
+    let mut stats: Vec<_> = items_per_def_id
+        .into_iter()
+        .map(|(def_id, items)| {
+            let name = with_no_trimmed_paths!(tcx.def_path_str(def_id));
+            let instantiation_count = items.len();
+            let size_estimate = items[0].size_estimate(tcx);
+            let total_estimate = instantiation_count * size_estimate;
+            MonoItem { name, instantiation_count, size_estimate, total_estimate }
+        })
+        .collect();
+    stats.sort_unstable_by_key(|item| cmp::Reverse(item.total_estimate));
+
+    if !stats.is_empty() {
+        match format {
+            DumpMonoStatsFormat::Json => serde_json::to_writer(file, &stats)?,
+            DumpMonoStatsFormat::Markdown => {
+                writeln!(
+                    file,
+                    "| Item | Instantiation count | Estimated Cost Per Instantiation | Total Estimated Cost |"
+                )?;
+                writeln!(file, "| --- | ---: | ---: | ---: |")?;
+
+                for MonoItem { name, instantiation_count, size_estimate, total_estimate } in stats {
+                    writeln!(
+                        file,
+                        "| `{name}` | {instantiation_count} | {size_estimate} | {total_estimate} |"
+                    )?;
+                }
+            }
+        }
+    }
+
+    Ok(())
+}
+
+fn codegened_and_inlined_items(tcx: TyCtxt<'_>, (): ()) -> &DefIdSet {
+    let (items, cgus) = tcx.collect_and_partition_mono_items(());
+    let mut visited = DefIdSet::default();
+    let mut result = items.clone();
+
+    for cgu in cgus {
+        for (item, _) in cgu.items() {
+            if let MonoItem::Fn(ref instance) = item {
+                let did = instance.def_id();
+                if !visited.insert(did) {
+                    continue;
+                }
+                let body = tcx.instance_mir(instance.def);
+                for block in body.basic_blocks.iter() {
+                    for statement in &block.statements {
+                        let mir::StatementKind::Coverage(_) = statement.kind else { continue };
+                        let scope = statement.source_info.scope;
+                        if let Some(inlined) = scope.inlined_instance(&body.source_scopes) {
+                            result.insert(inlined.def_id());
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    tcx.arena.alloc(result)
+}
+
+pub fn provide(providers: &mut Providers) {
+    providers.collect_and_partition_mono_items = collect_and_partition_mono_items;
+    providers.codegened_and_inlined_items = codegened_and_inlined_items;
+
+    providers.is_codegened_item = |tcx, def_id| {
+        let (all_mono_items, _) = tcx.collect_and_partition_mono_items(());
+        all_mono_items.contains(&def_id)
+    };
+
+    providers.codegen_unit = |tcx, name| {
+        let (_, all) = tcx.collect_and_partition_mono_items(());
+        all.iter()
+            .find(|cgu| cgu.name() == name)
+            .unwrap_or_else(|| panic!("failed to find cgu with name {name:?}"))
+    };
+}
diff --git a/compiler/rustc_monomorphize/src/partitioning/default.rs b/compiler/rustc_monomorphize/src/partitioning/default.rs
deleted file mode 100644
index 37b7f6bf8a8..00000000000
--- a/compiler/rustc_monomorphize/src/partitioning/default.rs
+++ /dev/null
@@ -1,568 +0,0 @@
-use std::collections::hash_map::Entry;
-
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_hir::def::DefKind;
-use rustc_hir::def_id::{DefId, LOCAL_CRATE};
-use rustc_hir::definitions::DefPathDataName;
-use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
-use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel};
-use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, Linkage, Visibility};
-use rustc_middle::mir::mono::{InstantiationMode, MonoItem};
-use rustc_middle::ty::print::characteristic_def_id_of_type;
-use rustc_middle::ty::{self, visit::TypeVisitableExt, InstanceDef, TyCtxt};
-use rustc_span::symbol::Symbol;
-
-use super::PartitioningCx;
-use crate::collector::InliningMap;
-use crate::partitioning::merging;
-use crate::partitioning::{
-    MonoItemPlacement, Partition, PostInliningPartitioning, PreInliningPartitioning,
-};
-
-pub struct DefaultPartitioning;
-
-impl<'tcx> Partition<'tcx> for DefaultPartitioning {
-    fn place_root_mono_items<I>(
-        &mut self,
-        cx: &PartitioningCx<'_, 'tcx>,
-        mono_items: &mut I,
-    ) -> PreInliningPartitioning<'tcx>
-    where
-        I: Iterator<Item = MonoItem<'tcx>>,
-    {
-        let mut roots = FxHashSet::default();
-        let mut codegen_units = FxHashMap::default();
-        let is_incremental_build = cx.tcx.sess.opts.incremental.is_some();
-        let mut internalization_candidates = FxHashSet::default();
-
-        // Determine if monomorphizations instantiated in this crate will be made
-        // available to downstream crates. This depends on whether we are in
-        // share-generics mode and whether the current crate can even have
-        // downstream crates.
-        let export_generics =
-            cx.tcx.sess.opts.share_generics() && cx.tcx.local_crate_exports_generics();
-
-        let cgu_name_builder = &mut CodegenUnitNameBuilder::new(cx.tcx);
-        let cgu_name_cache = &mut FxHashMap::default();
-
-        for mono_item in mono_items {
-            match mono_item.instantiation_mode(cx.tcx) {
-                InstantiationMode::GloballyShared { .. } => {}
-                InstantiationMode::LocalCopy => continue,
-            }
-
-            let characteristic_def_id = characteristic_def_id_of_mono_item(cx.tcx, mono_item);
-            let is_volatile = is_incremental_build && mono_item.is_generic_fn();
-
-            let codegen_unit_name = match characteristic_def_id {
-                Some(def_id) => compute_codegen_unit_name(
-                    cx.tcx,
-                    cgu_name_builder,
-                    def_id,
-                    is_volatile,
-                    cgu_name_cache,
-                ),
-                None => fallback_cgu_name(cgu_name_builder),
-            };
-
-            let codegen_unit = codegen_units
-                .entry(codegen_unit_name)
-                .or_insert_with(|| CodegenUnit::new(codegen_unit_name));
-
-            let mut can_be_internalized = true;
-            let (linkage, visibility) = mono_item_linkage_and_visibility(
-                cx.tcx,
-                &mono_item,
-                &mut can_be_internalized,
-                export_generics,
-            );
-            if visibility == Visibility::Hidden && can_be_internalized {
-                internalization_candidates.insert(mono_item);
-            }
-
-            codegen_unit.items_mut().insert(mono_item, (linkage, visibility));
-            roots.insert(mono_item);
-        }
-
-        // Always ensure we have at least one CGU; otherwise, if we have a
-        // crate with just types (for example), we could wind up with no CGU.
-        if codegen_units.is_empty() {
-            let codegen_unit_name = fallback_cgu_name(cgu_name_builder);
-            codegen_units.insert(codegen_unit_name, CodegenUnit::new(codegen_unit_name));
-        }
-
-        PreInliningPartitioning {
-            codegen_units: codegen_units.into_values().collect(),
-            roots,
-            internalization_candidates,
-        }
-    }
-
-    fn merge_codegen_units(
-        &mut self,
-        cx: &PartitioningCx<'_, 'tcx>,
-        initial_partitioning: &mut PreInliningPartitioning<'tcx>,
-    ) {
-        merging::merge_codegen_units(cx, initial_partitioning);
-    }
-
-    fn place_inlined_mono_items(
-        &mut self,
-        cx: &PartitioningCx<'_, 'tcx>,
-        initial_partitioning: PreInliningPartitioning<'tcx>,
-    ) -> PostInliningPartitioning<'tcx> {
-        let mut new_partitioning = Vec::new();
-        let mut mono_item_placements = FxHashMap::default();
-
-        let PreInliningPartitioning {
-            codegen_units: initial_cgus,
-            roots,
-            internalization_candidates,
-        } = initial_partitioning;
-
-        let single_codegen_unit = initial_cgus.len() == 1;
-
-        for old_codegen_unit in initial_cgus {
-            // Collect all items that need to be available in this codegen unit.
-            let mut reachable = FxHashSet::default();
-            for root in old_codegen_unit.items().keys() {
-                follow_inlining(*root, cx.inlining_map, &mut reachable);
-            }
-
-            let mut new_codegen_unit = CodegenUnit::new(old_codegen_unit.name());
-
-            // Add all monomorphizations that are not already there.
-            for mono_item in reachable {
-                if let Some(linkage) = old_codegen_unit.items().get(&mono_item) {
-                    // This is a root, just copy it over.
-                    new_codegen_unit.items_mut().insert(mono_item, *linkage);
-                } else {
-                    if roots.contains(&mono_item) {
-                        bug!(
-                            "GloballyShared mono-item inlined into other CGU: \
-                              {:?}",
-                            mono_item
-                        );
-                    }
-
-                    // This is a CGU-private copy.
-                    new_codegen_unit
-                        .items_mut()
-                        .insert(mono_item, (Linkage::Internal, Visibility::Default));
-                }
-
-                if !single_codegen_unit {
-                    // If there is more than one codegen unit, we need to keep track
-                    // in which codegen units each monomorphization is placed.
-                    match mono_item_placements.entry(mono_item) {
-                        Entry::Occupied(e) => {
-                            let placement = e.into_mut();
-                            debug_assert!(match *placement {
-                                MonoItemPlacement::SingleCgu { cgu_name } => {
-                                    cgu_name != new_codegen_unit.name()
-                                }
-                                MonoItemPlacement::MultipleCgus => true,
-                            });
-                            *placement = MonoItemPlacement::MultipleCgus;
-                        }
-                        Entry::Vacant(e) => {
-                            e.insert(MonoItemPlacement::SingleCgu {
-                                cgu_name: new_codegen_unit.name(),
-                            });
-                        }
-                    }
-                }
-            }
-
-            new_partitioning.push(new_codegen_unit);
-        }
-
-        return PostInliningPartitioning {
-            codegen_units: new_partitioning,
-            mono_item_placements,
-            internalization_candidates,
-        };
-
-        fn follow_inlining<'tcx>(
-            mono_item: MonoItem<'tcx>,
-            inlining_map: &InliningMap<'tcx>,
-            visited: &mut FxHashSet<MonoItem<'tcx>>,
-        ) {
-            if !visited.insert(mono_item) {
-                return;
-            }
-
-            inlining_map.with_inlining_candidates(mono_item, |target| {
-                follow_inlining(target, inlining_map, visited);
-            });
-        }
-    }
-
-    fn internalize_symbols(
-        &mut self,
-        cx: &PartitioningCx<'_, 'tcx>,
-        partitioning: &mut PostInliningPartitioning<'tcx>,
-    ) {
-        if partitioning.codegen_units.len() == 1 {
-            // Fast path for when there is only one codegen unit. In this case we
-            // can internalize all candidates, since there is nowhere else they
-            // could be accessed from.
-            for cgu in &mut partitioning.codegen_units {
-                for candidate in &partitioning.internalization_candidates {
-                    cgu.items_mut().insert(*candidate, (Linkage::Internal, Visibility::Default));
-                }
-            }
-
-            return;
-        }
-
-        // Build a map from every monomorphization to all the monomorphizations that
-        // reference it.
-        let mut accessor_map: FxHashMap<MonoItem<'tcx>, Vec<MonoItem<'tcx>>> = Default::default();
-        cx.inlining_map.iter_accesses(|accessor, accessees| {
-            for accessee in accessees {
-                accessor_map.entry(*accessee).or_default().push(accessor);
-            }
-        });
-
-        let mono_item_placements = &partitioning.mono_item_placements;
-
-        // For each internalization candidates in each codegen unit, check if it is
-        // accessed from outside its defining codegen unit.
-        for cgu in &mut partitioning.codegen_units {
-            let home_cgu = MonoItemPlacement::SingleCgu { cgu_name: cgu.name() };
-
-            for (accessee, linkage_and_visibility) in cgu.items_mut() {
-                if !partitioning.internalization_candidates.contains(accessee) {
-                    // This item is no candidate for internalizing, so skip it.
-                    continue;
-                }
-                debug_assert_eq!(mono_item_placements[accessee], home_cgu);
-
-                if let Some(accessors) = accessor_map.get(accessee) {
-                    if accessors
-                        .iter()
-                        .filter_map(|accessor| {
-                            // Some accessors might not have been
-                            // instantiated. We can safely ignore those.
-                            mono_item_placements.get(accessor)
-                        })
-                        .any(|placement| *placement != home_cgu)
-                    {
-                        // Found an accessor from another CGU, so skip to the next
-                        // item without marking this one as internal.
-                        continue;
-                    }
-                }
-
-                // If we got here, we did not find any accesses from other CGUs,
-                // so it's fine to make this monomorphization internal.
-                *linkage_and_visibility = (Linkage::Internal, Visibility::Default);
-            }
-        }
-    }
-}
-
-fn characteristic_def_id_of_mono_item<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    mono_item: MonoItem<'tcx>,
-) -> Option<DefId> {
-    match mono_item {
-        MonoItem::Fn(instance) => {
-            let def_id = match instance.def {
-                ty::InstanceDef::Item(def) => def,
-                ty::InstanceDef::VTableShim(..)
-                | ty::InstanceDef::ReifyShim(..)
-                | ty::InstanceDef::FnPtrShim(..)
-                | ty::InstanceDef::ClosureOnceShim { .. }
-                | ty::InstanceDef::Intrinsic(..)
-                | ty::InstanceDef::DropGlue(..)
-                | ty::InstanceDef::Virtual(..)
-                | ty::InstanceDef::CloneShim(..)
-                | ty::InstanceDef::ThreadLocalShim(..)
-                | ty::InstanceDef::FnPtrAddrShim(..) => return None,
-            };
-
-            // If this is a method, we want to put it into the same module as
-            // its self-type. If the self-type does not provide a characteristic
-            // DefId, we use the location of the impl after all.
-
-            if tcx.trait_of_item(def_id).is_some() {
-                let self_ty = instance.substs.type_at(0);
-                // This is a default implementation of a trait method.
-                return characteristic_def_id_of_type(self_ty).or(Some(def_id));
-            }
-
-            if let Some(impl_def_id) = tcx.impl_of_method(def_id) {
-                if tcx.sess.opts.incremental.is_some()
-                    && tcx.trait_id_of_impl(impl_def_id) == tcx.lang_items().drop_trait()
-                {
-                    // Put `Drop::drop` into the same cgu as `drop_in_place`
-                    // since `drop_in_place` is the only thing that can
-                    // call it.
-                    return None;
-                }
-
-                // When polymorphization is enabled, methods which do not depend on their generic
-                // parameters, but the self-type of their impl block do will fail to normalize.
-                if !tcx.sess.opts.unstable_opts.polymorphize || !instance.has_param() {
-                    // This is a method within an impl, find out what the self-type is:
-                    let impl_self_ty = tcx.subst_and_normalize_erasing_regions(
-                        instance.substs,
-                        ty::ParamEnv::reveal_all(),
-                        tcx.type_of(impl_def_id),
-                    );
-                    if let Some(def_id) = characteristic_def_id_of_type(impl_self_ty) {
-                        return Some(def_id);
-                    }
-                }
-            }
-
-            Some(def_id)
-        }
-        MonoItem::Static(def_id) => Some(def_id),
-        MonoItem::GlobalAsm(item_id) => Some(item_id.owner_id.to_def_id()),
-    }
-}
-
-fn compute_codegen_unit_name(
-    tcx: TyCtxt<'_>,
-    name_builder: &mut CodegenUnitNameBuilder<'_>,
-    def_id: DefId,
-    volatile: bool,
-    cache: &mut CguNameCache,
-) -> Symbol {
-    // Find the innermost module that is not nested within a function.
-    let mut current_def_id = def_id;
-    let mut cgu_def_id = None;
-    // Walk backwards from the item we want to find the module for.
-    loop {
-        if current_def_id.is_crate_root() {
-            if cgu_def_id.is_none() {
-                // If we have not found a module yet, take the crate root.
-                cgu_def_id = Some(def_id.krate.as_def_id());
-            }
-            break;
-        } else if tcx.def_kind(current_def_id) == DefKind::Mod {
-            if cgu_def_id.is_none() {
-                cgu_def_id = Some(current_def_id);
-            }
-        } else {
-            // If we encounter something that is not a module, throw away
-            // any module that we've found so far because we now know that
-            // it is nested within something else.
-            cgu_def_id = None;
-        }
-
-        current_def_id = tcx.parent(current_def_id);
-    }
-
-    let cgu_def_id = cgu_def_id.unwrap();
-
-    *cache.entry((cgu_def_id, volatile)).or_insert_with(|| {
-        let def_path = tcx.def_path(cgu_def_id);
-
-        let components = def_path.data.iter().map(|part| match part.data.name() {
-            DefPathDataName::Named(name) => name,
-            DefPathDataName::Anon { .. } => unreachable!(),
-        });
-
-        let volatile_suffix = volatile.then_some("volatile");
-
-        name_builder.build_cgu_name(def_path.krate, components, volatile_suffix)
-    })
-}
-
-// Anything we can't find a proper codegen unit for goes into this.
-fn fallback_cgu_name(name_builder: &mut CodegenUnitNameBuilder<'_>) -> Symbol {
-    name_builder.build_cgu_name(LOCAL_CRATE, &["fallback"], Some("cgu"))
-}
-
-fn mono_item_linkage_and_visibility<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    mono_item: &MonoItem<'tcx>,
-    can_be_internalized: &mut bool,
-    export_generics: bool,
-) -> (Linkage, Visibility) {
-    if let Some(explicit_linkage) = mono_item.explicit_linkage(tcx) {
-        return (explicit_linkage, Visibility::Default);
-    }
-    let vis = mono_item_visibility(tcx, mono_item, can_be_internalized, export_generics);
-    (Linkage::External, vis)
-}
-
-type CguNameCache = FxHashMap<(DefId, bool), Symbol>;
-
-fn static_visibility<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    can_be_internalized: &mut bool,
-    def_id: DefId,
-) -> Visibility {
-    if tcx.is_reachable_non_generic(def_id) {
-        *can_be_internalized = false;
-        default_visibility(tcx, def_id, false)
-    } else {
-        Visibility::Hidden
-    }
-}
-
-fn mono_item_visibility<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    mono_item: &MonoItem<'tcx>,
-    can_be_internalized: &mut bool,
-    export_generics: bool,
-) -> Visibility {
-    let instance = match mono_item {
-        // This is pretty complicated; see below.
-        MonoItem::Fn(instance) => instance,
-
-        // Misc handling for generics and such, but otherwise:
-        MonoItem::Static(def_id) => return static_visibility(tcx, can_be_internalized, *def_id),
-        MonoItem::GlobalAsm(item_id) => {
-            return static_visibility(tcx, can_be_internalized, item_id.owner_id.to_def_id());
-        }
-    };
-
-    let def_id = match instance.def {
-        InstanceDef::Item(def_id) | InstanceDef::DropGlue(def_id, Some(_)) => def_id,
-
-        // We match the visibility of statics here
-        InstanceDef::ThreadLocalShim(def_id) => {
-            return static_visibility(tcx, can_be_internalized, def_id);
-        }
-
-        // These are all compiler glue and such, never exported, always hidden.
-        InstanceDef::VTableShim(..)
-        | InstanceDef::ReifyShim(..)
-        | InstanceDef::FnPtrShim(..)
-        | InstanceDef::Virtual(..)
-        | InstanceDef::Intrinsic(..)
-        | InstanceDef::ClosureOnceShim { .. }
-        | InstanceDef::DropGlue(..)
-        | InstanceDef::CloneShim(..)
-        | InstanceDef::FnPtrAddrShim(..) => return Visibility::Hidden,
-    };
-
-    // The `start_fn` lang item is actually a monomorphized instance of a
-    // function in the standard library, used for the `main` function. We don't
-    // want to export it so we tag it with `Hidden` visibility but this symbol
-    // is only referenced from the actual `main` symbol which we unfortunately
-    // don't know anything about during partitioning/collection. As a result we
-    // forcibly keep this symbol out of the `internalization_candidates` set.
-    //
-    // FIXME: eventually we don't want to always force this symbol to have
-    //        hidden visibility, it should indeed be a candidate for
-    //        internalization, but we have to understand that it's referenced
-    //        from the `main` symbol we'll generate later.
-    //
-    //        This may be fixable with a new `InstanceDef` perhaps? Unsure!
-    if tcx.lang_items().start_fn() == Some(def_id) {
-        *can_be_internalized = false;
-        return Visibility::Hidden;
-    }
-
-    let is_generic = instance.substs.non_erasable_generics().next().is_some();
-
-    // Upstream `DefId` instances get different handling than local ones.
-    let Some(def_id) = def_id.as_local() else {
-        return if export_generics && is_generic {
-            // If it is an upstream monomorphization and we export generics, we must make
-            // it available to downstream crates.
-            *can_be_internalized = false;
-            default_visibility(tcx, def_id, true)
-        } else {
-            Visibility::Hidden
-        };
-    };
-
-    if is_generic {
-        if export_generics {
-            if tcx.is_unreachable_local_definition(def_id) {
-                // This instance cannot be used from another crate.
-                Visibility::Hidden
-            } else {
-                // This instance might be useful in a downstream crate.
-                *can_be_internalized = false;
-                default_visibility(tcx, def_id.to_def_id(), true)
-            }
-        } else {
-            // We are not exporting generics or the definition is not reachable
-            // for downstream crates, we can internalize its instantiations.
-            Visibility::Hidden
-        }
-    } else {
-        // If this isn't a generic function then we mark this a `Default` if
-        // this is a reachable item, meaning that it's a symbol other crates may
-        // access when they link to us.
-        if tcx.is_reachable_non_generic(def_id.to_def_id()) {
-            *can_be_internalized = false;
-            debug_assert!(!is_generic);
-            return default_visibility(tcx, def_id.to_def_id(), false);
-        }
-
-        // If this isn't reachable then we're gonna tag this with `Hidden`
-        // visibility. In some situations though we'll want to prevent this
-        // symbol from being internalized.
-        //
-        // There's two categories of items here:
-        //
-        // * First is weak lang items. These are basically mechanisms for
-        //   libcore to forward-reference symbols defined later in crates like
-        //   the standard library or `#[panic_handler]` definitions. The
-        //   definition of these weak lang items needs to be referencable by
-        //   libcore, so we're no longer a candidate for internalization.
-        //   Removal of these functions can't be done by LLVM but rather must be
-        //   done by the linker as it's a non-local decision.
-        //
-        // * Second is "std internal symbols". Currently this is primarily used
-        //   for allocator symbols. Allocators are a little weird in their
-        //   implementation, but the idea is that the compiler, at the last
-        //   minute, defines an allocator with an injected object file. The
-        //   `alloc` crate references these symbols (`__rust_alloc`) and the
-        //   definition doesn't get hooked up until a linked crate artifact is
-        //   generated.
-        //
-        //   The symbols synthesized by the compiler (`__rust_alloc`) are thin
-        //   veneers around the actual implementation, some other symbol which
-        //   implements the same ABI. These symbols (things like `__rg_alloc`,
-        //   `__rdl_alloc`, `__rde_alloc`, etc), are all tagged with "std
-        //   internal symbols".
-        //
-        //   The std-internal symbols here **should not show up in a dll as an
-        //   exported interface**, so they return `false` from
-        //   `is_reachable_non_generic` above and we'll give them `Hidden`
-        //   visibility below. Like the weak lang items, though, we can't let
-        //   LLVM internalize them as this decision is left up to the linker to
-        //   omit them, so prevent them from being internalized.
-        let attrs = tcx.codegen_fn_attrs(def_id);
-        if attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
-            *can_be_internalized = false;
-        }
-
-        Visibility::Hidden
-    }
-}
-
-fn default_visibility(tcx: TyCtxt<'_>, id: DefId, is_generic: bool) -> Visibility {
-    if !tcx.sess.target.default_hidden_visibility {
-        return Visibility::Default;
-    }
-
-    // Generic functions never have export-level C.
-    if is_generic {
-        return Visibility::Hidden;
-    }
-
-    // Things with export level C don't get instantiated in
-    // downstream crates.
-    if !id.is_local() {
-        return Visibility::Hidden;
-    }
-
-    // C-export level items remain at `Default`, all other internal
-    // items become `Hidden`.
-    match tcx.reachable_non_generics(id.krate).get(&id) {
-        Some(SymbolExportInfo { level: SymbolExportLevel::C, .. }) => Visibility::Default,
-        _ => Visibility::Hidden,
-    }
-}
diff --git a/compiler/rustc_monomorphize/src/partitioning/merging.rs b/compiler/rustc_monomorphize/src/partitioning/merging.rs
deleted file mode 100644
index 5c524a18454..00000000000
--- a/compiler/rustc_monomorphize/src/partitioning/merging.rs
+++ /dev/null
@@ -1,111 +0,0 @@
-use std::cmp;
-
-use rustc_data_structures::fx::FxHashMap;
-use rustc_hir::def_id::LOCAL_CRATE;
-use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder};
-use rustc_span::symbol::Symbol;
-
-use super::PartitioningCx;
-use crate::partitioning::PreInliningPartitioning;
-
-pub fn merge_codegen_units<'tcx>(
-    cx: &PartitioningCx<'_, 'tcx>,
-    initial_partitioning: &mut PreInliningPartitioning<'tcx>,
-) {
-    assert!(cx.target_cgu_count >= 1);
-    let codegen_units = &mut initial_partitioning.codegen_units;
-
-    // Note that at this point in time the `codegen_units` here may not be in a
-    // deterministic order (but we know they're deterministically the same set).
-    // We want this merging to produce a deterministic ordering of codegen units
-    // from the input.
-    //
-    // Due to basically how we've implemented the merging below (merge the two
-    // smallest into each other) we're sure to start off with a deterministic
-    // order (sorted by name). This'll mean that if two cgus have the same size
-    // the stable sort below will keep everything nice and deterministic.
-    codegen_units.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
-
-    // This map keeps track of what got merged into what.
-    let mut cgu_contents: FxHashMap<Symbol, Vec<Symbol>> =
-        codegen_units.iter().map(|cgu| (cgu.name(), vec![cgu.name()])).collect();
-
-    // Merge the two smallest codegen units until the target size is reached.
-    while codegen_units.len() > cx.target_cgu_count {
-        // Sort small cgus to the back
-        codegen_units.sort_by_cached_key(|cgu| cmp::Reverse(cgu.size_estimate()));
-        let mut smallest = codegen_units.pop().unwrap();
-        let second_smallest = codegen_units.last_mut().unwrap();
-
-        // Move the mono-items from `smallest` to `second_smallest`
-        second_smallest.modify_size_estimate(smallest.size_estimate());
-        for (k, v) in smallest.items_mut().drain() {
-            second_smallest.items_mut().insert(k, v);
-        }
-
-        // Record that `second_smallest` now contains all the stuff that was in
-        // `smallest` before.
-        let mut consumed_cgu_names = cgu_contents.remove(&smallest.name()).unwrap();
-        cgu_contents.get_mut(&second_smallest.name()).unwrap().append(&mut consumed_cgu_names);
-
-        debug!(
-            "CodegenUnit {} merged into CodegenUnit {}",
-            smallest.name(),
-            second_smallest.name()
-        );
-    }
-
-    let cgu_name_builder = &mut CodegenUnitNameBuilder::new(cx.tcx);
-
-    if cx.tcx.sess.opts.incremental.is_some() {
-        // If we are doing incremental compilation, we want CGU names to
-        // reflect the path of the source level module they correspond to.
-        // For CGUs that contain the code of multiple modules because of the
-        // merging done above, we use a concatenation of the names of
-        // all contained CGUs.
-        let new_cgu_names: FxHashMap<Symbol, String> = cgu_contents
-            .into_iter()
-            // This `filter` makes sure we only update the name of CGUs that
-            // were actually modified by merging.
-            .filter(|(_, cgu_contents)| cgu_contents.len() > 1)
-            .map(|(current_cgu_name, cgu_contents)| {
-                let mut cgu_contents: Vec<&str> = cgu_contents.iter().map(|s| s.as_str()).collect();
-
-                // Sort the names, so things are deterministic and easy to
-                // predict.
-
-                // We are sorting primitive &strs here so we can use unstable sort
-                cgu_contents.sort_unstable();
-
-                (current_cgu_name, cgu_contents.join("--"))
-            })
-            .collect();
-
-        for cgu in codegen_units.iter_mut() {
-            if let Some(new_cgu_name) = new_cgu_names.get(&cgu.name()) {
-                if cx.tcx.sess.opts.unstable_opts.human_readable_cgu_names {
-                    cgu.set_name(Symbol::intern(&new_cgu_name));
-                } else {
-                    // If we don't require CGU names to be human-readable, we
-                    // use a fixed length hash of the composite CGU name
-                    // instead.
-                    let new_cgu_name = CodegenUnit::mangle_name(&new_cgu_name);
-                    cgu.set_name(Symbol::intern(&new_cgu_name));
-                }
-            }
-        }
-    } else {
-        // If we are compiling non-incrementally we just generate simple CGU
-        // names containing an index.
-        for (index, cgu) in codegen_units.iter_mut().enumerate() {
-            cgu.set_name(numbered_codegen_unit_name(cgu_name_builder, index));
-        }
-    }
-}
-
-fn numbered_codegen_unit_name(
-    name_builder: &mut CodegenUnitNameBuilder<'_>,
-    index: usize,
-) -> Symbol {
-    name_builder.build_cgu_name_no_mangle(LOCAL_CRATE, &["cgu"], Some(index))
-}
diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs
deleted file mode 100644
index eafe57a0c02..00000000000
--- a/compiler/rustc_monomorphize/src/partitioning/mod.rs
+++ /dev/null
@@ -1,672 +0,0 @@
-//! Partitioning Codegen Units for Incremental Compilation
-//! ======================================================
-//!
-//! The task of this module is to take the complete set of monomorphizations of
-//! a crate and produce a set of codegen units from it, where a codegen unit
-//! is a named set of (mono-item, linkage) pairs. That is, this module
-//! decides which monomorphization appears in which codegen units with which
-//! linkage. The following paragraphs describe some of the background on the
-//! partitioning scheme.
-//!
-//! The most important opportunity for saving on compilation time with
-//! incremental compilation is to avoid re-codegenning and re-optimizing code.
-//! Since the unit of codegen and optimization for LLVM is "modules" or, how
-//! we call them "codegen units", the particulars of how much time can be saved
-//! by incremental compilation are tightly linked to how the output program is
-//! partitioned into these codegen units prior to passing it to LLVM --
-//! especially because we have to treat codegen units as opaque entities once
-//! they are created: There is no way for us to incrementally update an existing
-//! LLVM module and so we have to build any such module from scratch if it was
-//! affected by some change in the source code.
-//!
-//! From that point of view it would make sense to maximize the number of
-//! codegen units by, for example, putting each function into its own module.
-//! That way only those modules would have to be re-compiled that were actually
-//! affected by some change, minimizing the number of functions that could have
-//! been re-used but just happened to be located in a module that is
-//! re-compiled.
-//!
-//! However, since LLVM optimization does not work across module boundaries,
-//! using such a highly granular partitioning would lead to very slow runtime
-//! code since it would effectively prohibit inlining and other inter-procedure
-//! optimizations. We want to avoid that as much as possible.
-//!
-//! Thus we end up with a trade-off: The bigger the codegen units, the better
-//! LLVM's optimizer can do its work, but also the smaller the compilation time
-//! reduction we get from incremental compilation.
-//!
-//! Ideally, we would create a partitioning such that there are few big codegen
-//! units with few interdependencies between them. For now though, we use the
-//! following heuristic to determine the partitioning:
-//!
-//! - There are two codegen units for every source-level module:
-//! - One for "stable", that is non-generic, code
-//! - One for more "volatile" code, i.e., monomorphized instances of functions
-//!   defined in that module
-//!
-//! In order to see why this heuristic makes sense, let's take a look at when a
-//! codegen unit can get invalidated:
-//!
-//! 1. The most straightforward case is when the BODY of a function or global
-//! changes. Then any codegen unit containing the code for that item has to be
-//! re-compiled. Note that this includes all codegen units where the function
-//! has been inlined.
-//!
-//! 2. The next case is when the SIGNATURE of a function or global changes. In
-//! this case, all codegen units containing a REFERENCE to that item have to be
-//! re-compiled. This is a superset of case 1.
-//!
-//! 3. The final and most subtle case is when a REFERENCE to a generic function
-//! is added or removed somewhere. Even though the definition of the function
-//! might be unchanged, a new REFERENCE might introduce a new monomorphized
-//! instance of this function which has to be placed and compiled somewhere.
-//! Conversely, when removing a REFERENCE, it might have been the last one with
-//! that particular set of generic arguments and thus we have to remove it.
-//!
-//! From the above we see that just using one codegen unit per source-level
-//! module is not such a good idea, since just adding a REFERENCE to some
-//! generic item somewhere else would invalidate everything within the module
-//! containing the generic item. The heuristic above reduces this detrimental
-//! side-effect of references a little by at least not touching the non-generic
-//! code of the module.
-//!
-//! A Note on Inlining
-//! ------------------
-//! As briefly mentioned above, in order for LLVM to be able to inline a
-//! function call, the body of the function has to be available in the LLVM
-//! module where the call is made. This has a few consequences for partitioning:
-//!
-//! - The partitioning algorithm has to take care of placing functions into all
-//!   codegen units where they should be available for inlining. It also has to
-//!   decide on the correct linkage for these functions.
-//!
-//! - The partitioning algorithm has to know which functions are likely to get
-//!   inlined, so it can distribute function instantiations accordingly. Since
-//!   there is no way of knowing for sure which functions LLVM will decide to
-//!   inline in the end, we apply a heuristic here: Only functions marked with
-//!   `#[inline]` are considered for inlining by the partitioner. The current
-//!   implementation will not try to determine if a function is likely to be
-//!   inlined by looking at the functions definition.
-//!
-//! Note though that as a side-effect of creating a codegen units per
-//! source-level module, functions from the same module will be available for
-//! inlining, even when they are not marked `#[inline]`.
-
-mod default;
-mod merging;
-
-use std::cmp;
-use std::fs::{self, File};
-use std::io::{BufWriter, Write};
-use std::path::{Path, PathBuf};
-
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::sync;
-use rustc_hir::def_id::{DefIdSet, LOCAL_CRATE};
-use rustc_middle::mir;
-use rustc_middle::mir::mono::MonoItem;
-use rustc_middle::mir::mono::{CodegenUnit, Linkage};
-use rustc_middle::query::Providers;
-use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::TyCtxt;
-use rustc_session::config::{DumpMonoStatsFormat, SwitchWithOptPath};
-use rustc_span::symbol::Symbol;
-
-use crate::collector::InliningMap;
-use crate::collector::{self, MonoItemCollectionMode};
-use crate::errors::{
-    CouldntDumpMonoStats, SymbolAlreadyDefined, UnknownCguCollectionMode, UnknownPartitionStrategy,
-};
-
-enum Partitioner {
-    Default(default::DefaultPartitioning),
-    // Other partitioning strategies can go here.
-    Unknown,
-}
-
-impl<'tcx> Partition<'tcx> for Partitioner {
-    fn place_root_mono_items<I>(
-        &mut self,
-        cx: &PartitioningCx<'_, 'tcx>,
-        mono_items: &mut I,
-    ) -> PreInliningPartitioning<'tcx>
-    where
-        I: Iterator<Item = MonoItem<'tcx>>,
-    {
-        match self {
-            Partitioner::Default(partitioner) => partitioner.place_root_mono_items(cx, mono_items),
-            Partitioner::Unknown => cx.tcx.sess.emit_fatal(UnknownPartitionStrategy),
-        }
-    }
-
-    fn merge_codegen_units(
-        &mut self,
-        cx: &PartitioningCx<'_, 'tcx>,
-        initial_partitioning: &mut PreInliningPartitioning<'tcx>,
-    ) {
-        match self {
-            Partitioner::Default(partitioner) => {
-                partitioner.merge_codegen_units(cx, initial_partitioning)
-            }
-            Partitioner::Unknown => cx.tcx.sess.emit_fatal(UnknownPartitionStrategy),
-        }
-    }
-
-    fn place_inlined_mono_items(
-        &mut self,
-        cx: &PartitioningCx<'_, 'tcx>,
-        initial_partitioning: PreInliningPartitioning<'tcx>,
-    ) -> PostInliningPartitioning<'tcx> {
-        match self {
-            Partitioner::Default(partitioner) => {
-                partitioner.place_inlined_mono_items(cx, initial_partitioning)
-            }
-            Partitioner::Unknown => cx.tcx.sess.emit_fatal(UnknownPartitionStrategy),
-        }
-    }
-
-    fn internalize_symbols(
-        &mut self,
-        cx: &PartitioningCx<'_, 'tcx>,
-        post_inlining_partitioning: &mut PostInliningPartitioning<'tcx>,
-    ) {
-        match self {
-            Partitioner::Default(partitioner) => {
-                partitioner.internalize_symbols(cx, post_inlining_partitioning)
-            }
-            Partitioner::Unknown => cx.tcx.sess.emit_fatal(UnknownPartitionStrategy),
-        }
-    }
-}
-
-pub struct PartitioningCx<'a, 'tcx> {
-    tcx: TyCtxt<'tcx>,
-    target_cgu_count: usize,
-    inlining_map: &'a InliningMap<'tcx>,
-}
-
-trait Partition<'tcx> {
-    fn place_root_mono_items<I>(
-        &mut self,
-        cx: &PartitioningCx<'_, 'tcx>,
-        mono_items: &mut I,
-    ) -> PreInliningPartitioning<'tcx>
-    where
-        I: Iterator<Item = MonoItem<'tcx>>;
-
-    fn merge_codegen_units(
-        &mut self,
-        cx: &PartitioningCx<'_, 'tcx>,
-        initial_partitioning: &mut PreInliningPartitioning<'tcx>,
-    );
-
-    fn place_inlined_mono_items(
-        &mut self,
-        cx: &PartitioningCx<'_, 'tcx>,
-        initial_partitioning: PreInliningPartitioning<'tcx>,
-    ) -> PostInliningPartitioning<'tcx>;
-
-    fn internalize_symbols(
-        &mut self,
-        cx: &PartitioningCx<'_, 'tcx>,
-        partitioning: &mut PostInliningPartitioning<'tcx>,
-    );
-}
-
-fn get_partitioner(tcx: TyCtxt<'_>) -> Partitioner {
-    let strategy = match &tcx.sess.opts.unstable_opts.cgu_partitioning_strategy {
-        None => "default",
-        Some(s) => &s[..],
-    };
-
-    match strategy {
-        "default" => Partitioner::Default(default::DefaultPartitioning),
-        _ => Partitioner::Unknown,
-    }
-}
-
-pub fn partition<'tcx, I>(
-    tcx: TyCtxt<'tcx>,
-    mono_items: &mut I,
-    max_cgu_count: usize,
-    inlining_map: &InliningMap<'tcx>,
-) -> Vec<CodegenUnit<'tcx>>
-where
-    I: Iterator<Item = MonoItem<'tcx>>,
-{
-    let _prof_timer = tcx.prof.generic_activity("cgu_partitioning");
-
-    let mut partitioner = get_partitioner(tcx);
-    let cx = &PartitioningCx { tcx, target_cgu_count: max_cgu_count, inlining_map };
-    // In the first step, we place all regular monomorphizations into their
-    // respective 'home' codegen unit. Regular monomorphizations are all
-    // functions and statics defined in the local crate.
-    let mut initial_partitioning = {
-        let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_roots");
-        partitioner.place_root_mono_items(cx, mono_items)
-    };
-
-    for cgu in &mut initial_partitioning.codegen_units {
-        cgu.create_size_estimate(tcx);
-    }
-
-    debug_dump(tcx, "INITIAL PARTITIONING", &initial_partitioning.codegen_units);
-
-    // Merge until we have at most `max_cgu_count` codegen units.
-    {
-        let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_merge_cgus");
-        partitioner.merge_codegen_units(cx, &mut initial_partitioning);
-        debug_dump(tcx, "POST MERGING", &initial_partitioning.codegen_units);
-    }
-
-    // In the next step, we use the inlining map to determine which additional
-    // monomorphizations have to go into each codegen unit. These additional
-    // monomorphizations can be drop-glue, functions from external crates, and
-    // local functions the definition of which is marked with `#[inline]`.
-    let mut post_inlining = {
-        let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_inline_items");
-        partitioner.place_inlined_mono_items(cx, initial_partitioning)
-    };
-
-    for cgu in &mut post_inlining.codegen_units {
-        cgu.create_size_estimate(tcx);
-    }
-
-    debug_dump(tcx, "POST INLINING", &post_inlining.codegen_units);
-
-    // Next we try to make as many symbols "internal" as possible, so LLVM has
-    // more freedom to optimize.
-    if !tcx.sess.link_dead_code() {
-        let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_internalize_symbols");
-        partitioner.internalize_symbols(cx, &mut post_inlining);
-    }
-
-    let instrument_dead_code =
-        tcx.sess.instrument_coverage() && !tcx.sess.instrument_coverage_except_unused_functions();
-
-    if instrument_dead_code {
-        assert!(
-            post_inlining.codegen_units.len() > 0,
-            "There must be at least one CGU that code coverage data can be generated in."
-        );
-
-        // Find the smallest CGU that has exported symbols and put the dead
-        // function stubs in that CGU. We look for exported symbols to increase
-        // the likelihood the linker won't throw away the dead functions.
-        // FIXME(#92165): In order to truly resolve this, we need to make sure
-        // the object file (CGU) containing the dead function stubs is included
-        // in the final binary. This will probably require forcing these
-        // function symbols to be included via `-u` or `/include` linker args.
-        let mut cgus: Vec<_> = post_inlining.codegen_units.iter_mut().collect();
-        cgus.sort_by_key(|cgu| cgu.size_estimate());
-
-        let dead_code_cgu =
-            if let Some(cgu) = cgus.into_iter().rev().find(|cgu| {
-                cgu.items().iter().any(|(_, (linkage, _))| *linkage == Linkage::External)
-            }) {
-                cgu
-            } else {
-                // If there are no CGUs that have externally linked items,
-                // then we just pick the first CGU as a fallback.
-                &mut post_inlining.codegen_units[0]
-            };
-        dead_code_cgu.make_code_coverage_dead_code_cgu();
-    }
-
-    // Finally, sort by codegen unit name, so that we get deterministic results.
-    let PostInliningPartitioning {
-        codegen_units: mut result,
-        mono_item_placements: _,
-        internalization_candidates: _,
-    } = post_inlining;
-
-    result.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
-
-    debug_dump(tcx, "FINAL", &result);
-
-    result
-}
-
-pub struct PreInliningPartitioning<'tcx> {
-    codegen_units: Vec<CodegenUnit<'tcx>>,
-    roots: FxHashSet<MonoItem<'tcx>>,
-    internalization_candidates: FxHashSet<MonoItem<'tcx>>,
-}
-
-/// For symbol internalization, we need to know whether a symbol/mono-item is
-/// accessed from outside the codegen unit it is defined in. This type is used
-/// to keep track of that.
-#[derive(Clone, PartialEq, Eq, Debug)]
-enum MonoItemPlacement {
-    SingleCgu { cgu_name: Symbol },
-    MultipleCgus,
-}
-
-struct PostInliningPartitioning<'tcx> {
-    codegen_units: Vec<CodegenUnit<'tcx>>,
-    mono_item_placements: FxHashMap<MonoItem<'tcx>, MonoItemPlacement>,
-    internalization_candidates: FxHashSet<MonoItem<'tcx>>,
-}
-
-fn debug_dump<'a, 'tcx: 'a>(tcx: TyCtxt<'tcx>, label: &str, cgus: &[CodegenUnit<'tcx>]) {
-    let dump = move || {
-        use std::fmt::Write;
-
-        let num_cgus = cgus.len();
-        let max = cgus.iter().map(|cgu| cgu.size_estimate()).max().unwrap();
-        let min = cgus.iter().map(|cgu| cgu.size_estimate()).min().unwrap();
-        let ratio = max as f64 / min as f64;
-
-        let s = &mut String::new();
-        let _ = writeln!(
-            s,
-            "{label} ({num_cgus} CodegenUnits, max={max}, min={min}, max/min={ratio:.1}):"
-        );
-        for cgu in cgus {
-            let _ =
-                writeln!(s, "CodegenUnit {} estimated size {}:", cgu.name(), cgu.size_estimate());
-
-            for (mono_item, linkage) in cgu.items() {
-                let symbol_name = mono_item.symbol_name(tcx).name;
-                let symbol_hash_start = symbol_name.rfind('h');
-                let symbol_hash = symbol_hash_start.map_or("<no hash>", |i| &symbol_name[i..]);
-
-                let _ = with_no_trimmed_paths!(writeln!(
-                    s,
-                    " - {} [{:?}] [{}] estimated size {}",
-                    mono_item,
-                    linkage,
-                    symbol_hash,
-                    mono_item.size_estimate(tcx)
-                ));
-            }
-
-            let _ = writeln!(s);
-        }
-
-        std::mem::take(s)
-    };
-
-    debug!("{}", dump());
-}
-
-#[inline(never)] // give this a place in the profiler
-fn assert_symbols_are_distinct<'a, 'tcx, I>(tcx: TyCtxt<'tcx>, mono_items: I)
-where
-    I: Iterator<Item = &'a MonoItem<'tcx>>,
-    'tcx: 'a,
-{
-    let _prof_timer = tcx.prof.generic_activity("assert_symbols_are_distinct");
-
-    let mut symbols: Vec<_> =
-        mono_items.map(|mono_item| (mono_item, mono_item.symbol_name(tcx))).collect();
-
-    symbols.sort_by_key(|sym| sym.1);
-
-    for &[(mono_item1, ref sym1), (mono_item2, ref sym2)] in symbols.array_windows() {
-        if sym1 == sym2 {
-            let span1 = mono_item1.local_span(tcx);
-            let span2 = mono_item2.local_span(tcx);
-
-            // Deterministically select one of the spans for error reporting
-            let span = match (span1, span2) {
-                (Some(span1), Some(span2)) => {
-                    Some(if span1.lo().0 > span2.lo().0 { span1 } else { span2 })
-                }
-                (span1, span2) => span1.or(span2),
-            };
-
-            tcx.sess.emit_fatal(SymbolAlreadyDefined { span, symbol: sym1.to_string() });
-        }
-    }
-}
-
-fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> (&DefIdSet, &[CodegenUnit<'_>]) {
-    let collection_mode = match tcx.sess.opts.unstable_opts.print_mono_items {
-        Some(ref s) => {
-            let mode = s.to_lowercase();
-            let mode = mode.trim();
-            if mode == "eager" {
-                MonoItemCollectionMode::Eager
-            } else {
-                if mode != "lazy" {
-                    tcx.sess.emit_warning(UnknownCguCollectionMode { mode });
-                }
-
-                MonoItemCollectionMode::Lazy
-            }
-        }
-        None => {
-            if tcx.sess.link_dead_code() {
-                MonoItemCollectionMode::Eager
-            } else {
-                MonoItemCollectionMode::Lazy
-            }
-        }
-    };
-
-    let (items, inlining_map) = collector::collect_crate_mono_items(tcx, collection_mode);
-
-    tcx.sess.abort_if_errors();
-
-    let (codegen_units, _) = tcx.sess.time("partition_and_assert_distinct_symbols", || {
-        sync::join(
-            || {
-                let mut codegen_units = partition(
-                    tcx,
-                    &mut items.iter().copied(),
-                    tcx.sess.codegen_units(),
-                    &inlining_map,
-                );
-                codegen_units[0].make_primary();
-                &*tcx.arena.alloc_from_iter(codegen_units)
-            },
-            || assert_symbols_are_distinct(tcx, items.iter()),
-        )
-    });
-
-    if tcx.prof.enabled() {
-        // Record CGU size estimates for self-profiling.
-        for cgu in codegen_units {
-            tcx.prof.artifact_size(
-                "codegen_unit_size_estimate",
-                cgu.name().as_str(),
-                cgu.size_estimate() as u64,
-            );
-        }
-    }
-
-    let mono_items: DefIdSet = items
-        .iter()
-        .filter_map(|mono_item| match *mono_item {
-            MonoItem::Fn(ref instance) => Some(instance.def_id()),
-            MonoItem::Static(def_id) => Some(def_id),
-            _ => None,
-        })
-        .collect();
-
-    // Output monomorphization stats per def_id
-    if let SwitchWithOptPath::Enabled(ref path) = tcx.sess.opts.unstable_opts.dump_mono_stats {
-        if let Err(err) =
-            dump_mono_items_stats(tcx, &codegen_units, path, tcx.crate_name(LOCAL_CRATE))
-        {
-            tcx.sess.emit_fatal(CouldntDumpMonoStats { error: err.to_string() });
-        }
-    }
-
-    if tcx.sess.opts.unstable_opts.print_mono_items.is_some() {
-        let mut item_to_cgus: FxHashMap<_, Vec<_>> = Default::default();
-
-        for cgu in codegen_units {
-            for (&mono_item, &linkage) in cgu.items() {
-                item_to_cgus.entry(mono_item).or_default().push((cgu.name(), linkage));
-            }
-        }
-
-        let mut item_keys: Vec<_> = items
-            .iter()
-            .map(|i| {
-                let mut output = with_no_trimmed_paths!(i.to_string());
-                output.push_str(" @@");
-                let mut empty = Vec::new();
-                let cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty);
-                cgus.sort_by_key(|(name, _)| *name);
-                cgus.dedup();
-                for &(ref cgu_name, (linkage, _)) in cgus.iter() {
-                    output.push(' ');
-                    output.push_str(cgu_name.as_str());
-
-                    let linkage_abbrev = match linkage {
-                        Linkage::External => "External",
-                        Linkage::AvailableExternally => "Available",
-                        Linkage::LinkOnceAny => "OnceAny",
-                        Linkage::LinkOnceODR => "OnceODR",
-                        Linkage::WeakAny => "WeakAny",
-                        Linkage::WeakODR => "WeakODR",
-                        Linkage::Appending => "Appending",
-                        Linkage::Internal => "Internal",
-                        Linkage::Private => "Private",
-                        Linkage::ExternalWeak => "ExternalWeak",
-                        Linkage::Common => "Common",
-                    };
-
-                    output.push('[');
-                    output.push_str(linkage_abbrev);
-                    output.push(']');
-                }
-                output
-            })
-            .collect();
-
-        item_keys.sort();
-
-        for item in item_keys {
-            println!("MONO_ITEM {item}");
-        }
-    }
-
-    (tcx.arena.alloc(mono_items), codegen_units)
-}
-
-/// Outputs stats about instantiation counts and estimated size, per `MonoItem`'s
-/// def, to a file in the given output directory.
-fn dump_mono_items_stats<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    codegen_units: &[CodegenUnit<'tcx>],
-    output_directory: &Option<PathBuf>,
-    crate_name: Symbol,
-) -> Result<(), Box<dyn std::error::Error>> {
-    let output_directory = if let Some(ref directory) = output_directory {
-        fs::create_dir_all(directory)?;
-        directory
-    } else {
-        Path::new(".")
-    };
-
-    let format = tcx.sess.opts.unstable_opts.dump_mono_stats_format;
-    let ext = format.extension();
-    let filename = format!("{crate_name}.mono_items.{ext}");
-    let output_path = output_directory.join(&filename);
-    let file = File::create(&output_path)?;
-    let mut file = BufWriter::new(file);
-
-    // Gather instantiated mono items grouped by def_id
-    let mut items_per_def_id: FxHashMap<_, Vec<_>> = Default::default();
-    for cgu in codegen_units {
-        for (&mono_item, _) in cgu.items() {
-            // Avoid variable-sized compiler-generated shims
-            if mono_item.is_user_defined() {
-                items_per_def_id.entry(mono_item.def_id()).or_default().push(mono_item);
-            }
-        }
-    }
-
-    #[derive(serde::Serialize)]
-    struct MonoItem {
-        name: String,
-        instantiation_count: usize,
-        size_estimate: usize,
-        total_estimate: usize,
-    }
-
-    // Output stats sorted by total instantiated size, from heaviest to lightest
-    let mut stats: Vec<_> = items_per_def_id
-        .into_iter()
-        .map(|(def_id, items)| {
-            let name = with_no_trimmed_paths!(tcx.def_path_str(def_id));
-            let instantiation_count = items.len();
-            let size_estimate = items[0].size_estimate(tcx);
-            let total_estimate = instantiation_count * size_estimate;
-            MonoItem { name, instantiation_count, size_estimate, total_estimate }
-        })
-        .collect();
-    stats.sort_unstable_by_key(|item| cmp::Reverse(item.total_estimate));
-
-    if !stats.is_empty() {
-        match format {
-            DumpMonoStatsFormat::Json => serde_json::to_writer(file, &stats)?,
-            DumpMonoStatsFormat::Markdown => {
-                writeln!(
-                    file,
-                    "| Item | Instantiation count | Estimated Cost Per Instantiation | Total Estimated Cost |"
-                )?;
-                writeln!(file, "| --- | ---: | ---: | ---: |")?;
-
-                for MonoItem { name, instantiation_count, size_estimate, total_estimate } in stats {
-                    writeln!(
-                        file,
-                        "| `{name}` | {instantiation_count} | {size_estimate} | {total_estimate} |"
-                    )?;
-                }
-            }
-        }
-    }
-
-    Ok(())
-}
-
-fn codegened_and_inlined_items(tcx: TyCtxt<'_>, (): ()) -> &DefIdSet {
-    let (items, cgus) = tcx.collect_and_partition_mono_items(());
-    let mut visited = DefIdSet::default();
-    let mut result = items.clone();
-
-    for cgu in cgus {
-        for (item, _) in cgu.items() {
-            if let MonoItem::Fn(ref instance) = item {
-                let did = instance.def_id();
-                if !visited.insert(did) {
-                    continue;
-                }
-                let body = tcx.instance_mir(instance.def);
-                for block in body.basic_blocks.iter() {
-                    for statement in &block.statements {
-                        let mir::StatementKind::Coverage(_) = statement.kind else { continue };
-                        let scope = statement.source_info.scope;
-                        if let Some(inlined) = scope.inlined_instance(&body.source_scopes) {
-                            result.insert(inlined.def_id());
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    tcx.arena.alloc(result)
-}
-
-pub fn provide(providers: &mut Providers) {
-    providers.collect_and_partition_mono_items = collect_and_partition_mono_items;
-    providers.codegened_and_inlined_items = codegened_and_inlined_items;
-
-    providers.is_codegened_item = |tcx, def_id| {
-        let (all_mono_items, _) = tcx.collect_and_partition_mono_items(());
-        all_mono_items.contains(&def_id)
-    };
-
-    providers.codegen_unit = |tcx, name| {
-        let (_, all) = tcx.collect_and_partition_mono_items(());
-        all.iter()
-            .find(|cgu| cgu.name() == name)
-            .unwrap_or_else(|| panic!("failed to find cgu with name {name:?}"))
-    };
-}
diff --git a/compiler/rustc_monomorphize/src/util.rs b/compiler/rustc_monomorphize/src/util.rs
index d12bfc6f6bb..f6a80b0431f 100644
--- a/compiler/rustc_monomorphize/src/util.rs
+++ b/compiler/rustc_monomorphize/src/util.rs
@@ -29,12 +29,12 @@ pub(crate) fn dump_closure_profile<'tcx>(tcx: TyCtxt<'tcx>, closure_instance: In
         let before_feature_tys = tcx.subst_and_normalize_erasing_regions(
             closure_instance.substs,
             param_env,
-            ty::EarlyBinder(before_feature_tys),
+            ty::EarlyBinder::bind(before_feature_tys),
         );
         let after_feature_tys = tcx.subst_and_normalize_erasing_regions(
             closure_instance.substs,
             param_env,
-            ty::EarlyBinder(after_feature_tys),
+            ty::EarlyBinder::bind(after_feature_tys),
         );
 
         let new_size = tcx
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index 2d0f466e236..9263394508e 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -1,230 +1,298 @@
-parse_struct_literal_body_without_path =
-    struct literal body without path
-    .suggestion = you might have forgotten to add the struct literal inside the block
+parse_add_paren = try adding parentheses
 
-parse_struct_literal_needing_parens =
-    invalid struct literal
-    .suggestion = you might need to surround the struct literal in parentheses
+parse_ambiguous_missing_keyword_for_item_definition = missing `fn` or `struct` for function or struct definition
+    .suggestion = if you meant to call a macro, try
+    .help = if you meant to call a macro, remove the `pub` and add a trailing `!` after the identifier
 
-parse_maybe_report_ambiguous_plus =
-    ambiguous `+` in a type
-    .suggestion = use parentheses to disambiguate
+parse_ambiguous_range_pattern = the range pattern here has ambiguous interpretation
+    .suggestion = add parentheses to clarify the precedence
 
-parse_maybe_recover_from_bad_type_plus =
-    expected a path on the left-hand side of `+`, not `{$ty}`
+parse_array_brackets_instead_of_braces = this is a block expression, not an array
+    .suggestion = to make an array, use square brackets instead of curly braces
 
-parse_add_paren = try adding parentheses
+parse_assignment_else_not_allowed = <assignment> ... else {"{"} ... {"}"} is not allowed
 
-parse_forgot_paren = perhaps you forgot parentheses?
+parse_assoc_lifetime = associated lifetimes are not supported
+    .label = the lifetime is given here
+    .help = if you meant to specify a trait object, write `dyn Trait + 'lifetime`
 
-parse_expect_path = expected a path
+parse_associated_static_item_not_allowed = associated `static` items are not allowed
 
-parse_maybe_recover_from_bad_qpath_stage_2 =
-    missing angle brackets in associated item path
-    .suggestion = try: `{$ty}`
+parse_async_block_in_2015 = `async` blocks are only allowed in Rust 2018 or later
 
-parse_incorrect_semicolon =
-    expected item, found `;`
-    .suggestion = remove this semicolon
-    .help = {$name} declarations are not followed by a semicolon
+parse_async_fn_in_2015 = `async fn` is not permitted in Rust 2015
+    .label = to use `async fn`, switch to Rust 2018 or later
 
-parse_incorrect_use_of_await =
-    incorrect use of `await`
-    .parentheses_suggestion = `await` is not a method call, remove the parentheses
-    .postfix_suggestion = `await` is a postfix operation
+parse_async_move_order_incorrect = the order of `move` and `async` is incorrect
+    .suggestion = try switching the order
 
-parse_in_in_typo =
-    expected iterable, found keyword `in`
-    .suggestion = remove the duplicated `in`
+parse_attr_after_generic = trailing attribute after generic parameter
+    .label = attributes must go before parameters
 
-parse_invalid_variable_declaration =
-    invalid variable declaration
+parse_attr_without_generics = attribute without generic parameters
+    .label = attributes are only permitted when preceding parameters
 
-parse_switch_mut_let_order =
-    switch the order of `mut` and `let`
-parse_missing_let_before_mut = missing keyword
-parse_use_let_not_auto = write `let` instead of `auto` to introduce a new variable
-parse_use_let_not_var = write `let` instead of `var` to introduce a new variable
+parse_attribute_on_param_type = attributes cannot be applied to a function parameter's type
+    .label = attributes are not allowed here
 
-parse_invalid_comparison_operator = invalid comparison operator `{$invalid}`
-    .use_instead = `{$invalid}` is not a valid comparison operator, use `{$correct}`
-    .spaceship_operator_invalid = `<=>` is not a valid comparison operator, use `std::cmp::Ordering`
+parse_bad_assoc_type_bounds = bounds on associated types do not belong here
+    .label = belongs in `where` clause
 
-parse_invalid_logical_operator = `{$incorrect}` is not a logical operator
-    .note = unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators
-    .use_amp_amp_for_conjunction = use `&&` to perform logical conjunction
-    .use_pipe_pipe_for_disjunction = use `||` to perform logical disjunction
+parse_bad_item_kind = {$descr} is not supported in {$ctx}
+    .help = consider moving the {$descr} out to a nearby module scope
 
-parse_tilde_is_not_unary_operator = `~` cannot be used as a unary operator
-    .suggestion = use `!` to perform bitwise not
+parse_bad_return_type_notation_dotdot =
+    return type notation uses `()` instead of `(..)` for elided arguments
+    .suggestion = remove the `..`
 
-parse_unexpected_if_with_if = unexpected `if` in the condition expression
-    .suggestion = remove the `if`
+parse_bad_return_type_notation_output =
+    return type not allowed with return type notation
+    .suggestion = remove the return type
 
-parse_unexpected_token_after_not = unexpected {$negated_desc} after identifier
-parse_unexpected_token_after_not_bitwise = use `!` to perform bitwise not
-parse_unexpected_token_after_not_logical = use `!` to perform logical negation
-parse_unexpected_token_after_not_default = use `!` to perform logical negation or bitwise not
+parse_bare_cr = {$double_quotes ->
+    [true] bare CR not allowed in string, use `\r` instead
+    *[false] character constant must be escaped: `\r`
+    }
+    .escape = escape the character
 
-parse_malformed_loop_label = malformed loop label
-    .suggestion = use the correct loop label format
+parse_bare_cr_in_raw_string = bare CR not allowed in raw string
 
-parse_lifetime_in_borrow_expression = borrow expressions cannot be annotated with lifetimes
-    .suggestion = remove the lifetime annotation
-    .label = annotated with lifetime here
+parse_binary_float_literal_not_supported = binary float literal is not supported
+parse_bounds_not_allowed_on_trait_aliases = bounds are not allowed on trait aliases
 
-parse_field_expression_with_generic = field expressions cannot have generic arguments
+parse_box_not_pat = expected pattern, found {$descr}
+    .note = `box` is a reserved keyword
+    .suggestion = escape `box` to use it as an identifier
 
-parse_macro_invocation_with_qualified_path = macros cannot use qualified paths
+parse_box_syntax_removed = `box_syntax` has been removed
+    .suggestion = use `Box::new()` instead
 
-parse_unexpected_token_after_label = expected `while`, `for`, `loop` or `{"{"}` after a label
-    .suggestion_remove_label = consider removing the label
-    .suggestion_enclose_in_block = consider enclosing expression in a block
+parse_cannot_be_raw_ident = `{$ident}` cannot be a raw identifier
 
-parse_require_colon_after_labeled_expression = labeled expression must be followed by `:`
-    .note = labels are used before loops and blocks, allowing e.g., `break 'label` to them
-    .label = the label
-    .suggestion = add `:` after the label
+parse_catch_after_try = keyword `catch` cannot follow a `try` block
+    .help = try using `match` on the result of the `try` block instead
+
+parse_cfg_attr_bad_delim = wrong `cfg_attr` delimiters
+parse_colon_as_semi = statements are terminated with a semicolon
+    .suggestion = use a semicolon instead
+
+parse_comma_after_base_struct = cannot use a comma after the base struct
+    .note = the base struct must always be the last field
+    .suggestion = remove this comma
+
+parse_comparison_interpreted_as_generic =
+    `<` is interpreted as a start of generic arguments for `{$type}`, not a comparison
+    .label_args = interpreted as generic arguments
+    .label_comparison = not interpreted as comparison
+    .suggestion = try comparing the cast value
+
+parse_comparison_operators_cannot_be_chained = comparison operators cannot be chained
+    .sugg_parentheses_for_function_args = or use `(...)` if you meant to specify fn arguments
+    .sugg_split_comparison = split the comparison into two
+    .sugg_parenthesize = parenthesize the comparison
+parse_compound_assignment_expression_in_let = can't reassign to an uninitialized variable
+    .suggestion = initialize the variable
+    .help = if you meant to overwrite, remove the `let` binding
+
+parse_const_bounds_missing_tilde = const bounds must start with `~`
+    .suggestion = add `~`
+
+parse_const_generic_without_braces = expressions must be enclosed in braces to be used as const generic arguments
+    .suggestion = enclose the `const` expression in braces
+
+parse_const_global_cannot_be_mutable = const globals cannot be mutable
+    .label = cannot be mutable
+    .suggestion = you might want to declare a static instead
+
+parse_const_let_mutually_exclusive = `const` and `let` are mutually exclusive
+    .suggestion = remove `let`
+
+parse_cr_doc_comment = bare CR not allowed in {$block ->
+    [true] block doc-comment
+    *[false] doc-comment
+}
+
+parse_default_not_followed_by_item = `default` is not followed by an item
+    .label = the `default` qualifier
+    .note = only `fn`, `const`, `type`, or `impl` items may be prefixed by `default`
 
 parse_do_catch_syntax_removed = found removed `do catch` syntax
     .note = following RFC #2388, the new non-placeholder syntax is `try`
     .suggestion = replace with the new syntax
 
-parse_float_literal_requires_integer_part = float literals must have an integer part
-    .suggestion = must have an integer part
+parse_doc_comment_does_not_document_anything = found a documentation comment that doesn't document anything
+    .help = doc comments must come before what they document, if a comment was intended use `//`
+    .suggestion = missing comma here
 
-parse_invalid_int_literal_width = invalid width `{$width}` for integer literal
-    .help = valid widths are 8, 16, 32, 64 and 128
+parse_doc_comment_on_param_type = documentation comments cannot be applied to a function parameter's type
+    .label = doc comments are not allowed here
 
-parse_invalid_num_literal_base_prefix = invalid base prefix for number literal
-    .note = base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
-    .suggestion = try making the prefix lowercase
+parse_dot_dot_dot_for_remaining_fields = expected field pattern, found `{$token_str}`
+    .suggestion = to omit remaining fields, use `..`
 
-parse_invalid_num_literal_suffix = invalid suffix `{$suffix}` for number literal
-    .label = invalid suffix `{$suffix}`
-    .help = the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+parse_dot_dot_dot_range_to_pattern_not_allowed = range-to patterns with `...` are not allowed
+    .suggestion = use `..=` instead
 
-parse_invalid_float_literal_width = invalid width `{$width}` for float literal
-    .help = valid widths are 32 and 64
+parse_dotdotdot = unexpected token: `...`
+    .suggest_exclusive_range = use `..` for an exclusive range
+    .suggest_inclusive_range = or `..=` for an inclusive range
 
-parse_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float literal
-    .label = invalid suffix `{$suffix}`
-    .help = valid suffixes are `f32` and `f64`
+parse_dotdotdot_rest_pattern = unexpected `...`
+    .label = not a valid pattern
+    .suggestion = for a rest pattern, use `..` instead of `...`
 
-parse_int_literal_too_large = integer literal is too large
+parse_double_colon_in_bound = expected `:` followed by trait or lifetime
+    .suggestion = use single colon
 
-parse_missing_semicolon_before_array = expected `;`, found `[`
-    .suggestion = consider adding `;` here
+parse_dyn_after_mut = `mut` must precede `dyn`
+    .suggestion = place `mut` before `dyn`
 
-parse_invalid_block_macro_segment = cannot use a `block` macro fragment here
-    .label = the `block` fragment is within this context
+parse_empty_exponent_float = expected at least one digit in exponent
 
-parse_expect_dotdot_not_dotdotdot = expected `..`, found `...`
-    .suggestion = use `..` to fill in the rest of the fields
+parse_empty_unicode_escape = empty unicode escape
+    .label = this escape must have at least 1 hex digit
 
-parse_if_expression_missing_then_block = this `if` expression is missing a block after the condition
-    .add_then_block = add a block here
-    .condition_possibly_unfinished = this binary operation is possibly unfinished
+parse_enum_pattern_instead_of_identifier = expected identifier, found enum pattern
 
-parse_if_expression_missing_condition = missing condition for `if` expression
-    .condition_label = expected condition here
-    .block_label = if this block is the condition of the `if` expression, then it must be followed by another block
+parse_enum_struct_mutually_exclusive = `enum` and `struct` are mutually exclusive
+    .suggestion = replace `enum struct` with
 
-parse_expected_expression_found_let = expected expression, found `let` statement
+parse_eq_field_init = expected `:`, found `=`
+    .suggestion = replace equals symbol with a colon
+
+parse_equals_struct_default = default values on `struct` fields aren't supported
+    .suggestion = remove this unsupported default value
+
+parse_escape_only_char = {$byte ->
+    [true] byte
+    *[false] character
+    } constant must be escaped: `{$escaped_msg}`
+    .escape = escape the character
+
+parse_expect_dotdot_not_dotdotdot = expected `..`, found `...`
+    .suggestion = use `..` to fill in the rest of the fields
 
 parse_expect_eq_instead_of_eqeq = expected `=`, found `==`
     .suggestion = consider using `=` here
 
+parse_expect_label_found_ident = expected a label, found an identifier
+    .suggestion = labels start with a tick
+
+parse_expect_path = expected a path
+
+parse_expected_binding_left_of_at = left-hand side of `@` must be a binding
+    .label_lhs = interpreted as a pattern, not a binding
+    .label_rhs = also a pattern
+    .note = bindings are `x`, `mut x`, `ref x`, and `ref mut x`
+
+parse_expected_builtin_ident = expected identifier after `builtin #`
+
+parse_expected_comma_after_pattern_field = expected `,`
+
 parse_expected_else_block = expected `{"{"}`, found {$first_tok}
     .label = expected an `if` or a block after this `else`
     .suggestion = add an `if` if this is the condition of a chained `else if` statement
 
-parse_outer_attribute_not_allowed_on_if_else = outer attributes are not allowed on `if` and `else` branches
-    .branch_label = the attributes are attached to this branch
-    .ctx_label = the branch belongs to this `{$ctx}`
-    .suggestion = remove the attributes
+parse_expected_expression_found_let = expected expression, found `let` statement
 
-parse_missing_in_in_for_loop = missing `in` in `for` loop
-    .use_in_not_of = try using `in` here instead
-    .add_in = try adding `in` here
+parse_expected_fn_path_found_fn_keyword = expected identifier, found keyword `fn`
+    .suggestion = use `Fn` to refer to the trait
 
-parse_missing_expression_in_for_loop = missing expression to iterate on in `for` loop
-    .suggestion = try adding an expression to the `for` loop
+parse_expected_identifier = expected identifier
 
-parse_loop_else = `{$loop_kind}...else` loops are not supported
-    .note = consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
-    .loop_keyword = `else` is attached to this loop
+parse_expected_identifier_found_doc_comment = expected identifier, found doc comment
+parse_expected_identifier_found_doc_comment_str = expected identifier, found doc comment `{$token}`
+parse_expected_identifier_found_keyword = expected identifier, found keyword
+parse_expected_identifier_found_keyword_str = expected identifier, found keyword `{$token}`
+parse_expected_identifier_found_reserved_identifier = expected identifier, found reserved identifier
+parse_expected_identifier_found_reserved_identifier_str = expected identifier, found reserved identifier `{$token}`
+parse_expected_identifier_found_reserved_keyword = expected identifier, found reserved keyword
+parse_expected_identifier_found_reserved_keyword_str = expected identifier, found reserved keyword `{$token}`
+parse_expected_identifier_found_str = expected identifier, found `{$token}`
 
-parse_missing_comma_after_match_arm = expected `,` following `match` arm
-    .suggestion = missing a comma here to end this `match` arm
+parse_expected_mut_or_const_in_raw_pointer_type = expected `mut` or `const` keyword in raw pointer type
+    .suggestion = add `mut` or `const` here
 
-parse_catch_after_try = keyword `catch` cannot follow a `try` block
-    .help = try using `match` on the result of the `try` block instead
+parse_expected_semi_found_doc_comment_str = expected `;`, found doc comment `{$token}`
+parse_expected_semi_found_keyword_str = expected `;`, found keyword `{$token}`
+parse_expected_semi_found_reserved_identifier_str = expected `;`, found reserved identifier `{$token}`
+parse_expected_semi_found_reserved_keyword_str = expected `;`, found reserved keyword `{$token}`
+parse_expected_semi_found_str = expected `;`, found `{$token}`
 
-parse_comma_after_base_struct = cannot use a comma after the base struct
-    .note = the base struct must always be the last field
-    .suggestion = remove this comma
+parse_expected_statement_after_outer_attr = expected statement after outer attribute
 
-parse_eq_field_init = expected `:`, found `=`
-    .suggestion = replace equals symbol with a colon
+parse_expected_trait_in_trait_impl_found_type = expected a trait, found type
 
-parse_dotdotdot = unexpected token: `...`
-    .suggest_exclusive_range = use `..` for an exclusive range
-    .suggest_inclusive_range = or `..=` for an inclusive range
+parse_extern_crate_name_with_dashes = crate name using dashes are not valid in `extern crate` statements
+    .label = dash-separated idents are not valid
+    .suggestion = if the original crate name uses dashes you need to use underscores in the code
 
-parse_left_arrow_operator = unexpected token: `<-`
-    .suggestion = if you meant to write a comparison against a negative value, add a space in between `<` and `-`
+parse_extern_item_cannot_be_const = extern items cannot be `const`
+    .suggestion = try using a static value
+    .note = for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
 
-parse_remove_let = expected pattern, found `let`
-    .suggestion = remove the unnecessary `let` keyword
+parse_extra_if_in_let_else = remove the `if` if you meant to write a `let...else` statement
 
-parse_use_eq_instead = unexpected `==`
-    .suggestion = try using `=` instead
+parse_extra_impl_keyword_in_trait_impl = unexpected `impl` keyword
+    .suggestion = remove the extra `impl`
+    .note = this is parsed as an `impl Trait` type, but a trait is expected at this position
 
-parse_use_empty_block_not_semi = expected { "`{}`" }, found `;`
-    .suggestion = try using { "`{}`" } instead
 
-parse_comparison_interpreted_as_generic =
-    `<` is interpreted as a start of generic arguments for `{$type}`, not a comparison
-    .label_args = interpreted as generic arguments
-    .label_comparison = not interpreted as comparison
-    .suggestion = try comparing the cast value
+parse_field_expression_with_generic = field expressions cannot have generic arguments
 
-parse_shift_interpreted_as_generic =
-    `<<` is interpreted as a start of generic arguments for `{$type}`, not a shift
-    .label_args = interpreted as generic arguments
-    .label_comparison = not interpreted as shift
-    .suggestion = try shifting the cast value
+parse_float_literal_requires_integer_part = float literals must have an integer part
+    .suggestion = must have an integer part
+
+parse_float_literal_unsupported_base = {$base} float literal is not supported
+
+parse_fn_pointer_cannot_be_async = an `fn` pointer type cannot be `async`
+    .label = `async` because of this
+    .suggestion = remove the `async` qualifier
+
+parse_fn_pointer_cannot_be_const = an `fn` pointer type cannot be `const`
+    .label = `const` because of this
+    .suggestion = remove the `const` qualifier
+
+parse_fn_ptr_with_generics = function pointer types may not have generic parameters
+    .suggestion = consider moving the lifetime {$arity ->
+        [one] parameter
+        *[other] parameters
+    } to {$for_param_list_exists ->
+        [true] the
+        *[false] a
+    } `for` parameter list
+
+parse_forgot_paren = perhaps you forgot parentheses?
 
 parse_found_expr_would_be_stmt = expected expression, found `{$token}`
     .label = expected expression
 
-parse_leading_plus_not_supported = leading `+` is not supported
-    .label = unexpected `+`
-    .suggestion_remove_plus = try removing the `+`
+parse_function_body_equals_expr = function body cannot be `= expression;`
+    .suggestion = surround the expression with `{"{"}` and `{"}"}` instead of `=` and `;`
 
-parse_parentheses_with_struct_fields = invalid `struct` delimiters or `fn` call arguments
-    .suggestion_braces_for_struct = if `{$type}` is a struct, use braces as delimiters
-    .suggestion_no_fields_for_fn = if `{$type}` is a function, use the arguments directly
+parse_generic_parameters_without_angle_brackets = generic parameters without surrounding angle brackets
+    .suggestion = surround the type parameters with angle brackets
 
-parse_labeled_loop_in_break = parentheses are required around this expression to avoid confusion with a labeled break expression
+parse_generics_in_path = unexpected generic arguments in path
 
-parse_sugg_wrap_expression_in_parentheses = wrap the expression in parentheses
+parse_help_set_edition_cargo = set `edition = "{$edition}"` in `Cargo.toml`
+parse_help_set_edition_standalone = pass `--edition {$edition}` to `rustc`
+parse_hexadecimal_float_literal_not_supported = hexadecimal float literal is not supported
+parse_if_expression_missing_condition = missing condition for `if` expression
+    .condition_label = expected condition here
+    .block_label = if this block is the condition of the `if` expression, then it must be followed by another block
 
-parse_array_brackets_instead_of_braces = this is a block expression, not an array
-    .suggestion = to make an array, use square brackets instead of curly braces
+parse_if_expression_missing_then_block = this `if` expression is missing a block after the condition
+    .add_then_block = add a block here
+    .condition_possibly_unfinished = this binary operation is possibly unfinished
 
-parse_match_arm_body_without_braces = `match` arm body without braces
-    .label_statements = {$num_statements ->
-            [one] this statement is not surrounded by a body
-           *[other] these statements are not surrounded by a body
-        }
-    .label_arrow = while parsing the `match` arm starting here
-    .suggestion_add_braces = surround the {$num_statements ->
-            [one] statement
-           *[other] statements
-        } with a body
-    .suggestion_use_comma_not_semicolon = replace `;` with `,` to end a `match` arm expression
+parse_in_in_typo =
+    expected iterable, found keyword `in`
+    .suggestion = remove the duplicated `in`
+
+parse_inappropriate_default = {$article} {$descr} cannot be `default`
+    .label = `default` because of this
+    .note = only associated `fn`, `const`, and `type` items can be `default`
 
 parse_inclusive_range_extra_equals = unexpected `=` after inclusive range
     .suggestion_remove_eq = use `..=` instead
@@ -238,36 +306,18 @@ parse_inclusive_range_no_end = inclusive range with no end
     .suggestion_open_range = use `..` instead
     .note = inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
-parse_struct_literal_not_allowed_here = struct literals are not allowed here
-    .suggestion = surround the struct literal with parentheses
-
-parse_invalid_interpolated_expression = invalid interpolated expression
-
-parse_hexadecimal_float_literal_not_supported = hexadecimal float literal is not supported
-parse_octal_float_literal_not_supported = octal float literal is not supported
-parse_binary_float_literal_not_supported = binary float literal is not supported
-parse_not_supported = not supported
-
-parse_invalid_literal_suffix = suffixes on {$kind} literals are invalid
-    .label = invalid suffix `{$suffix}`
-
-parse_invalid_literal_suffix_on_tuple_index = suffixes on a tuple index are invalid
-    .label = invalid suffix `{$suffix}`
-    .tuple_exception_line_1 = `{$suffix}` is *temporarily* accepted on tuple index fields as it was incorrectly accepted on stable for a few releases
-    .tuple_exception_line_2 = on proc macros, you'll want to use `syn::Index::from` or `proc_macro::Literal::*_unsuffixed` for code that will desugar to tuple field access
-    .tuple_exception_line_3 = see issue #60210 <https://github.com/rust-lang/rust/issues/60210> for more information
-
-parse_expected_builtin_ident = expected identifier after `builtin #`
-
-parse_unknown_builtin_construct = unknown `builtin #` construct `{$name}`
+parse_incorrect_braces_trait_bounds = incorrect braces around trait bounds
+    .suggestion = remove the parentheses
 
-parse_non_string_abi_literal = non-string ABI literal
-    .suggestion = specify the ABI with a string literal
+parse_incorrect_semicolon =
+    expected item, found `;`
+    .suggestion = remove this semicolon
+    .help = {$name} declarations are not followed by a semicolon
 
-parse_mismatched_closing_delimiter = mismatched closing delimiter: `{$delimiter}`
-    .label_unmatched = mismatched closing delimiter
-    .label_opening_candidate = closing delimiter possibly meant for this
-    .label_unclosed = unclosed delimiter
+parse_incorrect_use_of_await =
+    incorrect use of `await`
+    .parentheses_suggestion = `await` is not a method call, remove the parentheses
+    .postfix_suggestion = `await` is a postfix operation
 
 parse_incorrect_visibility_restriction = incorrect visibility restriction
     .help = some possible visibility restrictions are:
@@ -276,36 +326,8 @@ parse_incorrect_visibility_restriction = incorrect visibility restriction
             `pub(in path::to::module)`: visible only on the specified path
     .suggestion = make this visible only to module `{$inner_str}` with `in`
 
-parse_assignment_else_not_allowed = <assignment> ... else {"{"} ... {"}"} is not allowed
-
-parse_expected_statement_after_outer_attr = expected statement after outer attribute
-
-parse_doc_comment_does_not_document_anything = found a documentation comment that doesn't document anything
-    .help = doc comments must come before what they document, if a comment was intended use `//`
-    .suggestion = missing comma here
-
-parse_const_let_mutually_exclusive = `const` and `let` are mutually exclusive
-    .suggestion = remove `let`
-
-parse_invalid_expression_in_let_else = a `{$operator}` expression cannot be directly assigned in `let...else`
-parse_invalid_curly_in_let_else = right curly brace `{"}"}` before `else` in a `let...else` statement not allowed
-parse_extra_if_in_let_else = remove the `if` if you meant to write a `let...else` statement
-
-parse_compound_assignment_expression_in_let = can't reassign to an uninitialized variable
-    .suggestion = initialize the variable
-    .help = if you meant to overwrite, remove the `let` binding
-
-parse_suffixed_literal_in_attribute = suffixed literals are not allowed in attributes
-    .help = instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
-
-parse_invalid_meta_item = expected unsuffixed literal or identifier, found `{$token}`
-
-parse_label_inner_attr_does_not_annotate_this = the inner attribute doesn't annotate this {$item}
-parse_sugg_change_inner_attr_to_outer = to annotate the {$item}, change the attribute from inner to outer style
-
-parse_inner_attr_not_permitted_after_outer_doc_comment = an inner attribute is not permitted following an outer doc comment
-    .label_attr = not permitted following an outer doc comment
-    .label_prev_doc_comment = previous doc comment
+parse_inner_attr_explanation = inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+parse_inner_attr_not_permitted = an inner attribute is not permitted in this context
     .label_does_not_annotate_this = {parse_label_inner_attr_does_not_annotate_this}
     .sugg_change_inner_to_outer = {parse_sugg_change_inner_attr_to_outer}
 
@@ -315,149 +337,189 @@ parse_inner_attr_not_permitted_after_outer_attr = an inner attribute is not perm
     .label_does_not_annotate_this = {parse_label_inner_attr_does_not_annotate_this}
     .sugg_change_inner_to_outer = {parse_sugg_change_inner_attr_to_outer}
 
-parse_inner_attr_not_permitted = an inner attribute is not permitted in this context
+parse_inner_attr_not_permitted_after_outer_doc_comment = an inner attribute is not permitted following an outer doc comment
+    .label_attr = not permitted following an outer doc comment
+    .label_prev_doc_comment = previous doc comment
     .label_does_not_annotate_this = {parse_label_inner_attr_does_not_annotate_this}
     .sugg_change_inner_to_outer = {parse_sugg_change_inner_attr_to_outer}
 
-parse_inner_attr_explanation = inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
-parse_outer_attr_explanation = outer attributes, like `#[test]`, annotate the item following them
-
 parse_inner_doc_comment_not_permitted = expected outer doc comment
     .note = inner doc comments like this (starting with `//!` or `/*!`) can only appear before items
     .suggestion = you might have meant to write a regular comment
     .label_does_not_annotate_this = the inner doc comment doesn't annotate this {$item}
     .sugg_change_inner_to_outer = to annotate the {$item}, change the doc comment from inner to outer style
 
-parse_expected_identifier_found_reserved_identifier_str = expected identifier, found reserved identifier `{$token}`
-parse_expected_identifier_found_keyword_str = expected identifier, found keyword `{$token}`
-parse_expected_identifier_found_reserved_keyword_str = expected identifier, found reserved keyword `{$token}`
-parse_expected_identifier_found_doc_comment_str = expected identifier, found doc comment `{$token}`
-parse_expected_identifier_found_str = expected identifier, found `{$token}`
+parse_int_literal_too_large = integer literal is too large
 
-parse_expected_identifier_found_reserved_identifier = expected identifier, found reserved identifier
-parse_expected_identifier_found_keyword = expected identifier, found keyword
-parse_expected_identifier_found_reserved_keyword = expected identifier, found reserved keyword
-parse_expected_identifier_found_doc_comment = expected identifier, found doc comment
-parse_expected_identifier = expected identifier
+parse_invalid_block_macro_segment = cannot use a `block` macro fragment here
+    .label = the `block` fragment is within this context
 
-parse_sugg_escape_identifier = escape `{$ident_name}` to use it as an identifier
+parse_invalid_char_in_escape = {parse_invalid_char_in_escape_msg}: `{$ch}`
+    .label = {parse_invalid_char_in_escape_msg}
 
-parse_sugg_remove_comma = remove this comma
-parse_sugg_add_let_for_stmt = you might have meant to introduce a new binding
+parse_invalid_char_in_escape_msg = invalid character in {$is_hex ->
+    [true] numeric character
+    *[false] unicode
+    } escape
 
-parse_expected_semi_found_reserved_identifier_str = expected `;`, found reserved identifier `{$token}`
-parse_expected_semi_found_keyword_str = expected `;`, found keyword `{$token}`
-parse_expected_semi_found_reserved_keyword_str = expected `;`, found reserved keyword `{$token}`
-parse_expected_semi_found_doc_comment_str = expected `;`, found doc comment `{$token}`
-parse_expected_semi_found_str = expected `;`, found `{$token}`
+parse_invalid_comparison_operator = invalid comparison operator `{$invalid}`
+    .use_instead = `{$invalid}` is not a valid comparison operator, use `{$correct}`
+    .spaceship_operator_invalid = `<=>` is not a valid comparison operator, use `std::cmp::Ordering`
 
-parse_sugg_change_this_to_semi = change this to `;`
-parse_sugg_add_semi = add `;` here
-parse_label_unexpected_token = unexpected token
+parse_invalid_curly_in_let_else = right curly brace `{"}"}` before `else` in a `let...else` statement not allowed
+parse_invalid_digit_literal = invalid digit for a base {$base} literal
 
-parse_unmatched_angle_brackets = {$num_extra_brackets ->
-        [one] unmatched angle bracket
-       *[other] unmatched angle brackets
+parse_invalid_dyn_keyword = invalid `dyn` keyword
+    .help = `dyn` is only needed at the start of a trait `+`-separated list
+    .suggestion = remove this keyword
+
+parse_invalid_expression_in_let_else = a `{$operator}` expression cannot be directly assigned in `let...else`
+parse_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float literal
+    .label = invalid suffix `{$suffix}`
+    .help = valid suffixes are `f32` and `f64`
+
+parse_invalid_float_literal_width = invalid width `{$width}` for float literal
+    .help = valid widths are 32 and 64
+
+parse_invalid_identifier_with_leading_number = identifiers cannot start with a number
+
+parse_invalid_int_literal_width = invalid width `{$width}` for integer literal
+    .help = valid widths are 8, 16, 32, 64 and 128
+
+parse_invalid_interpolated_expression = invalid interpolated expression
+
+parse_invalid_literal_suffix = suffixes on {$kind} literals are invalid
+    .label = invalid suffix `{$suffix}`
+
+parse_invalid_literal_suffix_on_tuple_index = suffixes on a tuple index are invalid
+    .label = invalid suffix `{$suffix}`
+    .tuple_exception_line_1 = `{$suffix}` is *temporarily* accepted on tuple index fields as it was incorrectly accepted on stable for a few releases
+    .tuple_exception_line_2 = on proc macros, you'll want to use `syn::Index::from` or `proc_macro::Literal::*_unsuffixed` for code that will desugar to tuple field access
+    .tuple_exception_line_3 = see issue #60210 <https://github.com/rust-lang/rust/issues/60210> for more information
+
+parse_invalid_logical_operator = `{$incorrect}` is not a logical operator
+    .note = unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators
+    .use_amp_amp_for_conjunction = use `&&` to perform logical conjunction
+    .use_pipe_pipe_for_disjunction = use `||` to perform logical disjunction
+
+parse_invalid_meta_item = expected unsuffixed literal or identifier, found `{$token}`
+
+parse_invalid_num_literal_base_prefix = invalid base prefix for number literal
+    .note = base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+    .suggestion = try making the prefix lowercase
+
+parse_invalid_num_literal_suffix = invalid suffix `{$suffix}` for number literal
+    .label = invalid suffix `{$suffix}`
+    .help = the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+parse_invalid_unicode_escape = invalid unicode character escape
+    .label = invalid escape
+    .help = unicode escape must {$surrogate ->
+    [true] not be a surrogate
+    *[false] be at most 10FFFF
     }
-    .suggestion = {$num_extra_brackets ->
-            [one] remove extra angle bracket
-           *[other] remove extra angle brackets
-        }
 
-parse_generic_parameters_without_angle_brackets = generic parameters without surrounding angle brackets
-    .suggestion = surround the type parameters with angle brackets
+parse_invalid_variable_declaration =
+    invalid variable declaration
 
-parse_comparison_operators_cannot_be_chained = comparison operators cannot be chained
-    .sugg_parentheses_for_function_args = or use `(...)` if you meant to specify fn arguments
-    .sugg_split_comparison = split the comparison into two
-    .sugg_parenthesize = parenthesize the comparison
-parse_sugg_turbofish_syntax = use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
+parse_kw_bad_case = keyword `{$kw}` is written in the wrong case
+    .suggestion = write it in the correct case
 
-parse_question_mark_in_type = invalid `?` in type
-    .label = `?` is only allowed on expressions, not types
-    .suggestion = if you meant to express that the type might not contain a value, use the `Option` wrapper type
+parse_label_inner_attr_does_not_annotate_this = the inner attribute doesn't annotate this {$item}
+parse_label_unexpected_token = unexpected token
 
-parse_unexpected_parentheses_in_for_head = unexpected parentheses surrounding `for` loop head
-    .suggestion = remove parentheses in `for` loop
+parse_label_while_parsing_or_pattern_here = while parsing this or-pattern starting here
 
-parse_doc_comment_on_param_type = documentation comments cannot be applied to a function parameter's type
-    .label = doc comments are not allowed here
+parse_labeled_loop_in_break = parentheses are required around this expression to avoid confusion with a labeled break expression
 
-parse_attribute_on_param_type = attributes cannot be applied to a function parameter's type
-    .label = attributes are not allowed here
+parse_leading_plus_not_supported = leading `+` is not supported
+    .label = unexpected `+`
+    .suggestion_remove_plus = try removing the `+`
 
-parse_pattern_method_param_without_body = patterns aren't allowed in methods without bodies
-    .suggestion = give this argument a name or use an underscore to ignore it
+parse_leading_underscore_unicode_escape = {parse_leading_underscore_unicode_escape_label}: `_`
+parse_leading_underscore_unicode_escape_label = invalid start of unicode escape
 
-parse_self_param_not_first = unexpected `self` parameter in function
-    .label = must be the first parameter of an associated function
+parse_left_arrow_operator = unexpected token: `<-`
+    .suggestion = if you meant to write a comparison against a negative value, add a space in between `<` and `-`
 
-parse_const_generic_without_braces = expressions must be enclosed in braces to be used as const generic arguments
-    .suggestion = enclose the `const` expression in braces
+parse_lifetime_after_mut = lifetime must precede `mut`
+    .suggestion = place the lifetime before `mut`
 
-parse_unexpected_const_param_declaration = unexpected `const` parameter declaration
-    .label = expected a `const` expression, not a parameter declaration
-    .suggestion = `const` parameters must be declared for the `impl`
+parse_lifetime_in_borrow_expression = borrow expressions cannot be annotated with lifetimes
+    .suggestion = remove the lifetime annotation
+    .label = annotated with lifetime here
 
-parse_unexpected_const_in_generic_param = expected lifetime, type, or constant, found keyword `const`
-    .suggestion = the `const` keyword is only needed in the definition of the type
+parse_lone_slash = invalid trailing slash in literal
+    .label = {parse_lone_slash}
 
-parse_async_move_order_incorrect = the order of `move` and `async` is incorrect
-    .suggestion = try switching the order
+parse_loop_else = `{$loop_kind}...else` loops are not supported
+    .note = consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
+    .loop_keyword = `else` is attached to this loop
 
-parse_double_colon_in_bound = expected `:` followed by trait or lifetime
-    .suggestion = use single colon
+parse_macro_invocation_visibility = can't qualify macro invocation with `pub`
+    .suggestion = remove the visibility
+    .help = try adjusting the macro to put `{$vis}` inside the invocation
 
-parse_fn_ptr_with_generics = function pointer types may not have generic parameters
-    .suggestion = consider moving the lifetime {$arity ->
-        [one] parameter
-        *[other] parameters
-    } to {$for_param_list_exists ->
-        [true] the
-        *[false] a
-    } `for` parameter list
+parse_macro_invocation_with_qualified_path = macros cannot use qualified paths
 
-parse_invalid_identifier_with_leading_number = identifiers cannot start with a number
+parse_macro_name_remove_bang = macro names aren't followed by a `!`
+    .suggestion = remove the `!`
 
-parse_maybe_fn_typo_with_impl = you might have meant to write `impl` instead of `fn`
-    .suggestion = replace `fn` with `impl` here
+parse_macro_rules_missing_bang = expected `!` after `macro_rules`
+    .suggestion = add a `!`
 
-parse_expected_fn_path_found_fn_keyword = expected identifier, found keyword `fn`
-    .suggestion = use `Fn` to refer to the trait
+parse_macro_rules_visibility = can't qualify macro_rules invocation with `{$vis}`
+    .suggestion = try exporting the macro
 
-parse_path_single_colon = path separator must be a double colon
-    .suggestion = use a double colon instead
+parse_malformed_cfg_attr = malformed `cfg_attr` attribute input
+    .suggestion = missing condition and attribute
+    .note = for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
 
-parse_colon_as_semi = statements are terminated with a semicolon
-    .suggestion = use a semicolon instead
+parse_malformed_loop_label = malformed loop label
+    .suggestion = use the correct loop label format
 
-parse_type_ascription_removed =
-    if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
+parse_match_arm_body_without_braces = `match` arm body without braces
+    .label_statements = {$num_statements ->
+            [one] this statement is not surrounded by a body
+           *[other] these statements are not surrounded by a body
+        }
+    .label_arrow = while parsing the `match` arm starting here
+    .suggestion_add_braces = surround the {$num_statements ->
+            [one] statement
+           *[other] statements
+        } with a body
+    .suggestion_use_comma_not_semicolon = replace `;` with `,` to end a `match` arm expression
 
-parse_where_clause_before_tuple_struct_body = where clauses are not allowed before tuple struct bodies
-    .label = unexpected where clause
-    .name_label = while parsing this tuple struct
-    .body_label = the struct body
-    .suggestion = move the body before the where clause
+parse_maybe_fn_typo_with_impl = you might have meant to write `impl` instead of `fn`
+    .suggestion = replace `fn` with `impl` here
 
-parse_async_fn_in_2015 = `async fn` is not permitted in Rust 2015
-    .label = to use `async fn`, switch to Rust 2018 or later
+parse_maybe_recover_from_bad_qpath_stage_2 =
+    missing angle brackets in associated item path
+    .suggestion = try: `{$ty}`
 
-parse_async_block_in_2015 = `async` blocks are only allowed in Rust 2018 or later
+parse_maybe_recover_from_bad_type_plus =
+    expected a path on the left-hand side of `+`, not `{$ty}`
 
-parse_self_argument_pointer = cannot pass `self` by raw pointer
-    .label = cannot pass `self` by raw pointer
+parse_maybe_report_ambiguous_plus =
+    ambiguous `+` in a type
+    .suggestion = use parentheses to disambiguate
 
-parse_visibility_not_followed_by_item = visibility `{$vis}` is not followed by an item
-    .label = the visibility
-    .help = you likely meant to define an item, e.g., `{$vis} fn foo() {"{}"}`
+parse_meta_bad_delim = wrong meta list delimiters
+parse_meta_bad_delim_suggestion = the delimiters should be `(` and `)`
 
-parse_default_not_followed_by_item = `default` is not followed by an item
-    .label = the `default` qualifier
-    .note = only `fn`, `const`, `type`, or `impl` items may be prefixed by `default`
+parse_mismatched_closing_delimiter = mismatched closing delimiter: `{$delimiter}`
+    .label_unmatched = mismatched closing delimiter
+    .label_opening_candidate = closing delimiter possibly meant for this
+    .label_unclosed = unclosed delimiter
 
-parse_missing_struct_for_struct_definition = missing `struct` for struct definition
-    .suggestion = add `struct` here to parse `{$ident}` as a public struct
+parse_missing_comma_after_match_arm = expected `,` following `match` arm
+    .suggestion = missing a comma here to end this `match` arm
+
+parse_missing_const_type = missing type for `{$kind}` item
+    .suggestion = provide a type for the item
+
+parse_missing_expression_in_for_loop = missing expression to iterate on in `for` loop
+    .suggestion = try adding an expression to the `for` loop
 
 parse_missing_fn_for_function_definition = missing `fn` for function definition
     .suggestion = add `fn` here to parse `{$ident}` as a public function
@@ -465,267 +527,275 @@ parse_missing_fn_for_function_definition = missing `fn` for function definition
 parse_missing_fn_for_method_definition = missing `fn` for method definition
     .suggestion = add `fn` here to parse `{$ident}` as a public method
 
-parse_ambiguous_missing_keyword_for_item_definition = missing `fn` or `struct` for function or struct definition
-    .suggestion = if you meant to call a macro, try
-    .help = if you meant to call a macro, remove the `pub` and add a trailing `!` after the identifier
-
-parse_missing_trait_in_trait_impl = missing trait in a trait impl
-    .suggestion_add_trait = add a trait here
-    .suggestion_remove_for = for an inherent impl, drop this `for`
-
 parse_missing_for_in_trait_impl = missing `for` in a trait impl
     .suggestion = add `for` here
 
-parse_expected_trait_in_trait_impl_found_type = expected a trait, found type
+parse_missing_in_in_for_loop = missing `in` in `for` loop
+    .use_in_not_of = try using `in` here instead
+    .add_in = try adding `in` here
 
-parse_extra_impl_keyword_in_trait_impl = unexpected `impl` keyword
-    .suggestion = remove the extra `impl`
-    .note = this is parsed as an `impl Trait` type, but a trait is expected at this position
+parse_missing_let_before_mut = missing keyword
+parse_missing_plus_in_bounds = expected `+` between lifetime and {$sym}
+    .suggestion = add `+`
 
+parse_missing_semicolon_before_array = expected `;`, found `[`
+    .suggestion = consider adding `;` here
 
-parse_non_item_in_item_list = non-item in item list
-    .suggestion_use_const_not_let = consider using `const` instead of `let` for associated const
-    .label_list_start = item list starts here
-    .label_non_item = non-item starts here
-    .label_list_end = item list ends here
-    .suggestion_remove_semicolon = consider removing this semicolon
+parse_missing_struct_for_struct_definition = missing `struct` for struct definition
+    .suggestion = add `struct` here to parse `{$ident}` as a public struct
 
-parse_bounds_not_allowed_on_trait_aliases = bounds are not allowed on trait aliases
+parse_missing_trait_in_trait_impl = missing trait in a trait impl
+    .suggestion_add_trait = add a trait here
+    .suggestion_remove_for = for an inherent impl, drop this `for`
 
-parse_trait_alias_cannot_be_auto = trait aliases cannot be `auto`
-parse_trait_alias_cannot_be_unsafe = trait aliases cannot be `unsafe`
+parse_modifier_lifetime = `{$sigil}` may only modify trait bounds, not lifetime bounds
+    .suggestion = remove the `{$sigil}`
 
-parse_associated_static_item_not_allowed = associated `static` items are not allowed
+parse_more_than_one_char = character literal may only contain one codepoint
+    .followed_by = this `{$chr}` is followed by the combining {$len ->
+        [one] mark
+        *[other] marks
+        } `{$escaped_marks}`
+    .non_printing = there are non-printing characters, the full sequence is `{$escaped}`
+    .consider_normalized = consider using the normalized form `{$ch}` of this character
+    .remove_non = consider removing the non-printing characters
+    .use_double_quotes = if you meant to write a {$is_byte ->
+        [true] byte string
+        *[false] `str`
+        } literal, use double quotes
 
-parse_extern_crate_name_with_dashes = crate name using dashes are not valid in `extern crate` statements
-    .label = dash-separated idents are not valid
-    .suggestion = if the original crate name uses dashes you need to use underscores in the code
+parse_multiple_skipped_lines = multiple lines skipped by escaped newline
+    .label = skipping everything up to and including this point
 
-parse_extern_item_cannot_be_const = extern items cannot be `const`
-    .suggestion = try using a static value
-    .note = for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
+parse_multiple_where_clauses = cannot define duplicate `where` clauses on an item
+    .label = previous `where` clause starts here
+    .suggestion = consider joining the two `where` clauses into one
 
-parse_const_global_cannot_be_mutable = const globals cannot be mutable
-    .label = cannot be mutable
-    .suggestion = you might want to declare a static instead
+parse_mut_on_nested_ident_pattern = `mut` must be attached to each individual binding
+    .suggestion = add `mut` to each binding
+parse_mut_on_non_ident_pattern = `mut` must be followed by a named binding
+    .suggestion = remove the `mut` prefix
+parse_need_plus_after_trait_object_lifetime = lifetime in trait object type must be followed by `+`
 
-parse_missing_const_type = missing type for `{$kind}` item
-    .suggestion = provide a type for the item
+parse_nested_adt = `{$kw_str}` definition cannot be nested inside `{$keyword}`
+    .suggestion = consider creating a new `{$kw_str}` definition instead of nesting
 
-parse_enum_struct_mutually_exclusive = `enum` and `struct` are mutually exclusive
-    .suggestion = replace `enum struct` with
+parse_nested_c_variadic_type = C-variadic type `...` may not be nested inside another type
 
-parse_unexpected_token_after_struct_name = expected `where`, `{"{"}`, `(`, or `;` after struct name
-parse_unexpected_token_after_struct_name_found_reserved_identifier = expected `where`, `{"{"}`, `(`, or `;` after struct name, found reserved identifier `{$token}`
-parse_unexpected_token_after_struct_name_found_keyword = expected `where`, `{"{"}`, `(`, or `;` after struct name, found keyword `{$token}`
-parse_unexpected_token_after_struct_name_found_reserved_keyword = expected `where`, `{"{"}`, `(`, or `;` after struct name, found reserved keyword `{$token}`
-parse_unexpected_token_after_struct_name_found_doc_comment = expected `where`, `{"{"}`, `(`, or `;` after struct name, found doc comment `{$token}`
-parse_unexpected_token_after_struct_name_found_other = expected `where`, `{"{"}`, `(`, or `;` after struct name, found `{$token}`
+parse_no_brace_unicode_escape = incorrect unicode escape sequence
+    .label = {parse_no_brace_unicode_escape}
+    .use_braces = format of unicode escape sequences uses braces
+    .format_of_unicode = format of unicode escape sequences is `\u{"{...}"}`
 
-parse_unexpected_self_in_generic_parameters = unexpected keyword `Self` in generic parameters
-    .note = you cannot use `Self` as a generic parameter because it is reserved for associated items
+parse_no_digits_literal = no valid digits found for number
 
-parse_unexpected_default_value_for_lifetime_in_generic_parameters = unexpected default lifetime parameter
-    .label = lifetime parameters cannot have default values
+parse_non_item_in_item_list = non-item in item list
+    .suggestion_use_const_not_let = consider using `const` instead of `let` for associated const
+    .label_list_start = item list starts here
+    .label_non_item = non-item starts here
+    .label_list_end = item list ends here
+    .suggestion_remove_semicolon = consider removing this semicolon
 
-parse_multiple_where_clauses = cannot define duplicate `where` clauses on an item
-    .label = previous `where` clause starts here
-    .suggestion = consider joining the two `where` clauses into one
+parse_non_string_abi_literal = non-string ABI literal
+    .suggestion = specify the ABI with a string literal
 
-parse_nonterminal_expected_item_keyword = expected an item keyword
-parse_nonterminal_expected_statement = expected a statement
 parse_nonterminal_expected_ident = expected ident, found `{$token}`
+parse_nonterminal_expected_item_keyword = expected an item keyword
 parse_nonterminal_expected_lifetime = expected a lifetime, found `{$token}`
 
-parse_or_pattern_not_allowed_in_let_binding = top-level or-patterns are not allowed in `let` bindings
-parse_or_pattern_not_allowed_in_fn_parameters = top-level or-patterns are not allowed in function parameters
-parse_sugg_remove_leading_vert_in_pattern = remove the `|`
-parse_sugg_wrap_pattern_in_parens = wrap the pattern in parentheses
+parse_nonterminal_expected_statement = expected a statement
+parse_not_supported = not supported
+
+parse_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide
+
+parse_note_mut_pattern_usage = `mut` may be followed by `variable` and `variable @ pattern`
 
 parse_note_pattern_alternatives_use_single_vert = alternatives in or-patterns are separated with `|`, not `||`
 
-parse_unexpected_vert_vert_before_function_parameter = unexpected `||` before function parameter
-    .suggestion = remove the `||`
+parse_octal_float_literal_not_supported = octal float literal is not supported
+parse_or_pattern_not_allowed_in_fn_parameters = top-level or-patterns are not allowed in function parameters
+parse_or_pattern_not_allowed_in_let_binding = top-level or-patterns are not allowed in `let` bindings
+parse_out_of_range_hex_escape = out of range hex escape
+    .label = must be a character in the range [\x00-\x7f]
 
-parse_label_while_parsing_or_pattern_here = while parsing this or-pattern starting here
+parse_outer_attr_explanation = outer attributes, like `#[test]`, annotate the item following them
 
-parse_unexpected_vert_vert_in_pattern = unexpected token `||` in pattern
-    .suggestion = use a single `|` to separate multiple alternative patterns
+parse_outer_attribute_not_allowed_on_if_else = outer attributes are not allowed on `if` and `else` branches
+    .branch_label = the attributes are attached to this branch
+    .ctx_label = the branch belongs to this `{$ctx}`
+    .suggestion = remove the attributes
 
-parse_trailing_vert_not_allowed = a trailing `|` is not allowed in an or-pattern
-    .suggestion = remove the `{$token}`
+parse_overlong_unicode_escape = overlong unicode escape
+    .label = must have at most 6 hex digits
 
-parse_dotdotdot_rest_pattern = unexpected `...`
-    .label = not a valid pattern
-    .suggestion = for a rest pattern, use `..` instead of `...`
+parse_parentheses_with_struct_fields = invalid `struct` delimiters or `fn` call arguments
+    .suggestion_braces_for_struct = if `{$type}` is a struct, use braces as delimiters
+    .suggestion_no_fields_for_fn = if `{$type}` is a function, use the arguments directly
+
+parse_parenthesized_lifetime = parenthesized lifetime bounds are not supported
+    .suggestion = remove the parentheses
+
+parse_path_single_colon = path separator must be a double colon
+    .suggestion = use a double colon instead
+
+parse_pattern_method_param_without_body = patterns aren't allowed in methods without bodies
+    .suggestion = give this argument a name or use an underscore to ignore it
 
 parse_pattern_on_wrong_side_of_at = pattern on wrong side of `@`
     .label_pattern = pattern on the left, should be on the right
     .label_binding = binding on the right, should be on the left
     .suggestion = switch the order
 
-parse_expected_binding_left_of_at = left-hand side of `@` must be a binding
-    .label_lhs = interpreted as a pattern, not a binding
-    .label_rhs = also a pattern
-    .note = bindings are `x`, `mut x`, `ref x`, and `ref mut x`
-
-parse_ambiguous_range_pattern = the range pattern here has ambiguous interpretation
-    .suggestion = add parentheses to clarify the precedence
+parse_question_mark_in_type = invalid `?` in type
+    .label = `?` is only allowed on expressions, not types
+    .suggestion = if you meant to express that the type might not contain a value, use the `Option` wrapper type
 
-parse_unexpected_lifetime_in_pattern = unexpected lifetime `{$symbol}` in pattern
-    .suggestion = remove the lifetime
+parse_recover_import_as_use = expected item, found {$token_name}
+    .suggestion = items are imported using the `use` keyword
 
 parse_ref_mut_order_incorrect = the order of `mut` and `ref` is incorrect
     .suggestion = try switching the order
 
-parse_mut_on_nested_ident_pattern = `mut` must be attached to each individual binding
-    .suggestion = add `mut` to each binding
-parse_mut_on_non_ident_pattern = `mut` must be followed by a named binding
-    .suggestion = remove the `mut` prefix
-parse_note_mut_pattern_usage = `mut` may be followed by `variable` and `variable @ pattern`
+parse_remove_let = expected pattern, found `let`
+    .suggestion = remove the unnecessary `let` keyword
 
 parse_repeated_mut_in_pattern = `mut` on a binding may not be repeated
     .suggestion = remove the additional `mut`s
 
-parse_dot_dot_dot_range_to_pattern_not_allowed = range-to patterns with `...` are not allowed
-    .suggestion = use `..=` instead
+parse_require_colon_after_labeled_expression = labeled expression must be followed by `:`
+    .note = labels are used before loops and blocks, allowing e.g., `break 'label` to them
+    .label = the label
+    .suggestion = add `:` after the label
 
-parse_enum_pattern_instead_of_identifier = expected identifier, found enum pattern
+parse_return_types_use_thin_arrow = return types are denoted using `->`
+    .suggestion = use `->` instead
 
-parse_dot_dot_dot_for_remaining_fields = expected field pattern, found `{$token_str}`
-    .suggestion = to omit remaining fields, use `..`
+parse_self_argument_pointer = cannot pass `self` by raw pointer
+    .label = cannot pass `self` by raw pointer
 
-parse_expected_comma_after_pattern_field = expected `,`
+parse_self_param_not_first = unexpected `self` parameter in function
+    .label = must be the first parameter of an associated function
 
-parse_return_types_use_thin_arrow = return types are denoted using `->`
-    .suggestion = use `->` instead
+parse_shift_interpreted_as_generic =
+    `<<` is interpreted as a start of generic arguments for `{$type}`, not a shift
+    .label_args = interpreted as generic arguments
+    .label_comparison = not interpreted as shift
+    .suggestion = try shifting the cast value
 
-parse_need_plus_after_trait_object_lifetime = lifetime in trait object type must be followed by `+`
+parse_single_colon_import_path = expected `::`, found `:`
+    .suggestion = use double colon
+    .note = import paths are delimited using `::`
 
-parse_expected_mut_or_const_in_raw_pointer_type = expected `mut` or `const` keyword in raw pointer type
-    .suggestion = add `mut` or `const` here
+parse_single_colon_struct_type = found single colon in a struct field type path
+    .suggestion = write a path separator here
 
-parse_lifetime_after_mut = lifetime must precede `mut`
-    .suggestion = place the lifetime before `mut`
+parse_struct_literal_body_without_path =
+    struct literal body without path
+    .suggestion = you might have forgotten to add the struct literal inside the block
 
-parse_dyn_after_mut = `mut` must precede `dyn`
-    .suggestion = place `mut` before `dyn`
+parse_struct_literal_needing_parens =
+    invalid struct literal
+    .suggestion = you might need to surround the struct literal in parentheses
 
-parse_fn_pointer_cannot_be_const = an `fn` pointer type cannot be `const`
-    .label = `const` because of this
-    .suggestion = remove the `const` qualifier
+parse_struct_literal_not_allowed_here = struct literals are not allowed here
+    .suggestion = surround the struct literal with parentheses
 
-parse_fn_pointer_cannot_be_async = an `fn` pointer type cannot be `async`
-    .label = `async` because of this
-    .suggestion = remove the `async` qualifier
+parse_suffixed_literal_in_attribute = suffixed literals are not allowed in attributes
+    .help = instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
 
-parse_nested_c_variadic_type = C-variadic type `...` may not be nested inside another type
+parse_sugg_add_let_for_stmt = you might have meant to introduce a new binding
 
-parse_invalid_dyn_keyword = invalid `dyn` keyword
-    .help = `dyn` is only needed at the start of a trait `+`-separated list
-    .suggestion = remove this keyword
+parse_sugg_add_semi = add `;` here
+parse_sugg_change_inner_attr_to_outer = to annotate the {$item}, change the attribute from inner to outer style
 
-parse_help_set_edition_cargo = set `edition = "{$edition}"` in `Cargo.toml`
-parse_help_set_edition_standalone = pass `--edition {$edition}` to `rustc`
-parse_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide
+parse_sugg_change_this_to_semi = change this to `;`
+parse_sugg_escape_identifier = escape `{$ident_name}` to use it as an identifier
 
-parse_unexpected_token_after_dot = unexpected token: `{$actual}`
+parse_sugg_remove_comma = remove this comma
+parse_sugg_remove_leading_vert_in_pattern = remove the `|`
+parse_sugg_turbofish_syntax = use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
 
-parse_cannot_be_raw_ident = `{$ident}` cannot be a raw identifier
+parse_sugg_wrap_expression_in_parentheses = wrap the expression in parentheses
 
-parse_cr_doc_comment = bare CR not allowed in {$block ->
-    [true] block doc-comment
-    *[false] doc-comment
-}
+parse_sugg_wrap_pattern_in_parens = wrap the pattern in parentheses
 
-parse_no_digits_literal = no valid digits found for number
+parse_switch_mut_let_order =
+    switch the order of `mut` and `let`
+parse_tilde_const_lifetime = `~const` may only modify trait bounds, not lifetime bounds
 
-parse_invalid_digit_literal = invalid digit for a base {$base} literal
+parse_tilde_is_not_unary_operator = `~` cannot be used as a unary operator
+    .suggestion = use `!` to perform bitwise not
 
-parse_empty_exponent_float = expected at least one digit in exponent
+parse_too_many_hashes = too many `#` symbols: raw strings may be delimited by up to 255 `#` symbols, but found {$num}
 
-parse_float_literal_unsupported_base = {$base} float literal is not supported
+parse_too_short_hex_escape = numeric character escape is too short
 
-parse_more_than_one_char = character literal may only contain one codepoint
-    .followed_by = this `{$chr}` is followed by the combining {$len ->
-        [one] mark
-        *[other] marks
-        } `{$escaped_marks}`
-    .non_printing = there are non-printing characters, the full sequence is `{$escaped}`
-    .consider_normalized = consider using the normalized form `{$ch}` of this character
-    .remove_non = consider removing the non-printing characters
-    .use_double_quotes = if you meant to write a {$is_byte ->
-        [true] byte string
-        *[false] `str`
-        } literal, use double quotes
+parse_trailing_vert_not_allowed = a trailing `|` is not allowed in an or-pattern
+    .suggestion = remove the `{$token}`
 
-parse_no_brace_unicode_escape = incorrect unicode escape sequence
-    .label = {parse_no_brace_unicode_escape}
-    .use_braces = format of unicode escape sequences uses braces
-    .format_of_unicode = format of unicode escape sequences is `\u{"{...}"}`
+parse_trait_alias_cannot_be_auto = trait aliases cannot be `auto`
+parse_trait_alias_cannot_be_unsafe = trait aliases cannot be `unsafe`
 
-parse_invalid_unicode_escape = invalid unicode character escape
-    .label = invalid escape
-    .help = unicode escape must {$surrogate ->
-    [true] not be a surrogate
-    *[false] be at most 10FFFF
-    }
+parse_type_ascription_removed =
+    if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
 
-parse_escape_only_char = {$byte ->
-    [true] byte
-    *[false] character
-    } constant must be escaped: `{$escaped_msg}`
-    .escape = escape the character
+parse_unclosed_unicode_escape = unterminated unicode escape
+    .label = missing a closing `{"}"}`
+    .terminate = terminate the unicode escape
 
-parse_bare_cr = {$double_quotes ->
-    [true] bare CR not allowed in string, use `\r` instead
-    *[false] character constant must be escaped: `\r`
-    }
-    .escape = escape the character
+parse_underscore_literal_suffix = underscore literal suffix is not allowed
 
-parse_bare_cr_in_raw_string = bare CR not allowed in raw string
+parse_unexpected_const_in_generic_param = expected lifetime, type, or constant, found keyword `const`
+    .suggestion = the `const` keyword is only needed in the definition of the type
 
-parse_too_short_hex_escape = numeric character escape is too short
+parse_unexpected_const_param_declaration = unexpected `const` parameter declaration
+    .label = expected a `const` expression, not a parameter declaration
+    .suggestion = `const` parameters must be declared for the `impl`
 
-parse_invalid_char_in_escape = {parse_invalid_char_in_escape_msg}: `{$ch}`
-    .label = {parse_invalid_char_in_escape_msg}
+parse_unexpected_default_value_for_lifetime_in_generic_parameters = unexpected default lifetime parameter
+    .label = lifetime parameters cannot have default values
 
-parse_invalid_char_in_escape_msg = invalid character in {$is_hex ->
-    [true] numeric character
-    *[false] unicode
-    } escape
+parse_unexpected_if_with_if = unexpected `if` in the condition expression
+    .suggestion = remove the `if`
 
-parse_out_of_range_hex_escape = out of range hex escape
-    .label = must be a character in the range [\x00-\x7f]
+parse_unexpected_lifetime_in_pattern = unexpected lifetime `{$symbol}` in pattern
+    .suggestion = remove the lifetime
 
-parse_leading_underscore_unicode_escape = {parse_leading_underscore_unicode_escape_label}: `_`
-parse_leading_underscore_unicode_escape_label = invalid start of unicode escape
+parse_unexpected_parentheses_in_for_head = unexpected parentheses surrounding `for` loop head
+    .suggestion = remove parentheses in `for` loop
 
-parse_overlong_unicode_escape = overlong unicode escape
-    .label = must have at most 6 hex digits
+parse_unexpected_self_in_generic_parameters = unexpected keyword `Self` in generic parameters
+    .note = you cannot use `Self` as a generic parameter because it is reserved for associated items
 
-parse_unclosed_unicode_escape = unterminated unicode escape
-    .label = missing a closing `{"}"}`
-    .terminate = terminate the unicode escape
+parse_unexpected_token_after_dot = unexpected token: `{$actual}`
 
-parse_unicode_escape_in_byte = unicode escape in byte string
-    .label = {parse_unicode_escape_in_byte}
-    .help = unicode escape sequences cannot be used as a byte or in a byte string
+parse_unexpected_token_after_label = expected `while`, `for`, `loop` or `{"{"}` after a label
+    .suggestion_remove_label = consider removing the label
+    .suggestion_enclose_in_block = consider enclosing expression in a block
 
-parse_empty_unicode_escape = empty unicode escape
-    .label = this escape must have at least 1 hex digit
+parse_unexpected_token_after_not = unexpected {$negated_desc} after identifier
+parse_unexpected_token_after_not_bitwise = use `!` to perform bitwise not
+parse_unexpected_token_after_not_default = use `!` to perform logical negation or bitwise not
 
-parse_zero_chars = empty character literal
-    .label = {parse_zero_chars}
+parse_unexpected_token_after_not_logical = use `!` to perform logical negation
+parse_unexpected_token_after_struct_name = expected `where`, `{"{"}`, `(`, or `;` after struct name
+parse_unexpected_token_after_struct_name_found_doc_comment = expected `where`, `{"{"}`, `(`, or `;` after struct name, found doc comment `{$token}`
+parse_unexpected_token_after_struct_name_found_keyword = expected `where`, `{"{"}`, `(`, or `;` after struct name, found keyword `{$token}`
+parse_unexpected_token_after_struct_name_found_other = expected `where`, `{"{"}`, `(`, or `;` after struct name, found `{$token}`
 
-parse_lone_slash = invalid trailing slash in literal
-    .label = {parse_lone_slash}
+parse_unexpected_token_after_struct_name_found_reserved_identifier = expected `where`, `{"{"}`, `(`, or `;` after struct name, found reserved identifier `{$token}`
+parse_unexpected_token_after_struct_name_found_reserved_keyword = expected `where`, `{"{"}`, `(`, or `;` after struct name, found reserved keyword `{$token}`
+parse_unexpected_vert_vert_before_function_parameter = unexpected `||` before function parameter
+    .suggestion = remove the `||`
 
-parse_unskipped_whitespace = whitespace symbol '{$ch}' is not skipped
-    .label = {parse_unskipped_whitespace}
+parse_unexpected_vert_vert_in_pattern = unexpected token `||` in pattern
+    .suggestion = use a single `|` to separate multiple alternative patterns
 
-parse_multiple_skipped_lines = multiple lines skipped by escaped newline
-    .label = skipping everything up to and including this point
+parse_unicode_escape_in_byte = unicode escape in byte string
+    .label = {parse_unicode_escape_in_byte}
+    .help = unicode escape sequences cannot be used as a byte or in a byte string
+
+parse_unknown_builtin_construct = unknown `builtin #` construct `{$name}`
 
 parse_unknown_prefix = prefix `{$prefix}` is unknown
     .label = unknown prefix
@@ -733,8 +803,6 @@ parse_unknown_prefix = prefix `{$prefix}` is unknown
     .suggestion_br = use `br` for a raw byte string
     .suggestion_whitespace = consider inserting whitespace here
 
-parse_too_many_hashes = too many `#` symbols: raw strings may be delimited by up to 255 `#` symbols, but found {$num}
-
 parse_unknown_start_of_token = unknown start of token: {$escaped}
     .sugg_quotes = Unicode characters '“' (Left Double Quotation Mark) and '”' (Right Double Quotation Mark) look like '{$ascii_str}' ({$ascii_name}), but are not
     .sugg_other = Unicode character '{$ch}' ({$u_name}) looks like '{$ascii_str}' ({$ascii_name}), but it is not
@@ -744,94 +812,6 @@ parse_unknown_start_of_token = unknown start of token: {$escaped}
         *[other] {$repeats} more times
     }
 
-parse_box_syntax_removed = `box_syntax` has been removed
-    .suggestion = use `Box::new()` instead
-
-parse_bad_return_type_notation_output =
-    return type not allowed with return type notation
-    .suggestion = remove the return type
-
-parse_bad_return_type_notation_dotdot =
-    return type notation uses `()` instead of `(..)` for elided arguments
-    .suggestion = remove the `..`
-
-parse_bad_assoc_type_bounds = bounds on associated types do not belong here
-    .label = belongs in `where` clause
-
-parse_attr_after_generic = trailing attribute after generic parameter
-    .label = attributes must go before parameters
-
-parse_attr_without_generics = attribute without generic parameters
-    .label = attributes are only permitted when preceding parameters
-
-parse_where_generics = generic parameters on `where` clauses are reserved for future use
-    .label = currently unsupported
-
-parse_generics_in_path = unexpected generic arguments in path
-
-parse_assoc_lifetime = associated lifetimes are not supported
-    .label = the lifetime is given here
-    .help = if you meant to specify a trait object, write `dyn Trait + 'lifetime`
-
-parse_tilde_const_lifetime = `~const` may only modify trait bounds, not lifetime bounds
-
-parse_modifier_lifetime = `{$sigil}` may only modify trait bounds, not lifetime bounds
-    .suggestion = remove the `{$sigil}`
-
-parse_parenthesized_lifetime = parenthesized lifetime bounds are not supported
-    .suggestion = remove the parentheses
-
-parse_const_bounds_missing_tilde = const bounds must start with `~`
-    .suggestion = add `~`
-
-parse_underscore_literal_suffix = underscore literal suffix is not allowed
-
-parse_expect_label_found_ident = expected a label, found an identifier
-    .suggestion = labels start with a tick
-
-parse_inappropriate_default = {$article} {$descr} cannot be `default`
-    .label = `default` because of this
-    .note = only associated `fn`, `const`, and `type` items can be `default`
-
-parse_recover_import_as_use = expected item, found {$token_name}
-    .suggestion = items are imported using the `use` keyword
-
-parse_single_colon_import_path = expected `::`, found `:`
-    .suggestion = use double colon
-    .note = import paths are delimited using `::`
-
-parse_bad_item_kind = {$descr} is not supported in {$ctx}
-    .help = consider moving the {$descr} out to a nearby module scope
-
-parse_single_colon_struct_type = found single colon in a struct field type path
-    .suggestion = write a path separator here
-
-parse_equals_struct_default = default values on `struct` fields aren't supported
-    .suggestion = remove this unsupported default value
-
-parse_macro_rules_missing_bang = expected `!` after `macro_rules`
-    .suggestion = add a `!`
-
-parse_macro_name_remove_bang = macro names aren't followed by a `!`
-    .suggestion = remove the `!`
-
-parse_macro_rules_visibility = can't qualify macro_rules invocation with `{$vis}`
-    .suggestion = try exporting the macro
-
-parse_macro_invocation_visibility = can't qualify macro invocation with `pub`
-    .suggestion = remove the visibility
-    .help = try adjusting the macro to put `{$vis}` inside the invocation
-
-parse_nested_adt = `{$kw_str}` definition cannot be nested inside `{$keyword}`
-    .suggestion = consider creating a new `{$kw_str}` definition instead of nesting
-
-parse_function_body_equals_expr = function body cannot be `= expression;`
-    .suggestion = surround the expression with `{"{"}` and `{"}"}` instead of `=` and `;`
-
-parse_box_not_pat = expected pattern, found {$descr}
-    .note = `box` is a reserved keyword
-    .suggestion = escape `box` to use it as an identifier
-
 parse_unmatched_angle = unmatched angle {$plural ->
     [true] brackets
     *[false] bracket
@@ -841,19 +821,39 @@ parse_unmatched_angle = unmatched angle {$plural ->
     *[false] bracket
     }
 
-parse_missing_plus_in_bounds = expected `+` between lifetime and {$sym}
-    .suggestion = add `+`
+parse_unmatched_angle_brackets = {$num_extra_brackets ->
+        [one] unmatched angle bracket
+       *[other] unmatched angle brackets
+    }
+    .suggestion = {$num_extra_brackets ->
+            [one] remove extra angle bracket
+           *[other] remove extra angle brackets
+        }
 
-parse_incorrect_braces_trait_bounds = incorrect braces around trait bounds
-    .suggestion = remove the parentheses
+parse_unskipped_whitespace = whitespace symbol '{$ch}' is not skipped
+    .label = {parse_unskipped_whitespace}
 
-parse_kw_bad_case = keyword `{$kw}` is written in the wrong case
-    .suggestion = write it in the correct case
+parse_use_empty_block_not_semi = expected { "`{}`" }, found `;`
+    .suggestion = try using { "`{}`" } instead
 
-parse_meta_bad_delim = wrong meta list delimiters
-parse_cfg_attr_bad_delim = wrong `cfg_attr` delimiters
-parse_meta_bad_delim_suggestion = the delimiters should be `(` and `)`
+parse_use_eq_instead = unexpected `==`
+    .suggestion = try using `=` instead
 
-parse_malformed_cfg_attr = malformed `cfg_attr` attribute input
-    .suggestion = missing condition and attribute
-    .note = for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
+parse_use_let_not_auto = write `let` instead of `auto` to introduce a new variable
+parse_use_let_not_var = write `let` instead of `var` to introduce a new variable
+
+parse_visibility_not_followed_by_item = visibility `{$vis}` is not followed by an item
+    .label = the visibility
+    .help = you likely meant to define an item, e.g., `{$vis} fn foo() {"{}"}`
+
+parse_where_clause_before_tuple_struct_body = where clauses are not allowed before tuple struct bodies
+    .label = unexpected where clause
+    .name_label = while parsing this tuple struct
+    .body_label = the struct body
+    .suggestion = move the body before the where clause
+
+parse_where_generics = generic parameters on `where` clauses are reserved for future use
+    .label = currently unsupported
+
+parse_zero_chars = empty character literal
+    .label = {parse_zero_chars}
diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs
index cd779b0b43e..8ab38c4fb8b 100644
--- a/compiler/rustc_parse/src/parser/generics.rs
+++ b/compiler/rustc_parse/src/parser/generics.rs
@@ -43,6 +43,15 @@ impl<'a> Parser<'a> {
     fn parse_ty_param(&mut self, preceding_attrs: AttrVec) -> PResult<'a, GenericParam> {
         let ident = self.parse_ident()?;
 
+        // We might have a typo'd `Const` that was parsed as a type parameter.
+        if self.may_recover()
+            && ident.name.as_str().to_ascii_lowercase() == kw::Const.as_str()
+            && self.check_ident()
+        // `Const` followed by IDENT
+        {
+            return Ok(self.recover_const_param_with_mistyped_const(preceding_attrs, ident)?);
+        }
+
         // Parse optional colon and param bounds.
         let mut colon_span = None;
         let bounds = if self.eat(&token::Colon) {
@@ -120,6 +129,41 @@ impl<'a> Parser<'a> {
         })
     }
 
+    pub(crate) fn recover_const_param_with_mistyped_const(
+        &mut self,
+        preceding_attrs: AttrVec,
+        mistyped_const_ident: Ident,
+    ) -> PResult<'a, GenericParam> {
+        let ident = self.parse_ident()?;
+        self.expect(&token::Colon)?;
+        let ty = self.parse_ty()?;
+
+        // Parse optional const generics default value.
+        let default = if self.eat(&token::Eq) { Some(self.parse_const_arg()?) } else { None };
+
+        let mut err = self.struct_span_err(
+            mistyped_const_ident.span,
+            format!("`const` keyword was mistyped as `{}`", mistyped_const_ident.as_str()),
+        );
+        err.span_suggestion_verbose(
+            mistyped_const_ident.span,
+            "use the `const` keyword",
+            kw::Const.as_str(),
+            Applicability::MachineApplicable,
+        );
+        err.emit();
+
+        Ok(GenericParam {
+            ident,
+            id: ast::DUMMY_NODE_ID,
+            attrs: preceding_attrs,
+            bounds: Vec::new(),
+            kind: GenericParamKind::Const { ty, kw_span: mistyped_const_ident.span, default },
+            is_placeholder: false,
+            colon_span: None,
+        })
+    }
+
     /// Parses a (possibly empty) list of lifetime and type parameters, possibly including
     /// a trailing comma and erroneous trailing attributes.
     pub(super) fn parse_generic_params(&mut self) -> PResult<'a, ThinVec<ast::GenericParam>> {
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 0c265d7af0e..c23420661fa 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -536,7 +536,9 @@ impl<'a> Parser<'a> {
         } else if inedible.contains(&self.token.kind) {
             // leave it in the input
             Ok(false)
-        } else if self.last_unexpected_token_span == Some(self.token.span) {
+        } else if self.token.kind != token::Eof
+            && self.last_unexpected_token_span == Some(self.token.span)
+        {
             FatalError.raise();
         } else {
             self.expected_one_of_not_found(edible, inedible)
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index 54f9fc5d2b9..9fcf51a04ec 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -23,6 +23,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult};
 use rustc_span::source_map::{BytePos, Span};
 use rustc_span::symbol::{kw, sym, Ident};
 
+use std::borrow::Cow;
 use std::mem;
 use thin_vec::{thin_vec, ThinVec};
 
@@ -364,7 +365,7 @@ impl<'a> Parser<'a> {
                         // `let...else if`. Emit the same error that `parse_block()` would,
                         // but explicitly point out that this pattern is not allowed.
                         let msg = "conditional `else if` is not supported for `let...else`";
-                        return Err(self.error_block_no_opening_brace_msg(msg));
+                        return Err(self.error_block_no_opening_brace_msg(Cow::from(msg)));
                     }
                     let els = self.parse_block()?;
                     self.check_let_else_init_bool_expr(&init);
@@ -438,7 +439,7 @@ impl<'a> Parser<'a> {
 
     fn error_block_no_opening_brace_msg(
         &mut self,
-        msg: &str,
+        msg: Cow<'static, str>,
     ) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
         let sp = self.token.span;
         let mut e = self.struct_span_err(sp, msg);
@@ -502,7 +503,7 @@ impl<'a> Parser<'a> {
     fn error_block_no_opening_brace<T>(&mut self) -> PResult<'a, T> {
         let tok = super::token_descr(&self.token);
         let msg = format!("expected `{{`, found {}", tok);
-        Err(self.error_block_no_opening_brace_msg(&msg))
+        Err(self.error_block_no_opening_brace_msg(Cow::from(msg)))
     }
 
     /// Parses a block. Inner attributes are allowed.
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index 40680150601..7f9222dac6c 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -4,118 +4,185 @@
 -passes_see_issue =
     see issue #{$issue} <https://github.com/rust-lang/rust/issues/{$issue}> for more information
 
-passes_incorrect_do_not_recommend_location =
-    `#[do_not_recommend]` can only be placed on trait implementations
+passes_abi =
+    abi: {$abi}
 
-passes_outer_crate_level_attr =
-    crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+passes_align =
+    align: {$align}
 
-passes_inner_crate_level_attr =
-    crate-level attribute should be in the root module
+passes_allow_incoherent_impl =
+    `rustc_allow_incoherent_impl` attribute should be applied to impl items.
+    .label = the only currently supported targets are inherent methods
 
-passes_ignored_attr_with_macro =
-    `#[{$sym}]` is ignored on struct fields, match arms and macro defs
-    .warn = {-passes_previously_accepted}
-    .note = {-passes_see_issue(issue: "80564")}
+passes_allow_internal_unstable =
+    attribute should be applied to a macro
+    .label = not a macro
 
-passes_ignored_attr =
-    `#[{$sym}]` is ignored on struct fields and match arms
-    .warn = {-passes_previously_accepted}
-    .note = {-passes_see_issue(issue: "80564")}
+passes_attr_application_enum =
+    attribute should be applied to an enum
+    .label = not an enum
 
-passes_inline_ignored_function_prototype =
-    `#[inline]` is ignored on function prototypes
+passes_attr_application_struct =
+    attribute should be applied to a struct
+    .label = not a struct
 
-passes_inline_ignored_constants =
-    `#[inline]` is ignored on constants
-    .warn = {-passes_previously_accepted}
-    .note = {-passes_see_issue(issue: "65833")}
+passes_attr_application_struct_enum_function_method_union =
+    attribute should be applied to a struct, enum, function, associated function, or union
+    .label = not a struct, enum, function, associated function, or union
 
-passes_inline_not_fn_or_closure =
-    attribute should be applied to function or closure
-    .label = not a function or closure
+passes_attr_application_struct_enum_union =
+    attribute should be applied to a struct, enum, or union
+    .label = not a struct, enum, or union
 
-passes_no_coverage_ignored_function_prototype =
-    `#[no_coverage]` is ignored on function prototypes
+passes_attr_application_struct_union =
+    attribute should be applied to a struct or union
+    .label = not a struct or union
 
-passes_no_coverage_propagate =
-    `#[no_coverage]` does not propagate into items and must be applied to the contained functions directly
+passes_attr_crate_level =
+    this attribute can only be applied at the crate level
+    .suggestion = to apply to the crate, use an inner attribute
+    .note = read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
 
-passes_no_coverage_fn_defn =
-    `#[no_coverage]` may only be applied to function definitions
+passes_attr_only_in_functions =
+    `{$attr}` attribute can only be used on functions
 
-passes_no_coverage_not_coverable =
-    `#[no_coverage]` must be applied to coverable code
-    .label = not coverable code
+passes_attr_only_on_main =
+    `{$attr}` attribute can only be used on `fn main()`
 
-passes_should_be_applied_to_fn =
-    attribute should be applied to a function definition
-    .label = {$on_crate ->
-        [true] cannot be applied to crates
-        *[false] not a function definition
-    }
+passes_attr_only_on_root_main =
+    `{$attr}` attribute can only be used on root `fn main()`
 
-passes_naked_tracked_caller =
-    cannot use `#[track_caller]` with `#[naked]`
+passes_both_ffi_const_and_pure =
+    `#[ffi_const]` function cannot be `#[ffi_pure]`
 
-passes_should_be_applied_to_struct_enum =
-    attribute should be applied to a struct or enum
-    .label = not a struct or enum
+passes_break_inside_async_block =
+    `{$name}` inside of an `async` block
+    .label = cannot `{$name}` inside of an `async` block
+    .async_block_label = enclosing `async` block
 
-passes_should_be_applied_to_trait =
-    attribute should be applied to a trait
-    .label = not a trait
+passes_break_inside_closure =
+    `{$name}` inside of a closure
+    .label = cannot `{$name}` inside of a closure
+    .closure_label = enclosing closure
 
-passes_target_feature_on_statement =
+passes_break_non_loop =
+    `break` with value from a `{$kind}` loop
+    .label = can only break with a value inside `loop` or breakable block
+    .label2 = you can't `break` with a value in a `{$kind}` loop
+    .suggestion = use `break` on its own without a value inside this `{$kind}` loop
+    .break_expr_suggestion = alternatively, you might have meant to use the available loop label
+
+passes_cannot_inline_naked_function =
+    naked functions cannot be inlined
+
+passes_cannot_stabilize_deprecated =
+    an API can't be stabilized after it is deprecated
+    .label = invalid version
+    .item = the stability attribute annotates this item
+
+passes_change_fields_to_be_of_unit_type =
+    consider changing the { $num ->
+      [one] field
+     *[other] fields
+    } to be of unit type to suppress this warning while preserving the field numbering, or remove the { $num ->
+      [one] field
+     *[other] fields
+    }
+
+passes_cold =
     {passes_should_be_applied_to_fn}
     .warn = {-passes_previously_accepted}
     .label = {passes_should_be_applied_to_fn.label}
 
-passes_should_be_applied_to_static =
-    attribute should be applied to a static
-    .label = not a static
+passes_collapse_debuginfo =
+    `collapse_debuginfo` attribute should be applied to macro definitions
+    .label = not a macro definition
 
-passes_doc_expect_str =
-    doc {$attr_name} attribute expects a string: #[doc({$attr_name} = "a")]
+passes_const_impl_const_trait =
+    const `impl`s must be for traits marked with `#[const_trait]`
+    .note = this trait must be annotated with `#[const_trait]`
 
-passes_doc_alias_empty =
-    {$attr_str} attribute cannot have empty value
+passes_const_trait =
+    attribute should be applied to a trait
+
+passes_continue_labeled_block =
+    `continue` pointing to a labeled block
+    .label = labeled blocks cannot be `continue`'d
+    .block_label = labeled block the `continue` points to
+
+passes_dead_codes =
+    { $multiple ->
+      *[true] multiple {$descr}s are
+       [false] { $num ->
+         [one] {$descr} {$name_list} is
+        *[other] {$descr}s {$name_list} are
+       }
+    } never {$participle}
+
+passes_debug_visualizer_invalid =
+    invalid argument
+    .note_1 = expected: `natvis_file = "..."`
+    .note_2 = OR
+    .note_3 = expected: `gdb_script_file = "..."`
+
+passes_debug_visualizer_placement =
+    attribute should be applied to a module
+
+passes_debug_visualizer_unreadable =
+    couldn't read {$file}: {$error}
+
+passes_deprecated =
+    attribute is ignored here
+
+passes_deprecated_annotation_has_no_effect =
+    this `#[deprecated]` annotation has no effect
+    .suggestion = remove the unnecessary deprecation attribute
+
+passes_deprecated_attribute =
+    deprecated attribute must be paired with either stable or unstable attribute
+
+passes_diagnostic_item_first_defined =
+    the diagnostic item is first defined here
 
 passes_doc_alias_bad_char =
     {$char_} character isn't allowed in {$attr_str}
 
-passes_doc_alias_start_end =
-    {$attr_str} cannot start or end with ' '
-
 passes_doc_alias_bad_location =
     {$attr_str} isn't allowed on {$location}
 
-passes_doc_alias_not_an_alias =
-    {$attr_str} is the same as the item's name
-
 passes_doc_alias_duplicated = doc alias is duplicated
     .label = first defined here
 
-passes_doc_alias_not_string_literal =
-    `#[doc(alias("a"))]` expects string literals
+passes_doc_alias_empty =
+    {$attr_str} attribute cannot have empty value
 
 passes_doc_alias_malformed =
     doc alias attribute expects a string `#[doc(alias = "a")]` or a list of strings `#[doc(alias("a", "b"))]`
 
-passes_doc_keyword_empty_mod =
-    `#[doc(keyword = "...")]` should be used on empty modules
+passes_doc_alias_not_an_alias =
+    {$attr_str} is the same as the item's name
 
-passes_doc_keyword_not_mod =
-    `#[doc(keyword = "...")]` should be used on modules
+passes_doc_alias_not_string_literal =
+    `#[doc(alias("a"))]` expects string literals
 
-passes_doc_keyword_invalid_ident =
-    `{$doc_keyword}` is not a valid identifier
+passes_doc_alias_start_end =
+    {$attr_str} cannot start or end with ' '
+
+passes_doc_attr_not_crate_level =
+    `#![doc({$attr_name} = "...")]` isn't allowed as a crate-level attribute
+
+passes_doc_cfg_hide_takes_list =
+    `#[doc(cfg_hide(...)]` takes a list of attributes
+
+passes_doc_expect_str =
+    doc {$attr_name} attribute expects a string: #[doc({$attr_name} = "a")]
 
 passes_doc_fake_variadic_not_valid =
     `#[doc(fake_variadic)]` must be used on the first of a set of tuple or fn pointer trait impls with varying arity
 
-passes_doc_keyword_only_impl =
-    `#[doc(keyword = "...")]` should be used on impl blocks
+passes_doc_inline_conflict =
+    conflicting doc inlining attributes
+    .help = remove one of the conflicting attributes
 
 passes_doc_inline_conflict_first =
     this attribute...
@@ -123,383 +190,274 @@ passes_doc_inline_conflict_first =
 passes_doc_inline_conflict_second =
     {"."}..conflicts with this attribute
 
-passes_doc_inline_conflict =
-    conflicting doc inlining attributes
-    .help = remove one of the conflicting attributes
-
 passes_doc_inline_only_use =
     this attribute can only be applied to a `use` item
     .label = only applicable on `use` items
     .not_a_use_item_label = not a `use` item
     .note = read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline> for more information
 
-passes_doc_attr_not_crate_level =
-    `#![doc({$attr_name} = "...")]` isn't allowed as a crate-level attribute
+passes_doc_invalid =
+    invalid `doc` attribute
 
-passes_attr_crate_level =
-    this attribute can only be applied at the crate level
-    .suggestion = to apply to the crate, use an inner attribute
-    .note = read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
+passes_doc_keyword_empty_mod =
+    `#[doc(keyword = "...")]` should be used on empty modules
 
-passes_doc_test_unknown =
-    unknown `doc(test)` attribute `{$path}`
+passes_doc_keyword_invalid_ident =
+    `{$doc_keyword}` is not a valid identifier
+
+passes_doc_keyword_not_mod =
+    `#[doc(keyword = "...")]` should be used on modules
+
+passes_doc_keyword_only_impl =
+    `#[doc(keyword = "...")]` should be used on impl blocks
 
 passes_doc_test_takes_list =
     `#[doc(test(...)]` takes a list of attributes
 
-passes_doc_cfg_hide_takes_list =
-    `#[doc(cfg_hide(...)]` takes a list of attributes
+passes_doc_test_unknown =
+    unknown `doc(test)` attribute `{$path}`
 
 passes_doc_test_unknown_any =
     unknown `doc` attribute `{$path}`
 
+passes_doc_test_unknown_include =
+    unknown `doc` attribute `{$path}`
+    .suggestion = use `doc = include_str!` instead
+
 passes_doc_test_unknown_spotlight =
     unknown `doc` attribute `{$path}`
     .note = `doc(spotlight)` was renamed to `doc(notable_trait)`
     .suggestion = use `notable_trait` instead
     .no_op_note = `doc(spotlight)` is now a no-op
 
-passes_doc_test_unknown_include =
-    unknown `doc` attribute `{$path}`
-    .suggestion = use `doc = include_str!` instead
+passes_duplicate_diagnostic_item_in_crate =
+    duplicate diagnostic item in crate `{$crate_name}`: `{$name}`.
+    .note = the diagnostic item is first defined in crate `{$orig_crate_name}`.
 
-passes_doc_invalid =
-    invalid `doc` attribute
+passes_duplicate_feature_err =
+    the feature `{$feature}` has already been declared
 
-passes_pass_by_value =
-    `pass_by_value` attribute should be applied to a struct, enum or type alias
-    .label = is not a struct, enum or type alias
+passes_duplicate_lang_item =
+    found duplicate lang item `{$lang_item_name}`
+    .first_defined_span = the lang item is first defined here
+    .first_defined_crate_depends = the lang item is first defined in crate `{$orig_crate_name}` (which `{$orig_dependency_of}` depends on)
+    .first_defined_crate = the lang item is first defined in crate `{$orig_crate_name}`.
+    .first_definition_local = first definition in the local crate (`{$orig_crate_name}`)
+    .second_definition_local = second definition in the local crate (`{$crate_name}`)
+    .first_definition_path = first definition in `{$orig_crate_name}` loaded from {$orig_path}
+    .second_definition_path = second definition in `{$crate_name}` loaded from {$path}
 
-passes_allow_incoherent_impl =
-    `rustc_allow_incoherent_impl` attribute should be applied to impl items.
-    .label = the only currently supported targets are inherent methods
+passes_duplicate_lang_item_crate =
+    duplicate lang item in crate `{$crate_name}`: `{$lang_item_name}`.
+    .first_defined_span = the lang item is first defined here
+    .first_defined_crate_depends = the lang item is first defined in crate `{$orig_crate_name}` (which `{$orig_dependency_of}` depends on)
+    .first_defined_crate = the lang item is first defined in crate `{$orig_crate_name}`.
+    .first_definition_local = first definition in the local crate (`{$orig_crate_name}`)
+    .second_definition_local = second definition in the local crate (`{$crate_name}`)
+    .first_definition_path = first definition in `{$orig_crate_name}` loaded from {$orig_path}
+    .second_definition_path = second definition in `{$crate_name}` loaded from {$path}
 
-passes_has_incoherent_inherent_impl =
-    `rustc_has_incoherent_inherent_impls` attribute should be applied to types or traits.
-    .label = only adts, extern types and traits are supported
+passes_duplicate_lang_item_crate_depends =
+    duplicate lang item in crate `{$crate_name}` (which `{$dependency_of}` depends on): `{$lang_item_name}`.
+    .first_defined_span = the lang item is first defined here
+    .first_defined_crate_depends = the lang item is first defined in crate `{$orig_crate_name}` (which `{$orig_dependency_of}` depends on)
+    .first_defined_crate = the lang item is first defined in crate `{$orig_crate_name}`.
+    .first_definition_local = first definition in the local crate (`{$orig_crate_name}`)
+    .second_definition_local = second definition in the local crate (`{$crate_name}`)
+    .first_definition_path = first definition in `{$orig_crate_name}` loaded from {$orig_path}
+    .second_definition_path = second definition in `{$crate_name}` loaded from {$path}
 
-passes_both_ffi_const_and_pure =
-    `#[ffi_const]` function cannot be `#[ffi_pure]`
+passes_export_name =
+    attribute should be applied to a free function, impl method or static
+    .label = not a free function, impl method or static
 
-passes_ffi_pure_invalid_target =
-    `#[ffi_pure]` may only be used on foreign functions
+passes_expr_not_allowed_in_context =
+    {$expr} is not allowed in a `{$context}`
+
+passes_extern_main =
+    the `main` function cannot be declared in an `extern` block
+
+passes_feature_only_on_nightly =
+    `#![feature]` may not be used on the {$release_channel} release channel
+
+passes_feature_previously_declared =
+    feature `{$feature}` is declared {$declared}, but was previously declared {$prev_declared}
+
+passes_feature_stable_twice =
+    feature `{$feature}` is declared stable since {$since}, but was previously declared stable since {$prev_since}
 
 passes_ffi_const_invalid_target =
     `#[ffi_const]` may only be used on foreign functions
 
+passes_ffi_pure_invalid_target =
+    `#[ffi_pure]` may only be used on foreign functions
+
 passes_ffi_returns_twice_invalid_target =
     `#[ffi_returns_twice]` may only be used on foreign functions
 
-passes_must_use_async =
-    `must_use` attribute on `async` functions applies to the anonymous `Future` returned by the function, not the value within
-    .label = this attribute does nothing, the `Future`s returned by async functions are already `must_use`
-
-passes_must_use_no_effect =
-    `#[must_use]` has no effect when applied to {$article} {$target}
-
-passes_must_not_suspend =
-    `must_not_suspend` attribute should be applied to a struct, enum, or trait
-    .label = is not a struct, enum, or trait
+passes_has_incoherent_inherent_impl =
+    `rustc_has_incoherent_inherent_impls` attribute should be applied to types or traits.
+    .label = only adts, extern types and traits are supported
 
-passes_cold =
-    {passes_should_be_applied_to_fn}
-    .warn = {-passes_previously_accepted}
-    .label = {passes_should_be_applied_to_fn.label}
+passes_homogeneous_aggregate =
+    homogeneous_aggregate: {$homogeneous_aggregate}
 
-passes_link =
-    attribute should be applied to an `extern` block with non-Rust ABI
+passes_ignored_attr =
+    `#[{$sym}]` is ignored on struct fields and match arms
     .warn = {-passes_previously_accepted}
-    .label = not an `extern` block
+    .note = {-passes_see_issue(issue: "80564")}
 
-passes_link_name =
-    attribute should be applied to a foreign function or static
+passes_ignored_attr_with_macro =
+    `#[{$sym}]` is ignored on struct fields, match arms and macro defs
     .warn = {-passes_previously_accepted}
-    .label = not a foreign function or static
-    .help = try `#[link(name = "{$value}")]` instead
-
-passes_no_link =
-    attribute should be applied to an `extern crate` item
-    .label = not an `extern crate` item
-
-passes_export_name =
-    attribute should be applied to a free function, impl method or static
-    .label = not a free function, impl method or static
-
-passes_rustc_layout_scalar_valid_range_not_struct =
-    attribute should be applied to a struct
-    .label = not a struct
+    .note = {-passes_see_issue(issue: "80564")}
 
-passes_rustc_layout_scalar_valid_range_arg =
-    expected exactly one integer literal argument
+passes_ignored_derived_impls =
+    `{$name}` has {$trait_list_len ->
+      [one] a derived impl
+     *[other] derived impls
+    } for the {$trait_list_len ->
+      [one] trait {$trait_list}, but this is
+     *[other] traits {$trait_list}, but these are
+    } intentionally ignored during dead code analysis
 
-passes_rustc_legacy_const_generics_only =
-    #[rustc_legacy_const_generics] functions must only have const generics
-    .label = non-const generic parameter
+passes_implied_feature_not_exist =
+    feature `{$implied_by}` implying `{$feature}` does not exist
 
-passes_rustc_legacy_const_generics_index =
-    #[rustc_legacy_const_generics] must have one index for each generic parameter
-    .label = generic parameters
+passes_incorrect_do_not_recommend_location =
+    `#[do_not_recommend]` can only be placed on trait implementations
 
-passes_rustc_legacy_const_generics_index_exceed =
-    index exceeds number of arguments
-    .label = there {$arg_count ->
-        [one] is
-        *[other] are
-    } only {$arg_count} {$arg_count ->
+passes_incorrect_target =
+    `{$name}` language item must be applied to a {$kind} with {$at_least ->
+        [true] at least {$num}
+        *[false] {$num}
+    } generic {$num ->
+        [one] argument
+        *[other] arguments
+    }
+    .label = this {$kind} has {$actual_num} generic {$actual_num ->
         [one] argument
         *[other] arguments
     }
 
-passes_rustc_legacy_const_generics_index_negative =
-    arguments should be non-negative integers
-
-passes_rustc_dirty_clean =
-    attribute requires -Z query-dep-graph to be enabled
-
-passes_link_section =
-    attribute should be applied to a function or static
-    .warn = {-passes_previously_accepted}
-    .label = not a function or static
-
-passes_no_mangle_foreign =
-    `#[no_mangle]` has no effect on a foreign {$foreign_item_kind}
-    .warn = {-passes_previously_accepted}
-    .label = foreign {$foreign_item_kind}
-    .note = symbol names in extern blocks are not mangled
-    .suggestion = remove this attribute
+passes_ineffective_unstable_impl = an `#[unstable]` annotation here has no effect
+    .note = see issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information
 
-passes_no_mangle =
-    attribute should be applied to a free function, impl method or static
+passes_inline_ignored_constants =
+    `#[inline]` is ignored on constants
     .warn = {-passes_previously_accepted}
-    .label = not a free function, impl method or static
-
-passes_repr_ident =
-    meta item in `repr` must be an identifier
-
-passes_repr_conflicting =
-    conflicting representation hints
-
-passes_used_static =
-    attribute must be applied to a `static` variable
-
-passes_used_compiler_linker =
-    `used(compiler)` and `used(linker)` can't be used together
-
-passes_allow_internal_unstable =
-    attribute should be applied to a macro
-    .label = not a macro
-
-passes_debug_visualizer_placement =
-    attribute should be applied to a module
-
-passes_debug_visualizer_invalid =
-    invalid argument
-    .note_1 = expected: `natvis_file = "..."`
-    .note_2 = OR
-    .note_3 = expected: `gdb_script_file = "..."`
-
-passes_debug_visualizer_unreadable =
-    couldn't read {$file}: {$error}
-
-passes_rustc_allow_const_fn_unstable =
-    attribute should be applied to `const fn`
-    .label = not a `const fn`
-
-passes_rustc_std_internal_symbol =
-    attribute should be applied to functions or statics
-    .label = not a function or static
-
-passes_const_trait =
-    attribute should be applied to a trait
-
-passes_stability_promotable =
-    attribute cannot be applied to an expression
-
-passes_deprecated =
-    attribute is ignored here
-
-passes_macro_use =
-    `#[{$name}]` only has an effect on `extern crate` and modules
-
-passes_macro_export =
-    `#[macro_export]` only has an effect on macro definitions
-
-passes_plugin_registrar =
-    `#[plugin_registrar]` only has an effect on functions
-
-passes_unused_empty_lints_note =
-    attribute `{$name}` with an empty list has no effect
-
-passes_unused_no_lints_note =
-    attribute `{$name}` without any lints has no effect
-
-passes_unused_default_method_body_const_note =
-    `default_method_body_is_const` has been replaced with `#[const_trait]` on traits
+    .note = {-passes_see_issue(issue: "65833")}
 
-passes_unused =
-    unused attribute
-    .suggestion = remove this attribute
+passes_inline_ignored_function_prototype =
+    `#[inline]` is ignored on function prototypes
 
-passes_non_exported_macro_invalid_attrs =
+passes_inline_not_fn_or_closure =
     attribute should be applied to function or closure
     .label = not a function or closure
 
-passes_unused_duplicate =
-    unused attribute
-    .suggestion = remove this attribute
-    .note = attribute also specified here
-    .warn = {-passes_previously_accepted}
-
-passes_unused_multiple =
-    multiple `{$name}` attributes
-    .suggestion = remove this attribute
-    .note = attribute also specified here
-
-passes_rustc_lint_opt_ty =
-    `#[rustc_lint_opt_ty]` should be applied to a struct
-    .label = not a struct
-
-passes_rustc_lint_opt_deny_field_access =
-    `#[rustc_lint_opt_deny_field_access]` should be applied to a field
-    .label = not a field
-
-passes_link_ordinal =
-    attribute should be applied to a foreign function or static
-    .label = not a foreign function or static
-
-passes_collapse_debuginfo =
-    `collapse_debuginfo` attribute should be applied to macro definitions
-    .label = not a macro definition
-
-passes_deprecated_annotation_has_no_effect =
-    this `#[deprecated]` annotation has no effect
-    .suggestion = remove the unnecessary deprecation attribute
-
-passes_unknown_external_lang_item =
-    unknown external lang item: `{$lang_item}`
-
-passes_missing_panic_handler =
-    `#[panic_handler]` function required, but not found
-
-passes_missing_lang_item =
-    language item required, but not found: `{$name}`
-    .note = this can occur when a binary crate with `#![no_std]` is compiled for a target where `{$name}` is defined in the standard library
-    .help = you may be able to compile for a target that doesn't need `{$name}`, specify a target with `--target` or in `.cargo/config`
-
-passes_lang_item_on_incorrect_target =
-    `{$name}` language item must be applied to a {$expected_target}
-    .label = attribute should be applied to a {$expected_target}, not a {$actual_target}
-
-passes_unknown_lang_item =
-    definition of an unknown language item: `{$name}`
-    .label = definition of unknown language item `{$name}`
+passes_inner_crate_level_attr =
+    crate-level attribute should be in the root module
 
 passes_invalid_attr_at_crate_level =
     `{$name}` attribute cannot be used at crate level
     .suggestion = perhaps you meant to use an outer attribute
 
-passes_duplicate_diagnostic_item_in_crate =
-    duplicate diagnostic item in crate `{$crate_name}`: `{$name}`.
-    .note = the diagnostic item is first defined in crate `{$orig_crate_name}`.
+passes_invalid_deprecation_version =
+    invalid deprecation version found
+    .label = invalid deprecation version
+    .item = the stability attribute annotates this item
 
-passes_diagnostic_item_first_defined =
-    the diagnostic item is first defined here
+passes_invalid_macro_export_arguments = `{$name}` isn't a valid `#[macro_export]` argument
 
-passes_abi =
-    abi: {$abi}
+passes_invalid_macro_export_arguments_too_many_items = `#[macro_export]` can only take 1 or 0 arguments
 
-passes_align =
-    align: {$align}
+passes_invalid_stability =
+    invalid stability version found
+    .label = invalid stability version
+    .item = the stability attribute annotates this item
 
-passes_size =
-    size: {$size}
+passes_lang_item_on_incorrect_target =
+    `{$name}` language item must be applied to a {$expected_target}
+    .label = attribute should be applied to a {$expected_target}, not a {$actual_target}
 
-passes_homogeneous_aggregate =
-    homogeneous_aggregate: {$homogeneous_aggregate}
+passes_layout =
+    layout error: {$layout_error}
 
 passes_layout_of =
     layout_of({$normalized_ty}) = {$ty_layout}
 
-passes_unrecognized_field =
-    unrecognized field name `{$name}`
-
-passes_layout =
-    layout error: {$layout_error}
+passes_link =
+    attribute should be applied to an `extern` block with non-Rust ABI
+    .warn = {-passes_previously_accepted}
+    .label = not an `extern` block
 
-passes_feature_stable_twice =
-    feature `{$feature}` is declared stable since {$since}, but was previously declared stable since {$prev_since}
+passes_link_name =
+    attribute should be applied to a foreign function or static
+    .warn = {-passes_previously_accepted}
+    .label = not a foreign function or static
+    .help = try `#[link(name = "{$value}")]` instead
 
-passes_feature_previously_declared =
-    feature `{$feature}` is declared {$declared}, but was previously declared {$prev_declared}
+passes_link_ordinal =
+    attribute should be applied to a foreign function or static
+    .label = not a foreign function or static
 
-passes_expr_not_allowed_in_context =
-    {$expr} is not allowed in a `{$context}`
+passes_link_section =
+    attribute should be applied to a function or static
+    .warn = {-passes_previously_accepted}
+    .label = not a function or static
 
-passes_const_impl_const_trait =
-    const `impl`s must be for traits marked with `#[const_trait]`
-    .note = this trait must be annotated with `#[const_trait]`
+passes_macro_export =
+    `#[macro_export]` only has an effect on macro definitions
 
-passes_break_non_loop =
-    `break` with value from a `{$kind}` loop
-    .label = can only break with a value inside `loop` or breakable block
-    .label2 = you can't `break` with a value in a `{$kind}` loop
-    .suggestion = use `break` on its own without a value inside this `{$kind}` loop
-    .break_expr_suggestion = alternatively, you might have meant to use the available loop label
+passes_macro_use =
+    `#[{$name}]` only has an effect on `extern crate` and modules
 
-passes_continue_labeled_block =
-    `continue` pointing to a labeled block
-    .label = labeled blocks cannot be `continue`'d
-    .block_label = labeled block the `continue` points to
+passes_maybe_string_interpolation = you might have meant to use string interpolation in this string literal
+passes_missing_const_err =
+    attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+    .help = make the function or method const
+    .label = attribute specified here
 
-passes_break_inside_closure =
-    `{$name}` inside of a closure
-    .label = cannot `{$name}` inside of a closure
-    .closure_label = enclosing closure
+passes_missing_const_stab_attr =
+    {$descr} has missing const stability attribute
 
-passes_break_inside_async_block =
-    `{$name}` inside of an `async` block
-    .label = cannot `{$name}` inside of an `async` block
-    .async_block_label = enclosing `async` block
+passes_missing_lang_item =
+    language item required, but not found: `{$name}`
+    .note = this can occur when a binary crate with `#![no_std]` is compiled for a target where `{$name}` is defined in the standard library
+    .help = you may be able to compile for a target that doesn't need `{$name}`, specify a target with `--target` or in `.cargo/config`
 
-passes_outside_loop =
-    `{$name}` outside of a loop{$is_break ->
-        [true] {" or labeled block"}
-        *[false] {""}
-    }
-    .label = cannot `{$name}` outside of a loop{$is_break ->
-        [true] {" or labeled block"}
-        *[false] {""}
-    }
+passes_missing_panic_handler =
+    `#[panic_handler]` function required, but not found
 
-passes_unlabeled_in_labeled_block =
-    unlabeled `{$cf_type}` inside of a labeled block
-    .label = `{$cf_type}` statements that would diverge to or through a labeled block need to bear a label
+passes_missing_stability_attr =
+    {$descr} has missing stability attribute
 
-passes_unlabeled_cf_in_while_condition =
-    `break` or `continue` with no label in the condition of a `while` loop
-    .label = unlabeled `{$cf_type}` in the condition of a `while` loop
+passes_multiple_rustc_main =
+    multiple functions with a `#[rustc_main]` attribute
+    .first = first `#[rustc_main]` function
+    .additional = additional `#[rustc_main]` function
 
-passes_cannot_inline_naked_function =
-    naked functions cannot be inlined
+passes_multiple_start_functions =
+    multiple `start` functions
+    .label = multiple `start` functions
+    .previous = previous `#[start]` function here
 
-passes_undefined_naked_function_abi =
-    Rust ABI is unsupported in naked functions
+passes_must_not_suspend =
+    `must_not_suspend` attribute should be applied to a struct, enum, or trait
+    .label = is not a struct, enum, or trait
 
-passes_no_patterns =
-    patterns not allowed in naked function parameters
+passes_must_use_async =
+    `must_use` attribute on `async` functions applies to the anonymous `Future` returned by the function, not the value within
+    .label = this attribute does nothing, the `Future`s returned by async functions are already `must_use`
 
-passes_params_not_allowed =
-    referencing function parameters is not allowed in naked functions
-    .help = follow the calling convention in asm block to use parameters
+passes_must_use_no_effect =
+    `#[must_use]` has no effect when applied to {$article} {$target}
 
 passes_naked_functions_asm_block =
     naked functions must contain a single asm block
     .label_multiple_asm = multiple asm blocks are unsupported in naked functions
     .label_non_asm = non-asm is unsupported in naked functions
 
-passes_naked_functions_operands =
-    only `const` and `sym` operands are supported in naked functions
-
 passes_naked_functions_asm_options =
     asm options unsupported in naked functions: {$unsupported_options}
 
@@ -507,30 +465,28 @@ passes_naked_functions_must_use_noreturn =
     asm in naked functions must use `noreturn` option
     .suggestion = consider specifying that the asm block is responsible for returning from the function
 
-passes_attr_only_on_main =
-    `{$attr}` attribute can only be used on `fn main()`
+passes_naked_functions_operands =
+    only `const` and `sym` operands are supported in naked functions
 
-passes_attr_only_on_root_main =
-    `{$attr}` attribute can only be used on root `fn main()`
+passes_naked_tracked_caller =
+    cannot use `#[track_caller]` with `#[naked]`
 
-passes_attr_only_in_functions =
-    `{$attr}` attribute can only be used on functions
+passes_no_coverage_fn_defn =
+    `#[no_coverage]` may only be applied to function definitions
 
-passes_multiple_rustc_main =
-    multiple functions with a `#[rustc_main]` attribute
-    .first = first `#[rustc_main]` function
-    .additional = additional `#[rustc_main]` function
+passes_no_coverage_ignored_function_prototype =
+    `#[no_coverage]` is ignored on function prototypes
 
-passes_multiple_start_functions =
-    multiple `start` functions
-    .label = multiple `start` functions
-    .previous = previous `#[start]` function here
+passes_no_coverage_not_coverable =
+    `#[no_coverage]` must be applied to coverable code
+    .label = not coverable code
 
-passes_extern_main =
-    the `main` function cannot be declared in an `extern` block
+passes_no_coverage_propagate =
+    `#[no_coverage]` does not propagate into items and must be applied to the contained functions directly
 
-passes_unix_sigpipe_values =
-    valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl`
+passes_no_link =
+    attribute should be applied to an `extern crate` item
+    .label = not an `extern crate` item
 
 passes_no_main_function =
     `main` function not found in crate `{$crate_name}`
@@ -546,54 +502,27 @@ passes_no_main_function =
     .teach_note = If you don't know the basics of Rust, you can go look to the Rust Book to get started: https://doc.rust-lang.org/book/
     .non_function_main = non-function item at `crate::main` is found
 
-passes_duplicate_lang_item =
-    found duplicate lang item `{$lang_item_name}`
-    .first_defined_span = the lang item is first defined here
-    .first_defined_crate_depends = the lang item is first defined in crate `{$orig_crate_name}` (which `{$orig_dependency_of}` depends on)
-    .first_defined_crate = the lang item is first defined in crate `{$orig_crate_name}`.
-    .first_definition_local = first definition in the local crate (`{$orig_crate_name}`)
-    .second_definition_local = second definition in the local crate (`{$crate_name}`)
-    .first_definition_path = first definition in `{$orig_crate_name}` loaded from {$orig_path}
-    .second_definition_path = second definition in `{$crate_name}` loaded from {$path}
+passes_no_mangle =
+    attribute should be applied to a free function, impl method or static
+    .warn = {-passes_previously_accepted}
+    .label = not a free function, impl method or static
 
-passes_duplicate_lang_item_crate =
-    duplicate lang item in crate `{$crate_name}`: `{$lang_item_name}`.
-    .first_defined_span = the lang item is first defined here
-    .first_defined_crate_depends = the lang item is first defined in crate `{$orig_crate_name}` (which `{$orig_dependency_of}` depends on)
-    .first_defined_crate = the lang item is first defined in crate `{$orig_crate_name}`.
-    .first_definition_local = first definition in the local crate (`{$orig_crate_name}`)
-    .second_definition_local = second definition in the local crate (`{$crate_name}`)
-    .first_definition_path = first definition in `{$orig_crate_name}` loaded from {$orig_path}
-    .second_definition_path = second definition in `{$crate_name}` loaded from {$path}
+passes_no_mangle_foreign =
+    `#[no_mangle]` has no effect on a foreign {$foreign_item_kind}
+    .warn = {-passes_previously_accepted}
+    .label = foreign {$foreign_item_kind}
+    .note = symbol names in extern blocks are not mangled
+    .suggestion = remove this attribute
 
-passes_duplicate_lang_item_crate_depends =
-    duplicate lang item in crate `{$crate_name}` (which `{$dependency_of}` depends on): `{$lang_item_name}`.
-    .first_defined_span = the lang item is first defined here
-    .first_defined_crate_depends = the lang item is first defined in crate `{$orig_crate_name}` (which `{$orig_dependency_of}` depends on)
-    .first_defined_crate = the lang item is first defined in crate `{$orig_crate_name}`.
-    .first_definition_local = first definition in the local crate (`{$orig_crate_name}`)
-    .second_definition_local = second definition in the local crate (`{$crate_name}`)
-    .first_definition_path = first definition in `{$orig_crate_name}` loaded from {$orig_path}
-    .second_definition_path = second definition in `{$crate_name}` loaded from {$path}
+passes_no_patterns =
+    patterns not allowed in naked function parameters
 
-passes_incorrect_target =
-    `{$name}` language item must be applied to a {$kind} with {$at_least ->
-        [true] at least {$num}
-        *[false] {$num}
-    } generic {$num ->
-        [one] argument
-        *[other] arguments
-    }
-    .label = this {$kind} has {$actual_num} generic {$actual_num ->
-        [one] argument
-        *[other] arguments
-    }
+passes_non_exported_macro_invalid_attrs =
+    attribute should be applied to function or closure
+    .label = not a function or closure
 
-passes_useless_assignment =
-    useless assignment of {$is_field_assign ->
-        [true] field
-        *[false] variable
-    } of type `{$ty}` to itself
+passes_object_lifetime_err =
+    {$repr}
 
 passes_only_has_effect_on =
     `#[{$attr_name}]` only has an effect on {$target_name ->
@@ -603,165 +532,236 @@ passes_only_has_effect_on =
         *[unspecified] (unspecified--this is a compiler bug)
     }
 
-passes_object_lifetime_err =
-    {$repr}
+passes_outer_crate_level_attr =
+    crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
 
-passes_unrecognized_repr_hint =
-    unrecognized representation hint
-    .help = valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`
+passes_outside_loop =
+    `{$name}` outside of a loop{$is_break ->
+        [true] {" or labeled block"}
+        *[false] {""}
+    }
+    .label = cannot `{$name}` outside of a loop{$is_break ->
+        [true] {" or labeled block"}
+        *[false] {""}
+    }
 
-passes_attr_application_enum =
-    attribute should be applied to an enum
-    .label = not an enum
+passes_params_not_allowed =
+    referencing function parameters is not allowed in naked functions
+    .help = follow the calling convention in asm block to use parameters
 
-passes_attr_application_struct =
+passes_parent_info =
+    {$num ->
+      [one] {$descr}
+     *[other] {$descr}s
+    } in this {$parent_descr}
+
+passes_pass_by_value =
+    `pass_by_value` attribute should be applied to a struct, enum or type alias
+    .label = is not a struct, enum or type alias
+
+passes_plugin_registrar =
+    `#[plugin_registrar]` only has an effect on functions
+
+passes_proc_macro_bad_sig = {$kind} has incorrect signature
+
+passes_repr_conflicting =
+    conflicting representation hints
+
+passes_repr_ident =
+    meta item in `repr` must be an identifier
+
+passes_rustc_allow_const_fn_unstable =
+    attribute should be applied to `const fn`
+    .label = not a `const fn`
+
+passes_rustc_dirty_clean =
+    attribute requires -Z query-dep-graph to be enabled
+
+passes_rustc_layout_scalar_valid_range_arg =
+    expected exactly one integer literal argument
+
+passes_rustc_layout_scalar_valid_range_not_struct =
     attribute should be applied to a struct
     .label = not a struct
 
-passes_attr_application_struct_union =
-    attribute should be applied to a struct or union
-    .label = not a struct or union
+passes_rustc_legacy_const_generics_index =
+    #[rustc_legacy_const_generics] must have one index for each generic parameter
+    .label = generic parameters
 
-passes_attr_application_struct_enum_union =
-    attribute should be applied to a struct, enum, or union
-    .label = not a struct, enum, or union
+passes_rustc_legacy_const_generics_index_exceed =
+    index exceeds number of arguments
+    .label = there {$arg_count ->
+        [one] is
+        *[other] are
+    } only {$arg_count} {$arg_count ->
+        [one] argument
+        *[other] arguments
+    }
 
-passes_attr_application_struct_enum_function_method_union =
-    attribute should be applied to a struct, enum, function, associated function, or union
-    .label = not a struct, enum, function, associated function, or union
+passes_rustc_legacy_const_generics_index_negative =
+    arguments should be non-negative integers
 
-passes_transparent_incompatible =
-    transparent {$target} cannot have other repr hints
+passes_rustc_legacy_const_generics_only =
+    #[rustc_legacy_const_generics] functions must only have const generics
+    .label = non-const generic parameter
 
-passes_deprecated_attribute =
-    deprecated attribute must be paired with either stable or unstable attribute
+passes_rustc_lint_opt_deny_field_access =
+    `#[rustc_lint_opt_deny_field_access]` should be applied to a field
+    .label = not a field
 
-passes_useless_stability =
-    this stability annotation is useless
-    .label = useless stability annotation
-    .item = the stability attribute annotates this item
+passes_rustc_lint_opt_ty =
+    `#[rustc_lint_opt_ty]` should be applied to a struct
+    .label = not a struct
 
-passes_invalid_stability =
-    invalid stability version found
-    .label = invalid stability version
-    .item = the stability attribute annotates this item
+passes_rustc_std_internal_symbol =
+    attribute should be applied to functions or statics
+    .label = not a function or static
 
-passes_cannot_stabilize_deprecated =
-    an API can't be stabilized after it is deprecated
-    .label = invalid version
-    .item = the stability attribute annotates this item
+passes_should_be_applied_to_fn =
+    attribute should be applied to a function definition
+    .label = {$on_crate ->
+        [true] cannot be applied to crates
+        *[false] not a function definition
+    }
 
-passes_invalid_deprecation_version =
-    invalid deprecation version found
-    .label = invalid deprecation version
-    .item = the stability attribute annotates this item
+passes_should_be_applied_to_static =
+    attribute should be applied to a static
+    .label = not a static
 
-passes_missing_stability_attr =
-    {$descr} has missing stability attribute
+passes_should_be_applied_to_struct_enum =
+    attribute should be applied to a struct or enum
+    .label = not a struct or enum
 
-passes_missing_const_stab_attr =
-    {$descr} has missing const stability attribute
+passes_should_be_applied_to_trait =
+    attribute should be applied to a trait
+    .label = not a trait
 
-passes_trait_impl_const_stable =
-    trait implementations cannot be const stable yet
-    .note = see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
+passes_size =
+    size: {$size}
 
-passes_feature_only_on_nightly =
-    `#![feature]` may not be used on the {$release_channel} release channel
+passes_skipping_const_checks = skipping const checks
 
-passes_unknown_feature =
-    unknown feature `{$feature}`
+passes_stability_promotable =
+    attribute cannot be applied to an expression
 
-passes_implied_feature_not_exist =
-    feature `{$implied_by}` implying `{$feature}` does not exist
+passes_string_interpolation_only_works = string interpolation only works in `format!` invocations
 
-passes_duplicate_feature_err =
-    the feature `{$feature}` has already been declared
+passes_target_feature_on_statement =
+    {passes_should_be_applied_to_fn}
+    .warn = {-passes_previously_accepted}
+    .label = {passes_should_be_applied_to_fn.label}
 
-passes_missing_const_err =
-    attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
-    .help = make the function or method const
-    .label = attribute specified here
+passes_trait_impl_const_stable =
+    trait implementations cannot be const stable yet
+    .note = see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
 
-passes_dead_codes =
-    { $multiple ->
-      *[true] multiple {$descr}s are
-       [false] { $num ->
-         [one] {$descr} {$name_list} is
-        *[other] {$descr}s {$name_list} are
-       }
-    } never {$participle}
+passes_transparent_incompatible =
+    transparent {$target} cannot have other repr hints
 
-passes_change_fields_to_be_of_unit_type =
-    consider changing the { $num ->
-      [one] field
-     *[other] fields
-    } to be of unit type to suppress this warning while preserving the field numbering, or remove the { $num ->
-      [one] field
-     *[other] fields
-    }
+passes_undefined_naked_function_abi =
+    Rust ABI is unsupported in naked functions
 
-passes_parent_info =
-    {$num ->
-      [one] {$descr}
-     *[other] {$descr}s
-    } in this {$parent_descr}
+passes_unix_sigpipe_values =
+    valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl`
 
-passes_ignored_derived_impls =
-    `{$name}` has {$trait_list_len ->
-      [one] a derived impl
-     *[other] derived impls
-    } for the {$trait_list_len ->
-      [one] trait {$trait_list}, but this is
-     *[other] traits {$trait_list}, but these are
-    } intentionally ignored during dead code analysis
+passes_unknown_external_lang_item =
+    unknown external lang item: `{$lang_item}`
 
-passes_proc_macro_bad_sig = {$kind} has incorrect signature
+passes_unknown_feature =
+    unknown feature `{$feature}`
 
-passes_skipping_const_checks = skipping const checks
+passes_unknown_lang_item =
+    definition of an unknown language item: `{$name}`
+    .label = definition of unknown language item `{$name}`
 
-passes_invalid_macro_export_arguments = `{$name}` isn't a valid `#[macro_export]` argument
+passes_unlabeled_cf_in_while_condition =
+    `break` or `continue` with no label in the condition of a `while` loop
+    .label = unlabeled `{$cf_type}` in the condition of a `while` loop
 
-passes_invalid_macro_export_arguments_too_many_items = `#[macro_export]` can only take 1 or 0 arguments
+passes_unlabeled_in_labeled_block =
+    unlabeled `{$cf_type}` inside of a labeled block
+    .label = `{$cf_type}` statements that would diverge to or through a labeled block need to bear a label
+
+passes_unnecessary_partial_stable_feature = the feature `{$feature}` has been partially stabilized since {$since} and is succeeded by the feature `{$implies}`
+    .suggestion = if you are using features which are still unstable, change to using `{$implies}`
+    .suggestion_remove = if you are using features which are now stable, remove this line
+
+passes_unnecessary_stable_feature = the feature `{$feature}` has been stable since {$since} and no longer requires an attribute to enable
 
 passes_unreachable_due_to_uninhabited = unreachable {$descr}
     .label = unreachable {$descr}
     .label_orig = any code following this expression is unreachable
     .note = this expression has type `{$ty}`, which is uninhabited
 
-passes_unused_var_maybe_capture_ref = unused variable: `{$name}`
-    .help = did you mean to capture by reference instead?
+passes_unrecognized_field =
+    unrecognized field name `{$name}`
+
+passes_unrecognized_repr_hint =
+    unrecognized representation hint
+    .help = valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`
+
+passes_unused =
+    unused attribute
+    .suggestion = remove this attribute
+
+passes_unused_assign = value assigned to `{$name}` is never read
+    .help = maybe it is overwritten before being read?
+
+passes_unused_assign_passed = value passed to `{$name}` is never read
+    .help = maybe it is overwritten before being read?
 
 passes_unused_capture_maybe_capture_ref = value captured by `{$name}` is never read
     .help = did you mean to capture by reference instead?
 
-passes_unused_var_remove_field = unused variable: `{$name}`
-passes_unused_var_remove_field_suggestion = try removing the field
+passes_unused_default_method_body_const_note =
+    `default_method_body_is_const` has been replaced with `#[const_trait]` on traits
 
-passes_unused_var_assigned_only = variable `{$name}` is assigned to, but never used
-    .note = consider using `_{$name}` instead
+passes_unused_duplicate =
+    unused attribute
+    .suggestion = remove this attribute
+    .note = attribute also specified here
+    .warn = {-passes_previously_accepted}
 
-passes_unnecessary_stable_feature = the feature `{$feature}` has been stable since {$since} and no longer requires an attribute to enable
+passes_unused_empty_lints_note =
+    attribute `{$name}` with an empty list has no effect
 
-passes_unnecessary_partial_stable_feature = the feature `{$feature}` has been partially stabilized since {$since} and is succeeded by the feature `{$implies}`
-    .suggestion = if you are using features which are still unstable, change to using `{$implies}`
-    .suggestion_remove = if you are using features which are now stable, remove this line
+passes_unused_multiple =
+    multiple `{$name}` attributes
+    .suggestion = remove this attribute
+    .note = attribute also specified here
 
-passes_ineffective_unstable_impl = an `#[unstable]` annotation here has no effect
-    .note = see issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information
+passes_unused_no_lints_note =
+    attribute `{$name}` without any lints has no effect
 
-passes_unused_assign = value assigned to `{$name}` is never read
-    .help = maybe it is overwritten before being read?
+passes_unused_var_assigned_only = variable `{$name}` is assigned to, but never used
+    .note = consider using `_{$name}` instead
 
-passes_unused_assign_passed = value passed to `{$name}` is never read
-    .help = maybe it is overwritten before being read?
+passes_unused_var_maybe_capture_ref = unused variable: `{$name}`
+    .help = did you mean to capture by reference instead?
 
-passes_maybe_string_interpolation = you might have meant to use string interpolation in this string literal
-passes_string_interpolation_only_works = string interpolation only works in `format!` invocations
+passes_unused_var_remove_field = unused variable: `{$name}`
+passes_unused_var_remove_field_suggestion = try removing the field
+
+passes_unused_variable_try_ignore = unused variable: `{$name}`
+    .suggestion = try ignoring the field
 
 passes_unused_variable_try_prefix = unused variable: `{$name}`
     .label = unused variable
     .suggestion = if this is intentional, prefix it with an underscore
 
-passes_unused_variable_try_ignore = unused variable: `{$name}`
-    .suggestion = try ignoring the field
+passes_used_compiler_linker =
+    `used(compiler)` and `used(linker)` can't be used together
+
+passes_used_static =
+    attribute must be applied to a `static` variable
+
+passes_useless_assignment =
+    useless assignment of {$is_field_assign ->
+        [true] field
+        *[false] variable
+    } of type `{$ty}` to itself
+
+passes_useless_stability =
+    this stability annotation is useless
+    .label = useless stability annotation
+    .item = the stability attribute annotates this item
diff --git a/compiler/rustc_privacy/messages.ftl b/compiler/rustc_privacy/messages.ftl
index a26d1b2b381..b68e8a78aab 100644
--- a/compiler/rustc_privacy/messages.ftl
+++ b/compiler/rustc_privacy/messages.ftl
@@ -2,22 +2,22 @@ privacy_field_is_private = field `{$field_name}` of {$variant_descr} `{$def_path
 privacy_field_is_private_is_update_syntax_label = field `{$field_name}` is private
 privacy_field_is_private_label = private field
 
-privacy_item_is_private = {$kind} `{$descr}` is private
-    .label = private {$kind}
-privacy_unnamed_item_is_private = {$kind} is private
-    .label = private {$kind}
+privacy_from_private_dep_in_public_interface =
+    {$kind} `{$descr}` from private dependency '{$krate}' in public interface
 
 privacy_in_public_interface = {$vis_descr} {$kind} `{$descr}` in public interface
     .label = can't leak {$vis_descr} {$kind}
     .visibility_label = `{$descr}` declared as {$vis_descr}
 
-privacy_report_effective_visibility = {$descr}
-
-privacy_from_private_dep_in_public_interface =
-    {$kind} `{$descr}` from private dependency '{$krate}' in public interface
-
+privacy_item_is_private = {$kind} `{$descr}` is private
+    .label = private {$kind}
 privacy_private_in_public_lint =
     {$vis_descr} {$kind} `{$descr}` in public interface (error {$kind ->
         [trait] E0445
         *[other] E0446
     })
+
+privacy_report_effective_visibility = {$descr}
+
+privacy_unnamed_item_is_private = {$kind} is private
+    .label = private {$kind}
diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml
index e596993465c..c9353b6fc9f 100644
--- a/compiler/rustc_query_impl/Cargo.toml
+++ b/compiler/rustc_query_impl/Cargo.toml
@@ -7,7 +7,7 @@ edition = "2021"
 
 
 [dependencies]
-memoffset = { version = "0.6.0", features = ["unstable_const"] }
+memoffset = { version = "0.8.0", features = ["unstable_const"] }
 field-offset = "0.3.5"
 measureme = "10.0.0"
 rustc_ast = { path = "../rustc_ast" }
diff --git a/compiler/rustc_query_system/messages.ftl b/compiler/rustc_query_system/messages.ftl
index 0d01123ad88..49b423d1ade 100644
--- a/compiler/rustc_query_system/messages.ftl
+++ b/compiler/rustc_query_system/messages.ftl
@@ -1,30 +1,30 @@
-query_system_reentrant = internal compiler error: reentrant incremental verify failure, suppressing message
-
-query_system_increment_compilation = internal compiler error: encountered incremental compilation error with {$dep_node}
-    .help = This is a known issue with the compiler. Run {$run_cmd} to allow your project to compile
-
-query_system_increment_compilation_note1 = Please follow the instructions below to create a bug report with the provided information
-query_system_increment_compilation_note2 = See <https://github.com/rust-lang/rust/issues/84970> for more information
-
 query_system_cycle = cycle detected when {$stack_bottom}
 
-query_system_cycle_usage = cycle used when {$usage}
+query_system_cycle_recursive_trait_alias = trait aliases cannot be recursive
 
-query_system_cycle_stack_single = ...which immediately requires {$stack_bottom} again
+query_system_cycle_recursive_ty_alias = type aliases cannot be recursive
+query_system_cycle_recursive_ty_alias_help1 = consider using a struct, enum, or union instead to break the cycle
+query_system_cycle_recursive_ty_alias_help2 = see <https://doc.rust-lang.org/reference/types.html#recursive-types> for more information
 
 query_system_cycle_stack_middle = ...which requires {$desc}...
 
 query_system_cycle_stack_multiple = ...which again requires {$stack_bottom}, completing the cycle
 
-query_system_cycle_recursive_ty_alias = type aliases cannot be recursive
-query_system_cycle_recursive_ty_alias_help1 = consider using a struct, enum, or union instead to break the cycle
-query_system_cycle_recursive_ty_alias_help2 = see <https://doc.rust-lang.org/reference/types.html#recursive-types> for more information
+query_system_cycle_stack_single = ...which immediately requires {$stack_bottom} again
 
-query_system_cycle_recursive_trait_alias = trait aliases cannot be recursive
+query_system_cycle_usage = cycle used when {$usage}
 
 query_system_cycle_which_requires = ...which requires {$desc}...
 
+query_system_increment_compilation = internal compiler error: encountered incremental compilation error with {$dep_node}
+    .help = This is a known issue with the compiler. Run {$run_cmd} to allow your project to compile
+
+query_system_increment_compilation_note1 = Please follow the instructions below to create a bug report with the provided information
+query_system_increment_compilation_note2 = See <https://github.com/rust-lang/rust/issues/84970> for more information
+
+query_system_layout_of_depth = query depth increased by {$depth} when {$desc}
+
 query_system_query_overflow = queries overflow the depth limit!
     .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
 
-query_system_layout_of_depth = query depth increased by {$depth} when {$desc}
+query_system_reentrant = internal compiler error: reentrant incremental verify failure, suppressing message
diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl
index 345255c4c69..539b88aa9d3 100644
--- a/compiler/rustc_resolve/messages.ftl
+++ b/compiler/rustc_resolve/messages.ftl
@@ -1,79 +1,90 @@
-resolve_parent_module_reset_for_binding =
-    parent module is reset for binding
+resolve_accessible_unsure = not sure whether the path is accessible or not
+    .note = the type may have associated items, but we are currently not checking them
+
+resolve_add_as_non_derive =
+    add as non-Derive macro
+    `#[{$macro_path}]`
 
 resolve_ampersand_used_without_explicit_lifetime_name =
     `&` without an explicit lifetime name cannot be used here
     .note = explicit lifetime name needed here
 
-resolve_underscore_lifetime_name_cannot_be_used_here =
-    `'_` cannot be used here
-    .note = `'_` is a reserved lifetime name
+resolve_ancestor_only =
+    visibilities can only be restricted to ancestor modules
 
-resolve_crate_may_not_be_imported =
-    `$crate` may not be imported
+resolve_associated_const_with_similar_name_exists =
+    there is an associated constant with a similar name
 
-resolve_crate_root_imports_must_be_named_explicitly =
-    crate root imports need to be explicitly named: `use crate as name;`
+resolve_associated_fn_with_similar_name_exists =
+    there is an associated function with a similar name
 
-resolve_generic_params_from_outer_function =
-    can't use generic parameters from outer function
-    .label = use of generic parameter from outer function
-    .suggestion = try using a local generic parameter instead
+resolve_associated_type_with_similar_name_exists =
+    there is an associated type with a similar name
 
-resolve_self_type_implicitly_declared_by_impl =
-    `Self` type implicitly declared here, by this `impl`
+resolve_attempt_to_use_non_constant_value_in_constant =
+    attempt to use a non-constant value in a constant
+
+resolve_attempt_to_use_non_constant_value_in_constant_label_with_suggestion =
+    non-constant value
+
+resolve_attempt_to_use_non_constant_value_in_constant_with_suggestion =
+    consider using `{$suggestion}` instead of `{$current}`
+
+resolve_attempt_to_use_non_constant_value_in_constant_without_suggestion =
+    this would need to be a `{$suggestion}`
+
+resolve_binding_shadows_something_unacceptable =
+    {$shadowing_binding}s cannot shadow {$shadowed_binding}s
+    .label = cannot be named the same as {$article} {$shadowed_binding}
+    .label_shadowed_binding = the {$shadowed_binding} `{$name}` is {$participle} here
+
+resolve_binding_shadows_something_unacceptable_suggestion =
+    try specify the pattern arguments
+
+resolve_cannot_capture_dynamic_environment_in_fn_item =
+    can't capture dynamic environment in a fn item
+    .help = use the `|| {"{"} ... {"}"}` closure form instead
 
 resolve_cannot_use_self_type_here =
     can't use `Self` here
 
-resolve_use_a_type_here_instead =
-    use a type here instead
-
-resolve_type_param_from_outer_fn =
-    type parameter from outer function
+resolve_const_not_member_of_trait =
+    const `{$const_}` is not a member of trait `{$trait_}`
+    .label = not a member of trait `{$trait_}`
 
 resolve_const_param_from_outer_fn =
     const parameter from outer function
 
-resolve_try_using_local_generic_parameter =
-    try using a local generic parameter instead
-
-resolve_try_adding_local_generic_param_on_method =
-    try adding a local generic parameter in this method instead
-
-resolve_help_try_using_local_generic_param =
-    try using a local generic parameter instead
+resolve_const_param_in_enum_discriminant =
+    const parameters may not be used in enum discriminant values
 
-resolve_name_is_already_used_as_generic_parameter =
-    the name `{$name}` is already used for a generic parameter in this item's generic parameters
-    .label = already used
-    .first_use_of_name = first use of `{$name}`
+resolve_const_param_in_non_trivial_anon_const =
+    const parameters may only be used as standalone arguments, i.e. `{$name}`
 
-resolve_method_not_member_of_trait =
-    method `{$method}` is not a member of trait `{$trait_}`
-    .label = not a member of trait `{$trait_}`
+resolve_const_param_in_ty_of_const_param =
+    const parameters may not be used in the type of const parameters
 
-resolve_associated_fn_with_similar_name_exists =
-    there is an associated function with a similar name
+resolve_crate_may_not_be_imported =
+    `$crate` may not be imported
 
-resolve_type_not_member_of_trait =
-    type `{$type_}` is not a member of trait `{$trait_}`
-    .label = not a member of trait `{$trait_}`
+resolve_crate_root_imports_must_be_named_explicitly =
+    crate root imports need to be explicitly named: `use crate as name;`
 
-resolve_associated_type_with_similar_name_exists =
-    there is an associated type with a similar name
+resolve_expected_found =
+    expected module, found {$res} `{$path_str}`
+    .label = not a module
 
-resolve_const_not_member_of_trait =
-    const `{$const_}` is not a member of trait `{$trait_}`
-    .label = not a member of trait `{$trait_}`
+resolve_forward_declared_generic_param =
+    generic parameters with a default cannot use forward declared identifiers
+    .label = defaulted generic parameters cannot be forward declared
 
-resolve_associated_const_with_similar_name_exists =
-    there is an associated constant with a similar name
+resolve_generic_params_from_outer_function =
+    can't use generic parameters from outer function
+    .label = use of generic parameter from outer function
+    .suggestion = try using a local generic parameter instead
 
-resolve_variable_bound_with_different_mode =
-    variable `{$variable_name}` is bound inconsistently across alternatives separated by `|`
-    .label = bound in different ways
-    .first_binding_span = first binding
+resolve_help_try_using_local_generic_param =
+    try using a local generic parameter instead
 
 resolve_ident_bound_more_than_once_in_parameter_list =
     identifier `{$identifier}` is bound more than once in this parameter list
@@ -83,125 +94,104 @@ resolve_ident_bound_more_than_once_in_same_pattern =
     identifier `{$identifier}` is bound more than once in the same pattern
     .label = used in a pattern more than once
 
-resolve_undeclared_label =
-    use of undeclared label `{$name}`
-    .label = undeclared label `{$name}`
+resolve_imported_crate = `$crate` may not be imported
 
-resolve_label_with_similar_name_reachable =
-    a label with a similar name is reachable
+resolve_indeterminate =
+    cannot determine resolution for the visibility
 
-resolve_try_using_similarly_named_label =
-    try using similarly named label
+resolve_invalid_asm_sym =
+    invalid `sym` operand
+    .label = is a local variable
+    .help = `sym` operands must refer to either a function or a static
 
-resolve_unreachable_label_with_similar_name_exists =
-    a label with a similar name exists but is unreachable
+resolve_label_with_similar_name_reachable =
+    a label with a similar name is reachable
 
-resolve_self_import_can_only_appear_once_in_the_list =
-    `self` import can only appear once in an import list
-    .label = can only appear once in an import list
+resolve_lifetime_param_in_enum_discriminant =
+    lifetime parameters may not be used in enum discriminant values
 
-resolve_self_import_only_in_import_list_with_non_empty_prefix =
-    `self` import can only appear in an import list with a non-empty prefix
-    .label = can only appear in an import list with a non-empty prefix
+resolve_lifetime_param_in_non_trivial_anon_const =
+    lifetime parameters may not be used in const expressions
 
-resolve_cannot_capture_dynamic_environment_in_fn_item =
-    can't capture dynamic environment in a fn item
-    .help = use the `|| {"{"} ... {"}"}` closure form instead
+resolve_lifetime_param_in_ty_of_const_param =
+    lifetime parameters may not be used in the type of const parameters
 
-resolve_attempt_to_use_non_constant_value_in_constant =
+resolve_lowercase_self =
     attempt to use a non-constant value in a constant
+    .suggestion = try using `Self`
 
-resolve_attempt_to_use_non_constant_value_in_constant_with_suggestion =
-    consider using `{$suggestion}` instead of `{$current}`
-
-resolve_attempt_to_use_non_constant_value_in_constant_label_with_suggestion =
-    non-constant value
+resolve_macro_expected_found =
+    expected {$expected}, found {$found} `{$macro_path}`
 
-resolve_attempt_to_use_non_constant_value_in_constant_without_suggestion =
-    this would need to be a `{$suggestion}`
+resolve_macro_use_extern_crate_self = `#[macro_use]` is not supported on `extern crate self`
 
-resolve_self_imports_only_allowed_within =
-    `self` imports are only allowed within a {"{"} {"}"} list
+resolve_method_not_member_of_trait =
+    method `{$method}` is not a member of trait `{$trait_}`
+    .label = not a member of trait `{$trait_}`
 
-resolve_self_imports_only_allowed_within_suggestion =
-    consider importing the module directly
+resolve_module_only =
+    visibility must resolve to a module
 
-resolve_self_imports_only_allowed_within_multipart_suggestion =
-    alternatively, use the multi-path `use` syntax to import `self`
+resolve_name_is_already_used_as_generic_parameter =
+    the name `{$name}` is already used for a generic parameter in this item's generic parameters
+    .label = already used
+    .first_use_of_name = first use of `{$name}`
 
-resolve_binding_shadows_something_unacceptable =
-    {$shadowing_binding}s cannot shadow {$shadowed_binding}s
-    .label = cannot be named the same as {$article} {$shadowed_binding}
-    .label_shadowed_binding = the {$shadowed_binding} `{$name}` is {$participle} here
+resolve_param_in_enum_discriminant =
+    generic parameters may not be used in enum discriminant values
+    .label = cannot perform const operation using `{$name}`
 
-resolve_binding_shadows_something_unacceptable_suggestion =
-    try specify the pattern arguments
+resolve_param_in_non_trivial_anon_const =
+    generic parameters may not be used in const operations
+    .label = cannot perform const operation using `{$name}`
 
-resolve_forward_declared_generic_param =
-    generic parameters with a default cannot use forward declared identifiers
-    .label = defaulted generic parameters cannot be forward declared
+resolve_param_in_non_trivial_anon_const_help =
+    use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 resolve_param_in_ty_of_const_param =
     the type of const parameters must not depend on other generic parameters
     .label = the type must not depend on the parameter `{$name}`
 
-resolve_type_param_in_ty_of_const_param =
-    type parameters may not be used in the type of const parameters
-
-resolve_const_param_in_ty_of_const_param =
-    const parameters may not be used in the type of const parameters
-
-resolve_lifetime_param_in_ty_of_const_param =
-    lifetime parameters may not be used in the type of const parameters
-
-resolve_self_in_generic_param_default =
-    generic parameters cannot use `Self` in their defaults
-    .label = `Self` in generic parameter default
-
-resolve_param_in_non_trivial_anon_const =
-    generic parameters may not be used in const operations
-    .label = cannot perform const operation using `{$name}`
+resolve_parent_module_reset_for_binding =
+    parent module is reset for binding
 
-resolve_param_in_non_trivial_anon_const_help =
-    use `#![feature(generic_const_exprs)]` to allow generic const expressions
+resolve_proc_macro_same_crate = can't use a procedural macro from the same crate that defines it
+    .help = you can define integration tests in a directory named `tests`
 
-resolve_type_param_in_non_trivial_anon_const =
-    type parameters may not be used in const expressions
+resolve_relative_2018 =
+    relative paths are not supported in visibilities in 2018 edition or later
+    .suggestion = try
 
-resolve_const_param_in_non_trivial_anon_const =
-    const parameters may only be used as standalone arguments, i.e. `{$name}`
+resolve_remove_surrounding_derive =
+    remove from the surrounding `derive()`
 
-resolve_lifetime_param_in_non_trivial_anon_const =
-    lifetime parameters may not be used in const expressions
+resolve_self_import_can_only_appear_once_in_the_list =
+    `self` import can only appear once in an import list
+    .label = can only appear once in an import list
 
-resolve_unreachable_label =
-    use of unreachable label `{$name}`
-    .label = unreachable label `{$name}`
-    .label_definition_span = unreachable label defined here
-    .note = labels are unreachable through functions, closures, async blocks and modules
+resolve_self_import_only_in_import_list_with_non_empty_prefix =
+    `self` import can only appear in an import list with a non-empty prefix
+    .label = can only appear in an import list with a non-empty prefix
 
-resolve_unreachable_label_suggestion_use_similarly_named =
-    try using similarly named label
+resolve_self_imports_only_allowed_within =
+    `self` imports are only allowed within a {"{"} {"}"} list
 
-resolve_unreachable_label_similar_name_reachable =
-    a label with a similar name is reachable
+resolve_self_imports_only_allowed_within_multipart_suggestion =
+    alternatively, use the multi-path `use` syntax to import `self`
 
-resolve_unreachable_label_similar_name_unreachable =
-    a label with a similar name exists but is also unreachable
+resolve_self_imports_only_allowed_within_suggestion =
+    consider importing the module directly
 
-resolve_trait_impl_mismatch =
-    item `{$name}` is an associated {$kind}, which doesn't match its trait `{$trait_path}`
-    .label = does not match trait
-    .label_trait_item = item in trait
+resolve_self_in_generic_param_default =
+    generic parameters cannot use `Self` in their defaults
+    .label = `Self` in generic parameter default
 
-resolve_invalid_asm_sym =
-    invalid `sym` operand
-    .label = is a local variable
-    .help = `sym` operands must refer to either a function or a static
+resolve_self_type_implicitly_declared_by_impl =
+    `Self` type implicitly declared here, by this `impl`
 
-resolve_lowercase_self =
-    attempt to use a non-constant value in a constant
-    .suggestion = try using `Self`
+resolve_tool_module_imported =
+    cannot use a tool module through an import
+    .note = the tool module imported here
 
 resolve_trait_impl_duplicate =
     duplicate definitions with name `{$name}`:
@@ -209,56 +199,66 @@ resolve_trait_impl_duplicate =
     .old_span_label = previous definition here
     .trait_item_span = item in trait
 
-resolve_relative_2018 =
-    relative paths are not supported in visibilities in 2018 edition or later
-    .suggestion = try
+resolve_trait_impl_mismatch =
+    item `{$name}` is an associated {$kind}, which doesn't match its trait `{$trait_path}`
+    .label = does not match trait
+    .label_trait_item = item in trait
 
-resolve_ancestor_only =
-    visibilities can only be restricted to ancestor modules
+resolve_try_adding_local_generic_param_on_method =
+    try adding a local generic parameter in this method instead
 
-resolve_expected_found =
-    expected module, found {$res} `{$path_str}`
-    .label = not a module
+resolve_try_using_local_generic_parameter =
+    try using a local generic parameter instead
 
-resolve_indeterminate =
-    cannot determine resolution for the visibility
+resolve_try_using_similarly_named_label =
+    try using similarly named label
 
-resolve_tool_module_imported =
-    cannot use a tool module through an import
-    .note = the tool module imported here
+resolve_type_not_member_of_trait =
+    type `{$type_}` is not a member of trait `{$trait_}`
+    .label = not a member of trait `{$trait_}`
 
-resolve_module_only =
-    visibility must resolve to a module
+resolve_type_param_from_outer_fn =
+    type parameter from outer function
 
-resolve_macro_expected_found =
-    expected {$expected}, found {$found} `{$macro_path}`
+resolve_type_param_in_enum_discriminant =
+    type parameters may not be used in enum discriminant values
 
-resolve_remove_surrounding_derive =
-    remove from the surrounding `derive()`
+resolve_type_param_in_non_trivial_anon_const =
+    type parameters may not be used in const expressions
 
-resolve_add_as_non_derive =
-    add as non-Derive macro
-    `#[{$macro_path}]`
+resolve_type_param_in_ty_of_const_param =
+    type parameters may not be used in the type of const parameters
 
-resolve_proc_macro_same_crate = can't use a procedural macro from the same crate that defines it
-    .help = you can define integration tests in a directory named `tests`
+resolve_undeclared_label =
+    use of undeclared label `{$name}`
+    .label = undeclared label `{$name}`
 
-resolve_imported_crate = `$crate` may not be imported
+resolve_underscore_lifetime_name_cannot_be_used_here =
+    `'_` cannot be used here
+    .note = `'_` is a reserved lifetime name
 
-resolve_macro_use_extern_crate_self = `#[macro_use]` is not supported on `extern crate self`
+resolve_unreachable_label =
+    use of unreachable label `{$name}`
+    .label = unreachable label `{$name}`
+    .label_definition_span = unreachable label defined here
+    .note = labels are unreachable through functions, closures, async blocks and modules
 
-resolve_accessible_unsure = not sure whether the path is accessible or not
-    .note = the type may have associated items, but we are currently not checking them
+resolve_unreachable_label_similar_name_reachable =
+    a label with a similar name is reachable
 
-resolve_param_in_enum_discriminant =
-    generic parameters may not be used in enum discriminant values
-    .label = cannot perform const operation using `{$name}`
+resolve_unreachable_label_similar_name_unreachable =
+    a label with a similar name exists but is also unreachable
 
-resolve_type_param_in_enum_discriminant =
-    type parameters may not be used in enum discriminant values
+resolve_unreachable_label_suggestion_use_similarly_named =
+    try using similarly named label
 
-resolve_const_param_in_enum_discriminant =
-    const parameters may not be used in enum discriminant values
+resolve_unreachable_label_with_similar_name_exists =
+    a label with a similar name exists but is unreachable
 
-resolve_lifetime_param_in_enum_discriminant =
-    lifetime parameters may not be used in enum discriminant values
+resolve_use_a_type_here_instead =
+    use a type here instead
+
+resolve_variable_bound_with_different_mode =
+    variable `{$variable_name}` is bound inconsistently across alternatives separated by `|`
+    .label = bound in different ways
+    .first_binding_span = first binding
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 8c6ac822a77..377652ce71b 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -2540,7 +2540,7 @@ fn show_candidates(
                 err.note(msg);
             }
             if let Some(note) = (*note).as_deref() {
-                err.note(note);
+                err.note(note.to_string());
             }
         } else {
             let (_, descr_first, _, _) = &inaccessible_path_strings[0];
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index 7c4c05d4b94..c1bb262c0d4 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -21,7 +21,8 @@ use rustc_middle::metadata::Reexport;
 use rustc_middle::span_bug;
 use rustc_middle::ty;
 use rustc_session::lint::builtin::{
-    AMBIGUOUS_GLOB_REEXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE, UNUSED_IMPORTS,
+    AMBIGUOUS_GLOB_REEXPORTS, HIDDEN_GLOB_REEXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE,
+    UNUSED_IMPORTS,
 };
 use rustc_session::lint::BuiltinLintDiagnostics;
 use rustc_span::edit_distance::find_best_match_for_name;
@@ -526,31 +527,71 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         }
     }
 
-    pub(crate) fn check_reexport_ambiguities(
+    pub(crate) fn check_hidden_glob_reexports(
         &mut self,
         exported_ambiguities: FxHashSet<Interned<'a, NameBinding<'a>>>,
     ) {
         for module in self.arenas.local_modules().iter() {
-            module.for_each_child(self, |this, ident, ns, binding| {
-                if let NameBindingKind::Import { import, .. } = binding.kind
-                && let Some((amb_binding, _)) = binding.ambiguity
-                && binding.res() != Res::Err
-                && exported_ambiguities.contains(&Interned::new_unchecked(binding))
-                {
-                    this.lint_buffer.buffer_lint_with_diagnostic(
-                        AMBIGUOUS_GLOB_REEXPORTS,
-                        import.root_id,
-                        import.root_span,
-                        "ambiguous glob re-exports",
-                        BuiltinLintDiagnostics::AmbiguousGlobReexports {
-                            name: ident.to_string(),
-                            namespace: ns.descr().to_string(),
-                            first_reexport_span: import.root_span,
-                            duplicate_reexport_span: amb_binding.span,
-                        },
-                    );
+            for (key, resolution) in self.resolutions(module).borrow().iter() {
+                let resolution = resolution.borrow();
+
+                if let Some(binding) = resolution.binding {
+                    if let NameBindingKind::Import { import, .. } = binding.kind
+                        && let Some((amb_binding, _)) = binding.ambiguity
+                        && binding.res() != Res::Err
+                        && exported_ambiguities.contains(&Interned::new_unchecked(binding))
+                    {
+                        self.lint_buffer.buffer_lint_with_diagnostic(
+                            AMBIGUOUS_GLOB_REEXPORTS,
+                            import.root_id,
+                            import.root_span,
+                            "ambiguous glob re-exports",
+                            BuiltinLintDiagnostics::AmbiguousGlobReexports {
+                                name: key.ident.to_string(),
+                                namespace: key.ns.descr().to_string(),
+                                first_reexport_span: import.root_span,
+                                duplicate_reexport_span: amb_binding.span,
+                            },
+                        );
+                    }
+
+                    if let Some(glob_binding) = resolution.shadowed_glob {
+                        let binding_id = match binding.kind {
+                            NameBindingKind::Res(res) => {
+                                Some(self.def_id_to_node_id[res.def_id().expect_local()])
+                            }
+                            NameBindingKind::Module(module) => {
+                                Some(self.def_id_to_node_id[module.def_id().expect_local()])
+                            }
+                            NameBindingKind::Import { import, .. } => import.id(),
+                        };
+
+                        if binding.res() != Res::Err
+                            && glob_binding.res() != Res::Err
+                            && let NameBindingKind::Import { import: glob_import, .. } = glob_binding.kind
+                            && let Some(binding_id) = binding_id
+                            && let Some(glob_import_id) = glob_import.id()
+                            && let glob_import_def_id = self.local_def_id(glob_import_id)
+                            && self.effective_visibilities.is_exported(glob_import_def_id)
+                            && glob_binding.vis.is_public()
+                            && !binding.vis.is_public()
+                        {
+                            self.lint_buffer.buffer_lint_with_diagnostic(
+                                HIDDEN_GLOB_REEXPORTS,
+                                binding_id,
+                                binding.span,
+                                "private item shadows public glob re-export",
+                                BuiltinLintDiagnostics::HiddenGlobReexports {
+                                    name: key.ident.name.to_string(),
+                                    namespace: key.ns.descr().to_owned(),
+                                    glob_reexport_span: glob_binding.span,
+                                    private_item_span: binding.span,
+                                },
+                            );
+                        }
+                    }
                 }
-            });
+            }
         }
     }
 
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index df65825802e..f79f8d0c6ca 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -29,6 +29,7 @@ use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::Span;
 
+use std::borrow::Cow;
 use std::iter;
 use std::ops::Deref;
 
@@ -1248,7 +1249,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                     }),
                 ) if followed_by_brace => {
                     if let Some(sp) = closing_brace {
-                        err.span_label(span, fallback_label);
+                        err.span_label(span, fallback_label.to_string());
                         err.multipart_suggestion(
                             "surround the struct literal with parentheses",
                             vec![
@@ -1320,7 +1321,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                     );
                 }
                 _ => {
-                    err.span_label(span, fallback_label);
+                    err.span_label(span, fallback_label.to_string());
                 }
             }
         };
@@ -1333,7 +1334,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                 }))
                 | PathSource::Struct,
             ) => {
-                err.span_label(span, fallback_label);
+                err.span_label(span, fallback_label.to_string());
                 err.span_suggestion_verbose(
                     span.shrink_to_hi(),
                     "use `!` to invoke the macro",
@@ -1345,7 +1346,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                 }
             }
             (Res::Def(DefKind::Macro(MacroKind::Bang), _), _) => {
-                err.span_label(span, fallback_label);
+                err.span_label(span, fallback_label.to_string());
             }
             (Res::Def(DefKind::TyAlias, def_id), PathSource::Trait(_)) => {
                 err.span_label(span, "type aliases cannot be used as traits");
@@ -1513,7 +1514,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                 );
             }
             (Res::SelfTyParam { .. } | Res::SelfTyAlias { .. }, _) if ns == ValueNS => {
-                err.span_label(span, fallback_label);
+                err.span_label(span, fallback_label.to_string());
                 err.note("can't use `Self` as a constructor, you must use the implemented struct");
             }
             (Res::Def(DefKind::TyAlias | DefKind::AssocTy, _), _) if ns == ValueNS => {
@@ -2243,7 +2244,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
         &self,
         err: &mut Diagnostic,
         name: Option<&str>,
-        suggest: impl Fn(&mut Diagnostic, bool, Span, &str, String) -> bool,
+        suggest: impl Fn(&mut Diagnostic, bool, Span, Cow<'static, str>, String) -> bool,
     ) {
         let mut suggest_note = true;
         for rib in self.lifetime_ribs.iter().rev() {
@@ -2288,22 +2289,23 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                         (span, sugg)
                     };
                     if higher_ranked {
-                        let message = format!(
+                        let message = Cow::from(format!(
                             "consider making the {} lifetime-generic with a new `{}` lifetime",
                             kind.descr(),
                             name.unwrap_or("'a"),
-                        );
-                        should_continue = suggest(err, true, span, &message, sugg);
+                        ));
+                        should_continue = suggest(err, true, span, message, sugg);
                         err.note_once(
                             "for more information on higher-ranked polymorphism, visit \
                              https://doc.rust-lang.org/nomicon/hrtb.html",
                         );
                     } else if let Some(name) = name {
-                        let message = format!("consider introducing lifetime `{}` here", name);
-                        should_continue = suggest(err, false, span, &message, sugg);
+                        let message =
+                            Cow::from(format!("consider introducing lifetime `{}` here", name));
+                        should_continue = suggest(err, false, span, message, sugg);
                     } else {
-                        let message = "consider introducing a named lifetime parameter";
-                        should_continue = suggest(err, false, span, &message, sugg);
+                        let message = Cow::from("consider introducing a named lifetime parameter");
+                        should_continue = suggest(err, false, span, message, sugg);
                     }
                 }
                 LifetimeRibKind::Item => break,
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 3d2bd842906..fd977e8e254 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -1496,8 +1496,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             let exported_ambiguities = self.tcx.sess.time("compute_effective_visibilities", || {
                 EffectiveVisibilitiesVisitor::compute_effective_visibilities(self, krate)
             });
-            self.tcx.sess.time("check_reexport_ambiguities", || {
-                self.check_reexport_ambiguities(exported_ambiguities)
+            self.tcx.sess.time("check_hidden_glob_reexports", || {
+                self.check_hidden_glob_reexports(exported_ambiguities)
             });
             self.tcx.sess.time("finalize_macro_resolutions", || self.finalize_macro_resolutions());
             self.tcx.sess.time("late_resolve_crate", || self.late_resolve_crate(krate));
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index df5c16a9375..d8a7bcbfff9 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -827,7 +827,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 if !is_allowed(feature) && !allowed_by_implication {
                     let lint_buffer = &mut self.lint_buffer;
                     let soft_handler =
-                        |lint, span, msg: &_| lint_buffer.buffer_lint(lint, node_id, span, msg);
+                        |lint, span, msg: String| lint_buffer.buffer_lint(lint, node_id, span, msg);
                     stability::report_unstable(
                         self.tcx.sess,
                         feature,
@@ -846,7 +846,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             let (message, lint) = stability::deprecation_message_and_lint(depr, "macro", &path);
             stability::early_report_deprecation(
                 &mut self.lint_buffer,
-                &message,
+                message,
                 depr.suggestion,
                 lint,
                 span,
diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl
index a8fe560d1a7..5a0b8f9f73c 100644
--- a/compiler/rustc_session/messages.ftl
+++ b/compiler/rustc_session/messages.ftl
@@ -1,13 +1,20 @@
-session_incorrect_cgu_reuse_type =
-    CGU-reuse for `{$cgu_user_name}` is `{$actual_reuse}` but should be {$at_least ->
-    [one] {"at least "}
-    *[other] {""}
-    }`{$expected_reuse}`
+session_binary_float_literal_not_supported = binary float literal is not supported
+session_branch_protection_requires_aarch64 = `-Zbranch-protection` is only supported on aarch64
+
+session_cannot_enable_crt_static_linux = sanitizer is incompatible with statically linked libc, disable it using `-C target-feature=-crt-static`
+
+session_cannot_mix_and_match_sanitizers = `-Zsanitizer={$first}` is incompatible with `-Zsanitizer={$second}`
 
 session_cgu_not_recorded =
     CGU-reuse for `{$cgu_user_name}` is (mangled: `{$cgu_name}`) was not recorded
 
-session_feature_gate_error = {$explain}
+session_crate_name_does_not_match = `--crate-name` and `#[crate_name]` are required to match, but `{$s}` != `{$name}`
+
+session_crate_name_empty = crate name must not be empty
+
+session_crate_name_invalid = crate names cannot start with a `-`, but `{$s}` has a leading hyphen
+
+session_expr_parentheses_needed = parentheses are required to parse this as an expression
 
 session_feature_diagnostic_for_issue =
     see issue #{$n} <https://github.com/rust-lang/rust/issues/{$n}> for more information
@@ -15,91 +22,84 @@ session_feature_diagnostic_for_issue =
 session_feature_diagnostic_help =
     add `#![feature({$feature})]` to the crate attributes to enable
 
-session_not_circumvent_feature = `-Zunleash-the-miri-inside-of-you` may not be used to circumvent feature gates, except when testing error paths in the CTFE engine
-
-session_profile_use_file_does_not_exist = file `{$path}` passed to `-C profile-use` does not exist.
-
-session_linker_plugin_lto_windows_not_supported = linker plugin based LTO is not supported together with `-C prefer-dynamic` when targeting Windows-like targets
+session_feature_gate_error = {$explain}
 
-session_profile_sample_use_file_does_not_exist = file `{$path}` passed to `-C profile-sample-use` does not exist.
+session_file_is_not_writeable = output file {$file} is not writeable -- check its permissions
 
-session_target_requires_unwind_tables = target requires unwind tables, they cannot be disabled with `-C force-unwind-tables=no`
+session_hexadecimal_float_literal_not_supported = hexadecimal float literal is not supported
+session_incorrect_cgu_reuse_type =
+    CGU-reuse for `{$cgu_user_name}` is `{$actual_reuse}` but should be {$at_least ->
+    [one] {"at least "}
+    *[other] {""}
+    }`{$expected_reuse}`
 
 session_instrumentation_not_supported = {$us} instrumentation is not supported for this target
 
-session_sanitizer_not_supported = {$us} sanitizer is not supported for this target
-
-session_sanitizers_not_supported = {$us} sanitizers are not supported for this target
-
-session_cannot_mix_and_match_sanitizers = `-Zsanitizer={$first}` is incompatible with `-Zsanitizer={$second}`
-
-session_cannot_enable_crt_static_linux = sanitizer is incompatible with statically linked libc, disable it using `-C target-feature=-crt-static`
+session_int_literal_too_large = integer literal is too large
+    .note = value exceeds limit of `{$limit}`
 
-session_sanitizer_cfi_requires_lto = `-Zsanitizer=cfi` requires `-Clto`, `-Clto=thin`, or `-Clinker-plugin-lto`
+session_invalid_character_in_create_name = invalid character `{$character}` in crate name: `{$crate_name}`
 
-session_sanitizer_cfi_canonical_jump_tables_requires_cfi = `-Zsanitizer-cfi-canonical-jump-tables` requires `-Zsanitizer=cfi`
+session_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float literal
+    .label = invalid suffix `{$suffix}`
+    .help = valid suffixes are `f32` and `f64`
 
-session_sanitizer_cfi_generalize_pointers_requires_cfi = `-Zsanitizer-cfi-generalize-pointers` requires `-Zsanitizer=cfi` or `-Zsanitizer=kcfi`
+session_invalid_float_literal_width = invalid width `{$width}` for float literal
+    .help = valid widths are 32 and 64
 
-session_sanitizer_cfi_normalize_integers_requires_cfi = `-Zsanitizer-cfi-normalize-integers` requires `-Zsanitizer=cfi` or `-Zsanitizer=kcfi`
+session_invalid_int_literal_width = invalid width `{$width}` for integer literal
+    .help = valid widths are 8, 16, 32, 64 and 128
 
-session_split_lto_unit_requires_lto = `-Zsplit-lto-unit` requires `-Clto`, `-Clto=thin`, or `-Clinker-plugin-lto`
+session_invalid_literal_suffix = suffixes on {$kind} literals are invalid
+    .label = invalid suffix `{$suffix}`
 
-session_unstable_virtual_function_elimination = `-Zvirtual-function-elimination` requires `-Clto`
+session_invalid_num_literal_base_prefix = invalid base prefix for number literal
+    .note = base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+    .suggestion = try making the prefix lowercase
 
-session_unsupported_dwarf_version = requested DWARF version {$dwarf_version} is greater than 5
+session_invalid_num_literal_suffix = invalid suffix `{$suffix}` for number literal
+    .label = invalid suffix `{$suffix}`
+    .help = the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
 
-session_target_stack_protector_not_supported = `-Z stack-protector={$stack_protector}` is not supported for target {$target_triple} and will be ignored
+session_linker_plugin_lto_windows_not_supported = linker plugin based LTO is not supported together with `-C prefer-dynamic` when targeting Windows-like targets
 
-session_branch_protection_requires_aarch64 = `-Zbranch-protection` is only supported on aarch64
+session_not_circumvent_feature = `-Zunleash-the-miri-inside-of-you` may not be used to circumvent feature gates, except when testing error paths in the CTFE engine
 
-session_split_debuginfo_unstable_platform = `-Csplit-debuginfo={$debuginfo}` is unstable on this platform
+session_not_supported = not supported
 
-session_file_is_not_writeable = output file {$file} is not writeable -- check its permissions
+session_nul_in_c_str = null characters in C string literals are not supported
 
-session_crate_name_does_not_match = `--crate-name` and `#[crate_name]` are required to match, but `{$s}` != `{$name}`
+session_octal_float_literal_not_supported = octal float literal is not supported
+session_optimization_fuel_exhausted = optimization-fuel-exhausted: {$msg}
 
-session_crate_name_invalid = crate names cannot start with a `-`, but `{$s}` has a leading hyphen
+session_profile_sample_use_file_does_not_exist = file `{$path}` passed to `-C profile-sample-use` does not exist.
 
-session_crate_name_empty = crate name must not be empty
+session_profile_use_file_does_not_exist = file `{$path}` passed to `-C profile-use` does not exist.
 
-session_invalid_character_in_create_name = invalid character `{$character}` in crate name: `{$crate_name}`
+session_sanitizer_cfi_canonical_jump_tables_requires_cfi = `-Zsanitizer-cfi-canonical-jump-tables` requires `-Zsanitizer=cfi`
 
-session_expr_parentheses_needed = parentheses are required to parse this as an expression
+session_sanitizer_cfi_generalize_pointers_requires_cfi = `-Zsanitizer-cfi-generalize-pointers` requires `-Zsanitizer=cfi` or `-Zsanitizer=kcfi`
 
-session_skipping_const_checks = skipping const checks
-session_unleashed_feature_help_named = skipping check for `{$gate}` feature
-session_unleashed_feature_help_unnamed = skipping check that does not even have a feature gate
+session_sanitizer_cfi_normalize_integers_requires_cfi = `-Zsanitizer-cfi-normalize-integers` requires `-Zsanitizer=cfi` or `-Zsanitizer=kcfi`
 
-session_hexadecimal_float_literal_not_supported = hexadecimal float literal is not supported
-session_octal_float_literal_not_supported = octal float literal is not supported
-session_binary_float_literal_not_supported = binary float literal is not supported
-session_not_supported = not supported
+session_sanitizer_cfi_requires_lto = `-Zsanitizer=cfi` requires `-Clto`, `-Clto=thin`, or `-Clinker-plugin-lto`
 
-session_invalid_literal_suffix = suffixes on {$kind} literals are invalid
-    .label = invalid suffix `{$suffix}`
+session_sanitizer_not_supported = {$us} sanitizer is not supported for this target
 
-session_invalid_num_literal_base_prefix = invalid base prefix for number literal
-    .note = base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
-    .suggestion = try making the prefix lowercase
+session_sanitizers_not_supported = {$us} sanitizers are not supported for this target
 
-session_invalid_num_literal_suffix = invalid suffix `{$suffix}` for number literal
-    .label = invalid suffix `{$suffix}`
-    .help = the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+session_skipping_const_checks = skipping const checks
+session_split_debuginfo_unstable_platform = `-Csplit-debuginfo={$debuginfo}` is unstable on this platform
 
-session_invalid_float_literal_width = invalid width `{$width}` for float literal
-    .help = valid widths are 32 and 64
+session_split_lto_unit_requires_lto = `-Zsplit-lto-unit` requires `-Clto`, `-Clto=thin`, or `-Clinker-plugin-lto`
 
-session_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float literal
-    .label = invalid suffix `{$suffix}`
-    .help = valid suffixes are `f32` and `f64`
+session_target_requires_unwind_tables = target requires unwind tables, they cannot be disabled with `-C force-unwind-tables=no`
 
-session_int_literal_too_large = integer literal is too large
-    .note = value exceeds limit of `{$limit}`
+session_target_stack_protector_not_supported = `-Z stack-protector={$stack_protector}` is not supported for target {$target_triple} and will be ignored
 
-session_invalid_int_literal_width = invalid width `{$width}` for integer literal
-    .help = valid widths are 8, 16, 32, 64 and 128
+session_unleashed_feature_help_named = skipping check for `{$gate}` feature
+session_unleashed_feature_help_unnamed = skipping check that does not even have a feature gate
 
-session_optimization_fuel_exhausted = optimization-fuel-exhausted: {$msg}
+session_unstable_virtual_function_elimination = `-Zvirtual-function-elimination` requires `-Clto`
 
-session_nul_in_c_str = null characters in C string literals are not supported
+session_unsupported_dwarf_version = requested DWARF version {$dwarf_version} is greater than 5
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 2c4c4a7a6ce..7cc2b2c880c 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -372,7 +372,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`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `shadow-call-stack`, or `thread`";
+    pub const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `safestack`, `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`";
@@ -694,6 +694,7 @@ mod parse {
                     "shadow-call-stack" => SanitizerSet::SHADOWCALLSTACK,
                     "thread" => SanitizerSet::THREAD,
                     "hwaddress" => SanitizerSet::HWADDRESS,
+                    "safestack" => SanitizerSet::SAFESTACK,
                     _ => return false,
                 }
             }
@@ -1371,8 +1372,6 @@ options! {
         "set options for branch target identification and pointer authentication on AArch64"),
     cf_protection: CFProtection = (CFProtection::None, parse_cfprotection, [TRACKED],
         "instrument control-flow architecture protection"),
-    cgu_partitioning_strategy: Option<String> = (None, parse_opt_string, [TRACKED],
-        "the codegen unit partitioning strategy to use"),
     codegen_backend: Option<String> = (None, parse_opt_string, [TRACKED],
         "the backend to use"),
     combine_cgu: bool = (false, parse_bool, [TRACKED],
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index 7b396dde91b..a433e2371c9 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -84,6 +84,7 @@ impl SymbolGallery {
 
 /// Construct a diagnostic for a language feature error due to the given `span`.
 /// The `feature`'s `Symbol` is the one you used in `active.rs` and `rustc_span::symbols`.
+#[track_caller]
 pub fn feature_err(
     sess: &ParseSess,
     feature: Symbol,
@@ -123,7 +124,7 @@ pub fn feature_err_issue(
 /// Construct a future incompatibility diagnostic for a feature gate.
 ///
 /// This diagnostic is only a warning and *does not cause compilation to fail*.
-pub fn feature_warn(sess: &ParseSess, feature: Symbol, span: Span, explain: &str) {
+pub fn feature_warn(sess: &ParseSess, feature: Symbol, span: Span, explain: &'static str) {
     feature_warn_issue(sess, feature, span, GateIssue::Language, explain);
 }
 
@@ -140,7 +141,7 @@ pub fn feature_warn_issue(
     feature: Symbol,
     span: Span,
     issue: GateIssue,
-    explain: &str,
+    explain: &'static str,
 ) {
     let mut err = sess.span_diagnostic.struct_span_warn(span, explain);
     add_feature_diagnostics_for_issue(&mut err, sess, feature, issue);
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index 6af43f5d3f3..5572108f495 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -309,7 +309,7 @@ fn rustc_terminator_to_terminator(
         Terminate => Terminator::Abort,
         Return => Terminator::Return,
         Unreachable => Terminator::Unreachable,
-        Drop { place, target, unwind } => Terminator::Drop {
+        Drop { place, target, unwind, replace: _ } => Terminator::Drop {
             place: rustc_place_to_place(place),
             target: target.as_usize(),
             unwind: rustc_unwind_to_unwind(unwind),
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index 6755657c727..b219fde4da9 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -1147,7 +1147,6 @@ pub enum DesugaringKind {
     Await,
     ForLoop,
     WhileLoop,
-    Replace,
 }
 
 impl DesugaringKind {
@@ -1163,7 +1162,6 @@ impl DesugaringKind {
             DesugaringKind::OpaqueTy => "`impl Trait`",
             DesugaringKind::ForLoop => "`for` loop",
             DesugaringKind::WhileLoop => "`while` loop",
-            DesugaringKind::Replace => "drop and replace",
         }
     }
 }
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 874d578fe1d..1185563ea80 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1454,6 +1454,10 @@ symbols! {
         stop_after_dataflow,
         store,
         str,
+        str_from_utf8,
+        str_from_utf8_mut,
+        str_from_utf8_unchecked,
+        str_from_utf8_unchecked_mut,
         str_split_whitespace,
         str_trim,
         str_trim_end,
diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
index 9fa49123a86..b245742e533 100644
--- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
+++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
@@ -10,7 +10,6 @@
 use core::fmt::Display;
 use rustc_data_structures::base_n;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::DiagnosticMessage;
 use rustc_hir as hir;
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
 use rustc_middle::ty::{
@@ -534,10 +533,7 @@ fn encode_ty<'tcx>(
                         tcx.sess
                             .struct_span_err(
                                 cfi_encoding.span,
-                                DiagnosticMessage::Str(format!(
-                                    "invalid `cfi_encoding` for `{:?}`",
-                                    ty.kind()
-                                )),
+                                format!("invalid `cfi_encoding` for `{:?}`", ty.kind()),
                             )
                             .emit();
                     }
@@ -589,10 +585,7 @@ fn encode_ty<'tcx>(
                         tcx.sess
                             .struct_span_err(
                                 cfi_encoding.span,
-                                DiagnosticMessage::Str(format!(
-                                    "invalid `cfi_encoding` for `{:?}`",
-                                    ty.kind()
-                                )),
+                                format!("invalid `cfi_encoding` for `{:?}`", ty.kind()),
                             )
                             .emit();
                     }
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 4cccc639892..0a805e2422d 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -274,7 +274,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
 
         let mut param_env = self.tcx.param_env_reveal_all_normalized(impl_def_id);
         if !substs.is_empty() {
-            param_env = EarlyBinder(param_env).subst(self.tcx, substs);
+            param_env = EarlyBinder::bind(param_env).subst(self.tcx, substs);
         }
 
         match &mut impl_trait_ref {
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs
index 2b135b67034..e2df7e0bdcc 100644
--- a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs
@@ -2,7 +2,7 @@ use super::apple_base::{opts, Arch};
 use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, TargetOptions};
 
 pub fn target() -> Target {
-    let llvm_target = "arm64-apple-ios-macabi";
+    let llvm_target = "arm64-apple-ios14.0-macabi";
 
     let arch = Arch::Arm64_macabi;
     let mut base = opts("ios", arch);
diff --git a/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs
index fc5dbd114e4..b9df0046b12 100644
--- a/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs
+++ b/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs
@@ -12,7 +12,7 @@ pub fn target() -> Target {
             endian: Endian::Big,
             // NOTE(mips64r2) matches C toolchain
             cpu: "mips64r2".into(),
-            features: "+mips64r2".into(),
+            features: "+mips64r2,+xgot".into(),
             max_atomic_width: Some(64),
             mcount: "_mcount".into(),
 
diff --git a/compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs
index e0d5f6f57f1..57ad8c47399 100644
--- a/compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs
+++ b/compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs
@@ -10,7 +10,7 @@ pub fn target() -> Target {
             abi: "abi64".into(),
             // NOTE(mips64r2) matches C toolchain
             cpu: "mips64r2".into(),
-            features: "+mips64r2".into(),
+            features: "+mips64r2,+xgot".into(),
             max_atomic_width: Some(64),
             mcount: "_mcount".into(),
 
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index ba4b89c9ea1..62f94209cf0 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -815,6 +815,7 @@ bitflags::bitflags! {
         const SHADOWCALLSTACK = 1 << 7;
         const KCFI    = 1 << 8;
         const KERNELADDRESS = 1 << 9;
+        const SAFESTACK = 1 << 10;
     }
 }
 
@@ -831,6 +832,7 @@ impl SanitizerSet {
             SanitizerSet::LEAK => "leak",
             SanitizerSet::MEMORY => "memory",
             SanitizerSet::MEMTAG => "memtag",
+            SanitizerSet::SAFESTACK => "safestack",
             SanitizerSet::SHADOWCALLSTACK => "shadow-call-stack",
             SanitizerSet::THREAD => "thread",
             SanitizerSet::HWADDRESS => "hwaddress",
@@ -871,6 +873,7 @@ impl IntoIterator for SanitizerSet {
             SanitizerSet::THREAD,
             SanitizerSet::HWADDRESS,
             SanitizerSet::KERNELADDRESS,
+            SanitizerSet::SAFESTACK,
         ]
         .iter()
         .copied()
@@ -2364,6 +2367,7 @@ impl Target {
                                 Some("leak") => SanitizerSet::LEAK,
                                 Some("memory") => SanitizerSet::MEMORY,
                                 Some("memtag") => SanitizerSet::MEMTAG,
+                                Some("safestack") => SanitizerSet::SAFESTACK,
                                 Some("shadow-call-stack") => SanitizerSet::SHADOWCALLSTACK,
                                 Some("thread") => SanitizerSet::THREAD,
                                 Some("hwaddress") => SanitizerSet::HWADDRESS,
diff --git a/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs
index 5a3e2a79bb9..9f3b0fab697 100644
--- a/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs
@@ -2,7 +2,7 @@ use super::apple_base::{opts, Arch};
 use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions};
 
 pub fn target() -> Target {
-    let llvm_target = "x86_64-apple-ios-macabi";
+    let llvm_target = "x86_64-apple-ios14.0-macabi";
 
     let arch = Arch::X86_64_macabi;
     let mut base = opts("ios", arch);
diff --git a/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs b/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs
index cb62a817322..d2906d6c4ae 100644
--- a/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs
+++ b/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs
@@ -7,7 +7,7 @@ pub fn target() -> Target {
     base.vendor = "pc".into();
     base.max_atomic_width = Some(64);
     base.stack_probes = StackProbeType::X86;
-    base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI;
+    base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::THREAD;
 
     Target {
         llvm_target: "x86_64-pc-solaris".into(),
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs b/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs
index 04a12a7bfa6..ca5b62e279c 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs
@@ -5,7 +5,7 @@ pub fn target() -> Target {
     base.add_pre_link_args(LinkerFlavor::Unix(Cc::Yes), &["-m64", "-std=c99"]);
     base.cpu = "x86-64".into();
     base.max_atomic_width = Some(64);
-    base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI;
+    base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::THREAD;
 
     Target {
         // LLVM does not currently have a separate illumos target,
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs
index 9af1049b870..deb15c02c68 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs
@@ -11,6 +11,7 @@ pub fn target() -> Target {
         | SanitizerSet::CFI
         | SanitizerSet::LEAK
         | SanitizerSet::MEMORY
+        | SanitizerSet::SAFESTACK
         | SanitizerSet::THREAD;
     base.supports_xray = true;
 
diff --git a/compiler/rustc_trait_selection/messages.ftl b/compiler/rustc_trait_selection/messages.ftl
index 8fea3fc140d..217ba71b631 100644
--- a/compiler/rustc_trait_selection/messages.ftl
+++ b/compiler/rustc_trait_selection/messages.ftl
@@ -1,17 +1,13 @@
 trait_selection_dump_vtable_entries = vtable entries for `{$trait_ref}`: {$entries}
 
-trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated}
-
 trait_selection_empty_on_clause_in_rustc_on_unimplemented = empty `on`-clause in `#[rustc_on_unimplemented]`
     .label = empty on-clause here
 
+trait_selection_inherent_projection_normalization_overflow = overflow evaluating associated type `{$ty}`
+
 trait_selection_invalid_on_clause_in_rustc_on_unimplemented = invalid `on`-clause in `#[rustc_on_unimplemented]`
     .label = invalid on-clause here
 
-trait_selection_no_value_in_rustc_on_unimplemented = this attribute must have a valid value
-    .label = expected value here
-    .note = eg `#[rustc_on_unimplemented(message="foo")]`
-
 trait_selection_negative_positive_conflict = found both positive and negative implementation of trait `{$trait_desc}`{$self_desc ->
         [none] {""}
        *[default] {" "}for type `{$self_desc}`
@@ -21,4 +17,8 @@ trait_selection_negative_positive_conflict = found both positive and negative im
     .positive_implementation_here = positive implementation here
     .positive_implementation_in_crate = positive implementation in crate `{$positive_impl_cname}`
 
-trait_selection_inherent_projection_normalization_overflow = overflow evaluating associated type `{$ty}`
+trait_selection_no_value_in_rustc_on_unimplemented = this attribute must have a valid value
+    .label = expected value here
+    .note = eg `#[rustc_on_unimplemented(message="foo")]`
+
+trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated}
diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs
index 142c20014a0..312bd38178f 100644
--- a/compiler/rustc_trait_selection/src/infer.rs
+++ b/compiler/rustc_trait_selection/src/infer.rs
@@ -5,7 +5,7 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
 use rustc_middle::arena::ArenaAllocatable;
 use rustc_middle::infer::canonical::{Canonical, CanonicalQueryResponse, QueryResponse};
-use rustc_middle::traits::query::Fallible;
+use rustc_middle::traits::query::NoSolution;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
 use rustc_middle::ty::{GenericArg, ToPredicate};
 use rustc_span::DUMMY_SP;
@@ -82,8 +82,8 @@ pub trait InferCtxtBuilderExt<'tcx> {
     fn enter_canonical_trait_query<K, R>(
         &mut self,
         canonical_key: &Canonical<'tcx, K>,
-        operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Fallible<R>,
-    ) -> Fallible<CanonicalQueryResponse<'tcx, R>>
+        operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Result<R, NoSolution>,
+    ) -> Result<CanonicalQueryResponse<'tcx, R>, NoSolution>
     where
         K: TypeFoldable<TyCtxt<'tcx>>,
         R: Debug + TypeFoldable<TyCtxt<'tcx>>,
@@ -110,8 +110,8 @@ impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> {
     fn enter_canonical_trait_query<K, R>(
         &mut self,
         canonical_key: &Canonical<'tcx, K>,
-        operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Fallible<R>,
-    ) -> Fallible<CanonicalQueryResponse<'tcx, R>>
+        operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Result<R, NoSolution>,
+    ) -> Result<CanonicalQueryResponse<'tcx, R>, NoSolution>
     where
         K: TypeFoldable<TyCtxt<'tcx>>,
         R: Debug + TypeFoldable<TyCtxt<'tcx>>,
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
index 0ede32c753c..0f3f8f1ac2c 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
@@ -96,7 +96,7 @@ pub(in crate::solve) fn replace_erased_lifetimes_with_bound_vars<'tcx>(
             let br =
                 ty::BoundRegion { var: ty::BoundVar::from_u32(counter), kind: ty::BrAnon(None) };
             counter += 1;
-            tcx.mk_re_late_bound(current_depth, br)
+            ty::Region::new_late_bound(tcx, current_depth, br)
         }
         // All free regions should be erased here.
         r => bug!("unexpected region: {r:?}"),
@@ -148,11 +148,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>(
 
         ty::Adt(def, substs) => {
             let sized_crit = def.sized_constraint(ecx.tcx());
-            Ok(sized_crit
-                .0
-                .iter()
-                .map(|ty| sized_crit.rebind(*ty).subst(ecx.tcx(), substs))
-                .collect())
+            Ok(sized_crit.subst_iter_copied(ecx.tcx(), substs).collect())
         }
     }
 }
diff --git a/compiler/rustc_trait_selection/src/solve/canonicalize.rs b/compiler/rustc_trait_selection/src/solve/canonicalize.rs
index ff4bff10cc8..29bdb5ff67d 100644
--- a/compiler/rustc_trait_selection/src/solve/canonicalize.rs
+++ b/compiler/rustc_trait_selection/src/solve/canonicalize.rs
@@ -255,7 +255,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
             }),
         );
         let br = ty::BoundRegion { var, kind: BrAnon(None) };
-        self.interner().mk_re_late_bound(self.binder_index, br)
+        ty::Region::new_late_bound(self.interner(), self.binder_index, br)
     }
 
     fn fold_ty(&mut self, mut t: Ty<'tcx>) -> Ty<'tcx> {
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
index fdb209fbff8..bca2343e424 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
@@ -137,6 +137,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
 
     #[instrument(level = "debug", skip(self), ret)]
     fn compute_external_query_constraints(&self) -> Result<ExternalConstraints<'tcx>, NoSolution> {
+        // We only check for leaks from universes which were entered inside
+        // of the query.
+        self.infcx.leak_check(self.max_input_universe, None).map_err(|e| {
+            debug!(?e, "failed the leak check");
+            NoSolution
+        })?;
+
         // Cannot use `take_registered_region_obligations` as we may compute the response
         // inside of a `probe` whenever we have multiple choices inside of the solver.
         let region_obligations = self.infcx.inner.borrow().region_obligations().to_owned();
diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs
index 26ace28f5fd..56a254d9c07 100644
--- a/compiler/rustc_trait_selection/src/solve/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/mod.rs
@@ -231,13 +231,21 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
 
                 let mut candidates = Vec::new();
                 // LHS normalizes-to RHS
-                candidates.extend(
-                    evaluate_normalizes_to(self, alias_lhs, rhs, direction, Invert::No).ok(),
-                );
+                candidates.extend(evaluate_normalizes_to(
+                    self,
+                    alias_lhs,
+                    rhs,
+                    direction,
+                    Invert::No,
+                ));
                 // RHS normalizes-to RHS
-                candidates.extend(
-                    evaluate_normalizes_to(self, alias_rhs, lhs, direction, Invert::Yes).ok(),
-                );
+                candidates.extend(evaluate_normalizes_to(
+                    self,
+                    alias_rhs,
+                    lhs,
+                    direction,
+                    Invert::Yes,
+                ));
                 // Relate via substs
                 let subst_relate_response = self.probe(|ecx| {
                     let span = tracing::span!(
@@ -265,10 +273,18 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
 
                 if let Some(merged) = self.try_merge_responses(&candidates) {
                     Ok(merged)
-                } else if let Ok(subst_relate_response) = subst_relate_response {
-                    Ok(subst_relate_response)
                 } else {
-                    self.flounder(&candidates)
+                    // When relating two aliases and we have ambiguity, we prefer
+                    // relating the generic arguments of the aliases over normalizing
+                    // them. This is necessary for inference during typeck.
+                    //
+                    // As this is incomplete, we must not do so during coherence.
+                    match (self.solver_mode(), subst_relate_response) {
+                        (SolverMode::Normal, Ok(response)) => Ok(response),
+                        (SolverMode::Normal, Err(NoSolution)) | (SolverMode::Coherence, _) => {
+                            self.flounder(&candidates)
+                        }
+                    }
                 }
             }
         }
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index e8c5a8fab2a..d6fd457de06 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -5,7 +5,7 @@
 //! [trait-specialization]: https://rustc-dev-guide.rust-lang.org/traits/specialization.html
 
 use crate::infer::outlives::env::OutlivesEnvironment;
-use crate::infer::{CombinedSnapshot, InferOk};
+use crate::infer::InferOk;
 use crate::traits::outlives_bounds::InferCtxtExt as _;
 use crate::traits::select::IntercrateAmbiguityCause;
 use crate::traits::util::impl_subject_and_oblig;
@@ -62,6 +62,21 @@ pub fn add_placeholder_note(err: &mut Diagnostic) {
     );
 }
 
+#[derive(Debug, Clone, Copy)]
+enum TrackAmbiguityCauses {
+    Yes,
+    No,
+}
+
+impl TrackAmbiguityCauses {
+    fn is_yes(self) -> bool {
+        match self {
+            TrackAmbiguityCauses::Yes => true,
+            TrackAmbiguityCauses::No => false,
+        }
+    }
+}
+
 /// If there are types that satisfy both impls, returns `Some`
 /// with a suitably-freshened `ImplHeader` with those types
 /// substituted. Otherwise, returns `None`.
@@ -97,29 +112,28 @@ pub fn overlapping_impls(
         return None;
     }
 
-    let infcx = tcx
-        .infer_ctxt()
-        .with_opaque_type_inference(DefiningAnchor::Bubble)
-        .intercrate(true)
-        .build();
-    let selcx = &mut SelectionContext::new(&infcx);
-    let overlaps =
-        overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode).is_some();
-    if !overlaps {
-        return None;
-    }
+    let _overlap_with_bad_diagnostics = overlap(
+        tcx,
+        TrackAmbiguityCauses::No,
+        skip_leak_check,
+        impl1_def_id,
+        impl2_def_id,
+        overlap_mode,
+    )?;
 
     // In the case where we detect an error, run the check again, but
     // this time tracking intercrate ambiguity causes for better
     // diagnostics. (These take time and can lead to false errors.)
-    let infcx = tcx
-        .infer_ctxt()
-        .with_opaque_type_inference(DefiningAnchor::Bubble)
-        .intercrate(true)
-        .build();
-    let selcx = &mut SelectionContext::new(&infcx);
-    selcx.enable_tracking_intercrate_ambiguity_causes();
-    Some(overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode).unwrap())
+    let overlap = overlap(
+        tcx,
+        TrackAmbiguityCauses::Yes,
+        skip_leak_check,
+        impl1_def_id,
+        impl2_def_id,
+        overlap_mode,
+    )
+    .unwrap();
+    Some(overlap)
 }
 
 fn with_fresh_ty_vars<'cx, 'tcx>(
@@ -146,40 +160,34 @@ fn with_fresh_ty_vars<'cx, 'tcx>(
 
 /// Can both impl `a` and impl `b` be satisfied by a common type (including
 /// where-clauses)? If so, returns an `ImplHeader` that unifies the two impls.
-fn overlap<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
+#[instrument(level = "debug", skip(tcx))]
+fn overlap<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    track_ambiguity_causes: TrackAmbiguityCauses,
     skip_leak_check: SkipLeakCheck,
     impl1_def_id: DefId,
     impl2_def_id: DefId,
     overlap_mode: OverlapMode,
 ) -> Option<OverlapResult<'tcx>> {
-    debug!(
-        "overlap(impl1_def_id={:?}, impl2_def_id={:?}, overlap_mode={:?})",
-        impl1_def_id, impl2_def_id, overlap_mode
-    );
-
-    selcx.infcx.probe_maybe_skip_leak_check(skip_leak_check.is_yes(), |snapshot| {
-        overlap_within_probe(selcx, impl1_def_id, impl2_def_id, overlap_mode, snapshot)
-    })
-}
-
-fn overlap_within_probe<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    impl1_def_id: DefId,
-    impl2_def_id: DefId,
-    overlap_mode: OverlapMode,
-    snapshot: &CombinedSnapshot<'tcx>,
-) -> Option<OverlapResult<'tcx>> {
-    let infcx = selcx.infcx;
-
     if overlap_mode.use_negative_impl() {
-        if negative_impl(infcx.tcx, impl1_def_id, impl2_def_id)
-            || negative_impl(infcx.tcx, impl2_def_id, impl1_def_id)
+        if negative_impl(tcx, impl1_def_id, impl2_def_id)
+            || negative_impl(tcx, impl2_def_id, impl1_def_id)
         {
             return None;
         }
     }
 
+    let infcx = tcx
+        .infer_ctxt()
+        .with_opaque_type_inference(DefiningAnchor::Bubble)
+        .skip_leak_check(skip_leak_check.is_yes())
+        .intercrate(true)
+        .build();
+    let selcx = &mut SelectionContext::new(&infcx);
+    if track_ambiguity_causes.is_yes() {
+        selcx.enable_tracking_intercrate_ambiguity_causes();
+    }
+
     // For the purposes of this check, we don't bring any placeholder
     // types into scope; instead, we replace the generic types with
     // fresh type variables, and hence we do our evaluations in an
@@ -198,18 +206,23 @@ fn overlap_within_probe<'cx, 'tcx>(
         }
     }
 
-    // We disable the leak when creating the `snapshot` by using
-    // `infcx.probe_maybe_disable_leak_check`.
-    if infcx.leak_check(true, snapshot).is_err() {
+    // We toggle the `leak_check` by using `skip_leak_check` when constructing the
+    // inference context, so this may be a noop.
+    if infcx.leak_check(ty::UniverseIndex::ROOT, None).is_err() {
         debug!("overlap: leak check failed");
         return None;
     }
 
     let intercrate_ambiguity_causes = selcx.take_intercrate_ambiguity_causes();
     debug!("overlap: intercrate_ambiguity_causes={:#?}", intercrate_ambiguity_causes);
-
-    let involves_placeholder =
-        matches!(selcx.infcx.region_constraints_added_in_snapshot(snapshot), Some(true));
+    let involves_placeholder = infcx
+        .inner
+        .borrow_mut()
+        .unwrap_region_constraints()
+        .data()
+        .constraints
+        .iter()
+        .any(|c| c.0.involves_placeholders());
 
     let impl_header = selcx.infcx.resolve_vars_if_possible(impl1_header);
     Some(OverlapResult { impl_header, intercrate_ambiguity_causes, involves_placeholder })
diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs
index 000427bbe83..2c5ffd664fe 100644
--- a/compiler/rustc_trait_selection/src/traits/engine.rs
+++ b/compiler/rustc_trait_selection/src/traits/engine.rs
@@ -14,11 +14,11 @@ use rustc_infer::infer::canonical::{
 };
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
-use rustc_infer::traits::query::Fallible;
 use rustc_infer::traits::{
     FulfillmentError, Obligation, ObligationCause, PredicateObligation, TraitEngineExt as _,
 };
 use rustc_middle::arena::ArenaAllocatable;
+use rustc_middle::traits::query::NoSolution;
 use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::ToPredicate;
 use rustc_middle::ty::TypeFoldable;
@@ -235,7 +235,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
         &self,
         inference_vars: CanonicalVarValues<'tcx>,
         answer: T,
-    ) -> Fallible<CanonicalQueryResponse<'tcx, T>>
+    ) -> Result<CanonicalQueryResponse<'tcx, T>, NoSolution>
     where
         T: Debug + TypeFoldable<TyCtxt<'tcx>>,
         Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index a10ececbb1e..9012bda4043 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -42,6 +42,7 @@ use rustc_session::Limit;
 use rustc_span::def_id::LOCAL_CRATE;
 use rustc_span::symbol::sym;
 use rustc_span::{ExpnKind, Span, DUMMY_SP};
+use std::borrow::Cow;
 use std::fmt;
 use std::iter;
 use std::ops::ControlFlow;
@@ -1602,7 +1603,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         }),
                     ) => Some((
                         ty.span,
-                        with_forced_trimmed_paths!(format!(
+                        with_forced_trimmed_paths!(Cow::from(format!(
                             "type mismatch resolving `{}`",
                             self.resolve_vars_if_possible(predicate)
                                 .print(FmtPrinter::new_with_limit(
@@ -1612,7 +1613,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                 ))
                                 .unwrap()
                                 .into_buffer()
-                        )),
+                        ))),
                     )),
                     _ => None,
                 }
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 82bad96ea42..b5b8c7fe3ac 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -38,6 +38,7 @@ use rustc_span::def_id::LocalDefId;
 use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::{BytePos, DesugaringKind, ExpnKind, MacroKind, Span, DUMMY_SP};
 use rustc_target::spec::abi;
+use std::borrow::Cow;
 use std::iter;
 use std::ops::Deref;
 
@@ -186,7 +187,12 @@ pub trait TypeErrCtxtExt<'tcx> {
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) -> bool;
 
-    fn get_closure_name(&self, def_id: DefId, err: &mut Diagnostic, msg: &str) -> Option<Symbol>;
+    fn get_closure_name(
+        &self,
+        def_id: DefId,
+        err: &mut Diagnostic,
+        msg: Cow<'static, str>,
+    ) -> Option<Symbol>;
 
     fn suggest_fn_call(
         &self,
@@ -857,7 +863,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
     /// Given a closure's `DefId`, return the given name of the closure.
     ///
     /// This doesn't account for reassignments, but it's only used for suggestions.
-    fn get_closure_name(&self, def_id: DefId, err: &mut Diagnostic, msg: &str) -> Option<Symbol> {
+    fn get_closure_name(
+        &self,
+        def_id: DefId,
+        err: &mut Diagnostic,
+        msg: Cow<'static, str>,
+    ) -> Option<Symbol> {
         let get_name = |err: &mut Diagnostic, kind: &hir::PatKind<'_>| -> Option<Symbol> {
             // Get the local name of this closure. This can be inaccurate because
             // of the possibility of reassignment, but this should be good enough.
@@ -934,17 +945,17 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         let msg = match def_id_or_name {
             DefIdOrName::DefId(def_id) => match self.tcx.def_kind(def_id) {
                 DefKind::Ctor(CtorOf::Struct, _) => {
-                    "use parentheses to construct this tuple struct".to_string()
+                    Cow::from("use parentheses to construct this tuple struct")
                 }
                 DefKind::Ctor(CtorOf::Variant, _) => {
-                    "use parentheses to construct this tuple variant".to_string()
+                    Cow::from("use parentheses to construct this tuple variant")
                 }
-                kind => format!(
+                kind => Cow::from(format!(
                     "use parentheses to call this {}",
                     self.tcx.def_kind_descr(kind, def_id)
-                ),
+                )),
             },
-            DefIdOrName::Name(name) => format!("use parentheses to call this {name}"),
+            DefIdOrName::Name(name) => Cow::from(format!("use parentheses to call this {name}")),
         };
 
         let args = inputs
@@ -979,7 +990,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     ..
                 })) => {
                     err.span_label(*fn_decl_span, "consider calling this closure");
-                    let Some(name) = self.get_closure_name(def_id, err, &msg) else {
+                    let Some(name) = self.get_closure_name(def_id, err, msg.clone()) else {
                         return false;
                     };
                     name.to_string()
@@ -1341,7 +1352,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         err.note(msg);
                     } else {
                         err.message =
-                            vec![(rustc_errors::DiagnosticMessage::Str(msg), Style::NoStyle)];
+                            vec![(rustc_errors::DiagnosticMessage::from(msg), Style::NoStyle)];
                     }
                     err.span_label(
                         span,
@@ -2958,7 +2969,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                 for ty in bound_tys.skip_binder() {
                                     with_forced_trimmed_paths!(write!(msg, "`{}`, ", ty).unwrap());
                                 }
-                                err.note(msg.trim_end_matches(", "))
+                                err.note(msg.trim_end_matches(", ").to_string())
                             }
                             ty::GeneratorWitnessMIR(def_id, substs) => {
                                 use std::fmt::Write;
@@ -2972,7 +2983,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                     let ty = bty.subst(tcx, substs);
                                     write!(msg, "`{}`, ", ty).unwrap();
                                 }
-                                err.note(msg.trim_end_matches(", "))
+                                err.note(msg.trim_end_matches(", ").to_string())
                             }
                             ty::Generator(def_id, _, _) => {
                                 let sp = self.tcx.def_span(def_id);
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 2f85c32b575..88d2091de0f 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -116,6 +116,7 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> {
 }
 
 impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
+    #[inline]
     fn register_predicate_obligation(
         &mut self,
         infcx: &InferCtxt<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index f265230ff77..4b38687eebe 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -14,10 +14,12 @@ mod object_safety;
 pub mod outlives_bounds;
 mod project;
 pub mod query;
+#[cfg_attr(not(bootstrap), allow(hidden_glob_reexports))]
 mod select;
 mod specialize;
 mod structural_match;
 mod structural_normalize;
+#[cfg_attr(not(bootstrap), allow(hidden_glob_reexports))]
 mod util;
 mod vtable;
 pub mod wf;
@@ -485,7 +487,7 @@ fn is_impossible_method(tcx: TyCtxt<'_>, (impl_def_id, trait_item_def_id): (DefI
                 tcx,
                 ObligationCause::dummy_with_span(*span),
                 param_env,
-                ty::EarlyBinder(*pred).subst(tcx, impl_trait_ref.substs),
+                ty::EarlyBinder::bind(*pred).subst(tcx, impl_trait_ref.substs),
             )
         })
     });
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index c81bf6ebc2e..9582479941b 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -642,7 +642,7 @@ fn receiver_for_self_ty<'tcx>(
         if param.index == 0 { self_ty.into() } else { tcx.mk_param_from_def(param) }
     });
 
-    let result = EarlyBinder(receiver_ty).subst(tcx, substs);
+    let result = EarlyBinder::bind(receiver_ty).subst(tcx, substs);
     debug!(
         "receiver_for_self_ty({:?}, {:?}, {:?}) = {:?}",
         receiver_ty, self_ty, method_def_id, result
diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
index 0db80232891..f8d056e321e 100644
--- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
@@ -1,9 +1,9 @@
 use crate::infer::InferCtxt;
-use crate::traits::query::type_op::{self, TypeOp, TypeOpOutput};
-use crate::traits::query::NoSolution;
 use crate::traits::{ObligationCause, ObligationCtxt};
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_infer::infer::resolve::OpportunisticRegionResolver;
+use rustc_infer::infer::InferOk;
+use rustc_middle::infer::canonical::{OriginalQueryValues, QueryRegionConstraints};
 use rustc_middle::ty::{self, ParamEnv, Ty, TypeFolder, TypeVisitableExt};
 use rustc_span::def_id::LocalDefId;
 
@@ -68,24 +68,29 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> {
             return vec![];
         }
 
-        let span = self.tcx.def_span(body_id);
-        let result = param_env
-            .and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty })
-            .fully_perform(self);
-        let result = match result {
-            Ok(r) => r,
-            Err(NoSolution) => {
-                self.tcx.sess.delay_span_bug(
-                    span,
-                    "implied_outlives_bounds failed to solve all obligations",
-                );
-                return vec![];
-            }
+        let mut canonical_var_values = OriginalQueryValues::default();
+        let canonical_ty =
+            self.canonicalize_query_keep_static(param_env.and(ty), &mut canonical_var_values);
+        let Ok(canonical_result) = self.tcx.implied_outlives_bounds(canonical_ty) else {
+            return vec![];
+        };
+
+        let mut constraints = QueryRegionConstraints::default();
+        let Ok(InferOk { value, obligations }) = self
+            .instantiate_nll_query_response_and_region_obligations(
+                &ObligationCause::dummy(),
+                param_env,
+                &canonical_var_values,
+                canonical_result,
+                &mut constraints,
+            ) else {
+            return vec![];
         };
+        assert_eq!(&obligations, &[]);
 
-        let TypeOpOutput { output, constraints, .. } = result;
+        if !constraints.is_empty() {
+            let span = self.tcx.def_span(body_id);
 
-        if let Some(constraints) = constraints {
             debug!(?constraints);
             if !constraints.member_constraints.is_empty() {
                 span_bug!(span, "{:#?}", constraints.member_constraints);
@@ -112,7 +117,7 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> {
             }
         };
 
-        output
+        value
     }
 
     fn implied_bounds_tys(
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 51069897120..65af0bb1c4e 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -824,7 +824,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for BoundVarReplacer<'_, 'tcx> {
                 let universe = self.universe_for(debruijn);
                 let p = ty::PlaceholderRegion { universe, bound: br };
                 self.mapped_regions.insert(p, br);
-                self.infcx.tcx.mk_re_placeholder(p)
+                ty::Region::new_placeholder(self.infcx.tcx, p)
             }
             _ => r,
         }
@@ -945,7 +945,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for PlaceholderReplacer<'_, 'tcx> {
                         let db = ty::DebruijnIndex::from_usize(
                             self.universe_indices.len() - index + self.current_index.as_usize() - 1,
                         );
-                        self.interner().mk_re_late_bound(db, *replace_var)
+                        ty::Region::new_late_bound(self.interner(), db, *replace_var)
                     }
                     None => r1,
                 }
diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
index 455b53bfb7d..709c3f432e6 100644
--- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
@@ -1,6 +1,11 @@
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use crate::traits::query::normalize::QueryNormalizeExt;
+use crate::traits::query::NoSolution;
+use crate::traits::{Normalized, ObligationCause, ObligationCtxt};
 
-pub use rustc_middle::traits::query::{DropckConstraint, DropckOutlivesResult};
+use rustc_data_structures::fx::FxHashSet;
+use rustc_middle::traits::query::{DropckConstraint, DropckOutlivesResult};
+use rustc_middle::ty::{self, EarlyBinder, ParamEnvAnd, Ty, TyCtxt};
+use rustc_span::source_map::{Span, DUMMY_SP};
 
 /// This returns true if the type `ty` is "trivial" for
 /// dropck-outlives -- that is, if it doesn't require any types to
@@ -71,3 +76,263 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
         | ty::Generator(..) => false,
     }
 }
+
+pub fn compute_dropck_outlives_inner<'tcx>(
+    ocx: &ObligationCtxt<'_, 'tcx>,
+    goal: ParamEnvAnd<'tcx, Ty<'tcx>>,
+) -> Result<DropckOutlivesResult<'tcx>, NoSolution> {
+    let tcx = ocx.infcx.tcx;
+    let ParamEnvAnd { param_env, value: for_ty } = goal;
+
+    let mut result = DropckOutlivesResult { kinds: vec![], overflows: vec![] };
+
+    // A stack of types left to process. Each round, we pop
+    // something from the stack and invoke
+    // `dtorck_constraint_for_ty_inner`. This may produce new types that
+    // have to be pushed on the stack. This continues until we have explored
+    // all the reachable types from the type `for_ty`.
+    //
+    // Example: Imagine that we have the following code:
+    //
+    // ```rust
+    // struct A {
+    //     value: B,
+    //     children: Vec<A>,
+    // }
+    //
+    // struct B {
+    //     value: u32
+    // }
+    //
+    // fn f() {
+    //   let a: A = ...;
+    //   ..
+    // } // here, `a` is dropped
+    // ```
+    //
+    // at the point where `a` is dropped, we need to figure out
+    // which types inside of `a` contain region data that may be
+    // accessed by any destructors in `a`. We begin by pushing `A`
+    // onto the stack, as that is the type of `a`. We will then
+    // invoke `dtorck_constraint_for_ty_inner` which will expand `A`
+    // into the types of its fields `(B, Vec<A>)`. These will get
+    // pushed onto the stack. Eventually, expanding `Vec<A>` will
+    // lead to us trying to push `A` a second time -- to prevent
+    // infinite recursion, we notice that `A` was already pushed
+    // once and stop.
+    let mut ty_stack = vec![(for_ty, 0)];
+
+    // Set used to detect infinite recursion.
+    let mut ty_set = FxHashSet::default();
+
+    let cause = ObligationCause::dummy();
+    let mut constraints = DropckConstraint::empty();
+    while let Some((ty, depth)) = ty_stack.pop() {
+        debug!(
+            "{} kinds, {} overflows, {} ty_stack",
+            result.kinds.len(),
+            result.overflows.len(),
+            ty_stack.len()
+        );
+        dtorck_constraint_for_ty_inner(tcx, DUMMY_SP, for_ty, depth, ty, &mut constraints)?;
+
+        // "outlives" represent types/regions that may be touched
+        // by a destructor.
+        result.kinds.append(&mut constraints.outlives);
+        result.overflows.append(&mut constraints.overflows);
+
+        // If we have even one overflow, we should stop trying to evaluate further --
+        // chances are, the subsequent overflows for this evaluation won't provide useful
+        // information and will just decrease the speed at which we can emit these errors
+        // (since we'll be printing for just that much longer for the often enormous types
+        // that result here).
+        if !result.overflows.is_empty() {
+            break;
+        }
+
+        // dtorck types are "types that will get dropped but which
+        // do not themselves define a destructor", more or less. We have
+        // to push them onto the stack to be expanded.
+        for ty in constraints.dtorck_types.drain(..) {
+            let Normalized { value: ty, obligations } =
+                ocx.infcx.at(&cause, param_env).query_normalize(ty)?;
+            ocx.register_obligations(obligations);
+
+            debug!("dropck_outlives: ty from dtorck_types = {:?}", ty);
+
+            match ty.kind() {
+                // All parameters live for the duration of the
+                // function.
+                ty::Param(..) => {}
+
+                // A projection that we couldn't resolve - it
+                // might have a destructor.
+                ty::Alias(..) => {
+                    result.kinds.push(ty.into());
+                }
+
+                _ => {
+                    if ty_set.insert(ty) {
+                        ty_stack.push((ty, depth + 1));
+                    }
+                }
+            }
+        }
+    }
+
+    debug!("dropck_outlives: result = {:#?}", result);
+    Ok(result)
+}
+
+/// Returns a set of constraints that needs to be satisfied in
+/// order for `ty` to be valid for destruction.
+pub fn dtorck_constraint_for_ty_inner<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    span: Span,
+    for_ty: Ty<'tcx>,
+    depth: usize,
+    ty: Ty<'tcx>,
+    constraints: &mut DropckConstraint<'tcx>,
+) -> Result<(), NoSolution> {
+    debug!("dtorck_constraint_for_ty_inner({:?}, {:?}, {:?}, {:?})", span, for_ty, depth, ty);
+
+    if !tcx.recursion_limit().value_within_limit(depth) {
+        constraints.overflows.push(ty);
+        return Ok(());
+    }
+
+    if trivial_dropck_outlives(tcx, ty) {
+        return Ok(());
+    }
+
+    match ty.kind() {
+        ty::Bool
+        | ty::Char
+        | ty::Int(_)
+        | ty::Uint(_)
+        | ty::Float(_)
+        | ty::Str
+        | ty::Never
+        | ty::Foreign(..)
+        | ty::RawPtr(..)
+        | ty::Ref(..)
+        | ty::FnDef(..)
+        | ty::FnPtr(_)
+        | ty::GeneratorWitness(..)
+        | ty::GeneratorWitnessMIR(..) => {
+            // these types never have a destructor
+        }
+
+        ty::Array(ety, _) | ty::Slice(ety) => {
+            // single-element containers, behave like their element
+            rustc_data_structures::stack::ensure_sufficient_stack(|| {
+                dtorck_constraint_for_ty_inner(tcx, span, for_ty, depth + 1, *ety, constraints)
+            })?;
+        }
+
+        ty::Tuple(tys) => rustc_data_structures::stack::ensure_sufficient_stack(|| {
+            for ty in tys.iter() {
+                dtorck_constraint_for_ty_inner(tcx, span, for_ty, depth + 1, ty, constraints)?;
+            }
+            Ok::<_, NoSolution>(())
+        })?,
+
+        ty::Closure(_, substs) => {
+            if !substs.as_closure().is_valid() {
+                // By the time this code runs, all type variables ought to
+                // be fully resolved.
+
+                tcx.sess.delay_span_bug(
+                    span,
+                    format!("upvar_tys for closure not found. Expected capture information for closure {ty}",),
+                );
+                return Err(NoSolution);
+            }
+
+            rustc_data_structures::stack::ensure_sufficient_stack(|| {
+                for ty in substs.as_closure().upvar_tys() {
+                    dtorck_constraint_for_ty_inner(tcx, span, for_ty, depth + 1, ty, constraints)?;
+                }
+                Ok::<_, NoSolution>(())
+            })?
+        }
+
+        ty::Generator(_, substs, _movability) => {
+            // rust-lang/rust#49918: types can be constructed, stored
+            // in the interior, and sit idle when generator yields
+            // (and is subsequently dropped).
+            //
+            // It would be nice to descend into interior of a
+            // generator to determine what effects dropping it might
+            // have (by looking at any drop effects associated with
+            // its interior).
+            //
+            // However, the interior's representation uses things like
+            // GeneratorWitness that explicitly assume they are not
+            // traversed in such a manner. So instead, we will
+            // simplify things for now by treating all generators as
+            // if they were like trait objects, where its upvars must
+            // all be alive for the generator's (potential)
+            // destructor.
+            //
+            // In particular, skipping over `_interior` is safe
+            // because any side-effects from dropping `_interior` can
+            // only take place through references with lifetimes
+            // derived from lifetimes attached to the upvars and resume
+            // argument, and we *do* incorporate those here.
+
+            if !substs.as_generator().is_valid() {
+                // By the time this code runs, all type variables ought to
+                // be fully resolved.
+                tcx.sess.delay_span_bug(
+                    span,
+                    format!("upvar_tys for generator not found. Expected capture information for generator {ty}",),
+                );
+                return Err(NoSolution);
+            }
+
+            constraints.outlives.extend(
+                substs
+                    .as_generator()
+                    .upvar_tys()
+                    .map(|t| -> ty::subst::GenericArg<'tcx> { t.into() }),
+            );
+            constraints.outlives.push(substs.as_generator().resume_ty().into());
+        }
+
+        ty::Adt(def, substs) => {
+            let DropckConstraint { dtorck_types, outlives, overflows } =
+                tcx.at(span).adt_dtorck_constraint(def.did())?;
+            // FIXME: we can try to recursively `dtorck_constraint_on_ty`
+            // there, but that needs some way to handle cycles.
+            constraints
+                .dtorck_types
+                .extend(dtorck_types.iter().map(|t| EarlyBinder::bind(*t).subst(tcx, substs)));
+            constraints
+                .outlives
+                .extend(outlives.iter().map(|t| EarlyBinder::bind(*t).subst(tcx, substs)));
+            constraints
+                .overflows
+                .extend(overflows.iter().map(|t| EarlyBinder::bind(*t).subst(tcx, substs)));
+        }
+
+        // Objects must be alive in order for their destructor
+        // to be called.
+        ty::Dynamic(..) => {
+            constraints.outlives.push(ty.into());
+        }
+
+        // Types that can't be resolved. Pass them forward.
+        ty::Alias(..) | ty::Param(..) => {
+            constraints.dtorck_types.push(ty);
+        }
+
+        ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => {
+            // By the time this code runs, all type variables ought to
+            // be fully resolved.
+            return Err(NoSolution);
+        }
+    }
+
+    Ok(())
+}
diff --git a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
index edbe2de8105..a8a74d7501a 100644
--- a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
@@ -90,7 +90,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
                     Ok(EvaluationResult::EvaluatedToAmbig)
                 } else if self.opaque_types_added_in_snapshot(snapshot) {
                     Ok(EvaluationResult::EvaluatedToOkModuloOpaqueTypes)
-                } else if self.region_constraints_added_in_snapshot(snapshot).is_some() {
+                } else if self.region_constraints_added_in_snapshot(snapshot) {
                     Ok(EvaluationResult::EvaluatedToOkModuloRegions)
                 } else {
                     Ok(EvaluationResult::EvaluatedToOk)
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs
index e6db96c9e55..01d7a1e7913 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs
@@ -1,8 +1,13 @@
 use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
-use crate::traits::query::Fallible;
-use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
+use crate::traits::ObligationCtxt;
+use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
+use rustc_infer::traits::Obligation;
+use rustc_middle::traits::query::NoSolution;
+use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
+use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, UserSelfTy, UserSubsts, UserType};
 
 pub use rustc_middle::traits::query::type_op::AscribeUserType;
+use rustc_span::{Span, DUMMY_SP};
 
 impl<'tcx> super::QueryTypeOp<'tcx> for AscribeUserType<'tcx> {
     type QueryResponse = ();
@@ -17,7 +22,119 @@ impl<'tcx> super::QueryTypeOp<'tcx> for AscribeUserType<'tcx> {
     fn perform_query(
         tcx: TyCtxt<'tcx>,
         canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
-    ) -> Fallible<CanonicalQueryResponse<'tcx, ()>> {
+    ) -> Result<CanonicalQueryResponse<'tcx, ()>, NoSolution> {
         tcx.type_op_ascribe_user_type(canonicalized)
     }
+
+    fn perform_locally_in_new_solver(
+        ocx: &ObligationCtxt<'_, 'tcx>,
+        key: ParamEnvAnd<'tcx, Self>,
+    ) -> Result<Self::QueryResponse, NoSolution> {
+        type_op_ascribe_user_type_with_span(ocx, key, None)
+    }
+}
+
+/// The core of the `type_op_ascribe_user_type` query: for diagnostics purposes in NLL HRTB errors,
+/// this query can be re-run to better track the span of the obligation cause, and improve the error
+/// message. Do not call directly unless you're in that very specific context.
+pub fn type_op_ascribe_user_type_with_span<'tcx>(
+    ocx: &ObligationCtxt<'_, 'tcx>,
+    key: ParamEnvAnd<'tcx, AscribeUserType<'tcx>>,
+    span: Option<Span>,
+) -> Result<(), NoSolution> {
+    let (param_env, AscribeUserType { mir_ty, user_ty }) = key.into_parts();
+    debug!("type_op_ascribe_user_type: mir_ty={:?} user_ty={:?}", mir_ty, user_ty);
+    let span = span.unwrap_or(DUMMY_SP);
+    match user_ty {
+        UserType::Ty(user_ty) => relate_mir_and_user_ty(ocx, param_env, span, mir_ty, user_ty)?,
+        UserType::TypeOf(def_id, user_substs) => {
+            relate_mir_and_user_substs(ocx, param_env, span, mir_ty, def_id, user_substs)?
+        }
+    };
+    Ok(())
+}
+
+#[instrument(level = "debug", skip(ocx, param_env, span))]
+fn relate_mir_and_user_ty<'tcx>(
+    ocx: &ObligationCtxt<'_, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    span: Span,
+    mir_ty: Ty<'tcx>,
+    user_ty: Ty<'tcx>,
+) -> Result<(), NoSolution> {
+    let cause = ObligationCause::dummy_with_span(span);
+    let user_ty = ocx.normalize(&cause, param_env, user_ty);
+    ocx.eq(&cause, param_env, mir_ty, user_ty)?;
+
+    // FIXME(#104764): We should check well-formedness before normalization.
+    let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(user_ty.into()));
+    ocx.register_obligation(Obligation::new(ocx.infcx.tcx, cause, param_env, predicate));
+    Ok(())
+}
+
+#[instrument(level = "debug", skip(ocx, param_env, span))]
+fn relate_mir_and_user_substs<'tcx>(
+    ocx: &ObligationCtxt<'_, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    span: Span,
+    mir_ty: Ty<'tcx>,
+    def_id: DefId,
+    user_substs: UserSubsts<'tcx>,
+) -> Result<(), NoSolution> {
+    let param_env = param_env.without_const();
+    let UserSubsts { user_self_ty, substs } = user_substs;
+    let tcx = ocx.infcx.tcx;
+    let cause = ObligationCause::dummy_with_span(span);
+
+    let ty = tcx.type_of(def_id).subst(tcx, substs);
+    let ty = ocx.normalize(&cause, param_env, ty);
+    debug!("relate_type_and_user_type: ty of def-id is {:?}", ty);
+
+    ocx.eq(&cause, param_env, mir_ty, ty)?;
+
+    // Prove the predicates coming along with `def_id`.
+    //
+    // Also, normalize the `instantiated_predicates`
+    // because otherwise we wind up with duplicate "type
+    // outlives" error messages.
+    let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs);
+
+    debug!(?instantiated_predicates);
+    for (instantiated_predicate, predicate_span) in instantiated_predicates {
+        let span = if span == DUMMY_SP { predicate_span } else { span };
+        let cause = ObligationCause::new(
+            span,
+            CRATE_DEF_ID,
+            ObligationCauseCode::AscribeUserTypeProvePredicate(predicate_span),
+        );
+        let instantiated_predicate =
+            ocx.normalize(&cause.clone(), param_env, instantiated_predicate);
+
+        ocx.register_obligation(Obligation::new(tcx, cause, param_env, instantiated_predicate));
+    }
+
+    if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty {
+        let self_ty = ocx.normalize(&cause, param_env, self_ty);
+        let impl_self_ty = tcx.type_of(impl_def_id).subst(tcx, substs);
+        let impl_self_ty = ocx.normalize(&cause, param_env, impl_self_ty);
+
+        ocx.eq(&cause, param_env, self_ty, impl_self_ty)?;
+        let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(impl_self_ty.into()));
+        ocx.register_obligation(Obligation::new(tcx, cause.clone(), param_env, predicate));
+    }
+
+    // In addition to proving the predicates, we have to
+    // prove that `ty` is well-formed -- this is because
+    // the WF of `ty` is predicated on the substs being
+    // well-formed, and we haven't proven *that*. We don't
+    // want to prove the WF of types from  `substs` directly because they
+    // haven't been normalized.
+    //
+    // FIXME(nmatsakis): Well, perhaps we should normalize
+    // them?  This would only be relevant if some input
+    // type were ill-formed but did not appear in `ty`,
+    // which...could happen with normalization...
+    let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into()));
+    ocx.register_obligation(Obligation::new(tcx, cause, param_env, predicate));
+    Ok(())
 }
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
index 3d6c1d9e2b0..6d8d2103f39 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
@@ -1,11 +1,12 @@
 use crate::infer::canonical::query_response;
 use crate::infer::InferCtxt;
 use crate::traits::query::type_op::TypeOpOutput;
-use crate::traits::query::Fallible;
 use crate::traits::ObligationCtxt;
+use rustc_errors::ErrorGuaranteed;
 use rustc_infer::infer::region_constraints::RegionConstraintData;
 use rustc_middle::traits::query::NoSolution;
 use rustc_span::source_map::DUMMY_SP;
+use rustc_span::Span;
 
 use std::fmt;
 
@@ -17,7 +18,7 @@ pub struct CustomTypeOp<F> {
 impl<F> CustomTypeOp<F> {
     pub fn new<'tcx, R>(closure: F, description: &'static str) -> Self
     where
-        F: FnOnce(&ObligationCtxt<'_, 'tcx>) -> Fallible<R>,
+        F: FnOnce(&ObligationCtxt<'_, 'tcx>) -> Result<R, NoSolution>,
     {
         CustomTypeOp { closure, description }
     }
@@ -25,7 +26,7 @@ impl<F> CustomTypeOp<F> {
 
 impl<'tcx, F, R: fmt::Debug> super::TypeOp<'tcx> for CustomTypeOp<F>
 where
-    F: FnOnce(&ObligationCtxt<'_, 'tcx>) -> Fallible<R>,
+    F: FnOnce(&ObligationCtxt<'_, 'tcx>) -> Result<R, NoSolution>,
 {
     type Output = R;
     /// We can't do any custom error reporting for `CustomTypeOp`, so
@@ -35,12 +36,16 @@ where
     /// Processes the operation and all resulting obligations,
     /// returning the final result along with any region constraints
     /// (they will be given over to the NLL region solver).
-    fn fully_perform(self, infcx: &InferCtxt<'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> {
+    fn fully_perform(
+        self,
+        infcx: &InferCtxt<'tcx>,
+        span: Span,
+    ) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed> {
         if cfg!(debug_assertions) {
             info!("fully_perform({:?})", self);
         }
 
-        Ok(scrape_region_constraints(infcx, self.closure)?.0)
+        Ok(scrape_region_constraints(infcx, self.closure, self.description, span)?.0)
     }
 }
 
@@ -54,8 +59,10 @@ impl<F> fmt::Debug for CustomTypeOp<F> {
 /// constraints that result, creating query-region-constraints.
 pub fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>(
     infcx: &InferCtxt<'tcx>,
-    op: impl FnOnce(&ObligationCtxt<'_, 'tcx>) -> Fallible<R>,
-) -> Fallible<(TypeOpOutput<'tcx, Op>, RegionConstraintData<'tcx>)> {
+    op: impl FnOnce(&ObligationCtxt<'_, 'tcx>) -> Result<R, NoSolution>,
+    name: &'static str,
+    span: Span,
+) -> Result<(TypeOpOutput<'tcx, Op>, RegionConstraintData<'tcx>), ErrorGuaranteed> {
     // During NLL, we expect that nobody will register region
     // obligations **except** as part of a custom type op (and, at the
     // end of each custom type op, we scrape out the region
@@ -70,16 +77,17 @@ pub fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>(
 
     let value = infcx.commit_if_ok(|_| {
         let ocx = ObligationCtxt::new_in_snapshot(infcx);
-        let value = op(&ocx)?;
+        let value = op(&ocx).map_err(|_| {
+            infcx.tcx.sess.delay_span_bug(span, format!("error performing operation: {name}"))
+        })?;
         let errors = ocx.select_all_or_error();
         if errors.is_empty() {
             Ok(value)
         } else {
-            infcx.tcx.sess.delay_span_bug(
+            Err(infcx.tcx.sess.delay_span_bug(
                 DUMMY_SP,
                 format!("errors selecting obligation during MIR typeck: {:?}", errors),
-            );
-            Err(NoSolution)
+            ))
         }
     })?;
 
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/eq.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/eq.rs
index 8c9b9610cb6..f6589308806 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/eq.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/eq.rs
@@ -1,5 +1,7 @@
 use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
-use crate::traits::query::Fallible;
+use crate::traits::ObligationCtxt;
+use rustc_middle::traits::query::NoSolution;
+use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
 
 pub use rustc_middle::traits::query::type_op::Eq;
@@ -17,7 +19,15 @@ impl<'tcx> super::QueryTypeOp<'tcx> for Eq<'tcx> {
     fn perform_query(
         tcx: TyCtxt<'tcx>,
         canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
-    ) -> Fallible<CanonicalQueryResponse<'tcx, ()>> {
+    ) -> Result<CanonicalQueryResponse<'tcx, ()>, NoSolution> {
         tcx.type_op_eq(canonicalized)
     }
+
+    fn perform_locally_in_new_solver(
+        ocx: &ObligationCtxt<'_, 'tcx>,
+        key: ParamEnvAnd<'tcx, Self>,
+    ) -> Result<Self::QueryResponse, NoSolution> {
+        ocx.eq(&ObligationCause::dummy(), key.param_env, key.value.a, key.value.b)?;
+        Ok(())
+    }
 }
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
index 18d7c9b1936..9989fc9c479 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
@@ -1,7 +1,15 @@
-use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
-use crate::traits::query::Fallible;
+use crate::traits::query::NoSolution;
+use crate::traits::wf;
+use crate::traits::ObligationCtxt;
+
+use rustc_infer::infer::canonical::Canonical;
+use rustc_infer::infer::outlives::components::{push_outlives_components, Component};
 use rustc_infer::traits::query::OutlivesBound;
-use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt};
+use rustc_middle::infer::canonical::CanonicalQueryResponse;
+use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
+use rustc_span::def_id::CRATE_DEF_ID;
+use rustc_span::source_map::DUMMY_SP;
+use smallvec::{smallvec, SmallVec};
 
 #[derive(Copy, Clone, Debug, HashStable, TypeFoldable, TypeVisitable, Lift)]
 pub struct ImpliedOutlivesBounds<'tcx> {
@@ -28,7 +36,7 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ImpliedOutlivesBounds<'tcx> {
     fn perform_query(
         tcx: TyCtxt<'tcx>,
         canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
-    ) -> Fallible<CanonicalQueryResponse<'tcx, Self::QueryResponse>> {
+    ) -> Result<CanonicalQueryResponse<'tcx, Self::QueryResponse>, NoSolution> {
         // FIXME this `unchecked_map` is only necessary because the
         // query is defined as taking a `ParamEnvAnd<Ty>`; it should
         // take an `ImpliedOutlivesBounds` instead
@@ -39,4 +47,169 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ImpliedOutlivesBounds<'tcx> {
 
         tcx.implied_outlives_bounds(canonicalized)
     }
+
+    fn perform_locally_in_new_solver(
+        ocx: &ObligationCtxt<'_, 'tcx>,
+        key: ParamEnvAnd<'tcx, Self>,
+    ) -> Result<Self::QueryResponse, NoSolution> {
+        compute_implied_outlives_bounds_inner(ocx, key.param_env, key.value.ty)
+    }
+}
+
+pub fn compute_implied_outlives_bounds_inner<'tcx>(
+    ocx: &ObligationCtxt<'_, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    ty: Ty<'tcx>,
+) -> Result<Vec<OutlivesBound<'tcx>>, NoSolution> {
+    let tcx = ocx.infcx.tcx;
+
+    // Sometimes when we ask what it takes for T: WF, we get back that
+    // U: WF is required; in that case, we push U onto this stack and
+    // process it next. Because the resulting predicates aren't always
+    // guaranteed to be a subset of the original type, so we need to store the
+    // WF args we've computed in a set.
+    let mut checked_wf_args = rustc_data_structures::fx::FxHashSet::default();
+    let mut wf_args = vec![ty.into()];
+
+    let mut outlives_bounds: Vec<ty::OutlivesPredicate<ty::GenericArg<'tcx>, ty::Region<'tcx>>> =
+        vec![];
+
+    while let Some(arg) = wf_args.pop() {
+        if !checked_wf_args.insert(arg) {
+            continue;
+        }
+
+        // Compute the obligations for `arg` to be well-formed. If `arg` is
+        // an unresolved inference variable, just substituted an empty set
+        // -- because the return type here is going to be things we *add*
+        // to the environment, it's always ok for this set to be smaller
+        // than the ultimate set. (Note: normally there won't be
+        // unresolved inference variables here anyway, but there might be
+        // during typeck under some circumstances.)
+        //
+        // FIXME(@lcnr): It's not really "always fine", having fewer implied
+        // bounds can be backward incompatible, e.g. #101951 was caused by
+        // us not dealing with inference vars in `TypeOutlives` predicates.
+        let obligations = wf::obligations(ocx.infcx, param_env, CRATE_DEF_ID, 0, arg, DUMMY_SP)
+            .unwrap_or_default();
+
+        for obligation in obligations {
+            debug!(?obligation);
+            assert!(!obligation.has_escaping_bound_vars());
+
+            // While these predicates should all be implied by other parts of
+            // the program, they are still relevant as they may constrain
+            // inference variables, which is necessary to add the correct
+            // implied bounds in some cases, mostly when dealing with projections.
+            //
+            // Another important point here: we only register `Projection`
+            // predicates, since otherwise we might register outlives
+            // predicates containing inference variables, and we don't
+            // learn anything new from those.
+            if obligation.predicate.has_non_region_infer() {
+                match obligation.predicate.kind().skip_binder() {
+                    ty::PredicateKind::Clause(ty::Clause::Projection(..))
+                    | ty::PredicateKind::AliasRelate(..) => {
+                        ocx.register_obligation(obligation.clone());
+                    }
+                    _ => {}
+                }
+            }
+
+            let pred = match obligation.predicate.kind().no_bound_vars() {
+                None => continue,
+                Some(pred) => pred,
+            };
+            match pred {
+                ty::PredicateKind::Clause(ty::Clause::Trait(..))
+                // FIXME(const_generics): Make sure that `<'a, 'b, const N: &'a &'b u32>` is sound
+                // if we ever support that
+                | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
+                | ty::PredicateKind::Subtype(..)
+                | ty::PredicateKind::Coerce(..)
+                | ty::PredicateKind::Clause(ty::Clause::Projection(..))
+                | ty::PredicateKind::ClosureKind(..)
+                | ty::PredicateKind::ObjectSafe(..)
+                | ty::PredicateKind::ConstEvaluatable(..)
+                | ty::PredicateKind::ConstEquate(..)
+                | ty::PredicateKind::Ambiguous
+                | ty::PredicateKind::AliasRelate(..)
+                | ty::PredicateKind::TypeWellFormedFromEnv(..) => {}
+
+                // We need to search through *all* WellFormed predicates
+                ty::PredicateKind::WellFormed(arg) => {
+                    wf_args.push(arg);
+                }
+
+                // We need to register region relationships
+                ty::PredicateKind::Clause(ty::Clause::RegionOutlives(ty::OutlivesPredicate(
+                    r_a,
+                    r_b,
+                ))) => outlives_bounds.push(ty::OutlivesPredicate(r_a.into(), r_b)),
+
+                ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate(
+                    ty_a,
+                    r_b,
+                ))) => outlives_bounds.push(ty::OutlivesPredicate(ty_a.into(), r_b)),
+            }
+        }
+    }
+
+    // This call to `select_all_or_error` is necessary to constrain inference variables, which we
+    // use further down when computing the implied bounds.
+    match ocx.select_all_or_error().as_slice() {
+        [] => (),
+        _ => return Err(NoSolution),
+    }
+
+    // We lazily compute the outlives components as
+    // `select_all_or_error` constrains inference variables.
+    let implied_bounds = outlives_bounds
+        .into_iter()
+        .flat_map(|ty::OutlivesPredicate(a, r_b)| match a.unpack() {
+            ty::GenericArgKind::Lifetime(r_a) => vec![OutlivesBound::RegionSubRegion(r_b, r_a)],
+            ty::GenericArgKind::Type(ty_a) => {
+                let ty_a = ocx.infcx.resolve_vars_if_possible(ty_a);
+                let mut components = smallvec![];
+                push_outlives_components(tcx, ty_a, &mut components);
+                implied_bounds_from_components(r_b, components)
+            }
+            ty::GenericArgKind::Const(_) => unreachable!(),
+        })
+        .collect();
+
+    Ok(implied_bounds)
+}
+
+/// When we have an implied bound that `T: 'a`, we can further break
+/// this down to determine what relationships would have to hold for
+/// `T: 'a` to hold. We get to assume that the caller has validated
+/// those relationships.
+fn implied_bounds_from_components<'tcx>(
+    sub_region: ty::Region<'tcx>,
+    sup_components: SmallVec<[Component<'tcx>; 4]>,
+) -> Vec<OutlivesBound<'tcx>> {
+    sup_components
+        .into_iter()
+        .filter_map(|component| {
+            match component {
+                Component::Region(r) => Some(OutlivesBound::RegionSubRegion(sub_region, r)),
+                Component::Param(p) => Some(OutlivesBound::RegionSubParam(sub_region, p)),
+                Component::Alias(p) => Some(OutlivesBound::RegionSubAlias(sub_region, p)),
+                Component::EscapingAlias(_) =>
+                // If the projection has escaping regions, don't
+                // try to infer any implied bounds even for its
+                // free components. This is conservative, because
+                // the caller will still have to prove that those
+                // free components outlive `sub_region`. But the
+                // idea is that the WAY that the caller proves
+                // that may change in the future and we want to
+                // give ourselves room to get smarter here.
+                {
+                    None
+                }
+                Component::UnresolvedInferenceVariable(..) => None,
+            }
+        })
+        .collect()
 }
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
index 9e8bc8bce9a..642fdec2d9a 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
@@ -2,13 +2,14 @@ use crate::infer::canonical::{
     Canonical, CanonicalQueryResponse, OriginalQueryValues, QueryRegionConstraints,
 };
 use crate::infer::{InferCtxt, InferOk};
-use crate::traits::query::Fallible;
-use crate::traits::ObligationCause;
+use crate::traits::{ObligationCause, ObligationCtxt};
+use rustc_errors::ErrorGuaranteed;
 use rustc_infer::infer::canonical::Certainty;
-use rustc_infer::traits::query::NoSolution;
 use rustc_infer::traits::PredicateObligations;
+use rustc_middle::traits::query::NoSolution;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
+use rustc_span::Span;
 use std::fmt;
 
 pub mod ascribe_user_type;
@@ -22,6 +23,8 @@ pub mod subtype;
 
 pub use rustc_middle::traits::query::type_op::*;
 
+use self::custom::scrape_region_constraints;
+
 /// "Type ops" are used in NLL to perform some particular action and
 /// extract out the resulting region constraints (or an error if it
 /// cannot be completed).
@@ -32,7 +35,11 @@ pub trait TypeOp<'tcx>: Sized + fmt::Debug {
     /// Processes the operation and all resulting obligations,
     /// returning the final result along with any region constraints
     /// (they will be given over to the NLL region solver).
-    fn fully_perform(self, infcx: &InferCtxt<'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>>;
+    fn fully_perform(
+        self,
+        infcx: &InferCtxt<'tcx>,
+        span: Span,
+    ) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed>;
 }
 
 /// The output from performing a type op
@@ -74,18 +81,32 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<TyCtxt<'tcx>> + 't
     fn perform_query(
         tcx: TyCtxt<'tcx>,
         canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
-    ) -> Fallible<CanonicalQueryResponse<'tcx, Self::QueryResponse>>;
+    ) -> Result<CanonicalQueryResponse<'tcx, Self::QueryResponse>, NoSolution>;
+
+    /// In the new trait solver, we already do caching in the solver itself,
+    /// so there's no need to canonicalize and cache via the query system.
+    /// Additionally, even if we were to canonicalize, we'd still need to
+    /// make sure to feed it predefined opaque types and the defining anchor
+    /// and that would require duplicating all of the tcx queries. Instead,
+    /// just perform these ops locally.
+    fn perform_locally_in_new_solver(
+        ocx: &ObligationCtxt<'_, 'tcx>,
+        key: ParamEnvAnd<'tcx, Self>,
+    ) -> Result<Self::QueryResponse, NoSolution>;
 
     fn fully_perform_into(
         query_key: ParamEnvAnd<'tcx, Self>,
         infcx: &InferCtxt<'tcx>,
         output_query_region_constraints: &mut QueryRegionConstraints<'tcx>,
-    ) -> Fallible<(
-        Self::QueryResponse,
-        Option<Canonical<'tcx, ParamEnvAnd<'tcx, Self>>>,
-        PredicateObligations<'tcx>,
-        Certainty,
-    )> {
+    ) -> Result<
+        (
+            Self::QueryResponse,
+            Option<Canonical<'tcx, ParamEnvAnd<'tcx, Self>>>,
+            PredicateObligations<'tcx>,
+            Certainty,
+        ),
+        NoSolution,
+    > {
         if let Some(result) = QueryTypeOp::try_fast_path(infcx.tcx, &query_key) {
             return Ok((result, None, vec![], Certainty::Proven));
         }
@@ -120,10 +141,26 @@ where
     type Output = Q::QueryResponse;
     type ErrorInfo = Canonical<'tcx, ParamEnvAnd<'tcx, Q>>;
 
-    fn fully_perform(self, infcx: &InferCtxt<'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> {
+    fn fully_perform(
+        self,
+        infcx: &InferCtxt<'tcx>,
+        span: Span,
+    ) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed> {
+        if infcx.tcx.trait_solver_next() {
+            return Ok(scrape_region_constraints(
+                infcx,
+                |ocx| QueryTypeOp::perform_locally_in_new_solver(ocx, self),
+                "query type op",
+                span,
+            )?
+            .0);
+        }
+
         let mut region_constraints = QueryRegionConstraints::default();
         let (output, error_info, mut obligations, _) =
-            Q::fully_perform_into(self, infcx, &mut region_constraints)?;
+            Q::fully_perform_into(self, infcx, &mut region_constraints).map_err(|_| {
+                infcx.tcx.sess.delay_span_bug(span, format!("error performing {self:?}"))
+            })?;
 
         // Typically, instantiating NLL query results does not
         // create obligations. However, in some cases there
@@ -151,7 +188,10 @@ where
                 }
             }
             if !progress {
-                return Err(NoSolution);
+                return Err(infcx.tcx.sess.delay_span_bug(
+                    span,
+                    format!("ambiguity processing {obligations:?} from {self:?}"),
+                ));
             }
         }
 
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs
index 5b216c07692..57ca14aa492 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs
@@ -1,5 +1,7 @@
 use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
-use crate::traits::query::Fallible;
+use crate::traits::ObligationCtxt;
+use rustc_middle::traits::query::NoSolution;
+use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::{self, Lift, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
 use std::fmt;
@@ -19,23 +21,31 @@ where
     fn perform_query(
         tcx: TyCtxt<'tcx>,
         canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
-    ) -> Fallible<CanonicalQueryResponse<'tcx, Self::QueryResponse>> {
+    ) -> Result<CanonicalQueryResponse<'tcx, Self::QueryResponse>, NoSolution> {
         T::type_op_method(tcx, canonicalized)
     }
+
+    fn perform_locally_in_new_solver(
+        ocx: &ObligationCtxt<'_, 'tcx>,
+        key: ParamEnvAnd<'tcx, Self>,
+    ) -> Result<Self::QueryResponse, NoSolution> {
+        // FIXME(-Ztrait-solver=next): shouldn't be using old normalizer
+        Ok(ocx.normalize(&ObligationCause::dummy(), key.param_env, key.value.value))
+    }
 }
 
 pub trait Normalizable<'tcx>: fmt::Debug + TypeFoldable<TyCtxt<'tcx>> + Lift<'tcx> + Copy {
     fn type_op_method(
         tcx: TyCtxt<'tcx>,
         canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
-    ) -> Fallible<CanonicalQueryResponse<'tcx, Self>>;
+    ) -> Result<CanonicalQueryResponse<'tcx, Self>, NoSolution>;
 }
 
 impl<'tcx> Normalizable<'tcx> for Ty<'tcx> {
     fn type_op_method(
         tcx: TyCtxt<'tcx>,
         canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
-    ) -> Fallible<CanonicalQueryResponse<'tcx, Self>> {
+    ) -> Result<CanonicalQueryResponse<'tcx, Self>, NoSolution> {
         tcx.type_op_normalize_ty(canonicalized)
     }
 }
@@ -44,7 +54,7 @@ impl<'tcx> Normalizable<'tcx> for ty::Predicate<'tcx> {
     fn type_op_method(
         tcx: TyCtxt<'tcx>,
         canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
-    ) -> Fallible<CanonicalQueryResponse<'tcx, Self>> {
+    ) -> Result<CanonicalQueryResponse<'tcx, Self>, NoSolution> {
         tcx.type_op_normalize_predicate(canonicalized)
     }
 }
@@ -53,7 +63,7 @@ impl<'tcx> Normalizable<'tcx> for ty::PolyFnSig<'tcx> {
     fn type_op_method(
         tcx: TyCtxt<'tcx>,
         canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
-    ) -> Fallible<CanonicalQueryResponse<'tcx, Self>> {
+    ) -> Result<CanonicalQueryResponse<'tcx, Self>, NoSolution> {
         tcx.type_op_normalize_poly_fn_sig(canonicalized)
     }
 }
@@ -62,7 +72,7 @@ impl<'tcx> Normalizable<'tcx> for ty::FnSig<'tcx> {
     fn type_op_method(
         tcx: TyCtxt<'tcx>,
         canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
-    ) -> Fallible<CanonicalQueryResponse<'tcx, Self>> {
+    ) -> Result<CanonicalQueryResponse<'tcx, Self>, NoSolution> {
         tcx.type_op_normalize_fn_sig(canonicalized)
     }
 }
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs
index 21ef4e24fdb..98894263374 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs
@@ -1,6 +1,9 @@
 use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
-use crate::traits::query::dropck_outlives::{trivial_dropck_outlives, DropckOutlivesResult};
-use crate::traits::query::Fallible;
+use crate::traits::query::dropck_outlives::{
+    compute_dropck_outlives_inner, trivial_dropck_outlives,
+};
+use crate::traits::ObligationCtxt;
+use rustc_middle::traits::query::{DropckOutlivesResult, NoSolution};
 use rustc_middle::ty::{ParamEnvAnd, Ty, TyCtxt};
 
 #[derive(Copy, Clone, Debug, HashStable, TypeFoldable, TypeVisitable, Lift)]
@@ -27,7 +30,7 @@ impl<'tcx> super::QueryTypeOp<'tcx> for DropckOutlives<'tcx> {
     fn perform_query(
         tcx: TyCtxt<'tcx>,
         canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
-    ) -> Fallible<CanonicalQueryResponse<'tcx, Self::QueryResponse>> {
+    ) -> Result<CanonicalQueryResponse<'tcx, Self::QueryResponse>, NoSolution> {
         // Subtle: note that we are not invoking
         // `infcx.at(...).dropck_outlives(...)` here, but rather the
         // underlying `dropck_outlives` query. This same underlying
@@ -48,4 +51,11 @@ impl<'tcx> super::QueryTypeOp<'tcx> for DropckOutlives<'tcx> {
 
         tcx.dropck_outlives(canonicalized)
     }
+
+    fn perform_locally_in_new_solver(
+        ocx: &ObligationCtxt<'_, 'tcx>,
+        key: ParamEnvAnd<'tcx, Self>,
+    ) -> Result<Self::QueryResponse, NoSolution> {
+        compute_dropck_outlives_inner(ocx, key.param_env.and(key.value.dropped_ty))
+    }
 }
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
index baa2fbb6751..47850bc330d 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
@@ -1,5 +1,8 @@
 use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
-use crate::traits::query::Fallible;
+use crate::traits::ObligationCtxt;
+use rustc_infer::traits::Obligation;
+use rustc_middle::traits::query::NoSolution;
+use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt};
 
 pub use rustc_middle::traits::query::type_op::ProvePredicate;
@@ -33,7 +36,20 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> {
     fn perform_query(
         tcx: TyCtxt<'tcx>,
         canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
-    ) -> Fallible<CanonicalQueryResponse<'tcx, ()>> {
+    ) -> Result<CanonicalQueryResponse<'tcx, ()>, NoSolution> {
         tcx.type_op_prove_predicate(canonicalized)
     }
+
+    fn perform_locally_in_new_solver(
+        ocx: &ObligationCtxt<'_, 'tcx>,
+        key: ParamEnvAnd<'tcx, Self>,
+    ) -> Result<Self::QueryResponse, NoSolution> {
+        ocx.register_obligation(Obligation::new(
+            ocx.infcx.tcx,
+            ObligationCause::dummy(),
+            key.param_env,
+            key.value.predicate,
+        ));
+        Ok(())
+    }
 }
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/subtype.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/subtype.rs
index c51292eba14..10976d5cd71 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/subtype.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/subtype.rs
@@ -1,5 +1,7 @@
 use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
-use crate::traits::query::Fallible;
+use crate::traits::ObligationCtxt;
+use rustc_middle::traits::query::NoSolution;
+use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
 
 pub use rustc_middle::traits::query::type_op::Subtype;
@@ -14,7 +16,15 @@ impl<'tcx> super::QueryTypeOp<'tcx> for Subtype<'tcx> {
     fn perform_query(
         tcx: TyCtxt<'tcx>,
         canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
-    ) -> Fallible<CanonicalQueryResponse<'tcx, ()>> {
+    ) -> Result<CanonicalQueryResponse<'tcx, ()>, NoSolution> {
         tcx.type_op_subtype(canonicalized)
     }
+
+    fn perform_locally_in_new_solver(
+        ocx: &ObligationCtxt<'_, 'tcx>,
+        key: ParamEnvAnd<'tcx, Self>,
+    ) -> Result<Self::QueryResponse, NoSolution> {
+        ocx.sub(&ObligationCause::dummy(), key.param_env, key.value.sub, key.value.sup)?;
+        Ok(())
+    }
 }
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 8bc82b9f549..3c223db5a0b 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -360,7 +360,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 // consider a "quick reject". This avoids creating more types
                 // and so forth that we need to.
                 let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap();
-                if !drcx.substs_refs_may_unify(obligation_substs, impl_trait_ref.0.substs) {
+                if !drcx
+                    .substs_refs_may_unify(obligation_substs, impl_trait_ref.skip_binder().substs)
+                {
                     return;
                 }
                 if self.reject_fn_ptr_impls(
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 0d9f55d4c2e..4e961c3ee73 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -527,9 +527,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                         substs.extend(trait_predicate.trait_ref.substs.iter());
                         let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> =
                             smallvec::SmallVec::with_capacity(
-                                bound.0.kind().bound_vars().len() + defs.count(),
+                                bound.skip_binder().kind().bound_vars().len() + defs.count(),
                             );
-                        bound_vars.extend(bound.0.kind().bound_vars().into_iter());
+                        bound_vars.extend(bound.skip_binder().kind().bound_vars().into_iter());
                         InternalSubsts::fill_single(&mut substs, defs, &mut |param, _| match param
                             .kind
                         {
@@ -550,7 +550,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                                 let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name);
                                 let bound_var = ty::BoundVariableKind::Region(kind);
                                 bound_vars.push(bound_var);
-                                tcx.mk_re_late_bound(
+                                ty::Region::new_late_bound(
+                                    tcx,
                                     ty::INNERMOST,
                                     ty::BoundRegion {
                                         var: ty::BoundVar::from_usize(bound_vars.len() - 1),
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 3baf1c97c9f..42c1b629ac2 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -561,9 +561,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         op: impl FnOnce(&mut Self) -> Result<EvaluationResult, OverflowError>,
     ) -> Result<EvaluationResult, OverflowError> {
         self.infcx.probe(|snapshot| -> Result<EvaluationResult, OverflowError> {
+            let outer_universe = self.infcx.universe();
             let result = op(self)?;
 
-            match self.infcx.leak_check(true, snapshot) {
+            match self.infcx.leak_check(outer_universe, Some(snapshot)) {
                 Ok(()) => {}
                 Err(_) => return Ok(EvaluatedToErr),
             }
@@ -572,9 +573,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 return Ok(result.max(EvaluatedToOkModuloOpaqueTypes));
             }
 
-            match self.infcx.region_constraints_added_in_snapshot(snapshot) {
-                None => Ok(result),
-                Some(_) => Ok(result.max(EvaluatedToOkModuloRegions)),
+            if self.infcx.region_constraints_added_in_snapshot(snapshot) {
+                Ok(result.max(EvaluatedToOkModuloRegions))
+            } else {
+                Ok(result)
             }
         })
     }
@@ -2149,13 +2151,11 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
             ty::Adt(def, substs) => {
                 let sized_crit = def.sized_constraint(self.tcx());
                 // (*) binder moved here
-                Where(obligation.predicate.rebind({
-                    sized_crit
-                        .0
-                        .iter()
-                        .map(|ty| sized_crit.rebind(*ty).subst(self.tcx(), substs))
-                        .collect()
-                }))
+                Where(
+                    obligation
+                        .predicate
+                        .rebind(sized_crit.subst_iter_copied(self.tcx(), substs).collect()),
+                )
             }
 
             ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => None,
@@ -3029,7 +3029,7 @@ fn bind_generator_hidden_types_above<'tcx>(
                             kind: ty::BrAnon(None),
                         };
                         counter += 1;
-                        tcx.mk_re_late_bound(current_depth, br)
+                        ty::Region::new_late_bound(tcx, current_depth, br)
                     }
                     r => bug!("unexpected region: {r:?}"),
                 })
diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs
index 82f3df40198..e2c9c62512e 100644
--- a/compiler/rustc_trait_selection/src/traits/util.rs
+++ b/compiler/rustc_trait_selection/src/traits/util.rs
@@ -41,7 +41,12 @@ impl<'tcx> TraitAliasExpansionInfo<'tcx> {
 
     /// Adds diagnostic labels to `diag` for the expansion path of a trait through all intermediate
     /// trait aliases.
-    pub fn label_with_exp_info(&self, diag: &mut Diagnostic, top_label: &str, use_desc: &str) {
+    pub fn label_with_exp_info(
+        &self,
+        diag: &mut Diagnostic,
+        top_label: &'static str,
+        use_desc: &str,
+    ) {
         diag.span_label(self.top().1, top_label);
         if self.path.len() > 1 {
             for (_, sp) in self.path.iter().rev().skip(1).take(self.path.len() - 2) {
diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs
index c319b2e31c7..38f94c38861 100644
--- a/compiler/rustc_traits/src/chalk/db.rs
+++ b/compiler/rustc_traits/src/chalk/db.rs
@@ -294,7 +294,7 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
         };
         Arc::new(chalk_solve::rust_ir::FnDefDatum {
             id: fn_def_id,
-            sig: sig.0.lower_into(self.interner),
+            sig: sig.skip_binder().lower_into(self.interner),
             binders: chalk_ir::Binders::new(binders, bound),
         })
     }
@@ -727,7 +727,7 @@ fn bound_vars_for_item(tcx: TyCtxt<'_>, def_id: DefId) -> SubstsRef<'_> {
                 var: ty::BoundVar::from_usize(substs.len()),
                 kind: ty::BrAnon(None),
             };
-            tcx.mk_re_late_bound(ty::INNERMOST, br).into()
+            ty::Region::new_late_bound(tcx, ty::INNERMOST, br).into()
         }
 
         ty::GenericParamDefKind::Const { .. } => tcx
diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs
index e447ab94f64..e6c6e0f13df 100644
--- a/compiler/rustc_traits/src/chalk/lowering.rs
+++ b/compiler/rustc_traits/src/chalk/lowering.rs
@@ -542,7 +542,8 @@ impl<'tcx> LowerInto<'tcx, Region<'tcx>> for &chalk_ir::Lifetime<RustInterner<'t
     fn lower_into(self, interner: RustInterner<'tcx>) -> Region<'tcx> {
         let tcx = interner.tcx;
         match self.data(interner) {
-            chalk_ir::LifetimeData::BoundVar(var) => tcx.mk_re_late_bound(
+            chalk_ir::LifetimeData::BoundVar(var) => ty::Region::new_late_bound(
+                tcx,
                 ty::DebruijnIndex::from_u32(var.debruijn.depth()),
                 ty::BoundRegion {
                     var: ty::BoundVar::from_usize(var.index),
@@ -550,13 +551,16 @@ impl<'tcx> LowerInto<'tcx, Region<'tcx>> for &chalk_ir::Lifetime<RustInterner<'t
                 },
             ),
             chalk_ir::LifetimeData::InferenceVar(_var) => unimplemented!(),
-            chalk_ir::LifetimeData::Placeholder(p) => tcx.mk_re_placeholder(ty::Placeholder {
-                universe: ty::UniverseIndex::from_usize(p.ui.counter),
-                bound: ty::BoundRegion {
-                    var: ty::BoundVar::from_usize(p.idx),
-                    kind: ty::BoundRegionKind::BrAnon(None),
+            chalk_ir::LifetimeData::Placeholder(p) => ty::Region::new_placeholder(
+                tcx,
+                ty::Placeholder {
+                    universe: ty::UniverseIndex::from_usize(p.ui.counter),
+                    bound: ty::BoundRegion {
+                        var: ty::BoundVar::from_usize(p.idx),
+                        kind: ty::BoundRegionKind::BrAnon(None),
+                    },
                 },
-            }),
+            ),
             chalk_ir::LifetimeData::Static => tcx.lifetimes.re_static,
             chalk_ir::LifetimeData::Erased => tcx.lifetimes.re_erased,
             chalk_ir::LifetimeData::Phantom(void, _) => match *void {},
@@ -1051,7 +1055,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for NamedBoundVarSubstitutor<'a, 'tcx> {
                 ty::BrNamed(def_id, _name) => match self.named_parameters.get(&def_id) {
                     Some(_) => {
                         let new_br = ty::BoundRegion { var: br.var, kind: ty::BrAnon(None) };
-                        return self.tcx.mk_re_late_bound(index, new_br);
+                        return ty::Region::new_late_bound(self.tcx, index, new_br);
                     }
                     None => panic!("Missing `BrNamed`."),
                 },
@@ -1142,7 +1146,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ParamsSubstitutor<'tcx> {
                         var: ty::BoundVar::from_u32(*idx),
                         kind: ty::BrAnon(None),
                     };
-                    self.tcx.mk_re_late_bound(self.binder_index, br)
+                    ty::Region::new_late_bound(self.tcx, self.binder_index, br)
                 }
                 None => {
                     let idx = self.named_regions.len() as u32;
@@ -1151,7 +1155,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ParamsSubstitutor<'tcx> {
                         kind: ty::BrAnon(None),
                     };
                     self.named_regions.insert(_re.def_id, idx);
-                    self.tcx.mk_re_late_bound(self.binder_index, br)
+                    ty::Region::new_late_bound(self.tcx, self.binder_index, br)
                 }
             },
 
diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs
index 83f6c7d07fe..f35c14eeac8 100644
--- a/compiler/rustc_traits/src/dropck_outlives.rs
+++ b/compiler/rustc_traits/src/dropck_outlives.rs
@@ -3,17 +3,14 @@ use rustc_hir::def_id::DefId;
 use rustc_infer::infer::canonical::{Canonical, QueryResponse};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::query::Providers;
+use rustc_middle::traits::query::{DropckConstraint, DropckOutlivesResult};
 use rustc_middle::ty::InternalSubsts;
-use rustc_middle::ty::{self, EarlyBinder, ParamEnvAnd, Ty, TyCtxt};
-use rustc_span::source_map::{Span, DUMMY_SP};
+use rustc_middle::ty::TyCtxt;
 use rustc_trait_selection::infer::InferCtxtBuilderExt;
-use rustc_trait_selection::traits::query::dropck_outlives::trivial_dropck_outlives;
 use rustc_trait_selection::traits::query::dropck_outlives::{
-    DropckConstraint, DropckOutlivesResult,
+    compute_dropck_outlives_inner, dtorck_constraint_for_ty_inner,
 };
-use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
 use rustc_trait_selection::traits::query::{CanonicalTyGoal, NoSolution};
-use rustc_trait_selection::traits::{Normalized, ObligationCause};
 
 pub(crate) fn provide(p: &mut Providers) {
     *p = Providers { dropck_outlives, adt_dtorck_constraint, ..*p };
@@ -26,263 +23,10 @@ fn dropck_outlives<'tcx>(
     debug!("dropck_outlives(goal={:#?})", canonical_goal);
 
     tcx.infer_ctxt().enter_canonical_trait_query(&canonical_goal, |ocx, goal| {
-        let tcx = ocx.infcx.tcx;
-        let ParamEnvAnd { param_env, value: for_ty } = goal;
-
-        let mut result = DropckOutlivesResult { kinds: vec![], overflows: vec![] };
-
-        // A stack of types left to process. Each round, we pop
-        // something from the stack and invoke
-        // `dtorck_constraint_for_ty`. This may produce new types that
-        // have to be pushed on the stack. This continues until we have explored
-        // all the reachable types from the type `for_ty`.
-        //
-        // Example: Imagine that we have the following code:
-        //
-        // ```rust
-        // struct A {
-        //     value: B,
-        //     children: Vec<A>,
-        // }
-        //
-        // struct B {
-        //     value: u32
-        // }
-        //
-        // fn f() {
-        //   let a: A = ...;
-        //   ..
-        // } // here, `a` is dropped
-        // ```
-        //
-        // at the point where `a` is dropped, we need to figure out
-        // which types inside of `a` contain region data that may be
-        // accessed by any destructors in `a`. We begin by pushing `A`
-        // onto the stack, as that is the type of `a`. We will then
-        // invoke `dtorck_constraint_for_ty` which will expand `A`
-        // into the types of its fields `(B, Vec<A>)`. These will get
-        // pushed onto the stack. Eventually, expanding `Vec<A>` will
-        // lead to us trying to push `A` a second time -- to prevent
-        // infinite recursion, we notice that `A` was already pushed
-        // once and stop.
-        let mut ty_stack = vec![(for_ty, 0)];
-
-        // Set used to detect infinite recursion.
-        let mut ty_set = FxHashSet::default();
-
-        let cause = ObligationCause::dummy();
-        let mut constraints = DropckConstraint::empty();
-        while let Some((ty, depth)) = ty_stack.pop() {
-            debug!(
-                "{} kinds, {} overflows, {} ty_stack",
-                result.kinds.len(),
-                result.overflows.len(),
-                ty_stack.len()
-            );
-            dtorck_constraint_for_ty(tcx, DUMMY_SP, for_ty, depth, ty, &mut constraints)?;
-
-            // "outlives" represent types/regions that may be touched
-            // by a destructor.
-            result.kinds.append(&mut constraints.outlives);
-            result.overflows.append(&mut constraints.overflows);
-
-            // If we have even one overflow, we should stop trying to evaluate further --
-            // chances are, the subsequent overflows for this evaluation won't provide useful
-            // information and will just decrease the speed at which we can emit these errors
-            // (since we'll be printing for just that much longer for the often enormous types
-            // that result here).
-            if !result.overflows.is_empty() {
-                break;
-            }
-
-            // dtorck types are "types that will get dropped but which
-            // do not themselves define a destructor", more or less. We have
-            // to push them onto the stack to be expanded.
-            for ty in constraints.dtorck_types.drain(..) {
-                let Normalized { value: ty, obligations } =
-                    ocx.infcx.at(&cause, param_env).query_normalize(ty)?;
-                ocx.register_obligations(obligations);
-
-                debug!("dropck_outlives: ty from dtorck_types = {:?}", ty);
-
-                match ty.kind() {
-                    // All parameters live for the duration of the
-                    // function.
-                    ty::Param(..) => {}
-
-                    // A projection that we couldn't resolve - it
-                    // might have a destructor.
-                    ty::Alias(..) => {
-                        result.kinds.push(ty.into());
-                    }
-
-                    _ => {
-                        if ty_set.insert(ty) {
-                            ty_stack.push((ty, depth + 1));
-                        }
-                    }
-                }
-            }
-        }
-
-        debug!("dropck_outlives: result = {:#?}", result);
-        Ok(result)
+        compute_dropck_outlives_inner(ocx, goal)
     })
 }
 
-/// Returns a set of constraints that needs to be satisfied in
-/// order for `ty` to be valid for destruction.
-fn dtorck_constraint_for_ty<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    span: Span,
-    for_ty: Ty<'tcx>,
-    depth: usize,
-    ty: Ty<'tcx>,
-    constraints: &mut DropckConstraint<'tcx>,
-) -> Result<(), NoSolution> {
-    debug!("dtorck_constraint_for_ty({:?}, {:?}, {:?}, {:?})", span, for_ty, depth, ty);
-
-    if !tcx.recursion_limit().value_within_limit(depth) {
-        constraints.overflows.push(ty);
-        return Ok(());
-    }
-
-    if trivial_dropck_outlives(tcx, ty) {
-        return Ok(());
-    }
-
-    match ty.kind() {
-        ty::Bool
-        | ty::Char
-        | ty::Int(_)
-        | ty::Uint(_)
-        | ty::Float(_)
-        | ty::Str
-        | ty::Never
-        | ty::Foreign(..)
-        | ty::RawPtr(..)
-        | ty::Ref(..)
-        | ty::FnDef(..)
-        | ty::FnPtr(_)
-        | ty::GeneratorWitness(..)
-        | ty::GeneratorWitnessMIR(..) => {
-            // these types never have a destructor
-        }
-
-        ty::Array(ety, _) | ty::Slice(ety) => {
-            // single-element containers, behave like their element
-            rustc_data_structures::stack::ensure_sufficient_stack(|| {
-                dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, *ety, constraints)
-            })?;
-        }
-
-        ty::Tuple(tys) => rustc_data_structures::stack::ensure_sufficient_stack(|| {
-            for ty in tys.iter() {
-                dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty, constraints)?;
-            }
-            Ok::<_, NoSolution>(())
-        })?,
-
-        ty::Closure(_, substs) => {
-            if !substs.as_closure().is_valid() {
-                // By the time this code runs, all type variables ought to
-                // be fully resolved.
-
-                tcx.sess.delay_span_bug(
-                    span,
-                    format!("upvar_tys for closure not found. Expected capture information for closure {ty}",),
-                );
-                return Err(NoSolution);
-            }
-
-            rustc_data_structures::stack::ensure_sufficient_stack(|| {
-                for ty in substs.as_closure().upvar_tys() {
-                    dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty, constraints)?;
-                }
-                Ok::<_, NoSolution>(())
-            })?
-        }
-
-        ty::Generator(_, substs, _movability) => {
-            // rust-lang/rust#49918: types can be constructed, stored
-            // in the interior, and sit idle when generator yields
-            // (and is subsequently dropped).
-            //
-            // It would be nice to descend into interior of a
-            // generator to determine what effects dropping it might
-            // have (by looking at any drop effects associated with
-            // its interior).
-            //
-            // However, the interior's representation uses things like
-            // GeneratorWitness that explicitly assume they are not
-            // traversed in such a manner. So instead, we will
-            // simplify things for now by treating all generators as
-            // if they were like trait objects, where its upvars must
-            // all be alive for the generator's (potential)
-            // destructor.
-            //
-            // In particular, skipping over `_interior` is safe
-            // because any side-effects from dropping `_interior` can
-            // only take place through references with lifetimes
-            // derived from lifetimes attached to the upvars and resume
-            // argument, and we *do* incorporate those here.
-
-            if !substs.as_generator().is_valid() {
-                // By the time this code runs, all type variables ought to
-                // be fully resolved.
-                tcx.sess.delay_span_bug(
-                    span,
-                    format!("upvar_tys for generator not found. Expected capture information for generator {ty}",),
-                );
-                return Err(NoSolution);
-            }
-
-            constraints.outlives.extend(
-                substs
-                    .as_generator()
-                    .upvar_tys()
-                    .map(|t| -> ty::subst::GenericArg<'tcx> { t.into() }),
-            );
-            constraints.outlives.push(substs.as_generator().resume_ty().into());
-        }
-
-        ty::Adt(def, substs) => {
-            let DropckConstraint { dtorck_types, outlives, overflows } =
-                tcx.at(span).adt_dtorck_constraint(def.did())?;
-            // FIXME: we can try to recursively `dtorck_constraint_on_ty`
-            // there, but that needs some way to handle cycles.
-            constraints
-                .dtorck_types
-                .extend(dtorck_types.iter().map(|t| EarlyBinder(*t).subst(tcx, substs)));
-            constraints
-                .outlives
-                .extend(outlives.iter().map(|t| EarlyBinder(*t).subst(tcx, substs)));
-            constraints
-                .overflows
-                .extend(overflows.iter().map(|t| EarlyBinder(*t).subst(tcx, substs)));
-        }
-
-        // Objects must be alive in order for their destructor
-        // to be called.
-        ty::Dynamic(..) => {
-            constraints.outlives.push(ty.into());
-        }
-
-        // Types that can't be resolved. Pass them forward.
-        ty::Alias(..) | ty::Param(..) => {
-            constraints.dtorck_types.push(ty);
-        }
-
-        ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => {
-            // By the time this code runs, all type variables ought to
-            // be fully resolved.
-            return Err(NoSolution);
-        }
-    }
-
-    Ok(())
-}
-
 /// Calculates the dtorck constraint for a type.
 pub(crate) fn adt_dtorck_constraint(
     tcx: TyCtxt<'_>,
@@ -311,7 +55,7 @@ pub(crate) fn adt_dtorck_constraint(
     let mut result = DropckConstraint::empty();
     for field in def.all_fields() {
         let fty = tcx.type_of(field.did).subst_identity();
-        dtorck_constraint_for_ty(tcx, span, fty, 0, fty, &mut result)?;
+        dtorck_constraint_for_ty_inner(tcx, span, fty, 0, fty, &mut result)?;
     }
     result.outlives.extend(tcx.destructor_constraints(def));
     dedup_dtorck_constraint(&mut result);
diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs
index 0c2bb863e1f..959838ab348 100644
--- a/compiler/rustc_traits/src/implied_outlives_bounds.rs
+++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs
@@ -3,18 +3,13 @@
 //! [`rustc_trait_selection::traits::query::type_op::implied_outlives_bounds`].
 
 use rustc_infer::infer::canonical::{self, Canonical};
-use rustc_infer::infer::outlives::components::{push_outlives_components, Component};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::query::OutlivesBound;
 use rustc_middle::query::Providers;
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
-use rustc_span::def_id::CRATE_DEF_ID;
-use rustc_span::source_map::DUMMY_SP;
+use rustc_middle::ty::TyCtxt;
 use rustc_trait_selection::infer::InferCtxtBuilderExt;
-use rustc_trait_selection::traits::query::{CanonicalTyGoal, Fallible, NoSolution};
-use rustc_trait_selection::traits::wf;
-use rustc_trait_selection::traits::ObligationCtxt;
-use smallvec::{smallvec, SmallVec};
+use rustc_trait_selection::traits::query::type_op::implied_outlives_bounds::compute_implied_outlives_bounds_inner;
+use rustc_trait_selection::traits::query::{CanonicalTyGoal, NoSolution};
 
 pub(crate) fn provide(p: &mut Providers) {
     *p = Providers { implied_outlives_bounds, ..*p };
@@ -29,164 +24,6 @@ fn implied_outlives_bounds<'tcx>(
 > {
     tcx.infer_ctxt().enter_canonical_trait_query(&goal, |ocx, key| {
         let (param_env, ty) = key.into_parts();
-        compute_implied_outlives_bounds(ocx, param_env, ty)
+        compute_implied_outlives_bounds_inner(ocx, param_env, ty)
     })
 }
-
-fn compute_implied_outlives_bounds<'tcx>(
-    ocx: &ObligationCtxt<'_, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    ty: Ty<'tcx>,
-) -> Fallible<Vec<OutlivesBound<'tcx>>> {
-    let tcx = ocx.infcx.tcx;
-
-    // Sometimes when we ask what it takes for T: WF, we get back that
-    // U: WF is required; in that case, we push U onto this stack and
-    // process it next. Because the resulting predicates aren't always
-    // guaranteed to be a subset of the original type, so we need to store the
-    // WF args we've computed in a set.
-    let mut checked_wf_args = rustc_data_structures::fx::FxHashSet::default();
-    let mut wf_args = vec![ty.into()];
-
-    let mut outlives_bounds: Vec<ty::OutlivesPredicate<ty::GenericArg<'tcx>, ty::Region<'tcx>>> =
-        vec![];
-
-    while let Some(arg) = wf_args.pop() {
-        if !checked_wf_args.insert(arg) {
-            continue;
-        }
-
-        // Compute the obligations for `arg` to be well-formed. If `arg` is
-        // an unresolved inference variable, just substituted an empty set
-        // -- because the return type here is going to be things we *add*
-        // to the environment, it's always ok for this set to be smaller
-        // than the ultimate set. (Note: normally there won't be
-        // unresolved inference variables here anyway, but there might be
-        // during typeck under some circumstances.)
-        //
-        // FIXME(@lcnr): It's not really "always fine", having fewer implied
-        // bounds can be backward incompatible, e.g. #101951 was caused by
-        // us not dealing with inference vars in `TypeOutlives` predicates.
-        let obligations = wf::obligations(ocx.infcx, param_env, CRATE_DEF_ID, 0, arg, DUMMY_SP)
-            .unwrap_or_default();
-
-        for obligation in obligations {
-            debug!(?obligation);
-            assert!(!obligation.has_escaping_bound_vars());
-
-            // While these predicates should all be implied by other parts of
-            // the program, they are still relevant as they may constrain
-            // inference variables, which is necessary to add the correct
-            // implied bounds in some cases, mostly when dealing with projections.
-            //
-            // Another important point here: we only register `Projection`
-            // predicates, since otherwise we might register outlives
-            // predicates containing inference variables, and we don't
-            // learn anything new from those.
-            if obligation.predicate.has_non_region_infer() {
-                match obligation.predicate.kind().skip_binder() {
-                    ty::PredicateKind::Clause(ty::Clause::Projection(..))
-                    | ty::PredicateKind::AliasRelate(..) => {
-                        ocx.register_obligation(obligation.clone());
-                    }
-                    _ => {}
-                }
-            }
-
-            let pred = match obligation.predicate.kind().no_bound_vars() {
-                None => continue,
-                Some(pred) => pred,
-            };
-            match pred {
-                ty::PredicateKind::Clause(ty::Clause::Trait(..))
-                // FIXME(const_generics): Make sure that `<'a, 'b, const N: &'a &'b u32>` is sound
-                // if we ever support that
-                | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
-                | ty::PredicateKind::Subtype(..)
-                | ty::PredicateKind::Coerce(..)
-                | ty::PredicateKind::Clause(ty::Clause::Projection(..))
-                | ty::PredicateKind::ClosureKind(..)
-                | ty::PredicateKind::ObjectSafe(..)
-                | ty::PredicateKind::ConstEvaluatable(..)
-                | ty::PredicateKind::ConstEquate(..)
-                | ty::PredicateKind::Ambiguous
-                | ty::PredicateKind::AliasRelate(..)
-                | ty::PredicateKind::TypeWellFormedFromEnv(..) => {}
-
-                // We need to search through *all* WellFormed predicates
-                ty::PredicateKind::WellFormed(arg) => {
-                    wf_args.push(arg);
-                }
-
-                // We need to register region relationships
-                ty::PredicateKind::Clause(ty::Clause::RegionOutlives(ty::OutlivesPredicate(
-                    r_a,
-                    r_b,
-                ))) => outlives_bounds.push(ty::OutlivesPredicate(r_a.into(), r_b)),
-
-                ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate(
-                    ty_a,
-                    r_b,
-                ))) => outlives_bounds.push(ty::OutlivesPredicate(ty_a.into(), r_b)),
-            }
-        }
-    }
-
-    // This call to `select_all_or_error` is necessary to constrain inference variables, which we
-    // use further down when computing the implied bounds.
-    match ocx.select_all_or_error().as_slice() {
-        [] => (),
-        _ => return Err(NoSolution),
-    }
-
-    // We lazily compute the outlives components as
-    // `select_all_or_error` constrains inference variables.
-    let implied_bounds = outlives_bounds
-        .into_iter()
-        .flat_map(|ty::OutlivesPredicate(a, r_b)| match a.unpack() {
-            ty::GenericArgKind::Lifetime(r_a) => vec![OutlivesBound::RegionSubRegion(r_b, r_a)],
-            ty::GenericArgKind::Type(ty_a) => {
-                let ty_a = ocx.infcx.resolve_vars_if_possible(ty_a);
-                let mut components = smallvec![];
-                push_outlives_components(tcx, ty_a, &mut components);
-                implied_bounds_from_components(r_b, components)
-            }
-            ty::GenericArgKind::Const(_) => unreachable!(),
-        })
-        .collect();
-
-    Ok(implied_bounds)
-}
-
-/// When we have an implied bound that `T: 'a`, we can further break
-/// this down to determine what relationships would have to hold for
-/// `T: 'a` to hold. We get to assume that the caller has validated
-/// those relationships.
-fn implied_bounds_from_components<'tcx>(
-    sub_region: ty::Region<'tcx>,
-    sup_components: SmallVec<[Component<'tcx>; 4]>,
-) -> Vec<OutlivesBound<'tcx>> {
-    sup_components
-        .into_iter()
-        .filter_map(|component| {
-            match component {
-                Component::Region(r) => Some(OutlivesBound::RegionSubRegion(sub_region, r)),
-                Component::Param(p) => Some(OutlivesBound::RegionSubParam(sub_region, p)),
-                Component::Alias(p) => Some(OutlivesBound::RegionSubAlias(sub_region, p)),
-                Component::EscapingAlias(_) =>
-                // If the projection has escaping regions, don't
-                // try to infer any implied bounds even for its
-                // free components. This is conservative, because
-                // the caller will still have to prove that those
-                // free components outlive `sub_region`. But the
-                // idea is that the WAY that the caller proves
-                // that may change in the future and we want to
-                // give ourselves room to get smarter here.
-                {
-                    None
-                }
-                Component::UnresolvedInferenceVariable(..) => None,
-            }
-        })
-        .collect()
-}
diff --git a/compiler/rustc_traits/src/lib.rs b/compiler/rustc_traits/src/lib.rs
index b0f9c57154f..907e2d39c51 100644
--- a/compiler/rustc_traits/src/lib.rs
+++ b/compiler/rustc_traits/src/lib.rs
@@ -21,7 +21,8 @@ mod normalize_erasing_regions;
 mod normalize_projection_ty;
 mod type_op;
 
-pub use type_op::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_with_cause};
+pub use rustc_trait_selection::traits::query::type_op::ascribe_user_type::type_op_ascribe_user_type_with_span;
+pub use type_op::type_op_prove_predicate_with_cause;
 
 use rustc_middle::query::Providers;
 
diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs
index b1cbd88ce27..9904acb1c0d 100644
--- a/compiler/rustc_traits/src/type_op.rs
+++ b/compiler/rustc_traits/src/type_op.rs
@@ -1,21 +1,19 @@
-use rustc_hir as hir;
 use rustc_infer::infer::canonical::{Canonical, QueryResponse};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::query::Providers;
-use rustc_middle::traits::{DefiningAnchor, ObligationCauseCode};
-use rustc_middle::ty::{self, FnSig, Lift, PolyFnSig, Ty, TyCtxt, TypeFoldable};
+use rustc_middle::traits::query::NoSolution;
+use rustc_middle::traits::DefiningAnchor;
+use rustc_middle::ty::{FnSig, Lift, PolyFnSig, Ty, TyCtxt, TypeFoldable};
 use rustc_middle::ty::{ParamEnvAnd, Predicate};
-use rustc_middle::ty::{UserSelfTy, UserSubsts, UserType};
-use rustc_span::def_id::CRATE_DEF_ID;
-use rustc_span::{Span, DUMMY_SP};
 use rustc_trait_selection::infer::InferCtxtBuilderExt;
 use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
-use rustc_trait_selection::traits::query::type_op::ascribe_user_type::AscribeUserType;
+use rustc_trait_selection::traits::query::type_op::ascribe_user_type::{
+    type_op_ascribe_user_type_with_span, AscribeUserType,
+};
 use rustc_trait_selection::traits::query::type_op::eq::Eq;
 use rustc_trait_selection::traits::query::type_op::normalize::Normalize;
 use rustc_trait_selection::traits::query::type_op::prove_predicate::ProvePredicate;
 use rustc_trait_selection::traits::query::type_op::subtype::Subtype;
-use rustc_trait_selection::traits::query::{Fallible, NoSolution};
 use rustc_trait_selection::traits::{Normalized, Obligation, ObligationCause, ObligationCtxt};
 use std::fmt;
 
@@ -42,111 +40,6 @@ fn type_op_ascribe_user_type<'tcx>(
     })
 }
 
-/// The core of the `type_op_ascribe_user_type` query: for diagnostics purposes in NLL HRTB errors,
-/// this query can be re-run to better track the span of the obligation cause, and improve the error
-/// message. Do not call directly unless you're in that very specific context.
-pub fn type_op_ascribe_user_type_with_span<'tcx>(
-    ocx: &ObligationCtxt<'_, 'tcx>,
-    key: ParamEnvAnd<'tcx, AscribeUserType<'tcx>>,
-    span: Option<Span>,
-) -> Result<(), NoSolution> {
-    let (param_env, AscribeUserType { mir_ty, user_ty }) = key.into_parts();
-    debug!("type_op_ascribe_user_type: mir_ty={:?} user_ty={:?}", mir_ty, user_ty);
-    let span = span.unwrap_or(DUMMY_SP);
-    match user_ty {
-        UserType::Ty(user_ty) => relate_mir_and_user_ty(ocx, param_env, span, mir_ty, user_ty)?,
-        UserType::TypeOf(def_id, user_substs) => {
-            relate_mir_and_user_substs(ocx, param_env, span, mir_ty, def_id, user_substs)?
-        }
-    };
-    Ok(())
-}
-
-#[instrument(level = "debug", skip(ocx, param_env, span))]
-fn relate_mir_and_user_ty<'tcx>(
-    ocx: &ObligationCtxt<'_, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    span: Span,
-    mir_ty: Ty<'tcx>,
-    user_ty: Ty<'tcx>,
-) -> Result<(), NoSolution> {
-    let cause = ObligationCause::dummy_with_span(span);
-    let user_ty = ocx.normalize(&cause, param_env, user_ty);
-    ocx.eq(&cause, param_env, mir_ty, user_ty)?;
-
-    // FIXME(#104764): We should check well-formedness before normalization.
-    let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(user_ty.into()));
-    ocx.register_obligation(Obligation::new(ocx.infcx.tcx, cause, param_env, predicate));
-    Ok(())
-}
-
-#[instrument(level = "debug", skip(ocx, param_env, span))]
-fn relate_mir_and_user_substs<'tcx>(
-    ocx: &ObligationCtxt<'_, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    span: Span,
-    mir_ty: Ty<'tcx>,
-    def_id: hir::def_id::DefId,
-    user_substs: UserSubsts<'tcx>,
-) -> Result<(), NoSolution> {
-    let param_env = param_env.without_const();
-    let UserSubsts { user_self_ty, substs } = user_substs;
-    let tcx = ocx.infcx.tcx;
-    let cause = ObligationCause::dummy_with_span(span);
-
-    let ty = tcx.type_of(def_id).subst(tcx, substs);
-    let ty = ocx.normalize(&cause, param_env, ty);
-    debug!("relate_type_and_user_type: ty of def-id is {:?}", ty);
-
-    ocx.eq(&cause, param_env, mir_ty, ty)?;
-
-    // Prove the predicates coming along with `def_id`.
-    //
-    // Also, normalize the `instantiated_predicates`
-    // because otherwise we wind up with duplicate "type
-    // outlives" error messages.
-    let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs);
-
-    debug!(?instantiated_predicates);
-    for (instantiated_predicate, predicate_span) in instantiated_predicates {
-        let span = if span == DUMMY_SP { predicate_span } else { span };
-        let cause = ObligationCause::new(
-            span,
-            CRATE_DEF_ID,
-            ObligationCauseCode::AscribeUserTypeProvePredicate(predicate_span),
-        );
-        let instantiated_predicate =
-            ocx.normalize(&cause.clone(), param_env, instantiated_predicate);
-
-        ocx.register_obligation(Obligation::new(tcx, cause, param_env, instantiated_predicate));
-    }
-
-    if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty {
-        let self_ty = ocx.normalize(&cause, param_env, self_ty);
-        let impl_self_ty = tcx.type_of(impl_def_id).subst(tcx, substs);
-        let impl_self_ty = ocx.normalize(&cause, param_env, impl_self_ty);
-
-        ocx.eq(&cause, param_env, self_ty, impl_self_ty)?;
-        let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(impl_self_ty.into()));
-        ocx.register_obligation(Obligation::new(tcx, cause.clone(), param_env, predicate));
-    }
-
-    // In addition to proving the predicates, we have to
-    // prove that `ty` is well-formed -- this is because
-    // the WF of `ty` is predicated on the substs being
-    // well-formed, and we haven't proven *that*. We don't
-    // want to prove the WF of types from  `substs` directly because they
-    // haven't been normalized.
-    //
-    // FIXME(nmatsakis): Well, perhaps we should normalize
-    // them?  This would only be relevant if some input
-    // type were ill-formed but did not appear in `ty`,
-    // which...could happen with normalization...
-    let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into()));
-    ocx.register_obligation(Obligation::new(tcx, cause, param_env, predicate));
-    Ok(())
-}
-
 fn type_op_eq<'tcx>(
     tcx: TyCtxt<'tcx>,
     canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Eq<'tcx>>>,
@@ -160,7 +53,7 @@ fn type_op_eq<'tcx>(
 fn type_op_normalize<'tcx, T>(
     ocx: &ObligationCtxt<'_, 'tcx>,
     key: ParamEnvAnd<'tcx, Normalize<T>>,
-) -> Fallible<T>
+) -> Result<T, NoSolution>
 where
     T: fmt::Debug + TypeFoldable<TyCtxt<'tcx>> + Lift<'tcx>,
 {
diff --git a/compiler/rustc_ty_utils/messages.ftl b/compiler/rustc_ty_utils/messages.ftl
index 5bc3e3c00c9..c416aa52a24 100644
--- a/compiler/rustc_ty_utils/messages.ftl
+++ b/compiler/rustc_ty_utils/messages.ftl
@@ -1,65 +1,65 @@
-ty_utils_needs_drop_overflow = overflow while checking whether `{$query_ty}` requires drop
+ty_utils_address_and_deref_not_supported = dereferencing or taking the address is not supported in generic constants
 
-ty_utils_generic_constant_too_complex = overly complex generic constant
-    .help = consider moving this anonymous constant into a `const` function
-    .maybe_supported = this operation may be supported in the future
+ty_utils_adt_not_supported = struct/enum construction is not supported in generic constants
 
-ty_utils_borrow_not_supported = borrowing is not supported in generic constants
+ty_utils_array_not_supported = array construction is not supported in generic constants
 
-ty_utils_address_and_deref_not_supported = dereferencing or taking the address is not supported in generic constants
+ty_utils_assign_not_supported = assignment is not supported in generic constants
 
-ty_utils_array_not_supported = array construction is not supported in generic constants
+ty_utils_binary_not_supported = unsupported binary operation in generic constants
 
 ty_utils_block_not_supported = blocks are not supported in generic constants
 
-ty_utils_never_to_any_not_supported = coercing the `never` type is not supported in generic constants
-
-ty_utils_tuple_not_supported = tuple construction is not supported in generic constants
+ty_utils_borrow_not_supported = borrowing is not supported in generic constants
 
-ty_utils_index_not_supported = indexing is not supported in generic constants
+ty_utils_box_not_supported = allocations are not allowed in generic constants
 
-ty_utils_field_not_supported = field access is not supported in generic constants
+ty_utils_closure_and_return_not_supported = closures and function keywords are not supported in generic constants
 
 ty_utils_const_block_not_supported = const blocks are not supported in generic constants
 
-ty_utils_adt_not_supported = struct/enum construction is not supported in generic constants
+ty_utils_control_flow_not_supported = control flow is not supported in generic constants
 
-ty_utils_pointer_not_supported = pointer casts are not allowed in generic constants
+ty_utils_field_not_supported = field access is not supported in generic constants
 
-ty_utils_yield_not_supported = generator control flow is not allowed in generic constants
+ty_utils_generic_constant_too_complex = overly complex generic constant
+    .help = consider moving this anonymous constant into a `const` function
+    .maybe_supported = this operation may be supported in the future
 
-ty_utils_loop_not_supported = loops and loop control flow are not supported in generic constants
+ty_utils_impl_trait_duplicate_arg = non-defining opaque type use in defining scope
+    .label = generic argument `{$arg}` used twice
+    .note = for this opaque type
 
-ty_utils_box_not_supported = allocations are not allowed in generic constants
+ty_utils_impl_trait_not_param = non-defining opaque type use in defining scope
+    .label = argument `{$arg}` is not a generic parameter
+    .note = for this opaque type
 
-ty_utils_binary_not_supported = unsupported binary operation in generic constants
+ty_utils_index_not_supported = indexing is not supported in generic constants
+
+ty_utils_inline_asm_not_supported = assembly is not supported in generic constants
 
 ty_utils_logical_op_not_supported = unsupported operation in generic constants, short-circuiting operations would imply control flow
 
-ty_utils_assign_not_supported = assignment is not supported in generic constants
+ty_utils_loop_not_supported = loops and loop control flow are not supported in generic constants
 
-ty_utils_closure_and_return_not_supported = closures and function keywords are not supported in generic constants
+ty_utils_multiple_array_fields_simd_type = monomorphising SIMD type `{$ty}` with more than one array field
 
-ty_utils_control_flow_not_supported = control flow is not supported in generic constants
+ty_utils_needs_drop_overflow = overflow while checking whether `{$query_ty}` requires drop
 
-ty_utils_inline_asm_not_supported = assembly is not supported in generic constants
+ty_utils_never_to_any_not_supported = coercing the `never` type is not supported in generic constants
 
-ty_utils_operation_not_supported = unsupported operation in generic constants
+ty_utils_non_primitive_simd_type = monomorphising SIMD type `{$ty}` with a non-primitive-scalar (integer/float/pointer) element type `{$e_ty}`
 
-ty_utils_unexpected_fnptr_associated_item = `FnPtr` trait with unexpected associated item
+ty_utils_operation_not_supported = unsupported operation in generic constants
 
-ty_utils_zero_length_simd_type = monomorphising SIMD type `{$ty}` of zero length
+ty_utils_oversized_simd_type = monomorphising SIMD type `{$ty}` of length greater than {$max_lanes}
 
-ty_utils_multiple_array_fields_simd_type = monomorphising SIMD type `{$ty}` with more than one array field
+ty_utils_pointer_not_supported = pointer casts are not allowed in generic constants
 
-ty_utils_oversized_simd_type = monomorphising SIMD type `{$ty}` of length greater than {$max_lanes}
+ty_utils_tuple_not_supported = tuple construction is not supported in generic constants
 
-ty_utils_non_primitive_simd_type = monomorphising SIMD type `{$ty}` with a non-primitive-scalar (integer/float/pointer) element type `{$e_ty}`
+ty_utils_unexpected_fnptr_associated_item = `FnPtr` trait with unexpected associated item
 
-ty_utils_impl_trait_duplicate_arg = non-defining opaque type use in defining scope
-    .label = generic argument `{$arg}` used twice
-    .note = for this opaque type
+ty_utils_yield_not_supported = generator control flow is not allowed in generic constants
 
-ty_utils_impl_trait_not_param = non-defining opaque type use in defining scope
-    .label = argument `{$arg}` is not a generic parameter
-    .note = for this opaque type
+ty_utils_zero_length_simd_type = monomorphising SIMD type `{$ty}` of zero length
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index 15c19104616..5b3ffc9fc36 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -81,7 +81,7 @@ fn fn_sig_for_fn_abi<'tcx>(
                 var: ty::BoundVar::from_usize(bound_vars.len() - 1),
                 kind: ty::BoundRegionKind::BrEnv,
             };
-            let env_region = tcx.mk_re_late_bound(ty::INNERMOST, br);
+            let env_region = ty::Region::new_late_bound(tcx, ty::INNERMOST, br);
             let env_ty = tcx.closure_env_ty(def_id, substs, env_region).unwrap();
 
             let sig = sig.skip_binder();
@@ -106,7 +106,7 @@ fn fn_sig_for_fn_abi<'tcx>(
                 var: ty::BoundVar::from_usize(bound_vars.len() - 1),
                 kind: ty::BoundRegionKind::BrEnv,
             };
-            let env_ty = tcx.mk_mut_ref(tcx.mk_re_late_bound(ty::INNERMOST, br), ty);
+            let env_ty = tcx.mk_mut_ref(ty::Region::new_late_bound(tcx, ty::INNERMOST, br), ty);
 
             let pin_did = tcx.require_lang_item(LangItem::Pin, None);
             let pin_adt_ref = tcx.adt_def(pin_did);
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index ed574f22e61..57b4183d336 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -301,7 +301,7 @@ fn associated_type_for_impl_trait_in_trait(
     trait_assoc_ty.impl_defaultness(tcx.impl_defaultness(fn_def_id));
 
     // Copy type_of of the opaque.
-    trait_assoc_ty.type_of(ty::EarlyBinder(tcx.mk_opaque(
+    trait_assoc_ty.type_of(ty::EarlyBinder::bind(tcx.mk_opaque(
         opaque_ty_def_id.to_def_id(),
         InternalSubsts::identity_for_item(tcx, opaque_ty_def_id),
     )));
diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs
index 1219bb40098..ce77df0df5d 100644
--- a/compiler/rustc_ty_utils/src/consts.rs
+++ b/compiler/rustc_ty_utils/src/consts.rs
@@ -419,7 +419,7 @@ pub fn thir_abstract_const(
 
     let root_span = body.exprs[body_id].span;
 
-    Ok(Some(ty::EarlyBinder(recurse_build(tcx, body, body_id, root_span)?)))
+    Ok(Some(ty::EarlyBinder::bind(recurse_build(tcx, body, body_id, root_span)?)))
 }
 
 pub fn provide(providers: &mut Providers) {
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 16cd8bc8e69..7015778e24b 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -610,7 +610,7 @@ fn generator_layout<'tcx>(
 ) -> Result<Layout<'tcx>, LayoutError<'tcx>> {
     use SavedLocalEligibility::*;
     let tcx = cx.tcx;
-    let subst_field = |ty: Ty<'tcx>| EarlyBinder(ty).subst(tcx, substs);
+    let subst_field = |ty: Ty<'tcx>| EarlyBinder::bind(ty).subst(tcx, substs);
 
     let Some(info) = tcx.generator_layout(def_id) else {
         return Err(LayoutError::Unknown(ty));
diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs
index 1f9701b9322..9d593dc5e04 100644
--- a/compiler/rustc_ty_utils/src/needs_drop.rs
+++ b/compiler/rustc_ty_utils/src/needs_drop.rs
@@ -210,7 +210,7 @@ fn drop_tys_helper<'tcx>(
             match subty.kind() {
                 ty::Adt(adt_id, subst) => {
                     for subty in tcx.adt_drop_tys(adt_id.did())? {
-                        vec.push(EarlyBinder(subty).subst(tcx, subst));
+                        vec.push(EarlyBinder::bind(subty).subst(tcx, subst));
                     }
                 }
                 _ => vec.push(subty),
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index 65dc3c39c6a..12ad8b0842f 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -44,9 +44,7 @@ fn sized_constraint_for_ty<'tcx>(
             let adt_tys = adt.sized_constraint(tcx);
             debug!("sized_constraint_for_ty({:?}) intermediate = {:?}", ty, adt_tys);
             adt_tys
-                .0
-                .iter()
-                .map(|ty| adt_tys.rebind(*ty).subst(tcx, substs))
+                .subst_iter_copied(tcx, substs)
                 .flat_map(|ty| sized_constraint_for_ty(tcx, adtdef, ty))
                 .collect()
         }
@@ -289,12 +287,13 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
             let shifted_alias_ty = self.tcx.fold_regions(unshifted_alias_ty, |re, depth| {
                 if let ty::ReLateBound(index, bv) = re.kind() {
                     if depth != ty::INNERMOST {
-                        return self.tcx.mk_re_error_with_message(
+                        return ty::Region::new_error_with_message(
+                            self.tcx,
                             DUMMY_SP,
                             "we shouldn't walk non-predicate binders with `impl Trait`...",
                         );
                     }
-                    self.tcx.mk_re_late_bound(index.shifted_out_to_binder(self.depth), bv)
+                    ty::Region::new_late_bound(self.tcx, index.shifted_out_to_binder(self.depth), bv)
                 } else {
                     re
                 }
@@ -508,7 +507,7 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<EarlyBinder<Ty<'
 
     if self_ty_matches {
         debug!("issue33140_self_ty - MATCHES!");
-        Some(EarlyBinder(self_ty))
+        Some(EarlyBinder::bind(self_ty))
     } else {
         debug!("issue33140_self_ty - non-matching self type");
         None
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index f6b44bdf27e..ae16fbb162e 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -52,7 +52,7 @@ pub trait Interner: Sized {
     type PolyFnSig: Clone + Debug + Hash + Ord;
     type ListBinderExistentialPredicate: Clone + Debug + Hash + Ord;
     type BinderListTy: Clone + Debug + Hash + Ord;
-    type ListTy: Clone + Debug + Hash + Ord;
+    type ListTy: Clone + Debug + Hash + Ord + IntoIterator<Item = Self::Ty>;
     type AliasTy: Clone + Debug + Hash + Ord;
     type ParamTy: Clone + Debug + Hash + Ord;
     type BoundTy: Clone + Debug + Hash + Ord;
@@ -67,6 +67,9 @@ pub trait Interner: Sized {
     type FreeRegion: Clone + Debug + Hash + Ord;
     type RegionVid: Clone + Debug + Hash + Ord;
     type PlaceholderRegion: Clone + Debug + Hash + Ord;
+
+    fn ty_and_mut_to_parts(ty_and_mut: Self::TypeAndMut) -> (Self::Ty, Self::Mutability);
+    fn mutability_is_mut(mutbl: Self::Mutability) -> bool;
 }
 
 /// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter`
@@ -390,7 +393,19 @@ impl DebruijnIndex {
     }
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+pub fn debug_bound_var<T: std::fmt::Write>(
+    fmt: &mut T,
+    debruijn: DebruijnIndex,
+    var: impl std::fmt::Debug,
+) -> Result<(), std::fmt::Error> {
+    if debruijn == INNERMOST {
+        write!(fmt, "^{:?}", var)
+    } else {
+        write!(fmt, "^{}_{:?}", debruijn.index(), var)
+    }
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
 #[derive(Encodable, Decodable, HashStable_Generic)]
 pub enum IntTy {
     Isize,
@@ -448,7 +463,7 @@ impl IntTy {
     }
 }
 
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Debug)]
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
 #[derive(Encodable, Decodable, HashStable_Generic)]
 pub enum UintTy {
     Usize,
@@ -506,7 +521,7 @@ impl UintTy {
     }
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
 #[derive(Encodable, Decodable, HashStable_Generic)]
 pub enum FloatTy {
     F32,
diff --git a/compiler/rustc_type_ir/src/structural_impls.rs b/compiler/rustc_type_ir/src/structural_impls.rs
index 45a2e9023c9..553d7f31b2d 100644
--- a/compiler/rustc_type_ir/src/structural_impls.rs
+++ b/compiler/rustc_type_ir/src/structural_impls.rs
@@ -4,11 +4,12 @@
 
 use crate::fold::{FallibleTypeFolder, TypeFoldable};
 use crate::visit::{TypeVisitable, TypeVisitor};
-use crate::Interner;
+use crate::{FloatTy, IntTy, Interner, UintTy};
 use rustc_data_structures::functor::IdFunctor;
 use rustc_data_structures::sync::Lrc;
 use rustc_index::{Idx, IndexVec};
 
+use core::fmt;
 use std::ops::ControlFlow;
 
 ///////////////////////////////////////////////////////////////////////////
@@ -163,3 +164,21 @@ impl<I: Interner, T: TypeVisitable<I>, Ix: Idx> TypeVisitable<I> for IndexVec<Ix
         self.iter().try_for_each(|t| t.visit_with(visitor))
     }
 }
+
+impl fmt::Debug for IntTy {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{}", self.name_str())
+    }
+}
+
+impl fmt::Debug for UintTy {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{}", self.name_str())
+    }
+}
+
+impl fmt::Debug for FloatTy {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{}", self.name_str())
+    }
+}
diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs
index f7344bacc02..fa18f921ee4 100644
--- a/compiler/rustc_type_ir/src/sty.rs
+++ b/compiler/rustc_type_ir/src/sty.rs
@@ -294,7 +294,7 @@ impl<I: Interner> Clone for TyKind<I> {
             Str => Str,
             Array(t, c) => Array(t.clone(), c.clone()),
             Slice(t) => Slice(t.clone()),
-            RawPtr(t) => RawPtr(t.clone()),
+            RawPtr(p) => RawPtr(p.clone()),
             Ref(r, t, m) => Ref(r.clone(), t.clone(), m.clone()),
             FnDef(d, s) => FnDef(d.clone(), s.clone()),
             FnPtr(s) => FnPtr(s.clone()),
@@ -499,33 +499,65 @@ impl<I: Interner> hash::Hash for TyKind<I> {
 impl<I: Interner> fmt::Debug for TyKind<I> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
-            Bool => f.write_str("Bool"),
-            Char => f.write_str("Char"),
-            Int(i) => f.debug_tuple_field1_finish("Int", i),
-            Uint(u) => f.debug_tuple_field1_finish("Uint", u),
-            Float(float) => f.debug_tuple_field1_finish("Float", float),
+            Bool => write!(f, "bool"),
+            Char => write!(f, "char"),
+            Int(i) => write!(f, "{i:?}"),
+            Uint(u) => write!(f, "{u:?}"),
+            Float(float) => write!(f, "{float:?}"),
             Adt(d, s) => f.debug_tuple_field2_finish("Adt", d, s),
             Foreign(d) => f.debug_tuple_field1_finish("Foreign", d),
-            Str => f.write_str("Str"),
-            Array(t, c) => f.debug_tuple_field2_finish("Array", t, c),
-            Slice(t) => f.debug_tuple_field1_finish("Slice", t),
-            RawPtr(t) => f.debug_tuple_field1_finish("RawPtr", t),
-            Ref(r, t, m) => f.debug_tuple_field3_finish("Ref", r, t, m),
+            Str => write!(f, "str"),
+            Array(t, c) => write!(f, "[{t:?}; {c:?}]"),
+            Slice(t) => write!(f, "[{t:?}]"),
+            RawPtr(p) => {
+                let (ty, mutbl) = I::ty_and_mut_to_parts(p.clone());
+                match I::mutability_is_mut(mutbl) {
+                    true => write!(f, "*mut "),
+                    false => write!(f, "*const "),
+                }?;
+                write!(f, "{ty:?}")
+            }
+            Ref(r, t, m) => match I::mutability_is_mut(m.clone()) {
+                true => write!(f, "&{r:?} mut {t:?}"),
+                false => write!(f, "&{r:?} {t:?}"),
+            },
             FnDef(d, s) => f.debug_tuple_field2_finish("FnDef", d, s),
-            FnPtr(s) => f.debug_tuple_field1_finish("FnPtr", s),
-            Dynamic(p, r, repr) => f.debug_tuple_field3_finish("Dynamic", p, r, repr),
+            FnPtr(s) => write!(f, "{s:?}"),
+            Dynamic(p, r, repr) => match repr {
+                DynKind::Dyn => write!(f, "dyn {p:?} + {r:?}"),
+                DynKind::DynStar => write!(f, "dyn* {p:?} + {r:?}"),
+            },
             Closure(d, s) => f.debug_tuple_field2_finish("Closure", d, s),
             Generator(d, s, m) => f.debug_tuple_field3_finish("Generator", d, s, m),
             GeneratorWitness(g) => f.debug_tuple_field1_finish("GeneratorWitness", g),
             GeneratorWitnessMIR(d, s) => f.debug_tuple_field2_finish("GeneratorWitnessMIR", d, s),
-            Never => f.write_str("Never"),
-            Tuple(t) => f.debug_tuple_field1_finish("Tuple", t),
+            Never => write!(f, "!"),
+            Tuple(t) => {
+                let mut iter = t.clone().into_iter();
+
+                write!(f, "(")?;
+
+                match iter.next() {
+                    None => return write!(f, ")"),
+                    Some(ty) => write!(f, "{ty:?}")?,
+                };
+
+                match iter.next() {
+                    None => return write!(f, ",)"),
+                    Some(ty) => write!(f, "{ty:?})")?,
+                }
+
+                for ty in iter {
+                    write!(f, ", {ty:?}")?;
+                }
+                write!(f, ")")
+            }
             Alias(i, a) => f.debug_tuple_field2_finish("Alias", i, a),
-            Param(p) => f.debug_tuple_field1_finish("Param", p),
-            Bound(d, b) => f.debug_tuple_field2_finish("Bound", d, b),
-            Placeholder(p) => f.debug_tuple_field1_finish("Placeholder", p),
-            Infer(t) => f.debug_tuple_field1_finish("Infer", t),
-            TyKind::Error(e) => f.debug_tuple_field1_finish("Error", e),
+            Param(p) => write!(f, "{p:?}"),
+            Bound(d, b) => crate::debug_bound_var(f, *d, b),
+            Placeholder(p) => write!(f, "{p:?}"),
+            Infer(t) => write!(f, "{t:?}"),
+            TyKind::Error(_) => write!(f, "{{type error}}"),
         }
     }
 }
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index 498fbd93288..c524d4c0367 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -1851,7 +1851,7 @@ impl String {
     }
 
     /// Consumes and leaks the `String`, returning a mutable reference to the contents,
-    /// `&'static mut str`.
+    /// `&'a mut str`.
     ///
     /// This is mainly useful for data that lives for the remainder of
     /// the program's life. Dropping the returned reference will cause a memory
@@ -1874,7 +1874,7 @@ impl String {
     /// ```
     #[unstable(feature = "string_leak", issue = "102929")]
     #[inline]
-    pub fn leak(self) -> &'static mut str {
+    pub fn leak<'a>(self) -> &'a mut str {
         let slice = self.vec.leak();
         unsafe { from_utf8_unchecked_mut(slice) }
     }
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 82f30a26d41..47661a3d384 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -2662,7 +2662,6 @@ impl<T: Clone, A: Allocator + Clone> Clone for Vec<T, A> {
 /// as required by the `core::borrow::Borrow` implementation.
 ///
 /// ```
-/// #![feature(build_hasher_simple_hash_one)]
 /// use std::hash::BuildHasher;
 ///
 /// let b = std::collections::hash_map::RandomState::new();
diff --git a/library/alloc/tests/str.rs b/library/alloc/tests/str.rs
index c1dbbde08b6..0ba5d088f61 100644
--- a/library/alloc/tests/str.rs
+++ b/library/alloc/tests/str.rs
@@ -1,3 +1,5 @@
+#![cfg_attr(not(bootstrap), allow(invalid_from_utf8))]
+
 use std::assert_matches::assert_matches;
 use std::borrow::Cow;
 use std::cmp::Ordering::{Equal, Greater, Less};
diff --git a/library/core/src/alloc/global.rs b/library/core/src/alloc/global.rs
index 18da70451f2..c582111701a 100644
--- a/library/core/src/alloc/global.rs
+++ b/library/core/src/alloc/global.rs
@@ -235,7 +235,8 @@ pub unsafe trait GlobalAlloc {
     /// * `new_size` must be greater than zero.
     ///
     /// * `new_size`, when rounded up to the nearest multiple of `layout.align()`,
-    ///   must not overflow (i.e., the rounded value must be less than `usize::MAX`).
+    ///   must not overflow isize (i.e., the rounded value must be less than or
+    ///   equal to `isize::MAX`).
     ///
     /// (Extension subtraits might provide more specific bounds on
     /// behavior, e.g., guarantee a sentinel address or a null pointer
diff --git a/library/core/src/alloc/mod.rs b/library/core/src/alloc/mod.rs
index d6ae2b8213f..78091c01729 100644
--- a/library/core/src/alloc/mod.rs
+++ b/library/core/src/alloc/mod.rs
@@ -94,8 +94,9 @@ impl fmt::Display for AllocError {
 ///
 /// # Safety
 ///
-/// * Memory blocks returned from an allocator must point to valid memory and retain their validity
-///   until the instance and all of its copies and clones are dropped,
+/// * Memory blocks returned from an allocator that are [*currently allocated*] must point to
+///   valid memory and retain their validity while they are [*currently allocated*] and at
+///   least one of the instance and all of its clones has not been dropped.
 ///
 /// * copying, cloning, or moving the allocator must not invalidate memory blocks returned from this
 ///   allocator. A copied or cloned allocator must behave like the same allocator, and
diff --git a/library/core/src/any.rs b/library/core/src/any.rs
index d1c1ae6526b..7969f4055dd 100644
--- a/library/core/src/any.rs
+++ b/library/core/src/any.rs
@@ -662,12 +662,20 @@ impl dyn Any + Send + Sync {
 /// While `TypeId` implements `Hash`, `PartialOrd`, and `Ord`, it is worth
 /// noting that the hashes and ordering will vary between Rust releases. Beware
 /// of relying on them inside of your code!
-#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
+#[derive(Clone, Copy, Debug, Hash, Eq, PartialOrd, Ord)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct TypeId {
     t: u64,
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
+impl PartialEq for TypeId {
+    #[inline]
+    fn eq(&self, other: &Self) -> bool {
+        self.t == other.t
+    }
+}
+
 impl TypeId {
     /// Returns the `TypeId` of the type this generic function has been
     /// instantiated with.
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs
index bdb4c975909..76b3589b9e4 100644
--- a/library/core/src/array/mod.rs
+++ b/library/core/src/array/mod.rs
@@ -204,6 +204,7 @@ where
 {
     type Error = TryFromSliceError;
 
+    #[inline]
     fn try_from(slice: &[T]) -> Result<[T; N], TryFromSliceError> {
         <&Self>::try_from(slice).map(|r| *r)
     }
@@ -228,6 +229,7 @@ where
 {
     type Error = TryFromSliceError;
 
+    #[inline]
     fn try_from(slice: &mut [T]) -> Result<[T; N], TryFromSliceError> {
         <Self>::try_from(&*slice)
     }
@@ -249,6 +251,7 @@ where
 impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N] {
     type Error = TryFromSliceError;
 
+    #[inline]
     fn try_from(slice: &'a [T]) -> Result<&'a [T; N], TryFromSliceError> {
         if slice.len() == N {
             let ptr = slice.as_ptr() as *const [T; N];
@@ -276,6 +279,7 @@ impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N] {
 impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N] {
     type Error = TryFromSliceError;
 
+    #[inline]
     fn try_from(slice: &'a mut [T]) -> Result<&'a mut [T; N], TryFromSliceError> {
         if slice.len() == N {
             let ptr = slice.as_mut_ptr() as *mut [T; N];
@@ -291,7 +295,6 @@ impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N] {
 /// as required by the `Borrow` implementation.
 ///
 /// ```
-/// #![feature(build_hasher_simple_hash_one)]
 /// use std::hash::BuildHasher;
 ///
 /// let b = std::collections::hash_map::RandomState::new();
@@ -535,29 +538,6 @@ impl<T, const N: usize> [T; N] {
         drain_array_with(self, |iter| try_from_trusted_iterator(iter.map(f)))
     }
 
-    /// 'Zips up' two arrays into a single array of pairs.
-    ///
-    /// `zip()` returns a new array where every element is a tuple where the
-    /// first element comes from the first array, and the second element comes
-    /// from the second array. In other words, it zips two arrays together,
-    /// into a single one.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(array_zip)]
-    /// let x = [1, 2, 3];
-    /// let y = [4, 5, 6];
-    /// let z = x.zip(y);
-    /// assert_eq!(z, [(1, 4), (2, 5), (3, 6)]);
-    /// ```
-    #[unstable(feature = "array_zip", issue = "80094")]
-    pub fn zip<U>(self, rhs: [U; N]) -> [(T, U); N] {
-        drain_array_with(self, |lhs| {
-            drain_array_with(rhs, |rhs| from_trusted_iterator(crate::iter::zip(lhs, rhs)))
-        })
-    }
-
     /// Returns a slice containing the entire array. Equivalent to `&s[..]`.
     #[stable(feature = "array_as_slice", since = "1.57.0")]
     #[rustc_const_stable(feature = "array_as_slice", since = "1.57.0")]
diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs
index a73b5b610a4..ca7c0772de8 100644
--- a/library/core/src/hash/mod.rs
+++ b/library/core/src/hash/mod.rs
@@ -674,8 +674,6 @@ pub trait BuildHasher {
     /// # Example
     ///
     /// ```
-    /// #![feature(build_hasher_simple_hash_one)]
-    ///
     /// use std::cmp::{max, min};
     /// use std::hash::{BuildHasher, Hash, Hasher};
     /// struct OrderAmbivalentPair<T: Ord>(T, T);
@@ -697,7 +695,7 @@ pub trait BuildHasher {
     ///     bh.hash_one(&OrderAmbivalentPair(2, 10))
     /// );
     /// ```
-    #[unstable(feature = "build_hasher_simple_hash_one", issue = "86161")]
+    #[stable(feature = "build_hasher_simple_hash_one", since = "CURRENT_RUSTC_VERSION")]
     fn hash_one<T: Hash>(&self, x: T) -> u64
     where
         Self: Sized,
diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs
index 0171d89812f..462f7170a55 100644
--- a/library/core/src/iter/range.rs
+++ b/library/core/src/iter/range.rs
@@ -619,9 +619,10 @@ impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> {
     #[inline]
     fn spec_next(&mut self) -> Option<T> {
         if self.start < self.end {
+            let old = self.start;
             // SAFETY: just checked precondition
-            let n = unsafe { Step::forward_unchecked(self.start.clone(), 1) };
-            Some(mem::replace(&mut self.start, n))
+            self.start = unsafe { Step::forward_unchecked(old, 1) };
+            Some(old)
         } else {
             None
         }
@@ -629,15 +630,15 @@ impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> {
 
     #[inline]
     fn spec_nth(&mut self, n: usize) -> Option<T> {
-        if let Some(plus_n) = Step::forward_checked(self.start.clone(), n) {
+        if let Some(plus_n) = Step::forward_checked(self.start, n) {
             if plus_n < self.end {
                 // SAFETY: just checked precondition
-                self.start = unsafe { Step::forward_unchecked(plus_n.clone(), 1) };
+                self.start = unsafe { Step::forward_unchecked(plus_n, 1) };
                 return Some(plus_n);
             }
         }
 
-        self.start = self.end.clone();
+        self.start = self.end;
         None
     }
 
@@ -655,7 +656,7 @@ impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> {
         // then steps_between either returns a bound to which we clamp or returns None which
         // together with the initial inequality implies more than usize::MAX steps.
         // Otherwise 0 is returned which always safe to use.
-        self.start = unsafe { Step::forward_unchecked(self.start.clone(), taken) };
+        self.start = unsafe { Step::forward_unchecked(self.start, taken) };
 
         NonZeroUsize::new(n - taken).map_or(Ok(()), Err)
     }
@@ -664,8 +665,8 @@ impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> {
     fn spec_next_back(&mut self) -> Option<T> {
         if self.start < self.end {
             // SAFETY: just checked precondition
-            self.end = unsafe { Step::backward_unchecked(self.end.clone(), 1) };
-            Some(self.end.clone())
+            self.end = unsafe { Step::backward_unchecked(self.end, 1) };
+            Some(self.end)
         } else {
             None
         }
@@ -673,15 +674,15 @@ impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> {
 
     #[inline]
     fn spec_nth_back(&mut self, n: usize) -> Option<T> {
-        if let Some(minus_n) = Step::backward_checked(self.end.clone(), n) {
+        if let Some(minus_n) = Step::backward_checked(self.end, n) {
             if minus_n > self.start {
                 // SAFETY: just checked precondition
                 self.end = unsafe { Step::backward_unchecked(minus_n, 1) };
-                return Some(self.end.clone());
+                return Some(self.end);
             }
         }
 
-        self.end = self.start.clone();
+        self.end = self.start;
         None
     }
 
@@ -696,7 +697,7 @@ impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> {
         let taken = available.min(n);
 
         // SAFETY: same as the spec_advance_by() implementation
-        self.end = unsafe { Step::backward_unchecked(self.end.clone(), taken) };
+        self.end = unsafe { Step::backward_unchecked(self.end, taken) };
 
         NonZeroUsize::new(n - taken).map_or(Ok(()), Err)
     }
diff --git a/library/core/src/iter/traits/marker.rs b/library/core/src/iter/traits/marker.rs
index af02848233d..c21a2aac1c9 100644
--- a/library/core/src/iter/traits/marker.rs
+++ b/library/core/src/iter/traits/marker.rs
@@ -86,4 +86,4 @@ pub unsafe trait InPlaceIterable: Iterator {}
 /// for details. Consumers are free to rely on the invariants in unsafe code.
 #[unstable(feature = "trusted_step", issue = "85731")]
 #[rustc_specialization_trait]
-pub unsafe trait TrustedStep: Step {}
+pub unsafe trait TrustedStep: Step + Copy {}
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index b24882ddb17..c4134dbcd25 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -1427,7 +1427,7 @@ pub(crate) mod builtin {
     #[rustc_builtin_macro]
     #[macro_export]
     #[rustc_diagnostic_item = "assert_macro"]
-    #[allow_internal_unstable(core_panic, edition_panic)]
+    #[allow_internal_unstable(core_panic, edition_panic, generic_assert_internals)]
     macro_rules! assert {
         ($cond:expr $(,)?) => {{ /* compiler built-in */ }};
         ($cond:expr, $($arg:tt)+) => {{ /* compiler built-in */ }};
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index bd1b16e8d73..62003ddf515 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -3005,8 +3005,9 @@ impl<T> [T] {
     ///
     /// # Current implementation
     ///
-    /// The current algorithm is based on the quickselect portion of the same quicksort algorithm
-    /// used for [`sort_unstable`].
+    /// The current algorithm is an introselect implementation based on Pattern Defeating Quicksort, which is also
+    /// the basis for [`sort_unstable`]. The fallback algorithm is Median of Medians using Tukey's Ninther for
+    /// pivot selection, which guarantees linear runtime for all inputs.
     ///
     /// [`sort_unstable`]: slice::sort_unstable
     ///
@@ -3056,8 +3057,9 @@ impl<T> [T] {
     ///
     /// # Current implementation
     ///
-    /// The current algorithm is based on the quickselect portion of the same quicksort algorithm
-    /// used for [`sort_unstable`].
+    /// The current algorithm is an introselect implementation based on Pattern Defeating Quicksort, which is also
+    /// the basis for [`sort_unstable`]. The fallback algorithm is Median of Medians using Tukey's Ninther for
+    /// pivot selection, which guarantees linear runtime for all inputs.
     ///
     /// [`sort_unstable`]: slice::sort_unstable
     ///
@@ -3111,8 +3113,9 @@ impl<T> [T] {
     ///
     /// # Current implementation
     ///
-    /// The current algorithm is based on the quickselect portion of the same quicksort algorithm
-    /// used for [`sort_unstable`].
+    /// The current algorithm is an introselect implementation based on Pattern Defeating Quicksort, which is also
+    /// the basis for [`sort_unstable`]. The fallback algorithm is Median of Medians using Tukey's Ninther for
+    /// pivot selection, which guarantees linear runtime for all inputs.
     ///
     /// [`sort_unstable`]: slice::sort_unstable
     ///
diff --git a/library/core/src/str/converts.rs b/library/core/src/str/converts.rs
index 5f8748206d7..0f23cf7ae23 100644
--- a/library/core/src/str/converts.rs
+++ b/library/core/src/str/converts.rs
@@ -84,6 +84,7 @@ use super::Utf8Error;
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_stable(feature = "const_str_from_utf8_shared", since = "1.63.0")]
 #[rustc_allow_const_fn_unstable(str_internals)]
+#[rustc_diagnostic_item = "str_from_utf8"]
 pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
     // FIXME: This should use `?` again, once it's `const`
     match run_utf8_validation(v) {
@@ -127,6 +128,7 @@ pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
 /// errors that can be returned.
 #[stable(feature = "str_mut_extras", since = "1.20.0")]
 #[rustc_const_unstable(feature = "const_str_from_utf8", issue = "91006")]
+#[rustc_diagnostic_item = "str_from_utf8_mut"]
 pub const fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> {
     // This should use `?` again, once it's `const`
     match run_utf8_validation(v) {
@@ -167,6 +169,7 @@ pub const fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> {
 #[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_stable(feature = "const_str_from_utf8_unchecked", since = "1.55.0")]
+#[rustc_diagnostic_item = "str_from_utf8_unchecked"]
 pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str {
     // SAFETY: the caller must guarantee that the bytes `v` are valid UTF-8.
     // Also relies on `&str` and `&[u8]` having the same layout.
@@ -194,6 +197,7 @@ pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str {
 #[must_use]
 #[stable(feature = "str_mut_extras", since = "1.20.0")]
 #[rustc_const_unstable(feature = "const_str_from_utf8_unchecked_mut", issue = "91005")]
+#[rustc_diagnostic_item = "str_from_utf8_unchecked_mut"]
 pub const unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str {
     // SAFETY: the caller must guarantee that the bytes `v`
     // are valid UTF-8, thus the cast to `*mut str` is safe.
diff --git a/library/portable-simd/Cargo.toml b/library/portable-simd/Cargo.toml
index 9802386e456..d1732aaec2f 100644
--- a/library/portable-simd/Cargo.toml
+++ b/library/portable-simd/Cargo.toml
@@ -1,5 +1,5 @@
 [workspace]
-
+resolver = "1"
 members = [
     "crates/core_simd",
     "crates/std_float",
diff --git a/library/std/src/ffi/mod.rs b/library/std/src/ffi/mod.rs
index d987bf69b25..3ddb8748753 100644
--- a/library/std/src/ffi/mod.rs
+++ b/library/std/src/ffi/mod.rs
@@ -127,6 +127,14 @@
 //! trait, which provides a [`from_wide`] method to convert a native Windows
 //! string (without the terminating nul character) to an [`OsString`].
 //!
+//! ## On all platforms
+//!
+//! On all platforms, [`OsStr`] consists of a sequence of bytes that is encoded as a superset of
+//! UTF-8; see [`OsString`] for more details on its encoding on different platforms.
+//!
+//! For limited, inexpensive conversions from and to bytes, see [`OsStr::as_os_str_bytes`] and
+//! [`OsStr::from_os_str_bytes_unchecked`].
+//!
 //! [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value
 //! [Unicode code point]: https://www.unicode.org/glossary/#code_point
 //! [`env::set_var()`]: crate::env::set_var "env::set_var"
diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs
index 5c0541d3caf..bb577acf769 100644
--- a/library/std/src/ffi/os_str.rs
+++ b/library/std/src/ffi/os_str.rs
@@ -667,6 +667,51 @@ impl OsStr {
         s.as_ref()
     }
 
+    /// Converts a slice of bytes to an OS string slice without checking that the string contains
+    /// valid `OsStr`-encoded data.
+    ///
+    /// The byte encoding is an unspecified, platform-specific, self-synchronizing superset of UTF-8.
+    /// By being a self-synchronizing superset of UTF-8, this encoding is also a superset of 7-bit
+    /// ASCII.
+    ///
+    /// See the [module's toplevel documentation about conversions][conversions] for safe,
+    /// cross-platform [conversions] from/to native representations.
+    ///
+    /// # Safety
+    ///
+    /// As the encoding is unspecified, callers must pass in bytes that originated as a mixture of
+    /// validated UTF-8 and bytes from [`OsStr::as_os_str_bytes`] from within the same rust version
+    /// built for the same target platform.  For example, reconstructing an `OsStr` from bytes sent
+    /// over the network or stored in a file will likely violate these safety rules.
+    ///
+    /// Due to the encoding being self-synchronizing, the bytes from [`OsStr::as_os_str_bytes`] can be
+    /// split either immediately before or immediately after any valid non-empty UTF-8 substring.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// #![feature(os_str_bytes)]
+    ///
+    /// use std::ffi::OsStr;
+    ///
+    /// let os_str = OsStr::new("Mary had a little lamb");
+    /// let bytes = os_str.as_os_str_bytes();
+    /// let words = bytes.split(|b| *b == b' ');
+    /// let words: Vec<&OsStr> = words.map(|word| {
+    ///     // SAFETY:
+    ///     // - Each `word` only contains content that originated from `OsStr::as_os_str_bytes`
+    ///     // - Only split with ASCII whitespace which is a non-empty UTF-8 substring
+    ///     unsafe { OsStr::from_os_str_bytes_unchecked(word) }
+    /// }).collect();
+    /// ```
+    ///
+    /// [conversions]: super#conversions
+    #[inline]
+    #[unstable(feature = "os_str_bytes", issue = "111544")]
+    pub unsafe fn from_os_str_bytes_unchecked(bytes: &[u8]) -> &Self {
+        Self::from_inner(Slice::from_os_str_bytes_unchecked(bytes))
+    }
+
     #[inline]
     fn from_inner(inner: &Slice) -> &OsStr {
         // SAFETY: OsStr is just a wrapper of Slice,
@@ -837,13 +882,24 @@ impl OsStr {
         OsString { inner: Buf::from_box(boxed) }
     }
 
-    /// Gets the underlying byte representation.
+    /// Converts an OS string slice to a byte slice.  To convert the byte slice back into an OS
+    /// string slice, use the [`OsStr::from_os_str_bytes_unchecked`] function.
+    ///
+    /// The byte encoding is an unspecified, platform-specific, self-synchronizing superset of UTF-8.
+    /// By being a self-synchronizing superset of UTF-8, this encoding is also a superset of 7-bit
+    /// ASCII.
+    ///
+    /// Note: As the encoding is unspecified, any sub-slice of bytes that is not valid UTF-8 should
+    /// be treated as opaque and only comparable within the same rust version built for the same
+    /// target platform.  For example, sending the slice over the network or storing it in a file
+    /// will likely result in incompatible byte slices.  See [`OsString`] for more encoding details
+    /// and [`std::ffi`] for platform-specific, specified conversions.
     ///
-    /// Note: it is *crucial* that this API is not externally public, to avoid
-    /// revealing the internal, platform-specific encodings.
+    /// [`std::ffi`]: crate::ffi
     #[inline]
-    pub(crate) fn bytes(&self) -> &[u8] {
-        unsafe { &*(&self.inner as *const _ as *const [u8]) }
+    #[unstable(feature = "os_str_bytes", issue = "111544")]
+    pub fn as_os_str_bytes(&self) -> &[u8] {
+        self.inner.as_os_str_bytes()
     }
 
     /// Converts this string to its ASCII lower case equivalent in-place.
@@ -1131,7 +1187,7 @@ impl Default for &OsStr {
 impl PartialEq for OsStr {
     #[inline]
     fn eq(&self, other: &OsStr) -> bool {
-        self.bytes().eq(other.bytes())
+        self.as_os_str_bytes().eq(other.as_os_str_bytes())
     }
 }
 
@@ -1158,23 +1214,23 @@ impl Eq for OsStr {}
 impl PartialOrd for OsStr {
     #[inline]
     fn partial_cmp(&self, other: &OsStr) -> Option<cmp::Ordering> {
-        self.bytes().partial_cmp(other.bytes())
+        self.as_os_str_bytes().partial_cmp(other.as_os_str_bytes())
     }
     #[inline]
     fn lt(&self, other: &OsStr) -> bool {
-        self.bytes().lt(other.bytes())
+        self.as_os_str_bytes().lt(other.as_os_str_bytes())
     }
     #[inline]
     fn le(&self, other: &OsStr) -> bool {
-        self.bytes().le(other.bytes())
+        self.as_os_str_bytes().le(other.as_os_str_bytes())
     }
     #[inline]
     fn gt(&self, other: &OsStr) -> bool {
-        self.bytes().gt(other.bytes())
+        self.as_os_str_bytes().gt(other.as_os_str_bytes())
     }
     #[inline]
     fn ge(&self, other: &OsStr) -> bool {
-        self.bytes().ge(other.bytes())
+        self.as_os_str_bytes().ge(other.as_os_str_bytes())
     }
 }
 
@@ -1193,7 +1249,7 @@ impl PartialOrd<str> for OsStr {
 impl Ord for OsStr {
     #[inline]
     fn cmp(&self, other: &OsStr) -> cmp::Ordering {
-        self.bytes().cmp(other.bytes())
+        self.as_os_str_bytes().cmp(other.as_os_str_bytes())
     }
 }
 
@@ -1243,7 +1299,7 @@ impl_cmp!(Cow<'a, OsStr>, OsString);
 impl Hash for OsStr {
     #[inline]
     fn hash<H: Hasher>(&self, state: &mut H) {
-        self.bytes().hash(state)
+        self.as_os_str_bytes().hash(state)
     }
 }
 
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index 9e09ce337bc..8a007d095d5 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -593,7 +593,8 @@ pub trait Read {
     /// This may happen for example because fewer bytes are actually available right now
     /// (e. g. being close to end-of-file) or because read() was interrupted by a signal.
     ///
-    /// As this trait is safe to implement, callers cannot rely on `n <= buf.len()` for safety.
+    /// As this trait is safe to implement, callers in unsafe code cannot rely on
+    /// `n <= buf.len()` for safety.
     /// Extra care needs to be taken when `unsafe` functions are used to access the read bytes.
     /// Callers have to ensure that no unchecked out-of-bounds accesses are possible even if
     /// `n > buf.len()`.
@@ -603,8 +604,8 @@ pub trait Read {
     /// contents of `buf` being true. It is recommended that *implementations*
     /// only write data to `buf` instead of reading its contents.
     ///
-    /// Correspondingly, however, *callers* of this method must not assume any guarantees
-    /// about how the implementation uses `buf`. The trait is safe to implement,
+    /// Correspondingly, however, *callers* of this method in unsafe code must not assume
+    /// any guarantees about how the implementation uses `buf`. The trait is safe to implement,
     /// so it is possible that the code that's supposed to write to the buffer might also read
     /// from it. It is your responsibility to make sure that `buf` is initialized
     /// before calling `read`. Calling `read` with an uninitialized `buf` (of the kind one
diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs
index 6d59266b6f8..a6a370409c0 100644
--- a/library/std/src/panicking.rs
+++ b/library/std/src/panicking.rs
@@ -298,8 +298,18 @@ pub mod panic_count {
 
     pub const ALWAYS_ABORT_FLAG: usize = 1 << (usize::BITS - 1);
 
-    // Panic count for the current thread.
-    thread_local! { static LOCAL_PANIC_COUNT: Cell<usize> = const { Cell::new(0) } }
+    /// A reason for forcing an immediate abort on panic.
+    #[derive(Debug)]
+    pub enum MustAbort {
+        AlwaysAbort,
+        PanicInHook,
+    }
+
+    // Panic count for the current thread and whether a panic hook is currently
+    // being executed..
+    thread_local! {
+        static LOCAL_PANIC_COUNT: Cell<(usize, bool)> = const { Cell::new((0, false)) }
+    }
 
     // Sum of panic counts from all threads. The purpose of this is to have
     // a fast path in `count_is_zero` (which is used by `panicking`). In any particular
@@ -328,34 +338,39 @@ pub mod panic_count {
     // panicking thread consumes at least 2 bytes of address space.
     static GLOBAL_PANIC_COUNT: AtomicUsize = AtomicUsize::new(0);
 
-    // Return the state of the ALWAYS_ABORT_FLAG and number of panics.
+    // Increases the global and local panic count, and returns whether an
+    // immediate abort is required.
     //
-    // If ALWAYS_ABORT_FLAG is not set, the number is determined on a per-thread
-    // base (stored in LOCAL_PANIC_COUNT), i.e. it is the amount of recursive calls
-    // of the calling thread.
-    // If ALWAYS_ABORT_FLAG is set, the number equals the *global* number of panic
-    // calls. See above why LOCAL_PANIC_COUNT is not used.
-    pub fn increase() -> (bool, usize) {
+    // This also updates thread-local state to keep track of whether a panic
+    // hook is currently executing.
+    pub fn increase(run_panic_hook: bool) -> Option<MustAbort> {
         let global_count = GLOBAL_PANIC_COUNT.fetch_add(1, Ordering::Relaxed);
-        let must_abort = global_count & ALWAYS_ABORT_FLAG != 0;
-        let panics = if must_abort {
-            global_count & !ALWAYS_ABORT_FLAG
-        } else {
-            LOCAL_PANIC_COUNT.with(|c| {
-                let next = c.get() + 1;
-                c.set(next);
-                next
-            })
-        };
-        (must_abort, panics)
+        if global_count & ALWAYS_ABORT_FLAG != 0 {
+            return Some(MustAbort::AlwaysAbort);
+        }
+
+        LOCAL_PANIC_COUNT.with(|c| {
+            let (count, in_panic_hook) = c.get();
+            if in_panic_hook {
+                return Some(MustAbort::PanicInHook);
+            }
+            c.set((count + 1, run_panic_hook));
+            None
+        })
+    }
+
+    pub fn finished_panic_hook() {
+        LOCAL_PANIC_COUNT.with(|c| {
+            let (count, _) = c.get();
+            c.set((count, false));
+        });
     }
 
     pub fn decrease() {
         GLOBAL_PANIC_COUNT.fetch_sub(1, Ordering::Relaxed);
         LOCAL_PANIC_COUNT.with(|c| {
-            let next = c.get() - 1;
-            c.set(next);
-            next
+            let (count, _) = c.get();
+            c.set((count - 1, false));
         });
     }
 
@@ -366,7 +381,7 @@ pub mod panic_count {
     // Disregards ALWAYS_ABORT_FLAG
     #[must_use]
     pub fn get_count() -> usize {
-        LOCAL_PANIC_COUNT.with(|c| c.get())
+        LOCAL_PANIC_COUNT.with(|c| c.get().0)
     }
 
     // Disregards ALWAYS_ABORT_FLAG
@@ -394,7 +409,7 @@ pub mod panic_count {
     #[inline(never)]
     #[cold]
     fn is_zero_slow_path() -> bool {
-        LOCAL_PANIC_COUNT.with(|c| c.get() == 0)
+        LOCAL_PANIC_COUNT.with(|c| c.get().0 == 0)
     }
 }
 
@@ -655,23 +670,22 @@ fn rust_panic_with_hook(
     location: &Location<'_>,
     can_unwind: bool,
 ) -> ! {
-    let (must_abort, panics) = panic_count::increase();
-
-    // If this is the third nested call (e.g., panics == 2, this is 0-indexed),
-    // the panic hook probably triggered the last panic, otherwise the
-    // double-panic check would have aborted the process. In this case abort the
-    // process real quickly as we don't want to try calling it again as it'll
-    // probably just panic again.
-    if must_abort || panics > 2 {
-        if panics > 2 {
-            // Don't try to print the message in this case
-            // - perhaps that is causing the recursive panics.
-            rtprintpanic!("thread panicked while processing panic. aborting.\n");
-        } else {
-            // Unfortunately, this does not print a backtrace, because creating
-            // a `Backtrace` will allocate, which we must to avoid here.
-            let panicinfo = PanicInfo::internal_constructor(message, location, can_unwind);
-            rtprintpanic!("{panicinfo}\npanicked after panic::always_abort(), aborting.\n");
+    let must_abort = panic_count::increase(true);
+
+    // Check if we need to abort immediately.
+    if let Some(must_abort) = must_abort {
+        match must_abort {
+            panic_count::MustAbort::PanicInHook => {
+                // Don't try to print the message in this case
+                // - perhaps that is causing the recursive panics.
+                rtprintpanic!("thread panicked while processing panic. aborting.\n");
+            }
+            panic_count::MustAbort::AlwaysAbort => {
+                // Unfortunately, this does not print a backtrace, because creating
+                // a `Backtrace` will allocate, which we must to avoid here.
+                let panicinfo = PanicInfo::internal_constructor(message, location, can_unwind);
+                rtprintpanic!("{panicinfo}\npanicked after panic::always_abort(), aborting.\n");
+            }
         }
         crate::sys::abort_internal();
     }
@@ -697,16 +711,16 @@ fn rust_panic_with_hook(
     };
     drop(hook);
 
-    if panics > 1 || !can_unwind {
-        // If a thread panics while it's already unwinding then we
-        // have limited options. Currently our preference is to
-        // just abort. In the future we may consider resuming
-        // unwinding or otherwise exiting the thread cleanly.
-        if !can_unwind {
-            rtprintpanic!("thread caused non-unwinding panic. aborting.\n");
-        } else {
-            rtprintpanic!("thread panicked while panicking. aborting.\n");
-        }
+    // Indicate that we have finished executing the panic hook. After this point
+    // it is fine if there is a panic while executing destructors, as long as it
+    // it contained within a `catch_unwind`.
+    panic_count::finished_panic_hook();
+
+    if !can_unwind {
+        // If a thread panics while running destructors or tries to unwind
+        // through a nounwind function (e.g. extern "C") then we cannot continue
+        // unwinding and have to abort immediately.
+        rtprintpanic!("thread caused non-unwinding panic. aborting.\n");
         crate::sys::abort_internal();
     }
 
@@ -716,7 +730,7 @@ fn rust_panic_with_hook(
 /// This is the entry point for `resume_unwind`.
 /// It just forwards the payload to the panic runtime.
 pub fn rust_panic_without_hook(payload: Box<dyn Any + Send>) -> ! {
-    panic_count::increase();
+    panic_count::increase(false);
 
     struct RewrapBox(Box<dyn Any + Send>);
 
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index febdeb51463..28cd3c4e4db 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -193,7 +193,7 @@ impl<'a> Prefix<'a> {
     fn len(&self) -> usize {
         use self::Prefix::*;
         fn os_str_len(s: &OsStr) -> usize {
-            s.bytes().len()
+            s.as_os_str_bytes().len()
         }
         match *self {
             Verbatim(x) => 4 + os_str_len(x),
@@ -299,20 +299,6 @@ where
     }
 }
 
-unsafe fn u8_slice_as_os_str(s: &[u8]) -> &OsStr {
-    // SAFETY: See note at the top of this module to understand why this and
-    // `OsStr::bytes` are used:
-    //
-    // This casts are safe as OsStr is internally a wrapper around [u8] on all
-    // platforms.
-    //
-    // Note that currently this relies on the special knowledge that std has;
-    // these types are single-element structs but are not marked
-    // repr(transparent) or repr(C) which would make these casts not allowable
-    // outside std.
-    unsafe { &*(s as *const [u8] as *const OsStr) }
-}
-
 // Detect scheme on Redox
 fn has_redox_scheme(s: &[u8]) -> bool {
     cfg!(target_os = "redox") && s.contains(&b':')
@@ -330,7 +316,7 @@ fn has_physical_root(s: &[u8], prefix: Option<Prefix<'_>>) -> bool {
 
 // basic workhorse for splitting stem and extension
 fn rsplit_file_at_dot(file: &OsStr) -> (Option<&OsStr>, Option<&OsStr>) {
-    if file.bytes() == b".." {
+    if file.as_os_str_bytes() == b".." {
         return (Some(file), None);
     }
 
@@ -338,18 +324,23 @@ fn rsplit_file_at_dot(file: &OsStr) -> (Option<&OsStr>, Option<&OsStr>) {
     // and back. This is safe to do because (1) we only look at ASCII
     // contents of the encoding and (2) new &OsStr values are produced
     // only from ASCII-bounded slices of existing &OsStr values.
-    let mut iter = file.bytes().rsplitn(2, |b| *b == b'.');
+    let mut iter = file.as_os_str_bytes().rsplitn(2, |b| *b == b'.');
     let after = iter.next();
     let before = iter.next();
     if before == Some(b"") {
         (Some(file), None)
     } else {
-        unsafe { (before.map(|s| u8_slice_as_os_str(s)), after.map(|s| u8_slice_as_os_str(s))) }
+        unsafe {
+            (
+                before.map(|s| OsStr::from_os_str_bytes_unchecked(s)),
+                after.map(|s| OsStr::from_os_str_bytes_unchecked(s)),
+            )
+        }
     }
 }
 
 fn split_file_at_dot(file: &OsStr) -> (&OsStr, Option<&OsStr>) {
-    let slice = file.bytes();
+    let slice = file.as_os_str_bytes();
     if slice == b".." {
         return (file, None);
     }
@@ -364,7 +355,12 @@ fn split_file_at_dot(file: &OsStr) -> (&OsStr, Option<&OsStr>) {
     };
     let before = &slice[..i];
     let after = &slice[i + 1..];
-    unsafe { (u8_slice_as_os_str(before), Some(u8_slice_as_os_str(after))) }
+    unsafe {
+        (
+            OsStr::from_os_str_bytes_unchecked(before),
+            Some(OsStr::from_os_str_bytes_unchecked(after)),
+        )
+    }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -743,7 +739,7 @@ impl<'a> Components<'a> {
             // separately via `include_cur_dir`
             b".." => Some(Component::ParentDir),
             b"" => None,
-            _ => Some(Component::Normal(unsafe { u8_slice_as_os_str(comp) })),
+            _ => Some(Component::Normal(unsafe { OsStr::from_os_str_bytes_unchecked(comp) })),
         }
     }
 
@@ -900,7 +896,7 @@ impl<'a> Iterator for Components<'a> {
                     let raw = &self.path[..self.prefix_len()];
                     self.path = &self.path[self.prefix_len()..];
                     return Some(Component::Prefix(PrefixComponent {
-                        raw: unsafe { u8_slice_as_os_str(raw) },
+                        raw: unsafe { OsStr::from_os_str_bytes_unchecked(raw) },
                         parsed: self.prefix.unwrap(),
                     }));
                 }
@@ -972,7 +968,7 @@ impl<'a> DoubleEndedIterator for Components<'a> {
                 State::Prefix if self.prefix_len() > 0 => {
                     self.back = State::Done;
                     return Some(Component::Prefix(PrefixComponent {
-                        raw: unsafe { u8_slice_as_os_str(self.path) },
+                        raw: unsafe { OsStr::from_os_str_bytes_unchecked(self.path) },
                         parsed: self.prefix.unwrap(),
                     }));
                 }
@@ -1481,17 +1477,17 @@ impl PathBuf {
     fn _set_extension(&mut self, extension: &OsStr) -> bool {
         let file_stem = match self.file_stem() {
             None => return false,
-            Some(f) => f.bytes(),
+            Some(f) => f.as_os_str_bytes(),
         };
 
         // truncate until right after the file stem
         let end_file_stem = file_stem[file_stem.len()..].as_ptr().addr();
-        let start = self.inner.bytes().as_ptr().addr();
+        let start = self.inner.as_os_str_bytes().as_ptr().addr();
         let v = self.as_mut_vec();
         v.truncate(end_file_stem.wrapping_sub(start));
 
         // add the new extension, if any
-        let new = extension.bytes();
+        let new = extension.as_os_str_bytes();
         if !new.is_empty() {
             v.reserve_exact(new.len() + 1);
             v.push(b'.');
@@ -2011,11 +2007,11 @@ impl Path {
     // The following (private!) function allows construction of a path from a u8
     // slice, which is only safe when it is known to follow the OsStr encoding.
     unsafe fn from_u8_slice(s: &[u8]) -> &Path {
-        unsafe { Path::new(u8_slice_as_os_str(s)) }
+        unsafe { Path::new(OsStr::from_os_str_bytes_unchecked(s)) }
     }
     // The following (private!) function reveals the byte encoding used for OsStr.
     fn as_u8_slice(&self) -> &[u8] {
-        self.inner.bytes()
+        self.inner.as_os_str_bytes()
     }
 
     /// Directly wraps a string slice as a `Path` slice.
diff --git a/library/std/src/sys/common/small_c_string.rs b/library/std/src/sys/common/small_c_string.rs
index 01acd519135..963d17a47e4 100644
--- a/library/std/src/sys/common/small_c_string.rs
+++ b/library/std/src/sys/common/small_c_string.rs
@@ -19,7 +19,7 @@ pub fn run_path_with_cstr<T, F>(path: &Path, f: F) -> io::Result<T>
 where
     F: FnOnce(&CStr) -> io::Result<T>,
 {
-    run_with_cstr(path.as_os_str().bytes(), f)
+    run_with_cstr(path.as_os_str().as_os_str_bytes(), f)
 }
 
 #[inline]
diff --git a/library/std/src/sys/common/tests.rs b/library/std/src/sys/common/tests.rs
index fb6f5d6af83..0a1cbcbe8ef 100644
--- a/library/std/src/sys/common/tests.rs
+++ b/library/std/src/sys/common/tests.rs
@@ -8,7 +8,7 @@ use core::iter::repeat;
 fn stack_allocation_works() {
     let path = Path::new("abc");
     let result = run_path_with_cstr(path, |p| {
-        assert_eq!(p, &*CString::new(path.as_os_str().bytes()).unwrap());
+        assert_eq!(p, &*CString::new(path.as_os_str().as_os_str_bytes()).unwrap());
         Ok(42)
     });
     assert_eq!(result.unwrap(), 42);
@@ -25,7 +25,7 @@ fn heap_allocation_works() {
     let path = repeat("a").take(384).collect::<String>();
     let path = Path::new(&path);
     let result = run_path_with_cstr(path, |p| {
-        assert_eq!(p, &*CString::new(path.as_os_str().bytes()).unwrap());
+        assert_eq!(p, &*CString::new(path.as_os_str().as_os_str_bytes()).unwrap());
         Ok(42)
     });
     assert_eq!(result.unwrap(), 42);
diff --git a/library/std/src/sys/unix/os_str.rs b/library/std/src/sys/unix/os_str.rs
index 488217f3941..142fcb9ed0b 100644
--- a/library/std/src/sys/unix/os_str.rs
+++ b/library/std/src/sys/unix/os_str.rs
@@ -193,13 +193,18 @@ impl Buf {
 
 impl Slice {
     #[inline]
-    fn from_u8_slice(s: &[u8]) -> &Slice {
+    pub fn as_os_str_bytes(&self) -> &[u8] {
+        &self.inner
+    }
+
+    #[inline]
+    pub unsafe fn from_os_str_bytes_unchecked(s: &[u8]) -> &Slice {
         unsafe { mem::transmute(s) }
     }
 
     #[inline]
     pub fn from_str(s: &str) -> &Slice {
-        Slice::from_u8_slice(s.as_bytes())
+        unsafe { Slice::from_os_str_bytes_unchecked(s.as_bytes()) }
     }
 
     pub fn to_str(&self) -> Option<&str> {
diff --git a/library/std/src/sys/unix/os_str/tests.rs b/library/std/src/sys/unix/os_str/tests.rs
index 22ba0c92350..91bc0e61a4a 100644
--- a/library/std/src/sys/unix/os_str/tests.rs
+++ b/library/std/src/sys/unix/os_str/tests.rs
@@ -2,7 +2,7 @@ use super::*;
 
 #[test]
 fn slice_debug_output() {
-    let input = Slice::from_u8_slice(b"\xF0hello,\tworld");
+    let input = unsafe { Slice::from_os_str_bytes_unchecked(b"\xF0hello,\tworld") };
     let expected = r#""\xF0hello,\tworld""#;
     let output = format!("{input:?}");
 
@@ -11,8 +11,7 @@ fn slice_debug_output() {
 
 #[test]
 fn display() {
-    assert_eq!(
-        "Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye",
-        Slice::from_u8_slice(b"Hello\xC0\x80 There\xE6\x83 Goodbye").to_string(),
-    );
+    assert_eq!("Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye", unsafe {
+        Slice::from_os_str_bytes_unchecked(b"Hello\xC0\x80 There\xE6\x83 Goodbye").to_string()
+    },);
 }
diff --git a/library/std/src/sys/unix/path.rs b/library/std/src/sys/unix/path.rs
index a98a69e2db8..935245f637b 100644
--- a/library/std/src/sys/unix/path.rs
+++ b/library/std/src/sys/unix/path.rs
@@ -30,7 +30,7 @@ pub(crate) fn absolute(path: &Path) -> io::Result<PathBuf> {
 
     // Get the components, skipping the redundant leading "." component if it exists.
     let mut components = path.strip_prefix(".").unwrap_or(path).components();
-    let path_os = path.as_os_str().bytes();
+    let path_os = path.as_os_str().as_os_str_bytes();
 
     let mut normalized = if path.is_absolute() {
         // "If a pathname begins with two successive <slash> characters, the
diff --git a/library/std/src/sys/unix/process/process_common.rs b/library/std/src/sys/unix/process/process_common.rs
index afd03d79c0b..640648e8707 100644
--- a/library/std/src/sys/unix/process/process_common.rs
+++ b/library/std/src/sys/unix/process/process_common.rs
@@ -164,9 +164,9 @@ pub enum ProgramKind {
 
 impl ProgramKind {
     fn new(program: &OsStr) -> Self {
-        if program.bytes().starts_with(b"/") {
+        if program.as_os_str_bytes().starts_with(b"/") {
             Self::Absolute
-        } else if program.bytes().contains(&b'/') {
+        } else if program.as_os_str_bytes().contains(&b'/') {
             // If the program has more than one component in it, it is a relative path.
             Self::Relative
         } else {
diff --git a/library/std/src/sys/windows/args.rs b/library/std/src/sys/windows/args.rs
index 5bfd8b52ed0..6b597f499bc 100644
--- a/library/std/src/sys/windows/args.rs
+++ b/library/std/src/sys/windows/args.rs
@@ -226,7 +226,7 @@ pub(crate) fn append_arg(cmd: &mut Vec<u16>, arg: &Arg, force_quotes: bool) -> i
     // that it actually gets passed through on the command line or otherwise
     // it will be dropped entirely when parsed on the other end.
     ensure_no_nuls(arg)?;
-    let arg_bytes = arg.bytes();
+    let arg_bytes = arg.as_os_str_bytes();
     let (quote, escape) = match quote {
         Quote::Always => (true, true),
         Quote::Auto => {
@@ -297,7 +297,9 @@ pub(crate) fn make_bat_command_line(
         // * `|<>` pipe/redirect characters.
         const SPECIAL: &[u8] = b"\t &()[]{}^=;!'+,`~%|<>";
         let force_quotes = match arg {
-            Arg::Regular(arg) if !force_quotes => arg.bytes().iter().any(|c| SPECIAL.contains(c)),
+            Arg::Regular(arg) if !force_quotes => {
+                arg.as_os_str_bytes().iter().any(|c| SPECIAL.contains(c))
+            }
             _ => force_quotes,
         };
         append_arg(&mut cmd, arg, force_quotes)?;
diff --git a/library/std/src/sys/windows/os_str.rs b/library/std/src/sys/windows/os_str.rs
index 2f2b0e56e08..611f0d040f0 100644
--- a/library/std/src/sys/windows/os_str.rs
+++ b/library/std/src/sys/windows/os_str.rs
@@ -152,6 +152,16 @@ impl Buf {
 
 impl Slice {
     #[inline]
+    pub fn as_os_str_bytes(&self) -> &[u8] {
+        self.inner.as_bytes()
+    }
+
+    #[inline]
+    pub unsafe fn from_os_str_bytes_unchecked(s: &[u8]) -> &Slice {
+        mem::transmute(Wtf8::from_bytes_unchecked(s))
+    }
+
+    #[inline]
     pub fn from_str(s: &str) -> &Slice {
         unsafe { mem::transmute(Wtf8::from_str(s)) }
     }
diff --git a/library/std/src/sys/windows/path.rs b/library/std/src/sys/windows/path.rs
index c3573d14c7f..c9c2d10e6c4 100644
--- a/library/std/src/sys/windows/path.rs
+++ b/library/std/src/sys/windows/path.rs
@@ -1,7 +1,6 @@
 use super::{c, fill_utf16_buf, to_u16s};
 use crate::ffi::{OsStr, OsString};
 use crate::io;
-use crate::mem;
 use crate::path::{Path, PathBuf, Prefix};
 use crate::ptr;
 
@@ -11,16 +10,6 @@ mod tests;
 pub const MAIN_SEP_STR: &str = "\\";
 pub const MAIN_SEP: char = '\\';
 
-/// # Safety
-///
-/// `bytes` must be a valid wtf8 encoded slice
-#[inline]
-unsafe fn bytes_as_os_str(bytes: &[u8]) -> &OsStr {
-    // &OsStr is layout compatible with &Slice, which is compatible with &Wtf8,
-    // which is compatible with &[u8].
-    mem::transmute(bytes)
-}
-
 #[inline]
 pub fn is_sep_byte(b: u8) -> bool {
     b == b'/' || b == b'\\'
@@ -33,12 +22,12 @@ pub fn is_verbatim_sep(b: u8) -> bool {
 
 /// Returns true if `path` looks like a lone filename.
 pub(crate) fn is_file_name(path: &OsStr) -> bool {
-    !path.bytes().iter().copied().any(is_sep_byte)
+    !path.as_os_str_bytes().iter().copied().any(is_sep_byte)
 }
 pub(crate) fn has_trailing_slash(path: &OsStr) -> bool {
-    let is_verbatim = path.bytes().starts_with(br"\\?\");
+    let is_verbatim = path.as_os_str_bytes().starts_with(br"\\?\");
     let is_separator = if is_verbatim { is_verbatim_sep } else { is_sep_byte };
-    if let Some(&c) = path.bytes().last() { is_separator(c) } else { false }
+    if let Some(&c) = path.as_os_str_bytes().last() { is_separator(c) } else { false }
 }
 
 /// Appends a suffix to a path.
@@ -60,7 +49,7 @@ impl<'a, const LEN: usize> PrefixParser<'a, LEN> {
     fn get_prefix(path: &OsStr) -> [u8; LEN] {
         let mut prefix = [0; LEN];
         // SAFETY: Only ASCII characters are modified.
-        for (i, &ch) in path.bytes().iter().take(LEN).enumerate() {
+        for (i, &ch) in path.as_os_str_bytes().iter().take(LEN).enumerate() {
             prefix[i] = if ch == b'/' { b'\\' } else { ch };
         }
         prefix
@@ -93,7 +82,7 @@ impl<'a> PrefixParserSlice<'a, '_> {
     }
 
     fn prefix_bytes(&self) -> &'a [u8] {
-        &self.path.bytes()[..self.index]
+        &self.path.as_os_str_bytes()[..self.index]
     }
 
     fn finish(self) -> &'a OsStr {
@@ -101,7 +90,7 @@ impl<'a> PrefixParserSlice<'a, '_> {
         // &[u8] and back. This is safe to do because (1) we only look at ASCII
         // contents of the encoding and (2) new &OsStr values are produced only
         // from ASCII-bounded slices of existing &OsStr values.
-        unsafe { bytes_as_os_str(&self.path.bytes()[self.index..]) }
+        unsafe { OsStr::from_os_str_bytes_unchecked(&self.path.as_os_str_bytes()[self.index..]) }
     }
 }
 
@@ -173,7 +162,7 @@ fn parse_drive(path: &OsStr) -> Option<u8> {
         drive.is_ascii_alphabetic()
     }
 
-    match path.bytes() {
+    match path.as_os_str_bytes() {
         [drive, b':', ..] if is_valid_drive_letter(drive) => Some(drive.to_ascii_uppercase()),
         _ => None,
     }
@@ -182,7 +171,7 @@ fn parse_drive(path: &OsStr) -> Option<u8> {
 // Parses a drive prefix exactly, e.g. "C:"
 fn parse_drive_exact(path: &OsStr) -> Option<u8> {
     // only parse two bytes: the drive letter and the drive separator
-    if path.bytes().get(2).map(|&x| is_sep_byte(x)).unwrap_or(true) {
+    if path.as_os_str_bytes().get(2).map(|&x| is_sep_byte(x)).unwrap_or(true) {
         parse_drive(path)
     } else {
         None
@@ -196,21 +185,26 @@ fn parse_drive_exact(path: &OsStr) -> Option<u8> {
 fn parse_next_component(path: &OsStr, verbatim: bool) -> (&OsStr, &OsStr) {
     let separator = if verbatim { is_verbatim_sep } else { is_sep_byte };
 
-    match path.bytes().iter().position(|&x| separator(x)) {
+    match path.as_os_str_bytes().iter().position(|&x| separator(x)) {
         Some(separator_start) => {
             let separator_end = separator_start + 1;
 
-            let component = &path.bytes()[..separator_start];
+            let component = &path.as_os_str_bytes()[..separator_start];
 
             // Panic safe
             // The max `separator_end` is `bytes.len()` and `bytes[bytes.len()..]` is a valid index.
-            let path = &path.bytes()[separator_end..];
+            let path = &path.as_os_str_bytes()[separator_end..];
 
             // SAFETY: `path` is a valid wtf8 encoded slice and each of the separators ('/', '\')
             // is encoded in a single byte, therefore `bytes[separator_start]` and
             // `bytes[separator_end]` must be code point boundaries and thus
             // `bytes[..separator_start]` and `bytes[separator_end..]` are valid wtf8 slices.
-            unsafe { (bytes_as_os_str(component), bytes_as_os_str(path)) }
+            unsafe {
+                (
+                    OsStr::from_os_str_bytes_unchecked(component),
+                    OsStr::from_os_str_bytes_unchecked(path),
+                )
+            }
         }
         None => (path, OsStr::new("")),
     }
@@ -329,7 +323,7 @@ pub(crate) fn absolute(path: &Path) -> io::Result<PathBuf> {
     // Verbatim paths should not be modified.
     if prefix.map(|x| x.is_verbatim()).unwrap_or(false) {
         // NULs in verbatim paths are rejected for consistency.
-        if path.bytes().contains(&0) {
+        if path.as_os_str_bytes().contains(&0) {
             return Err(io::const_io_error!(
                 io::ErrorKind::InvalidInput,
                 "strings passed to WinAPI cannot contain NULs",
diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs
index df3667c0fd7..a573a05c39c 100644
--- a/library/std/src/sys/windows/process.rs
+++ b/library/std/src/sys/windows/process.rs
@@ -395,7 +395,7 @@ fn resolve_exe<'a>(
     // Test if the file name has the `exe` extension.
     // This does a case-insensitive `ends_with`.
     let has_exe_suffix = if exe_path.len() >= EXE_SUFFIX.len() {
-        exe_path.bytes()[exe_path.len() - EXE_SUFFIX.len()..]
+        exe_path.as_os_str_bytes()[exe_path.len() - EXE_SUFFIX.len()..]
             .eq_ignore_ascii_case(EXE_SUFFIX.as_bytes())
     } else {
         false
@@ -425,7 +425,7 @@ fn resolve_exe<'a>(
         // From the `CreateProcessW` docs:
         // > If the file name does not contain an extension, .exe is appended.
         // Note that this rule only applies when searching paths.
-        let has_extension = exe_path.bytes().contains(&b'.');
+        let has_extension = exe_path.as_os_str_bytes().contains(&b'.');
 
         // Search the directories given by `search_paths`.
         let result = search_paths(parent_paths, child_paths, |mut path| {
diff --git a/library/std/src/sys_common/wtf8.rs b/library/std/src/sys_common/wtf8.rs
index ff96c35fb0b..31bb0ad25a6 100644
--- a/library/std/src/sys_common/wtf8.rs
+++ b/library/std/src/sys_common/wtf8.rs
@@ -570,7 +570,7 @@ impl Wtf8 {
     /// Since the byte slice is not checked for valid WTF-8, this functions is
     /// marked unsafe.
     #[inline]
-    unsafe fn from_bytes_unchecked(value: &[u8]) -> &Wtf8 {
+    pub unsafe fn from_bytes_unchecked(value: &[u8]) -> &Wtf8 {
         mem::transmute(value)
     }
 
@@ -614,6 +614,12 @@ impl Wtf8 {
         Wtf8CodePoints { bytes: self.bytes.iter() }
     }
 
+    /// Access raw bytes of WTF-8 data
+    #[inline]
+    pub fn as_bytes(&self) -> &[u8] {
+        &self.bytes
+    }
+
     /// Tries to convert the string to UTF-8 and return a `&str` slice.
     ///
     /// Returns `None` if the string contains surrogates.
diff --git a/library/test/src/options.rs b/library/test/src/options.rs
index 75ec0b616e1..3eaad59474a 100644
--- a/library/test/src/options.rs
+++ b/library/test/src/options.rs
@@ -16,19 +16,21 @@ pub enum ShouldPanic {
 }
 
 /// Whether should console output be colored or not
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone, Default, Debug)]
 pub enum ColorConfig {
+    #[default]
     AutoColor,
     AlwaysColor,
     NeverColor,
 }
 
 /// Format of the test results output
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
 pub enum OutputFormat {
     /// Verbose output
     Pretty,
     /// Quiet output
+    #[default]
     Terse,
     /// JSON output
     Json,
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
index 8f8778efee7..311ac175160 100644
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
@@ -58,7 +58,6 @@ dependencies = [
  "once_cell",
  "opener",
  "pretty_assertions",
- "semver",
  "serde",
  "serde_derive",
  "serde_json",
@@ -647,12 +646,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
 
 [[package]]
-name = "semver"
-version = "1.0.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
-
-[[package]]
 name = "serde"
 version = "1.0.160"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index 367c6190967..70ade776d7d 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -57,7 +57,6 @@ walkdir = "2"
 sysinfo = { version = "0.26.0", optional = true }
 clap = { version = "4.2.4", default-features = false, features = ["std", "usage", "help", "derive", "error-context"] }
 clap_complete = "4.2.2"
-semver = "1.0.17"
 
 # Solaris doesn't support flock() and thus fd-lock is not option now
 [target.'cfg(not(target_os = "solaris"))'.dependencies]
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index d75ffd4ac22..75df5345169 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -226,16 +226,13 @@ def format_build_time(duration):
 
 def default_build_triple(verbose):
     """Build triple as in LLVM"""
-    # If the user already has a host build triple with an existing `rustc`
-    # install, use their preference. This fixes most issues with Windows builds
-    # being detected as GNU instead of MSVC.
+    # If we're on Windows and have an existing `rustc` toolchain, use `rustc --version --verbose`
+    # to find our host target triple. This fixes an issue with Windows builds being detected
+    # as GNU instead of MSVC.
+    # Otherwise, detect it via `uname`
     default_encoding = sys.getdefaultencoding()
 
-    if sys.platform == 'darwin':
-        if verbose:
-            print("not using rustc detection as it is unreliable on macOS", file=sys.stderr)
-            print("falling back to auto-detect", file=sys.stderr)
-    else:
+    if platform_is_win32():
         try:
             version = subprocess.check_output(["rustc", "--version", "--verbose"],
                     stderr=subprocess.DEVNULL)
@@ -253,19 +250,17 @@ def default_build_triple(verbose):
                 print("falling back to auto-detect", file=sys.stderr)
 
     required = not platform_is_win32()
-    ostype = require(["uname", "-s"], exit=required)
-    cputype = require(['uname', '-m'], exit=required)
+    uname = require(["uname", "-smp"], exit=required)
 
     # If we do not have `uname`, assume Windows.
-    if ostype is None or cputype is None:
+    if uname is None:
         return 'x86_64-pc-windows-msvc'
 
-    ostype = ostype.decode(default_encoding)
-    cputype = cputype.decode(default_encoding)
+    kernel, cputype, processor = uname.decode(default_encoding).split()
 
     # The goal here is to come up with the same triple as LLVM would,
     # at least for the subset of platforms we're willing to target.
-    ostype_mapper = {
+    kerneltype_mapper = {
         'Darwin': 'apple-darwin',
         'DragonFly': 'unknown-dragonfly',
         'FreeBSD': 'unknown-freebsd',
@@ -275,17 +270,18 @@ def default_build_triple(verbose):
     }
 
     # Consider the direct transformation first and then the special cases
-    if ostype in ostype_mapper:
-        ostype = ostype_mapper[ostype]
-    elif ostype == 'Linux':
-        os_from_sp = subprocess.check_output(
-            ['uname', '-o']).strip().decode(default_encoding)
-        if os_from_sp == 'Android':
-            ostype = 'linux-android'
+    if kernel in kerneltype_mapper:
+        kernel = kerneltype_mapper[kernel]
+    elif kernel == 'Linux':
+        # Apple doesn't support `-o` so this can't be used in the combined
+        # uname invocation above
+        ostype = require(["uname", "-o"], exit=required).decode(default_encoding)
+        if ostype == 'Android':
+            kernel = 'linux-android'
         else:
-            ostype = 'unknown-linux-gnu'
-    elif ostype == 'SunOS':
-        ostype = 'pc-solaris'
+            kernel = 'unknown-linux-gnu'
+    elif kernel == 'SunOS':
+        kernel = 'pc-solaris'
         # On Solaris, uname -m will return a machine classification instead
         # of a cpu type, so uname -p is recommended instead.  However, the
         # output from that option is too generic for our purposes (it will
@@ -294,34 +290,34 @@ def default_build_triple(verbose):
         cputype = require(['isainfo', '-k']).decode(default_encoding)
         # sparc cpus have sun as a target vendor
         if 'sparc' in cputype:
-            ostype = 'sun-solaris'
-    elif ostype.startswith('MINGW'):
+            kernel = 'sun-solaris'
+    elif kernel.startswith('MINGW'):
         # msys' `uname` does not print gcc configuration, but prints msys
         # configuration. so we cannot believe `uname -m`:
         # msys1 is always i686 and msys2 is always x86_64.
         # instead, msys defines $MSYSTEM which is MINGW32 on i686 and
         # MINGW64 on x86_64.
-        ostype = 'pc-windows-gnu'
+        kernel = 'pc-windows-gnu'
         cputype = 'i686'
         if os.environ.get('MSYSTEM') == 'MINGW64':
             cputype = 'x86_64'
-    elif ostype.startswith('MSYS'):
-        ostype = 'pc-windows-gnu'
-    elif ostype.startswith('CYGWIN_NT'):
+    elif kernel.startswith('MSYS'):
+        kernel = 'pc-windows-gnu'
+    elif kernel.startswith('CYGWIN_NT'):
         cputype = 'i686'
-        if ostype.endswith('WOW64'):
+        if kernel.endswith('WOW64'):
             cputype = 'x86_64'
-        ostype = 'pc-windows-gnu'
-    elif sys.platform == 'win32':
+        kernel = 'pc-windows-gnu'
+    elif platform_is_win32():
         # Some Windows platforms might have a `uname` command that returns a
         # non-standard string (e.g. gnuwin32 tools returns `windows32`). In
         # these cases, fall back to using sys.platform.
         return 'x86_64-pc-windows-msvc'
     else:
-        err = "unknown OS type: {}".format(ostype)
+        err = "unknown OS type: {}".format(kernel)
         sys.exit(err)
 
-    if cputype in ['powerpc', 'riscv'] and ostype == 'unknown-freebsd':
+    if cputype in ['powerpc', 'riscv'] and kernel == 'unknown-freebsd':
         cputype = subprocess.check_output(
               ['uname', '-p']).strip().decode(default_encoding)
     cputype_mapper = {
@@ -354,24 +350,23 @@ def default_build_triple(verbose):
         cputype = cputype_mapper[cputype]
     elif cputype in {'xscale', 'arm'}:
         cputype = 'arm'
-        if ostype == 'linux-android':
-            ostype = 'linux-androideabi'
-        elif ostype == 'unknown-freebsd':
-            cputype = subprocess.check_output(
-                ['uname', '-p']).strip().decode(default_encoding)
-            ostype = 'unknown-freebsd'
+        if kernel == 'linux-android':
+            kernel = 'linux-androideabi'
+        elif kernel == 'unknown-freebsd':
+            cputype = processor
+            kernel = 'unknown-freebsd'
     elif cputype == 'armv6l':
         cputype = 'arm'
-        if ostype == 'linux-android':
-            ostype = 'linux-androideabi'
+        if kernel == 'linux-android':
+            kernel = 'linux-androideabi'
         else:
-            ostype += 'eabihf'
+            kernel += 'eabihf'
     elif cputype in {'armv7l', 'armv8l'}:
         cputype = 'armv7'
-        if ostype == 'linux-android':
-            ostype = 'linux-androideabi'
+        if kernel == 'linux-android':
+            kernel = 'linux-androideabi'
         else:
-            ostype += 'eabihf'
+            kernel += 'eabihf'
     elif cputype == 'mips':
         if sys.byteorder == 'big':
             cputype = 'mips'
@@ -387,14 +382,14 @@ def default_build_triple(verbose):
         else:
             raise ValueError('unknown byteorder: {}'.format(sys.byteorder))
         # only the n64 ABI is supported, indicate it
-        ostype += 'abi64'
+        kernel += 'abi64'
     elif cputype == 'sparc' or cputype == 'sparcv9' or cputype == 'sparc64':
         pass
     else:
         err = "unknown cpu type: {}".format(cputype)
         sys.exit(err)
 
-    return "{}-{}".format(cputype, ostype)
+    return "{}-{}".format(cputype, kernel)
 
 
 @contextlib.contextmanager
@@ -882,6 +877,12 @@ class RustBuild(object):
 
         # preserve existing RUSTFLAGS
         env.setdefault("RUSTFLAGS", "")
+        # we need to explicitly add +xgot here so that we can successfully bootstrap
+        # a usable stage1 compiler
+        # FIXME: remove this if condition on the next bootstrap bump
+        # cfg(bootstrap)
+        if self.build_triple().startswith('mips'):
+            env["RUSTFLAGS"] += " -Ctarget-feature=+xgot"
         target_features = []
         if self.get_toml("crt-static", build_section) == "true":
             target_features += ["+crt-static"]
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index cf7c6596c02..43c859b0063 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -103,11 +103,14 @@ impl RunConfig<'_> {
     }
 
     /// Return a list of crate names selected by `run.paths`.
+    #[track_caller]
     pub fn cargo_crates_in_set(&self) -> Interned<Vec<String>> {
         let mut crates = Vec::new();
         for krate in &self.paths {
             let path = krate.assert_single_path();
-            let crate_name = self.builder.crate_paths[&path.path];
+            let Some(crate_name) = self.builder.crate_paths.get(&path.path) else {
+                panic!("missing crate for path {}", path.path.display())
+            };
             crates.push(crate_name.to_string());
         }
         INTERNER.intern_list(crates)
@@ -264,7 +267,7 @@ impl PathSet {
 
     /// A convenience wrapper for Steps which know they have no aliases and all their sets contain only a single path.
     ///
-    /// This can be used with [`ShouldRun::krate`], [`ShouldRun::path`], or [`ShouldRun::alias`].
+    /// This can be used with [`ShouldRun::crate_or_deps`], [`ShouldRun::path`], or [`ShouldRun::alias`].
     #[track_caller]
     pub fn assert_single_path(&self) -> &TaskPath {
         match self {
@@ -378,7 +381,7 @@ impl StepDescription {
             eprintln!(
                 "note: if you are adding a new Step to bootstrap itself, make sure you register it with `describe!`"
             );
-            crate::detail_exit(1);
+            crate::detail_exit_macro!(1);
         }
     }
 }
@@ -430,25 +433,6 @@ impl<'a> ShouldRun<'a> {
     /// Indicates it should run if the command-line selects the given crate or
     /// any of its (local) dependencies.
     ///
-    /// Compared to `krate`, this treats the dependencies as aliases for the
-    /// same job. Generally it is preferred to use `krate`, and treat each
-    /// individual path separately. For example `./x.py test src/liballoc`
-    /// (which uses `krate`) will test just `liballoc`. However, `./x.py check
-    /// src/liballoc` (which uses `all_krates`) will check all of `libtest`.
-    /// `all_krates` should probably be removed at some point.
-    pub fn all_krates(mut self, name: &str) -> Self {
-        let mut set = BTreeSet::new();
-        for krate in self.builder.in_tree_crates(name, None) {
-            let path = krate.local_path(self.builder);
-            set.insert(TaskPath { path, kind: Some(self.kind) });
-        }
-        self.paths.insert(PathSet::Set(set));
-        self
-    }
-
-    /// Indicates it should run if the command-line selects the given crate or
-    /// any of its (local) dependencies.
-    ///
     /// `make_run` will be called a single time with all matching command-line paths.
     pub fn crate_or_deps(self, name: &str) -> Self {
         let crates = self.builder.in_tree_crates(name, None);
@@ -458,6 +442,8 @@ impl<'a> ShouldRun<'a> {
     /// Indicates it should run if the command-line selects any of the given crates.
     ///
     /// `make_run` will be called a single time with all matching command-line paths.
+    ///
+    /// Prefer [`ShouldRun::crate_or_deps`] to this function where possible.
     pub(crate) fn crates(mut self, crates: Vec<&Crate>) -> Self {
         for krate in crates {
             let path = krate.local_path(self.builder);
@@ -487,7 +473,15 @@ impl<'a> ShouldRun<'a> {
         self.paths(&[path])
     }
 
-    // multiple aliases for the same job
+    /// Multiple aliases for the same job.
+    ///
+    /// This differs from [`path`] in that multiple calls to path will end up calling `make_run`
+    /// multiple times, whereas a single call to `paths` will only ever generate a single call to
+    /// `paths`.
+    ///
+    /// This is analogous to `all_krates`, although `all_krates` is gone now. Prefer [`path`] where possible.
+    ///
+    /// [`path`]: ShouldRun::path
     pub fn paths(mut self, paths: &[&str]) -> Self {
         static SUBMODULES_PATHS: OnceCell<Vec<String>> = OnceCell::new();
 
@@ -641,12 +635,16 @@ impl Kind {
         }
     }
 
-    pub fn test_description(&self) -> &'static str {
+    pub fn description(&self) -> String {
         match self {
             Kind::Test => "Testing",
             Kind::Bench => "Benchmarking",
-            _ => panic!("not a test command: {}!", self.as_str()),
+            Kind::Doc => "Documenting",
+            Kind::Run => "Running",
+            Kind::Suggest => "Suggesting",
+            _ => return format!("{self:?}"),
         }
+        .to_owned()
     }
 }
 
@@ -689,7 +687,8 @@ impl<'a> Builder<'a> {
                 tool::Miri,
                 tool::CargoMiri,
                 llvm::Lld,
-                llvm::CrtBeginEnd
+                llvm::CrtBeginEnd,
+                tool::RustdocGUITest,
             ),
             Kind::Check | Kind::Clippy | Kind::Fix => describe!(
                 check::Std,
@@ -787,6 +786,7 @@ impl<'a> Builder<'a> {
                 doc::EditionGuide,
                 doc::StyleGuide,
                 doc::Tidy,
+                doc::Bootstrap,
             ),
             Kind::Dist => describe!(
                 dist::Docs,
@@ -1355,7 +1355,7 @@ impl<'a> Builder<'a> {
                         "error: `x.py clippy` requires a host `rustc` toolchain with the `clippy` component"
                     );
                     eprintln!("help: try `rustup component add clippy`");
-                    crate::detail_exit(1);
+                    crate::detail_exit_macro!(1);
                 });
                 if !t!(std::str::from_utf8(&output.stdout)).contains("nightly") {
                     rustflags.arg("--cfg=bootstrap");
@@ -1915,10 +1915,10 @@ impl<'a> Builder<'a> {
         }
 
         // For `cargo doc` invocations, make rustdoc print the Rust version into the docs
-        // This replaces spaces with newlines because RUSTDOCFLAGS does not
+        // This replaces spaces with tabs because RUSTDOCFLAGS does not
         // support arguments with regular spaces. Hopefully someday Cargo will
         // have space support.
-        let rust_version = self.rust_version().replace(' ', "\n");
+        let rust_version = self.rust_version().replace(' ', "\t");
         rustdocflags.arg("--crate-version").arg(&rust_version);
 
         // Environment variables *required* throughout the build
diff --git a/src/bootstrap/builder/tests.rs b/src/bootstrap/builder/tests.rs
index edca8fe9b13..d76b830b0e5 100644
--- a/src/bootstrap/builder/tests.rs
+++ b/src/bootstrap/builder/tests.rs
@@ -1,5 +1,6 @@
 use super::*;
 use crate::config::{Config, DryRun, TargetSelection};
+use crate::doc::DocumentationFormat;
 use std::thread;
 
 fn configure(cmd: &str, host: &[&str], target: &[&str]) -> Config {
@@ -66,6 +67,16 @@ macro_rules! std {
     };
 }
 
+macro_rules! doc_std {
+    ($host:ident => $target:ident, stage = $stage:literal) => {
+        doc::Std::new(
+            $stage,
+            TargetSelection::from_user(stringify!($target)),
+            DocumentationFormat::HTML,
+        )
+    };
+}
+
 macro_rules! rustc {
     ($host:ident => $target:ident, stage = $stage:literal) => {
         compile::Rustc::new(
@@ -144,6 +155,9 @@ fn alias_and_path_for_library() {
         first(cache.all::<compile::Std>()),
         &[std!(A => A, stage = 0), std!(A => A, stage = 1)]
     );
+
+    let mut cache = run_build(&["library".into(), "core".into()], configure("doc", &["A"], &["A"]));
+    assert_eq!(first(cache.all::<doc::Std>()), &[doc_std!(A => A, stage = 0)]);
 }
 
 #[test]
diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs
index b11be96cefe..f5a93854bf2 100644
--- a/src/bootstrap/check.rs
+++ b/src/bootstrap/check.rs
@@ -1,8 +1,10 @@
 //! Implementation of compiling the compiler and standard library, in "check"-based modes.
 
-use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
+use crate::builder::{crate_description, Builder, Kind, RunConfig, ShouldRun, Step};
 use crate::cache::Interned;
-use crate::compile::{add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo};
+use crate::compile::{
+    add_to_sysroot, make_run_crates, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo,
+};
 use crate::config::TargetSelection;
 use crate::tool::{prepare_tool_cargo, SourceType};
 use crate::INTERNER;
@@ -12,6 +14,12 @@ use std::path::{Path, PathBuf};
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub struct Std {
     pub target: TargetSelection,
+    /// Whether to build only a subset of crates.
+    ///
+    /// This shouldn't be used from other steps; see the comment on [`compile::Rustc`].
+    ///
+    /// [`compile::Rustc`]: crate::compile::Rustc
+    crates: Interned<Vec<String>>,
 }
 
 /// Returns args for the subcommand itself (not for cargo)
@@ -66,16 +74,23 @@ fn cargo_subcommand(kind: Kind) -> &'static str {
     }
 }
 
+impl Std {
+    pub fn new(target: TargetSelection) -> Self {
+        Self { target, crates: INTERNER.intern_list(vec![]) }
+    }
+}
+
 impl Step for Std {
     type Output = ();
     const DEFAULT: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.all_krates("sysroot").path("library")
+        run.crate_or_deps("sysroot").path("library")
     }
 
     fn make_run(run: RunConfig<'_>) {
-        run.builder.ensure(Std { target: run.target });
+        let crates = make_run_crates(&run, "library");
+        run.builder.ensure(Std { target: run.target, crates });
     }
 
     fn run(self, builder: &Builder<'_>) {
@@ -97,7 +112,14 @@ impl Step for Std {
             cargo.arg("--lib");
         }
 
-        let _guard = builder.msg_check("library artifacts", target);
+        for krate in &*self.crates {
+            cargo.arg("-p").arg(krate);
+        }
+
+        let _guard = builder.msg_check(
+            format_args!("library artifacts{}", crate_description(&self.crates)),
+            target,
+        );
         run_cargo(
             builder,
             cargo,
@@ -117,7 +139,8 @@ impl Step for Std {
         }
 
         // don't run on std twice with x.py clippy
-        if builder.kind == Kind::Clippy {
+        // don't check test dependencies if we haven't built libtest
+        if builder.kind == Kind::Clippy || !self.crates.is_empty() {
             return;
         }
 
@@ -147,8 +170,8 @@ impl Step for Std {
         // Explicitly pass -p for all dependencies krates -- this will force cargo
         // to also check the tests/benches/examples for these crates, rather
         // than just the leaf crate.
-        for krate in builder.in_tree_crates("test", Some(target)) {
-            cargo.arg("-p").arg(krate.name);
+        for krate in &*self.crates {
+            cargo.arg("-p").arg(krate);
         }
 
         let _guard = builder.msg_check("library test/bench/example targets", target);
@@ -167,6 +190,22 @@ impl Step for Std {
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub struct Rustc {
     pub target: TargetSelection,
+    /// Whether to build only a subset of crates.
+    ///
+    /// This shouldn't be used from other steps; see the comment on [`compile::Rustc`].
+    ///
+    /// [`compile::Rustc`]: crate::compile::Rustc
+    crates: Interned<Vec<String>>,
+}
+
+impl Rustc {
+    pub fn new(target: TargetSelection, builder: &Builder<'_>) -> Self {
+        let mut crates = vec![];
+        for krate in builder.in_tree_crates("rustc-main", None) {
+            crates.push(krate.name.to_string());
+        }
+        Self { target, crates: INTERNER.intern_list(crates) }
+    }
 }
 
 impl Step for Rustc {
@@ -175,11 +214,12 @@ impl Step for Rustc {
     const DEFAULT: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.all_krates("rustc-main").path("compiler")
+        run.crate_or_deps("rustc-main").path("compiler")
     }
 
     fn make_run(run: RunConfig<'_>) {
-        run.builder.ensure(Rustc { target: run.target });
+        let crates = make_run_crates(&run, "compiler");
+        run.builder.ensure(Rustc { target: run.target, crates });
     }
 
     /// Builds the compiler.
@@ -200,7 +240,7 @@ impl Step for Rustc {
             builder.ensure(crate::compile::Std::new(compiler, compiler.host));
             builder.ensure(crate::compile::Std::new(compiler, target));
         } else {
-            builder.ensure(Std { target });
+            builder.ensure(Std::new(target));
         }
 
         let mut cargo = builder.cargo(
@@ -218,14 +258,17 @@ impl Step for Rustc {
             cargo.arg("--all-targets");
         }
 
-        // Explicitly pass -p for all compiler krates -- this will force cargo
+        // Explicitly pass -p for all compiler crates -- this will force cargo
         // to also check the tests/benches/examples for these crates, rather
         // than just the leaf crate.
-        for krate in builder.in_tree_crates("rustc-main", Some(target)) {
-            cargo.arg("-p").arg(krate.name);
+        for krate in &*self.crates {
+            cargo.arg("-p").arg(krate);
         }
 
-        let _guard = builder.msg_check("compiler artifacts", target);
+        let _guard = builder.msg_check(
+            format_args!("compiler artifacts{}", crate_description(&self.crates)),
+            target,
+        );
         run_cargo(
             builder,
             cargo,
@@ -268,7 +311,7 @@ impl Step for CodegenBackend {
         let target = self.target;
         let backend = self.backend;
 
-        builder.ensure(Rustc { target });
+        builder.ensure(Rustc::new(target, builder));
 
         let mut cargo = builder.cargo(
             compiler,
@@ -318,7 +361,7 @@ impl Step for RustAnalyzer {
         let compiler = builder.compiler(builder.top_stage, builder.config.build);
         let target = self.target;
 
-        builder.ensure(Std { target });
+        builder.ensure(Std::new(target));
 
         let mut cargo = prepare_tool_cargo(
             builder,
@@ -386,7 +429,7 @@ macro_rules! tool_check_step {
                 let compiler = builder.compiler(builder.top_stage, builder.config.build);
                 let target = self.target;
 
-                builder.ensure(Rustc { target });
+                builder.ensure(Rustc::new(target, builder));
 
                 let mut cargo = prepare_tool_cargo(
                     builder,
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 33addb90da3..1c66c00eda7 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -48,6 +48,17 @@ impl Std {
     }
 }
 
+/// Given an `alias` selected by the `Step` and the paths passed on the command line,
+/// return a list of the crates that should be built.
+///
+/// Normally, people will pass *just* `library` if they pass it.
+/// But it's possible (although strange) to pass something like `library std core`.
+/// Build all crates anyway, as if they hadn't passed the other args.
+pub(crate) fn make_run_crates(run: &RunConfig<'_>, alias: &str) -> Interned<Vec<String>> {
+    let has_alias = run.paths.iter().any(|set| set.assert_single_path().path.ends_with(alias));
+    if has_alias { Default::default() } else { run.cargo_crates_in_set() }
+}
+
 impl Step for Std {
     type Output = ();
     const DEFAULT: bool = true;
@@ -62,16 +73,10 @@ impl Step for Std {
     }
 
     fn make_run(run: RunConfig<'_>) {
-        // Normally, people will pass *just* library if they pass it.
-        // But it's possible (although strange) to pass something like `library std core`.
-        // Build all crates anyway, as if they hadn't passed the other args.
-        let has_library =
-            run.paths.iter().any(|set| set.assert_single_path().path.ends_with("library"));
-        let crates = if has_library { Default::default() } else { run.cargo_crates_in_set() };
         run.builder.ensure(Std {
             compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
             target: run.target,
-            crates,
+            crates: make_run_crates(&run, "library"),
         });
     }
 
@@ -615,6 +620,8 @@ impl Step for Rustc {
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
         let mut crates = run.builder.in_tree_crates("rustc-main", None);
         for (i, krate) in crates.iter().enumerate() {
+            // We can't allow `build rustc` as an alias for this Step, because that's reserved by `Assemble`.
+            // Ideally Assemble would use `build compiler` instead, but that seems too confusing to be worth the breaking change.
             if krate.name == "rustc-main" {
                 crates.swap_remove(i);
                 break;
@@ -1679,7 +1686,7 @@ pub fn run_cargo(
     });
 
     if !ok {
-        crate::detail_exit(1);
+        crate::detail_exit_macro!(1);
     }
 
     // Ok now we need to actually find all the files listed in `toplevel`. We've
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index e192cda9a9a..45ad1547eb7 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -23,8 +23,8 @@ use crate::channel::{self, GitInfo};
 pub use crate::flags::Subcommand;
 use crate::flags::{Color, Flags, Warnings};
 use crate::util::{exe, output, t};
+use build_helper::detail_exit_macro;
 use once_cell::sync::OnceCell;
-use semver::Version;
 use serde::{Deserialize, Deserializer};
 use serde_derive::Deserialize;
 
@@ -580,7 +580,7 @@ macro_rules! define_config {
                                         panic!("overriding existing option")
                                     } else {
                                         eprintln!("overriding existing option: `{}`", stringify!($field));
-                                        crate::detail_exit(2);
+                                        detail_exit_macro!(2);
                                     }
                                 } else {
                                     self.$field = other.$field;
@@ -679,7 +679,7 @@ impl<T> Merge for Option<T> {
                             panic!("overriding existing option")
                         } else {
                             eprintln!("overriding existing option");
-                            crate::detail_exit(2);
+                            detail_exit_macro!(2);
                         }
                     } else {
                         *self = other;
@@ -945,7 +945,7 @@ impl Config {
                 .and_then(|table: toml::Value| TomlConfig::deserialize(table))
                 .unwrap_or_else(|err| {
                     eprintln!("failed to parse TOML configuration '{}': {err}", file.display());
-                    crate::detail_exit(2);
+                    detail_exit_macro!(2);
                 })
         }
         Self::parse_inner(args, get_toml)
@@ -979,7 +979,7 @@ impl Config {
             eprintln!(
                 "Cannot use both `llvm_bolt_profile_generate` and `llvm_bolt_profile_use` at the same time"
             );
-            crate::detail_exit(1);
+            detail_exit_macro!(1);
         }
 
         // Infer the rest of the configuration.
@@ -1095,7 +1095,7 @@ impl Config {
                 }
             }
             eprintln!("failed to parse override `{option}`: `{err}");
-            crate::detail_exit(2)
+            detail_exit_macro!(2)
         }
         toml.merge(override_toml, ReplaceOpt::Override);
 
@@ -1118,7 +1118,6 @@ impl Config {
             config.download_beta_toolchain();
             config.out.join(config.build.triple).join("stage0/bin/rustc")
         });
-
         config.initial_cargo = build
             .cargo
             .map(|cargo| {
@@ -1780,42 +1779,6 @@ impl Config {
         self.rust_codegen_backends.get(0).cloned()
     }
 
-    pub fn check_build_rustc_version(&self) {
-        if self.dry_run() {
-            return;
-        }
-
-        // check rustc version is same or lower with 1 apart from the building one
-        let mut cmd = Command::new(&self.initial_rustc);
-        cmd.arg("--version");
-        let rustc_output = output(&mut cmd)
-            .lines()
-            .next()
-            .unwrap()
-            .split(' ')
-            .nth(1)
-            .unwrap()
-            .split('-')
-            .next()
-            .unwrap()
-            .to_owned();
-        let rustc_version = Version::parse(&rustc_output.trim()).unwrap();
-        let source_version =
-            Version::parse(&fs::read_to_string(self.src.join("src/version")).unwrap().trim())
-                .unwrap();
-        if !(source_version == rustc_version
-            || (source_version.major == rustc_version.major
-                && source_version.minor == rustc_version.minor + 1))
-        {
-            let prev_version = format!("{}.{}.x", source_version.major, source_version.minor - 1);
-            eprintln!(
-                "Unexpected rustc version: {}, we should use {}/{} to build source with {}",
-                rustc_version, prev_version, source_version, source_version
-            );
-            crate::detail_exit(1);
-        }
-    }
-
     /// Returns the commit to download, or `None` if we shouldn't download CI artifacts.
     fn download_ci_rustc_commit(&self, download_rustc: Option<StringOrBool>) -> Option<String> {
         // If `download-rustc` is not set, default to rebuilding.
@@ -1848,7 +1811,7 @@ impl Config {
             println!("help: maybe your repository history is too shallow?");
             println!("help: consider disabling `download-rustc`");
             println!("help: or fetch enough history to include one upstream commit");
-            crate::detail_exit(1);
+            crate::detail_exit_macro!(1);
         }
 
         // Warn if there were changes to the compiler or standard library since the ancestor commit.
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index b49845386da..46fc5b80e99 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -106,11 +106,7 @@ impl Step for JsonDocs {
     /// Builds the `rust-docs-json` installer component.
     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
         let host = self.host;
-        builder.ensure(crate::doc::Std {
-            stage: builder.top_stage,
-            target: host,
-            format: DocumentationFormat::JSON,
-        });
+        builder.ensure(crate::doc::Std::new(builder.top_stage, host, DocumentationFormat::JSON));
 
         let dest = "share/doc/rust/json";
 
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 8f5d9bb66e1..3de85c91516 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -7,7 +7,6 @@
 //! Everything here is basically just a shim around calling either `rustbook` or
 //! `rustdoc`.
 
-use std::ffi::OsStr;
 use std::fs;
 use std::io;
 use std::path::{Path, PathBuf};
@@ -16,6 +15,7 @@ use crate::builder::crate_description;
 use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step};
 use crate::cache::{Interned, INTERNER};
 use crate::compile;
+use crate::compile::make_run_crates;
 use crate::config::{Config, TargetSelection};
 use crate::tool::{self, prepare_tool_cargo, SourceType, Tool};
 use crate::util::{symlink_dir, t, up_to_date};
@@ -87,15 +87,6 @@ book!(
     StyleGuide, "src/doc/style-guide", "style-guide";
 );
 
-// "library/std" -> ["library", "std"]
-//
-// Used for deciding whether a particular step is one requested by the user on
-// the `x.py doc` command line, which determines whether `--open` will open that
-// page.
-pub(crate) fn components_simplified(path: &PathBuf) -> Vec<&str> {
-    path.iter().map(|component| component.to_str().unwrap_or("???")).collect()
-}
-
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
 pub struct UnstableBook {
     target: TargetSelection,
@@ -425,11 +416,18 @@ impl Step for SharedAssets {
     }
 }
 
-#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
 pub struct Std {
     pub stage: u32,
     pub target: TargetSelection,
     pub format: DocumentationFormat,
+    crates: Interned<Vec<String>>,
+}
+
+impl Std {
+    pub(crate) fn new(stage: u32, target: TargetSelection, format: DocumentationFormat) -> Self {
+        Std { stage, target, format, crates: INTERNER.intern_list(vec![]) }
+    }
 }
 
 impl Step for Std {
@@ -438,7 +436,7 @@ impl Step for Std {
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
         let builder = run.builder;
-        run.all_krates("sysroot").path("library").default_condition(builder.config.docs)
+        run.crate_or_deps("sysroot").path("library").default_condition(builder.config.docs)
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -450,6 +448,7 @@ impl Step for Std {
             } else {
                 DocumentationFormat::HTML
             },
+            crates: make_run_crates(&run, "library"),
         });
     }
 
@@ -457,7 +456,7 @@ impl Step for Std {
     ///
     /// This will generate all documentation for the standard library and its
     /// dependencies. This is largely just a wrapper around `cargo doc`.
-    fn run(self, builder: &Builder<'_>) {
+    fn run(mut self, builder: &Builder<'_>) {
         let stage = self.stage;
         let target = self.target;
         let out = match self.format {
@@ -471,41 +470,24 @@ impl Step for Std {
             builder.ensure(SharedAssets { target: self.target });
         }
 
-        let index_page = builder.src.join("src/doc/index.md").into_os_string();
+        let index_page = builder
+            .src
+            .join("src/doc/index.md")
+            .into_os_string()
+            .into_string()
+            .expect("non-utf8 paths are unsupported");
         let mut extra_args = match self.format {
-            DocumentationFormat::HTML => vec![
-                OsStr::new("--markdown-css"),
-                OsStr::new("rust.css"),
-                OsStr::new("--markdown-no-toc"),
-                OsStr::new("--index-page"),
-                &index_page,
-            ],
-            DocumentationFormat::JSON => vec![OsStr::new("--output-format"), OsStr::new("json")],
+            DocumentationFormat::HTML => {
+                vec!["--markdown-css", "rust.css", "--markdown-no-toc", "--index-page", &index_page]
+            }
+            DocumentationFormat::JSON => vec!["--output-format", "json"],
         };
 
         if !builder.config.docs_minification {
-            extra_args.push(OsStr::new("--disable-minification"));
+            extra_args.push("--disable-minification");
         }
 
-        let requested_crates = builder
-            .paths
-            .iter()
-            .map(components_simplified)
-            .filter_map(|path| {
-                if path.len() >= 2 && path.get(0) == Some(&"library") {
-                    // single crate
-                    Some(path[1].to_owned())
-                } else if !path.is_empty() {
-                    // ??
-                    Some(path[0].to_owned())
-                } else {
-                    // all library crates
-                    None
-                }
-            })
-            .collect::<Vec<_>>();
-
-        doc_std(builder, self.format, stage, target, &out, &extra_args, &requested_crates);
+        doc_std(builder, self.format, stage, target, &out, &extra_args, &self.crates);
 
         // Don't open if the format is json
         if let DocumentationFormat::JSON = self.format {
@@ -514,7 +496,11 @@ impl Step for Std {
 
         // Look for library/std, library/core etc in the `x.py doc` arguments and
         // open the corresponding rendered docs.
-        for requested_crate in requested_crates {
+        if self.crates.is_empty() {
+            self.crates = INTERNER.intern_list(vec!["library".to_owned()]);
+        };
+
+        for requested_crate in &*self.crates {
             if requested_crate == "library" {
                 // For `x.py doc library --open`, open `std` by default.
                 let index = out.join("std").join("index.html");
@@ -538,7 +524,7 @@ impl Step for Std {
 /// or remote link.
 const STD_PUBLIC_CRATES: [&str; 5] = ["core", "alloc", "std", "proc_macro", "test"];
 
-#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
 pub enum DocumentationFormat {
     HTML,
     JSON,
@@ -563,24 +549,22 @@ fn doc_std(
     stage: u32,
     target: TargetSelection,
     out: &Path,
-    extra_args: &[&OsStr],
+    extra_args: &[&str],
     requested_crates: &[String],
 ) {
-    builder.info(&format!(
-        "Documenting{} stage{} library ({}) in {} format",
-        crate_description(requested_crates),
-        stage,
-        target,
-        format.as_str()
-    ));
     if builder.no_std(target) == Some(true) {
         panic!(
             "building std documentation for no_std target {target} is not supported\n\
-             Set `docs = false` in the config to disable documentation."
+             Set `docs = false` in the config to disable documentation, or pass `--exclude doc::library`."
         );
     }
+
     let compiler = builder.compiler(stage, builder.config.build);
 
+    let description =
+        format!("library{} in {} format", crate_description(&requested_crates), format.as_str());
+    let _guard = builder.msg(Kind::Doc, stage, &description, compiler.host, target);
+
     let target_doc_dir_name = if format == DocumentationFormat::JSON { "json-doc" } else { "doc" };
     let target_dir =
         builder.stage_out(compiler, Mode::Std).join(target.triple).join(target_doc_dir_name);
@@ -590,35 +574,42 @@ fn doc_std(
     // as a function parameter.
     let out_dir = target_dir.join(target.triple).join("doc");
 
-    let run_cargo_rustdoc_for = |package: &str| {
-        let mut cargo = builder.cargo(compiler, Mode::Std, SourceType::InTree, target, "rustdoc");
-        compile::std_cargo(builder, target, compiler.stage, &mut cargo);
-        cargo
-            .arg("--target-dir")
-            .arg(&*target_dir.to_string_lossy())
-            .arg("-p")
-            .arg(package)
-            .arg("-Zskip-rustdoc-fingerprint")
-            .arg("--")
-            .arg("-Z")
-            .arg("unstable-options")
-            .arg("--resource-suffix")
-            .arg(&builder.version)
-            .args(extra_args);
-        if builder.config.library_docs_private_items {
-            cargo.arg("--document-private-items").arg("--document-hidden-items");
-        }
-        builder.run(&mut cargo.into());
+    let mut cargo = builder.cargo(compiler, Mode::Std, SourceType::InTree, target, "doc");
+    compile::std_cargo(builder, target, compiler.stage, &mut cargo);
+    cargo
+        .arg("--no-deps")
+        .arg("--target-dir")
+        .arg(&*target_dir.to_string_lossy())
+        .arg("-Zskip-rustdoc-fingerprint")
+        .rustdocflag("-Z")
+        .rustdocflag("unstable-options")
+        .rustdocflag("--resource-suffix")
+        .rustdocflag(&builder.version);
+    for arg in extra_args {
+        cargo.rustdocflag(arg);
+    }
+
+    if builder.config.library_docs_private_items {
+        cargo.rustdocflag("--document-private-items").rustdocflag("--document-hidden-items");
+    }
+
+    // HACK: because we use `--manifest-path library/sysroot/Cargo.toml`, cargo thinks we only want to document that specific crate, not its dependencies.
+    // Override its default.
+    let built_crates = if requested_crates.is_empty() {
+        builder
+            .in_tree_crates("sysroot", None)
+            .into_iter()
+            .map(|krate| krate.name.to_string())
+            .collect()
+    } else {
+        requested_crates.to_vec()
     };
 
-    for krate in STD_PUBLIC_CRATES {
-        run_cargo_rustdoc_for(krate);
-        if requested_crates.iter().any(|p| p == krate) {
-            // No need to document more of the libraries if we have the one we want.
-            break;
-        }
+    for krate in built_crates {
+        cargo.arg("-p").arg(krate);
     }
 
+    builder.run(&mut cargo.into());
     builder.cp_r(&out_dir, &out);
 }
 
@@ -626,6 +617,28 @@ fn doc_std(
 pub struct Rustc {
     pub stage: u32,
     pub target: TargetSelection,
+    crates: Interned<Vec<String>>,
+}
+
+impl Rustc {
+    pub(crate) fn new(stage: u32, target: TargetSelection, builder: &Builder<'_>) -> Self {
+        // Find dependencies for top level crates.
+        let root_crates = vec![
+            INTERNER.intern_str("rustc_driver"),
+            INTERNER.intern_str("rustc_codegen_llvm"),
+            INTERNER.intern_str("rustc_codegen_ssa"),
+        ];
+        let crates: Vec<_> = root_crates
+            .iter()
+            .flat_map(|krate| {
+                builder
+                    .in_tree_crates(krate, Some(target))
+                    .into_iter()
+                    .map(|krate| krate.name.to_string())
+            })
+            .collect();
+        Self { stage, target, crates: INTERNER.intern_list(crates) }
+    }
 }
 
 impl Step for Rustc {
@@ -641,7 +654,11 @@ impl Step for Rustc {
     }
 
     fn make_run(run: RunConfig<'_>) {
-        run.builder.ensure(Rustc { stage: run.builder.top_stage, target: run.target });
+        run.builder.ensure(Rustc {
+            stage: run.builder.top_stage,
+            target: run.target,
+            crates: make_run_crates(&run, "compiler"),
+        });
     }
 
     /// Generates compiler documentation.
@@ -654,15 +671,6 @@ impl Step for Rustc {
         let stage = self.stage;
         let target = self.target;
 
-        let paths = builder
-            .paths
-            .iter()
-            .filter(|path| {
-                let components = components_simplified(path);
-                components.len() >= 2 && components[0] == "compiler"
-            })
-            .collect::<Vec<_>>();
-
         // This is the intended out directory for compiler documentation.
         let out = builder.compiler_doc_out(target);
         t!(fs::create_dir_all(&out));
@@ -672,7 +680,13 @@ impl Step for Rustc {
         let compiler = builder.compiler(stage, builder.config.build);
         builder.ensure(compile::Std::new(compiler, builder.config.build));
 
-        builder.info(&format!("Documenting stage{} compiler ({})", stage, target));
+        let _guard = builder.msg(
+            Kind::Doc,
+            stage,
+            &format!("compiler{}", crate_description(&self.crates)),
+            compiler.host,
+            target,
+        );
 
         // This uses a shared directory so that librustdoc documentation gets
         // correctly built and merged with the rustc documentation. This is
@@ -710,22 +724,8 @@ impl Step for Rustc {
         cargo.rustdocflag("--extern-html-root-url");
         cargo.rustdocflag("ena=https://docs.rs/ena/latest/");
 
-        let root_crates = if paths.is_empty() {
-            vec![
-                INTERNER.intern_str("rustc_driver"),
-                INTERNER.intern_str("rustc_codegen_llvm"),
-                INTERNER.intern_str("rustc_codegen_ssa"),
-            ]
-        } else {
-            paths.into_iter().map(|p| builder.crate_paths[p]).collect()
-        };
-        // Find dependencies for top level crates.
-        let compiler_crates = root_crates.iter().flat_map(|krate| {
-            builder.in_tree_crates(krate, Some(target)).into_iter().map(|krate| krate.name)
-        });
-
         let mut to_open = None;
-        for krate in compiler_crates {
+        for krate in &*self.crates {
             // Create all crate output directories first to make sure rustdoc uses
             // relative links.
             // FIXME: Cargo should probably do this itself.
@@ -785,7 +785,7 @@ macro_rules! tool_doc {
 
                 if true $(&& $rustc_tool)? {
                     // Build rustc docs so that we generate relative links.
-                    builder.ensure(Rustc { stage, target });
+                    builder.ensure(Rustc::new(stage, target, builder));
 
                     // Rustdoc needs the rustc sysroot available to build.
                     // FIXME: is there a way to only ensure `check::Rustc` here? Last time I tried it failed
@@ -839,6 +839,8 @@ macro_rules! tool_doc {
                 )+
 
                 cargo.rustdocflag("--document-private-items");
+                // Since we always pass --document-private-items, there's no need to warn about linking to private items.
+                cargo.rustdocflag("-Arustdoc::private-intra-doc-links");
                 cargo.rustdocflag("--enable-index-page");
                 cargo.rustdocflag("--show-type-layout");
                 cargo.rustdocflag("--generate-link-to-definition");
@@ -882,7 +884,8 @@ tool_doc!(
         // "cargo-credential-wincred",
     ]
 );
-tool_doc!(Tidy, "tidy", "src/tools/tidy", ["tidy"]);
+tool_doc!(Tidy, "tidy", "src/tools/tidy", rustc_tool = false, ["tidy"]);
+tool_doc!(Bootstrap, "bootstrap", "src/bootstrap", rustc_tool = false, ["bootstrap"]);
 
 #[derive(Ord, PartialOrd, Debug, Copy, Clone, Hash, PartialEq, Eq)]
 pub struct ErrorIndex {
diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs
index 25df5b2573b..12780df2175 100644
--- a/src/bootstrap/download.rs
+++ b/src/bootstrap/download.rs
@@ -7,6 +7,7 @@ use std::{
     process::{Command, Stdio},
 };
 
+use build_helper::util::try_run;
 use once_cell::sync::OnceCell;
 use xz2::bufread::XzDecoder;
 
@@ -14,7 +15,7 @@ use crate::{
     config::RustfmtMetadata,
     llvm::detect_llvm_sha,
     t,
-    util::{check_run, exe, program_out_of_date, try_run},
+    util::{check_run, exe, program_out_of_date},
     Config,
 };
 
@@ -123,7 +124,7 @@ impl Config {
     /// This is only required on NixOS and uses the PatchELF utility to
     /// change the interpreter/RPATH of ELF executables.
     ///
-    /// Please see https://nixos.org/patchelf.html for more information
+    /// Please see <https://nixos.org/patchelf.html> for more information
     fn fix_bin_or_dylib(&self, fname: &Path) {
         assert_eq!(SHOULD_FIX_BINS_AND_DYLIBS.get(), Some(&true));
         println!("attempting to patch {}", fname.display());
@@ -245,7 +246,7 @@ impl Config {
             if !help_on_error.is_empty() {
                 eprintln!("{}", help_on_error);
             }
-            crate::detail_exit(1);
+            crate::detail_exit_macro!(1);
         }
     }
 
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index 80e71577798..dc05f47ee9c 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -193,7 +193,7 @@ impl Flags {
             } else {
                 panic!("No paths available for subcommand `{}`", subcommand.as_str());
             }
-            crate::detail_exit(0);
+            crate::detail_exit_macro!(0);
         }
 
         Flags::parse_from(it)
@@ -538,7 +538,7 @@ pub fn get_completion<G: clap_complete::Generator>(shell: G, path: &Path) -> Opt
     } else {
         std::fs::read_to_string(path).unwrap_or_else(|_| {
             eprintln!("couldn't read {}", path.display());
-            crate::detail_exit(1)
+            crate::detail_exit_macro!(1)
         })
     };
     let mut buf = Vec::new();
diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs
index d8d3f300a35..ebf068b2cb1 100644
--- a/src/bootstrap/format.rs
+++ b/src/bootstrap/format.rs
@@ -40,7 +40,7 @@ fn rustfmt(src: &Path, rustfmt: &Path, paths: &[PathBuf], check: bool) -> impl F
                         code, run `./x.py fmt` instead.",
                 cmd_debug,
             );
-            crate::detail_exit(1);
+            crate::detail_exit_macro!(1);
         }
         true
     }
@@ -196,7 +196,7 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) {
 
     let rustfmt_path = build.initial_rustfmt().unwrap_or_else(|| {
         eprintln!("./x.py fmt is not supported on this channel");
-        crate::detail_exit(1);
+        crate::detail_exit_macro!(1);
     });
     assert!(rustfmt_path.exists(), "{}", rustfmt_path.display());
     let src = build.src.clone();
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 6ee50ee6573..a1aaee68c62 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -27,6 +27,7 @@ use std::process::{Command, Stdio};
 use std::str;
 
 use build_helper::ci::{gha, CiEnv};
+use build_helper::detail_exit_macro;
 use channel::GitInfo;
 use config::{DryRun, Target};
 use filetime::FileTime;
@@ -414,7 +415,6 @@ impl Build {
                 bootstrap_out.display()
             )
         }
-        config.check_build_rustc_version();
 
         if rust_info.is_from_tarball() && config.description.is_none() {
             config.description = Some("built from a source tarball".to_owned());
@@ -700,7 +700,7 @@ impl Build {
             for failure in failures.iter() {
                 eprintln!("  - {}\n", failure);
             }
-            detail_exit(1);
+            detail_exit_macro!(1);
         }
 
         #[cfg(feature = "build-metrics")]
@@ -1011,6 +1011,8 @@ impl Build {
     }
 
     /// Return a `Group` guard for a [`Step`] that is built for each `--stage`.
+    ///
+    /// [`Step`]: crate::builder::Step
     fn msg(
         &self,
         action: impl Into<Kind>,
@@ -1019,8 +1021,8 @@ impl Build {
         host: impl Into<Option<TargetSelection>>,
         target: impl Into<Option<TargetSelection>>,
     ) -> Option<gha::Group> {
-        let action = action.into();
-        let msg = |fmt| format!("{action:?}ing stage{stage} {what}{fmt}");
+        let action = action.into().description();
+        let msg = |fmt| format!("{action} stage{stage} {what}{fmt}");
         let msg = if let Some(target) = target.into() {
             let host = host.into().unwrap();
             if host == target {
@@ -1035,6 +1037,8 @@ impl Build {
     }
 
     /// Return a `Group` guard for a [`Step`] that is only built once and isn't affected by `--stage`.
+    ///
+    /// [`Step`]: crate::builder::Step
     fn msg_unstaged(
         &self,
         action: impl Into<Kind>,
@@ -1479,7 +1483,7 @@ impl Build {
                 "Error: Unable to find the stamp file {}, did you try to keep a nonexistent build stage?",
                 stamp.display()
             );
-            crate::detail_exit(1);
+            crate::detail_exit_macro!(1);
         }
 
         let mut paths = Vec::new();
@@ -1671,7 +1675,7 @@ Alternatively, set `download-ci-llvm = true` in that `[llvm]` section
 to download LLVM rather than building it.
 "
                 );
-                detail_exit(1);
+                detail_exit_macro!(1);
             }
         }
 
@@ -1736,18 +1740,6 @@ fn chmod(path: &Path, perms: u32) {
 #[cfg(windows)]
 fn chmod(_path: &Path, _perms: u32) {}
 
-/// If code is not 0 (successful exit status), exit status is 101 (rust's default error code.)
-/// 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) {
-        panic!("status code: {}", code);
-    } else {
-        // otherwise,exit with provided status code
-        std::process::exit(code);
-    }
-}
-
 impl Compiler {
     pub fn with_stage(mut self, stage: u32) -> Compiler {
         self.stage = stage;
diff --git a/src/bootstrap/llvm.rs b/src/bootstrap/llvm.rs
index 040a12f5d10..3fd0cca40e5 100644
--- a/src/bootstrap/llvm.rs
+++ b/src/bootstrap/llvm.rs
@@ -1017,7 +1017,7 @@ fn supported_sanitizers(
         "x86_64-unknown-illumos" => common_libs("illumos", "x86_64", &["asan"]),
         "x86_64-pc-solaris" => common_libs("solaris", "x86_64", &["asan"]),
         "x86_64-unknown-linux-gnu" => {
-            common_libs("linux", "x86_64", &["asan", "lsan", "msan", "tsan"])
+            common_libs("linux", "x86_64", &["asan", "lsan", "msan", "safestack", "tsan"])
         }
         "x86_64-unknown-linux-musl" => {
             common_libs("linux", "x86_64", &["asan", "lsan", "msan", "tsan"])
diff --git a/src/bootstrap/metrics.rs b/src/bootstrap/metrics.rs
index e19d56ccd6a..5990f33b9bc 100644
--- a/src/bootstrap/metrics.rs
+++ b/src/bootstrap/metrics.rs
@@ -14,6 +14,25 @@ use std::io::BufWriter;
 use std::time::{Duration, Instant, SystemTime};
 use sysinfo::{CpuExt, System, SystemExt};
 
+// Update this number whenever a breaking change is made to the build metrics.
+//
+// The output format is versioned for two reasons:
+//
+// - The metadata is intended to be consumed by external tooling, and exposing a format version
+//   helps the tools determine whether they're compatible with a metrics file.
+//
+// - If a developer enables build metrics in their local checkout, making a breaking change to the
+//   metrics format would result in a hard-to-diagnose error message when an existing metrics file
+//   is not compatible with the new changes. With a format version number, bootstrap can discard
+//   incompatible metrics files instead of appending metrics to them.
+//
+// Version changelog:
+//
+// - v0: initial version
+// - v1: replaced JsonNode::Test with JsonNode::TestSuite
+//
+const CURRENT_FORMAT_VERSION: usize = 1;
+
 pub(crate) struct BuildMetrics {
     state: RefCell<MetricsState>,
 }
@@ -57,7 +76,7 @@ impl BuildMetrics {
             duration_excluding_children_sec: Duration::ZERO,
 
             children: Vec::new(),
-            tests: Vec::new(),
+            test_suites: Vec::new(),
         });
     }
 
@@ -84,6 +103,17 @@ impl BuildMetrics {
         }
     }
 
+    pub(crate) fn begin_test_suite(&self, metadata: TestSuiteMetadata, builder: &Builder<'_>) {
+        // Do not record dry runs, as they'd be duplicates of the actual steps.
+        if builder.config.dry_run() {
+            return;
+        }
+
+        let mut state = self.state.borrow_mut();
+        let step = state.running_steps.last_mut().unwrap();
+        step.test_suites.push(TestSuite { metadata, tests: Vec::new() });
+    }
+
     pub(crate) fn record_test(&self, name: &str, outcome: TestOutcome, builder: &Builder<'_>) {
         // Do not record dry runs, as they'd be duplicates of the actual steps.
         if builder.config.dry_run() {
@@ -91,12 +121,13 @@ impl BuildMetrics {
         }
 
         let mut state = self.state.borrow_mut();
-        state
-            .running_steps
-            .last_mut()
-            .unwrap()
-            .tests
-            .push(Test { name: name.to_string(), outcome });
+        let step = state.running_steps.last_mut().unwrap();
+
+        if let Some(test_suite) = step.test_suites.last_mut() {
+            test_suite.tests.push(Test { name: name.to_string(), outcome });
+        } else {
+            panic!("metrics.record_test() called without calling metrics.begin_test_suite() first");
+        }
     }
 
     fn collect_stats(&self, state: &mut MetricsState) {
@@ -131,7 +162,20 @@ impl BuildMetrics {
         // Some of our CI builds consist of multiple independent CI invocations. Ensure all the
         // previous invocations are still present in the resulting file.
         let mut invocations = match std::fs::read(&dest) {
-            Ok(contents) => t!(serde_json::from_slice::<JsonRoot>(&contents)).invocations,
+            Ok(contents) => {
+                // We first parse just the format_version field to have the check succeed even if
+                // the rest of the contents are not valid anymore.
+                let version: OnlyFormatVersion = t!(serde_json::from_slice(&contents));
+                if version.format_version == CURRENT_FORMAT_VERSION {
+                    t!(serde_json::from_slice::<JsonRoot>(&contents)).invocations
+                } else {
+                    println!(
+                        "warning: overriding existing build/metrics.json, as it's not \
+                         compatible with build metrics format version {CURRENT_FORMAT_VERSION}."
+                    );
+                    Vec::new()
+                }
+            }
             Err(err) => {
                 if err.kind() != std::io::ErrorKind::NotFound {
                     panic!("failed to open existing metrics file at {}: {err}", dest.display());
@@ -149,7 +193,7 @@ impl BuildMetrics {
             children: steps.into_iter().map(|step| self.prepare_json_step(step)).collect(),
         });
 
-        let json = JsonRoot { system_stats, invocations };
+        let json = JsonRoot { format_version: CURRENT_FORMAT_VERSION, system_stats, invocations };
 
         t!(std::fs::create_dir_all(dest.parent().unwrap()));
         let mut file = BufWriter::new(t!(File::create(&dest)));
@@ -159,11 +203,7 @@ impl BuildMetrics {
     fn prepare_json_step(&self, step: StepMetrics) -> JsonNode {
         let mut children = Vec::new();
         children.extend(step.children.into_iter().map(|child| self.prepare_json_step(child)));
-        children.extend(
-            step.tests
-                .into_iter()
-                .map(|test| JsonNode::Test { name: test.name, outcome: test.outcome }),
-        );
+        children.extend(step.test_suites.into_iter().map(JsonNode::TestSuite));
 
         JsonNode::RustbuildStep {
             type_: step.type_,
@@ -198,17 +238,14 @@ struct StepMetrics {
     duration_excluding_children_sec: Duration,
 
     children: Vec<StepMetrics>,
-    tests: Vec<Test>,
-}
-
-struct Test {
-    name: String,
-    outcome: TestOutcome,
+    test_suites: Vec<TestSuite>,
 }
 
 #[derive(Serialize, Deserialize)]
 #[serde(rename_all = "snake_case")]
 struct JsonRoot {
+    #[serde(default)] // For version 0 the field was not present.
+    format_version: usize,
     system_stats: JsonInvocationSystemStats,
     invocations: Vec<JsonInvocation>,
 }
@@ -237,14 +274,42 @@ enum JsonNode {
 
         children: Vec<JsonNode>,
     },
-    Test {
-        name: String,
-        #[serde(flatten)]
-        outcome: TestOutcome,
+    TestSuite(TestSuite),
+}
+
+#[derive(Serialize, Deserialize)]
+struct TestSuite {
+    metadata: TestSuiteMetadata,
+    tests: Vec<Test>,
+}
+
+#[derive(Serialize, Deserialize)]
+#[serde(tag = "kind", rename_all = "snake_case")]
+pub(crate) enum TestSuiteMetadata {
+    CargoPackage {
+        crates: Vec<String>,
+        target: String,
+        host: String,
+        stage: u32,
+    },
+    Compiletest {
+        suite: String,
+        mode: String,
+        compare_mode: Option<String>,
+        target: String,
+        host: String,
+        stage: u32,
     },
 }
 
 #[derive(Serialize, Deserialize)]
+pub(crate) struct Test {
+    name: String,
+    #[serde(flatten)]
+    outcome: TestOutcome,
+}
+
+#[derive(Serialize, Deserialize)]
 #[serde(tag = "outcome", rename_all = "snake_case")]
 pub(crate) enum TestOutcome {
     Passed,
@@ -266,3 +331,9 @@ struct JsonInvocationSystemStats {
 struct JsonStepSystemStats {
     cpu_utilization_percent: f64,
 }
+
+#[derive(Deserialize)]
+struct OnlyFormatVersion {
+    #[serde(default)] // For version 0 the field was not present.
+    format_version: usize,
+}
diff --git a/src/bootstrap/render_tests.rs b/src/bootstrap/render_tests.rs
index fa0a4806618..872b75f6c15 100644
--- a/src/bootstrap/render_tests.rs
+++ b/src/bootstrap/render_tests.rs
@@ -30,7 +30,7 @@ pub(crate) fn try_run_tests(builder: &Builder<'_>, cmd: &mut Command) -> bool {
 
     if !run_tests(builder, cmd) {
         if builder.fail_fast {
-            crate::detail_exit(1);
+            crate::detail_exit_macro!(1);
         } else {
             let mut failures = builder.delayed_failures.borrow_mut();
             failures.push(format!("{cmd:?}"));
diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs
index 140259b0213..8f5ba42736b 100644
--- a/src/bootstrap/sanity.rs
+++ b/src/bootstrap/sanity.rs
@@ -104,7 +104,7 @@ You should install cmake, or set `download-ci-llvm = true` in the
 than building it.
 "
             );
-            crate::detail_exit(1);
+            crate::detail_exit_macro!(1);
         }
     }
 
diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs
index 09f26862b4a..40038df8332 100644
--- a/src/bootstrap/setup.rs
+++ b/src/bootstrap/setup.rs
@@ -194,7 +194,7 @@ fn setup_config_toml(path: &PathBuf, profile: Profile, config: &Config) {
             "note: this will use the configuration in {}",
             profile.include_path(&config.src).display()
         );
-        crate::detail_exit(1);
+        crate::detail_exit_macro!(1);
     }
 
     let settings = format!(
@@ -380,7 +380,7 @@ pub fn interactive_path() -> io::Result<Profile> {
         io::stdin().read_line(&mut input)?;
         if input.is_empty() {
             eprintln!("EOF on stdin, when expecting answer to question.  Giving up.");
-            crate::detail_exit(1);
+            crate::detail_exit_macro!(1);
         }
         break match parse_with_abbrev(&input) {
             Ok(profile) => profile,
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 2b72d6c48eb..3290e6e0309 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -101,7 +101,7 @@ impl Step for CrateBootstrap {
         );
         builder.info(&format!(
             "{} {} stage0 ({})",
-            builder.kind.test_description(),
+            builder.kind.description(),
             path,
             bootstrap_host,
         ));
@@ -220,7 +220,7 @@ impl Step for HtmlCheck {
         }
         // Ensure that a few different kinds of documentation are available.
         builder.default_doc(&[]);
-        builder.ensure(crate::doc::Rustc { target: self.target, stage: builder.top_stage });
+        builder.ensure(crate::doc::Rustc::new(builder.top_stage, self.target, builder));
 
         try_run(builder, builder.tool_cmd(Tool::HtmlChecker).arg(builder.doc_out(self.target)));
     }
@@ -317,6 +317,17 @@ impl Step for Cargo {
         cargo.env("CARGO_TEST_DISABLE_NIGHTLY", "1");
         cargo.env("PATH", &path_for_cargo(builder, compiler));
 
+        #[cfg(feature = "build-metrics")]
+        builder.metrics.begin_test_suite(
+            crate::metrics::TestSuiteMetadata::CargoPackage {
+                crates: vec!["cargo".into()],
+                target: self.host.triple.to_string(),
+                host: self.host.triple.to_string(),
+                stage: self.stage,
+            },
+            builder,
+        );
+
         let _time = util::timeit(&builder);
         add_flags_and_try_run_tests(builder, &mut cargo);
     }
@@ -762,7 +773,7 @@ impl Step for Clippy {
         }
 
         if !builder.config.cmd.bless() {
-            crate::detail_exit(1);
+            crate::detail_exit_macro!(1);
         }
 
         let mut cargo = builder.cargo(compiler, Mode::ToolRustc, SourceType::InTree, host, "run");
@@ -875,11 +886,11 @@ impl Step for RustdocJSStd {
                     command.arg("--test-file").arg(path);
                 }
             }
-            builder.ensure(crate::doc::Std {
-                target: self.target,
-                stage: builder.top_stage,
-                format: DocumentationFormat::HTML,
-            });
+            builder.ensure(crate::doc::Std::new(
+                builder.top_stage,
+                self.target,
+                DocumentationFormat::HTML,
+            ));
             builder.run(&mut command);
         } else {
             builder.info("No nodejs found, skipping \"tests/rustdoc-js-std\" tests");
@@ -944,28 +955,6 @@ fn get_browser_ui_test_version(npm: &Path) -> Option<String> {
         .or_else(|| get_browser_ui_test_version_inner(npm, true))
 }
 
-fn compare_browser_ui_test_version(installed_version: &str, src: &Path) {
-    match fs::read_to_string(
-        src.join("src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version"),
-    ) {
-        Ok(v) => {
-            if v.trim() != installed_version {
-                eprintln!(
-                    "⚠️ Installed version of browser-ui-test (`{}`) is different than the \
-                     one used in the CI (`{}`)",
-                    installed_version, v
-                );
-                eprintln!(
-                    "You can install this version using `npm update browser-ui-test` or by using \
-                     `npm install browser-ui-test@{}`",
-                    v,
-                );
-            }
-        }
-        Err(e) => eprintln!("Couldn't find the CI browser-ui-test version: {:?}", e),
-    }
-}
-
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
 pub struct RustdocGUI {
     pub target: TargetSelection,
@@ -997,79 +986,30 @@ impl Step for RustdocGUI {
     }
 
     fn run(self, builder: &Builder<'_>) {
-        let nodejs = builder.config.nodejs.as_ref().expect("nodejs isn't available");
-        let npm = builder.config.npm.as_ref().expect("npm isn't available");
-
         builder.ensure(compile::Std::new(self.compiler, self.target));
 
-        // The goal here is to check if the necessary packages are installed, and if not, we
-        // panic.
-        match get_browser_ui_test_version(&npm) {
-            Some(version) => {
-                // We also check the version currently used in CI and emit a warning if it's not the
-                // same one.
-                compare_browser_ui_test_version(&version, &builder.build.src);
-            }
-            None => {
-                eprintln!(
-                    "error: rustdoc-gui test suite cannot be run because npm `browser-ui-test` \
-                     dependency is missing",
-                );
-                eprintln!(
-                    "If you want to install the `{0}` dependency, run `npm install {0}`",
-                    "browser-ui-test",
-                );
-                panic!("Cannot run rustdoc-gui tests");
-            }
-        }
+        let mut cmd = builder.tool_cmd(Tool::RustdocGUITest);
 
         let out_dir = builder.test_out(self.target).join("rustdoc-gui");
-
-        // We remove existing folder to be sure there won't be artifacts remaining.
         builder.clear_if_dirty(&out_dir, &builder.rustdoc(self.compiler));
 
-        let src_path = builder.build.src.join("tests/rustdoc-gui/src");
-        // We generate docs for the libraries present in the rustdoc-gui's src folder.
-        for entry in src_path.read_dir().expect("read_dir call failed") {
-            if let Ok(entry) = entry {
-                let path = entry.path();
+        if let Some(src) = builder.config.src.to_str() {
+            cmd.arg("--rust-src").arg(src);
+        }
 
-                if !path.is_dir() {
-                    continue;
-                }
+        if let Some(out_dir) = out_dir.to_str() {
+            cmd.arg("--out-dir").arg(out_dir);
+        }
 
-                let mut cargo = Command::new(&builder.initial_cargo);
-                cargo
-                    .arg("doc")
-                    .arg("--target-dir")
-                    .arg(&out_dir)
-                    .env("RUSTC_BOOTSTRAP", "1")
-                    .env("RUSTDOC", builder.rustdoc(self.compiler))
-                    .env("RUSTC", builder.rustc(self.compiler))
-                    .current_dir(path);
-                // FIXME: implement a `// compile-flags` command or similar
-                //        instead of hard-coding this test
-                if entry.file_name() == "link_to_definition" {
-                    cargo.env("RUSTDOCFLAGS", "-Zunstable-options --generate-link-to-definition");
-                } else if entry.file_name() == "scrape_examples" {
-                    cargo.arg("-Zrustdoc-scrape-examples");
-                } else if entry.file_name() == "extend_css" {
-                    cargo.env("RUSTDOCFLAGS", &format!("--extend-css extra.css"));
-                }
-                builder.run(&mut cargo);
-            }
+        if let Some(initial_cargo) = builder.config.initial_cargo.to_str() {
+            cmd.arg("--initial-cargo").arg(initial_cargo);
         }
 
-        // We now run GUI tests.
-        let mut command = Command::new(&nodejs);
-        command
-            .arg(builder.build.src.join("src/tools/rustdoc-gui/tester.js"))
-            .arg("--jobs")
-            .arg(&builder.jobs().to_string())
-            .arg("--doc-folder")
-            .arg(out_dir.join("doc"))
-            .arg("--tests-folder")
-            .arg(builder.build.src.join("tests/rustdoc-gui"));
+        cmd.arg("--jobs").arg(builder.jobs().to_string());
+
+        cmd.env("RUSTDOC", builder.rustdoc(self.compiler))
+            .env("RUSTC", builder.rustc(self.compiler));
+
         for path in &builder.paths {
             if let Some(p) = util::is_valid_test_suite_arg(path, "tests/rustdoc-gui", builder) {
                 if !p.ends_with(".goml") {
@@ -1077,14 +1017,25 @@ impl Step for RustdocGUI {
                     panic!("Cannot run rustdoc-gui tests");
                 }
                 if let Some(name) = path.file_name().and_then(|f| f.to_str()) {
-                    command.arg("--file").arg(name);
+                    cmd.arg("--goml-file").arg(name);
                 }
             }
         }
+
         for test_arg in builder.config.test_args() {
-            command.arg(test_arg);
+            cmd.arg("--test-arg").arg(test_arg);
+        }
+
+        if let Some(ref nodejs) = builder.config.nodejs {
+            cmd.arg("--nodejs").arg(nodejs);
+        }
+
+        if let Some(ref npm) = builder.config.npm {
+            cmd.arg("--npm").arg(npm);
         }
-        builder.run(&mut command);
+
+        let _time = util::timeit(&builder);
+        crate::render_tests::try_run_tests(builder, &mut cmd);
     }
 }
 
@@ -1134,7 +1085,7 @@ help: to skip test's attempt to check tidiness, pass `--exclude src/tools/tidy`
                     PATH = inferred_rustfmt_dir.display(),
                     CHAN = builder.config.channel,
                 );
-                crate::detail_exit(1);
+                crate::detail_exit_macro!(1);
             }
             crate::format::format(&builder, !builder.config.cmd.bless(), &[]);
         }
@@ -1157,7 +1108,7 @@ help: to skip test's attempt to check tidiness, pass `--exclude src/tools/tidy`
                 eprintln!(
                     "x.py completions were changed; run `x.py run generate-completions` to update them"
                 );
-                crate::detail_exit(1);
+                crate::detail_exit_macro!(1);
             }
         }
     }
@@ -1378,7 +1329,7 @@ help: to test the compiler, use `--stage 1` instead
 help: to test the standard library, use `--stage 0 library/std` instead
 note: if you're sure you want to do this, please open an issue as to why. In the meantime, you can override this with `COMPILETEST_FORCE_STAGE0=1`."
             );
-            crate::detail_exit(1);
+            crate::detail_exit_macro!(1);
         }
 
         let mut compiler = self.compiler;
@@ -1753,12 +1704,21 @@ note: if you're sure you want to do this, please open an issue as to why. In the
             cmd.arg("--git-hash");
         }
 
-        if let Some(commit) = builder.config.download_rustc_commit() {
-            cmd.env("FAKE_DOWNLOAD_RUSTC_PREFIX", format!("/rustc/{commit}"));
-        }
-
         builder.ci_env.force_coloring_in_ci(&mut cmd);
 
+        #[cfg(feature = "build-metrics")]
+        builder.metrics.begin_test_suite(
+            crate::metrics::TestSuiteMetadata::Compiletest {
+                suite: suite.into(),
+                mode: mode.into(),
+                compare_mode: None,
+                target: self.target.triple.to_string(),
+                host: self.compiler.host.triple.to_string(),
+                stage: self.compiler.stage,
+            },
+            builder,
+        );
+
         builder.info(&format!(
             "Check compiletest suite={} mode={} ({} -> {})",
             suite, mode, &compiler.host, target
@@ -1768,6 +1728,20 @@ note: if you're sure you want to do this, please open an issue as to why. In the
 
         if let Some(compare_mode) = compare_mode {
             cmd.arg("--compare-mode").arg(compare_mode);
+
+            #[cfg(feature = "build-metrics")]
+            builder.metrics.begin_test_suite(
+                crate::metrics::TestSuiteMetadata::Compiletest {
+                    suite: suite.into(),
+                    mode: mode.into(),
+                    compare_mode: Some(compare_mode.into()),
+                    target: self.target.triple.to_string(),
+                    host: self.compiler.host.triple.to_string(),
+                    stage: self.compiler.stage,
+                },
+                builder,
+            );
+
             builder.info(&format!(
                 "Check compiletest suite={} mode={} compare_mode={} ({} -> {})",
                 suite, mode, compare_mode, &compiler.host, target
@@ -2094,6 +2068,17 @@ fn run_cargo_test(
     let mut cargo =
         prepare_cargo_test(cargo, libtest_args, crates, primary_crate, compiler, target, builder);
     let _time = util::timeit(&builder);
+
+    #[cfg(feature = "build-metrics")]
+    builder.metrics.begin_test_suite(
+        crate::metrics::TestSuiteMetadata::CargoPackage {
+            crates: crates.iter().map(|c| c.to_string()).collect(),
+            target: target.triple.to_string(),
+            host: compiler.host.triple.to_string(),
+            stage: compiler.stage,
+        },
+        builder,
+    );
     add_flags_and_try_run_tests(builder, &mut cargo)
 }
 
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index f13d365e375..0f0a3bb8775 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -116,7 +116,7 @@ impl Step for ToolBuild {
 
         if !is_expected {
             if !is_optional_tool {
-                crate::detail_exit(1);
+                crate::detail_exit_macro!(1);
             } else {
                 None
             }
@@ -302,6 +302,7 @@ bootstrap_tool!(
     GenerateCopyright, "src/tools/generate-copyright", "generate-copyright";
     SuggestTests, "src/tools/suggest-tests", "suggest-tests";
     GenerateWindowsSys, "src/tools/generate-windows-sys", "generate-windows-sys";
+    RustdocGUITest, "src/tools/rustdoc-gui-test", "rustdoc-gui-test", is_unstable_tool = true, allow_features = "test";
 );
 
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
diff --git a/src/bootstrap/toolstate.rs b/src/bootstrap/toolstate.rs
index 7aab88a1a73..9c4d0ea265d 100644
--- a/src/bootstrap/toolstate.rs
+++ b/src/bootstrap/toolstate.rs
@@ -91,7 +91,7 @@ fn print_error(tool: &str, submodule: &str) {
     eprintln!("If you do NOT intend to update '{}', please ensure you did not accidentally", tool);
     eprintln!("change the submodule at '{}'. You may ask your reviewer for the", submodule);
     eprintln!("proper steps.");
-    crate::detail_exit(3);
+    crate::detail_exit_macro!(3);
 }
 
 fn check_changed_files(toolstates: &HashMap<Box<str>, ToolState>) {
@@ -106,7 +106,7 @@ fn check_changed_files(toolstates: &HashMap<Box<str>, ToolState>) {
         Ok(o) => o,
         Err(e) => {
             eprintln!("Failed to get changed files: {:?}", e);
-            crate::detail_exit(1);
+            crate::detail_exit_macro!(1);
         }
     };
 
@@ -177,7 +177,7 @@ impl Step for ToolStateCheck {
         }
 
         if did_error {
-            crate::detail_exit(1);
+            crate::detail_exit_macro!(1);
         }
 
         check_changed_files(&toolstates);
@@ -223,7 +223,7 @@ impl Step for ToolStateCheck {
         }
 
         if did_error {
-            crate::detail_exit(1);
+            crate::detail_exit_macro!(1);
         }
 
         if builder.config.channel == "nightly" && env::var_os("TOOLSTATE_PUBLISH").is_some() {
diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs
index 2e1adbf63bb..e4bbccdb067 100644
--- a/src/bootstrap/util.rs
+++ b/src/bootstrap/util.rs
@@ -3,6 +3,7 @@
 //! Simple things like testing the various filesystem operations here and there,
 //! not a lot of interesting happenings here unfortunately.
 
+use build_helper::util::{fail, try_run};
 use std::env;
 use std::fs;
 use std::io;
@@ -230,25 +231,10 @@ pub fn is_valid_test_suite_arg<'a, P: AsRef<Path>>(
 
 pub fn run(cmd: &mut Command, print_cmd_on_fail: bool) {
     if !try_run(cmd, print_cmd_on_fail) {
-        crate::detail_exit(1);
+        crate::detail_exit_macro!(1);
     }
 }
 
-pub fn try_run(cmd: &mut Command, print_cmd_on_fail: bool) -> bool {
-    let status = match cmd.status() {
-        Ok(status) => status,
-        Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", cmd, e)),
-    };
-    if !status.success() && print_cmd_on_fail {
-        println!(
-            "\n\ncommand did not execute successfully: {:?}\n\
-             expected success, got: {}\n\n",
-            cmd, status
-        );
-    }
-    status.success()
-}
-
 pub fn check_run(cmd: &mut Command, print_cmd_on_fail: bool) -> bool {
     let status = match cmd.status() {
         Ok(status) => status,
@@ -269,7 +255,7 @@ pub fn check_run(cmd: &mut Command, print_cmd_on_fail: bool) -> bool {
 
 pub fn run_suppressed(cmd: &mut Command) {
     if !try_run_suppressed(cmd) {
-        crate::detail_exit(1);
+        crate::detail_exit_macro!(1);
     }
 }
 
@@ -374,11 +360,6 @@ fn dir_up_to_date(src: &Path, threshold: SystemTime) -> bool {
     })
 }
 
-fn fail(s: &str) -> ! {
-    eprintln!("\n\n{}\n\n", s);
-    crate::detail_exit(1);
-}
-
 /// Copied from `std::path::absolute` until it stabilizes.
 ///
 /// FIXME: this shouldn't exist.
@@ -488,7 +469,7 @@ fn absolute_windows(path: &std::path::Path) -> std::io::Result<std::path::PathBu
     }
 }
 
-/// Adapted from https://github.com/llvm/llvm-project/blob/782e91224601e461c019e0a4573bbccc6094fbcd/llvm/cmake/modules/HandleLLVMOptions.cmake#L1058-L1079
+/// Adapted from <https://github.com/llvm/llvm-project/blob/782e91224601e461c019e0a4573bbccc6094fbcd/llvm/cmake/modules/HandleLLVMOptions.cmake#L1058-L1079>
 ///
 /// When `clang-cl` is used with instrumentation, we need to add clang's runtime library resource
 /// directory to the linker flags, otherwise there will be linker errors about the profiler runtime
diff --git a/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/Cargo.toml b/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/Cargo.toml
index fa8e5b3d080..2d17cf7d47a 100644
--- a/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/Cargo.toml
+++ b/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/Cargo.toml
@@ -4,6 +4,7 @@ version = "0.0.0"
 edition = "2021"
 
 [workspace]
+resolver = "1"
 
 [dependencies]
 r-efi = "4.1.0"
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
index 806935b827f..3ccca1e8b89 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
@@ -1 +1 @@
-0.16.4
\ No newline at end of file
+0.16.5
\ No newline at end of file
diff --git a/src/doc/rustc/src/exploit-mitigations.md b/src/doc/rustc/src/exploit-mitigations.md
index a82a53248d4..172048704f4 100644
--- a/src/doc/rustc/src/exploit-mitigations.md
+++ b/src/doc/rustc/src/exploit-mitigations.md
@@ -55,88 +55,18 @@ Table I \
 Summary of exploit mitigations supported by the Rust compiler when building
 programs for the Linux operating system on the AMD64 architecture and
 equivalent.
-<table class="table">
-  <tr>
-   <td><strong>Exploit mitigation</strong>
-   </td>
-   <td><strong>Supported and enabled by default</strong>
-   </td>
-   <td><strong>Since</strong>
-   </td>
-  </tr>
-  <tr>
-   <td>Position-independent executable
-   </td>
-   <td>Yes
-   </td>
-   <td>0.12.0 (2014-10-09)
-   </td>
-  </tr>
-  <tr>
-   <td>Integer overflow checks
-   </td>
-   <td>Yes (enabled when debug assertions are enabled, and disabled when debug assertions are disabled)
-   </td>
-   <td>1.1.0 (2015-06-25)
-   </td>
-  </tr>
-  <tr>
-   <td>Non-executable memory regions
-   </td>
-   <td>Yes
-   </td>
-   <td>1.8.0 (2016-04-14)
-   </td>
-  </tr>
-  <tr>
-   <td>Stack clashing protection
-   </td>
-   <td>Yes
-   </td>
-   <td>1.20.0 (2017-08-31)
-   </td>
-  </tr>
-  <tr>
-   <td>Read-only relocations and immediate binding
-   </td>
-   <td>Yes
-   </td>
-   <td>1.21.0 (2017-10-12)
-   </td>
-  </tr>
-  <tr>
-   <td>Heap corruption protection
-   </td>
-   <td>Yes
-   </td>
-   <td>1.32.0 (2019-01-17) (via operating system default or specified allocator)
-   </td>
-  </tr>
-  <tr>
-   <td>Stack smashing protection
-   </td>
-   <td>Yes
-   </td>
-   <td>Nightly
-   </td>
-  </tr>
-  <tr>
-   <td>Forward-edge control flow protection
-   </td>
-   <td>Yes
-   </td>
-   <td>Nightly
-   </td>
-  </tr>
-  <tr>
-   <td>Backward-edge control flow protection (e.g., shadow and safe stack)
-   </td>
-   <td>No
-   </td>
-   <td>
-   </td>
-  </tr>
-</table>
+
+| Exploit mitigation | Supported and enabled by default | Since |
+| - | - | - |
+| Position-independent executable | Yes | 0.12.0 (2014-10-09) |
+| Integer overflow checks | Yes (enabled when debug assertions are enabled, and disabled when debug assertions are disabled) | 1.1.0 (2015-06-25) |
+| Non-executable memory regions | Yes | 1.8.0 (2016-04-14) |
+| Stack clashing protection | Yes | 1.20.0 (2017-08-31) |
+| Read-only relocations and immediate binding | Yes | 1.21.0 (2017-10-12) |
+| Heap corruption protection | Yes | 1.32.0 (2019-01-17) (via operating system default or specified allocator) |
+| Stack smashing protection | Yes | Nightly |
+| Forward-edge control flow protection | Yes | Nightly |
+| Backward-edge control flow protection (e.g., shadow and safe stack) | Yes | Nightly |
 
 <small id="fn:1">1\. See
 <https://github.com/rust-lang/rust/tree/master/compiler/rustc_target/src/spec>
@@ -513,20 +443,21 @@ Newer processors provide hardware assistance for backward-edge control flow
 protection, such as ARM Pointer Authentication, and Intel Shadow Stack as
 part of Intel CET.
 
-The Rust compiler does not support shadow or safe stack. There is work
-currently ongoing to add support for the sanitizers[40], which may or may
-not include support for safe stack<sup id="fnref:7" role="doc-noteref"><a
-href="#fn:7" class="footnote">7</a></sup>.
+The Rust compiler supports shadow stack for aarch64 only
+<sup id="fnref:7" role="doc-noteref"><a href="#fn:7" class="footnote">7</a></sup>
+on nightly Rust compilers [43]-[44]. Safe stack is available on nightly
+Rust compilers [45]-[46].
 
 ```text
 $ readelf -s target/release/hello-rust | grep __safestack_init
+  1177: 00000000000057b0   444 FUNC    GLOBAL DEFAULT    9 __safestack_init
 ```
 Fig. 16. Checking if LLVM SafeStack is enabled for a given binary.
 
 The presence of the `__safestack_init` symbol indicates that LLVM SafeStack
-is enabled for a given binary. Conversely, the absence of the
+is enabled for a given binary (see Fig. 16). Conversely, the absence of the
 `__safestack_init` symbol indicates that LLVM SafeStack is not enabled for a
-given binary (see Fig. 16).
+given binary.
 
 <small id="fn:7">7\. The shadow stack implementation for the AMD64
 architecture and equivalent in LLVM was removed due to performance and
@@ -698,3 +629,15 @@ defaults (unrelated to `READ_IMPLIES_EXEC`).
 
 42. bbjornse. “add codegen option for using LLVM stack smash protection #84197.”
     GitHub. <https://github.com/rust-lang/rust/pull/84197>
+
+43. ivanloz. “Add support for LLVM ShadowCallStack. #98208.” GitHub.
+    <https://github.com/rust-lang/rust/pull/98208>.
+
+44. “ShadowCallStack.” The Rust Unstable Book.
+    [https://doc.rust-lang.org/unstable-book/compiler-flags/sanitizer.html#shadowcallstack](../unstable-book/compiler-flags/sanitizer.html#shadowcallstack).
+
+45. W. Wiser. “Add support for LLVM SafeStack #112000” GitHub.
+    <https://github.com/rust-lang/rust/pull/112000>
+
+46. “SafeStack.” The Rust Unstable Book.
+    [https://doc.rust-lang/org/unstable-book/compiler-flags/sanitizer.html#safestack](../unstable-book/compiler-flags/sanitizer.html#safestack).
diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
index aa776daf09d..49389b28c8f 100644
--- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md
+++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
@@ -21,7 +21,8 @@ This feature allows for use of one of following sanitizers:
 * [MemorySanitizer](#memorysanitizer) a detector of uninitialized reads.
 * [MemTagSanitizer](#memtagsanitizer) fast memory error detector based on
   Armv8.5-A Memory Tagging Extension.
-* [ShadowCallStack](#shadowcallstack) provides backward-edge control flow protection.
+* [SafeStack](#safestack) provides backward-edge control flow protection by separating the stack into safe and unsafe regions.
+* [ShadowCallStack](#shadowcallstack) provides backward-edge control flow protection (aarch64 only).
 * [ThreadSanitizer](#threadsanitizer) a fast data race detector.
 
 To enable a sanitizer compile with `-Zsanitizer=address`,`-Zsanitizer=cfi`,
@@ -712,6 +713,16 @@ To enable this target feature compile with `-C target-feature="+mte"`.
 
 See the [LLVM MemTagSanitizer documentation][llvm-memtag] for more details.
 
+# SafeStack
+
+SafeStack provides backward edge control flow protection by separating the stack into data which is only accessed safely (the safe stack) and all other data (the unsafe stack).
+
+SafeStack can be enabled with the `-Zsanitizer=safestack` option and is supported on the following targets:
+
+* `x86_64-unknown-linux-gnu`
+
+See the [Clang SafeStack documentation][clang-safestack] for more details.
+
 # ShadowCallStack
 
 ShadowCallStack provides backward edge control flow protection by storing a function's return address in a separately allocated 'shadow call stack' and loading the return address from that shadow call stack.
@@ -828,6 +839,7 @@ Sanitizers produce symbolized stacktraces when llvm-symbolizer binary is in `PAT
 [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-safestack]: https://clang.llvm.org/docs/SafeStack.html
 [clang-scs]: https://clang.llvm.org/docs/ShadowCallStack.html
 [clang-tsan]: https://clang.llvm.org/docs/ThreadSanitizer.html
 [linux-kasan]: https://www.kernel.org/doc/html/latest/dev-tools/kasan.html
diff --git a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md
index 532cb9eea11..c634dc50d6d 100644
--- a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md
+++ b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md
@@ -17,7 +17,6 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
 - AVR
 - MSP430
 - M68k
-- LoongArch
 - s390x
 
 ## Register classes
@@ -47,8 +46,6 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
 | M68k         | `reg`          | `d[0-7]`, `a[0-7]`                 | `r`                  |
 | M68k         | `reg_data`     | `d[0-7]`                           | `d`                  |
 | M68k         | `reg_addr`     | `a[0-3]`                           | `a`                  |
-| LoongArch    | `reg`          | `$r1`, `$r[4-20]`, `$r[23,30]`     | `r`                  |
-| LoongArch    | `freg`         | `$f[0-31]`                         | `f`                  |
 | s390x        | `reg`          | `r[0-10]`, `r[12-14]`              | `r`                  |
 | s390x        | `freg`         | `f[0-15]`                          | `f`                  |
 
@@ -82,8 +79,6 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
 | MSP430       | `reg`                           | None           | `i8`, `i16`                             |
 | M68k         | `reg`, `reg_addr`               | None           | `i16`, `i32`                            |
 | M68k         | `reg_data`                      | None           | `i8`, `i16`, `i32`                      |
-| LoongArch64  | `reg`                           | None           | `i8`, `i16`, `i32`, `i64`, `f32`, `f64` |
-| LoongArch64  | `freg`                          | None           | `f32`, `f64`                            |
 | s390x        | `reg`                           | None           | `i8`, `i16`, `i32`, `i64`               |
 | s390x        | `freg`                          | None           | `f32`, `f64`                            |
 
@@ -107,10 +102,6 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
 | M68k         | `a5`          | `bp`      |
 | M68k         | `a6`          | `fp`      |
 | M68k         | `a7`          | `sp`, `usp`, `ssp`, `isp` |
-| LoongArch    | `$r0`         | `zero`    |
-| LoongArch    | `$r2`         | `tp`      |
-| LoongArch    | `$r3`         | `sp`      |
-| LoongArch    | `$r22`        | `fp`      |
 
 > **Notes**:
 > - TI does not mandate a frame pointer for MSP430, but toolchains are allowed
@@ -121,7 +112,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
 | Architecture | Unsupported register                    | Reason                                                                                                                                                                              |
 | ------------ | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
 | All          | `sp`, `r15` (s390x)                     | The stack pointer must be restored to its original value at the end of an asm code block.                                                                                           |
-| All          | `fr` (Hexagon), `$fp` (MIPS), `Y` (AVR), `r4` (MSP430), `a6` (M68k), `$fp` (LoongArch), `r11` (s390x) | The frame pointer cannot be used as an input or output.                                                                                                                             |
+| All          | `fr` (Hexagon), `$fp` (MIPS), `Y` (AVR), `r4` (MSP430), `a6` (M68k), `r11` (s390x) | The frame pointer cannot be used as an input or output.                                                                                                                             |
 | All          | `r19` (Hexagon)                         | This is used internally by LLVM as a "base pointer" for functions with complex stack frames.                                                                                        |
 | MIPS         | `$0` or `$zero`                         | This is a constant zero register which can't be modified.                                                                                                                           |
 | MIPS         | `$1` or `$at`                           | Reserved for assembler.                                                                                                                                                             |
@@ -132,10 +123,6 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
 | AVR          | `r0`, `r1`, `r1r0`                      | Due to an issue in LLVM, the `r0` and `r1` registers cannot be used as inputs or outputs.  If modified, they must be restored to their original values before the end of the block. |
 |MSP430        | `r0`, `r2`, `r3`                        | These are the program counter, status register, and constant generator respectively. Neither the status register nor constant generator can be written to.                          |
 | M68k         | `a4`, `a5`                              | Used internally by LLVM for the base pointer and global base pointer. |
-| LoongArch    | `$r0` or `$zero`                        | This is a constant zero register which can't be modified.                                                                                                                           |
-| LoongArch    | `$r2` or `$tp`                          | This is reserved for TLS.                                                                                                                                                           |
-| LoongArch    | `$r21`                                  | This is reserved by the ABI.                                                                                                                                                        |
-| LoongArch    | `$r31` or `$s8`                         | This is used internally by LLVM.                                                                                                                                                    |
 
 ## Template modifiers
 
@@ -150,8 +137,6 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
 | PowerPC      | `reg`          | None     | `0`            | None          |
 | PowerPC      | `reg_nonzero`  | None     | `3`            | `b`           |
 | PowerPC      | `freg`         | None     | `0`            | None          |
-| LoongArch    | `reg`          | None     | `$r2`          | None          |
-| LoongArch    | `freg`         | None     | `$f0`          | None          |
 | s390x        | `reg`          | None     | `%r0`          | None          |
 | s390x        | `freg`         | None     | `%f0`          | None          |
 
diff --git a/src/etc/test-float-parse/Cargo.toml b/src/etc/test-float-parse/Cargo.toml
index 7ee19a0b6d9..6d7b227d0ad 100644
--- a/src/etc/test-float-parse/Cargo.toml
+++ b/src/etc/test-float-parse/Cargo.toml
@@ -5,6 +5,7 @@ edition = "2021"
 publish = false
 
 [workspace]
+resolver = "1"
 
 [dependencies]
 rand = "0.4"
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index e4c05b57378..83887cc44b9 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -21,7 +21,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
         let mut impls = Vec::new();
         for trait_def_id in cx.tcx.all_traits() {
             if !cx.cache.effective_visibilities.is_reachable(cx.tcx, trait_def_id)
-                || cx.generated_synthetics.get(&(ty.0, trait_def_id)).is_some()
+                || cx.generated_synthetics.get(&(ty.skip_binder(), trait_def_id)).is_some()
             {
                 continue;
             }
@@ -34,13 +34,13 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
                     impl_def_id
                 );
                 let trait_ref = cx.tcx.impl_trait_ref(impl_def_id).unwrap();
-                if !matches!(trait_ref.0.self_ty().kind(), ty::Param(_)) {
+                if !matches!(trait_ref.skip_binder().self_ty().kind(), ty::Param(_)) {
                     continue;
                 }
                 let infcx = cx.tcx.infer_ctxt().build();
                 let substs = infcx.fresh_substs_for_item(DUMMY_SP, item_def_id);
                 let impl_ty = ty.subst(infcx.tcx, substs);
-                let param_env = EarlyBinder(param_env).subst(infcx.tcx, substs);
+                let param_env = EarlyBinder::bind(param_env).subst(infcx.tcx, substs);
 
                 let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
                 let impl_trait_ref = trait_ref.subst(infcx.tcx, impl_substs);
@@ -87,7 +87,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
                     trait_ref, ty
                 );
 
-                cx.generated_synthetics.insert((ty.0, trait_def_id));
+                cx.generated_synthetics.insert((ty.skip_binder(), trait_def_id));
 
                 impls.push(Item {
                     name: None,
@@ -104,10 +104,10 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
                         // the post-inference `trait_ref`, as it's more accurate.
                         trait_: Some(clean_trait_ref_with_bindings(
                             cx,
-                            ty::Binder::dummy(trait_ref.0),
+                            ty::Binder::dummy(trait_ref.skip_binder()),
                             ThinVec::new(),
                         )),
-                        for_: clean_middle_ty(ty::Binder::dummy(ty.0), cx, None),
+                        for_: clean_middle_ty(ty::Binder::dummy(ty.skip_binder()), cx, None),
                         items: cx
                             .tcx
                             .associated_items(impl_def_id)
@@ -116,7 +116,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
                             .collect::<Vec<_>>(),
                         polarity: ty::ImplPolarity::Positive,
                         kind: ImplKind::Blanket(Box::new(clean_middle_ty(
-                            ty::Binder::dummy(trait_ref.0.self_ty()),
+                            ty::Binder::dummy(trait_ref.skip_binder().self_ty()),
                             cx,
                             None,
                         ))),
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index c852f9cca2b..7dc08b3b1ff 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -355,9 +355,9 @@ pub(crate) fn build_impl(
         return;
     }
 
-    let _prof_timer = cx.tcx.sess.prof.generic_activity("build_impl");
-
     let tcx = cx.tcx;
+    let _prof_timer = tcx.sess.prof.generic_activity("build_impl");
+
     let associated_trait = tcx.impl_trait_ref(did).map(ty::EarlyBinder::skip_binder);
 
     // Only inline impl if the implemented trait is
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 59a3e631724..5fd867189fd 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1111,8 +1111,8 @@ fn clean_fn_decl_with_args<'tcx>(
     args: Arguments,
 ) -> FnDecl {
     let output = match decl.output {
-        hir::FnRetTy::Return(typ) => Return(clean_ty(typ, cx)),
-        hir::FnRetTy::DefaultReturn(..) => DefaultReturn,
+        hir::FnRetTy::Return(typ) => clean_ty(typ, cx),
+        hir::FnRetTy::DefaultReturn(..) => Type::Tuple(Vec::new()),
     };
     FnDecl { inputs: args, output, c_variadic: decl.c_variadic }
 }
@@ -1126,10 +1126,7 @@ fn clean_fn_decl_from_did_and_sig<'tcx>(
 
     // We assume all empty tuples are default return type. This theoretically can discard `-> ()`,
     // but shouldn't change any code meaning.
-    let output = match clean_middle_ty(sig.output(), cx, None) {
-        Type::Tuple(inner) if inner.is_empty() => DefaultReturn,
-        ty => Return(ty),
-    };
+    let output = clean_middle_ty(sig.output(), cx, None);
 
     FnDecl {
         output,
@@ -2592,7 +2589,8 @@ fn clean_use_statement_inner<'tcx>(
     } else {
         if inline_attr.is_none()
             && let Res::Def(DefKind::Mod, did) = path.res
-            && !did.is_local() && did.is_crate_root()
+            && !did.is_local()
+            && did.is_crate_root()
         {
             // if we're `pub use`ing an extern crate root, don't inline it unless we
             // were specifically asked for it
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index e9ccea2cf27..1999a6b671d 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -42,7 +42,6 @@ use crate::formats::item_type::ItemType;
 use crate::html::render::Context;
 use crate::passes::collect_intra_doc_links::UrlFragment;
 
-pub(crate) use self::FnRetTy::*;
 pub(crate) use self::ItemKind::*;
 pub(crate) use self::SelfTy::*;
 pub(crate) use self::Type::{
@@ -1353,7 +1352,7 @@ pub(crate) struct Function {
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub(crate) struct FnDecl {
     pub(crate) inputs: Arguments,
-    pub(crate) output: FnRetTy,
+    pub(crate) output: Type,
     pub(crate) c_variadic: bool,
 }
 
@@ -1371,18 +1370,16 @@ impl FnDecl {
     ///
     /// This function will panic if the return type does not match the expected sugaring for async
     /// functions.
-    pub(crate) fn sugared_async_return_type(&self) -> FnRetTy {
-        match &self.output {
-            FnRetTy::Return(Type::ImplTrait(bounds)) => match &bounds[0] {
-                GenericBound::TraitBound(PolyTrait { trait_, .. }, ..) => {
-                    let bindings = trait_.bindings().unwrap();
-                    let ret_ty = bindings[0].term();
-                    let ty = ret_ty.ty().expect("Unexpected constant return term");
-                    FnRetTy::Return(ty.clone())
-                }
-                _ => panic!("unexpected desugaring of async function"),
-            },
-            _ => panic!("unexpected desugaring of async function"),
+    pub(crate) fn sugared_async_return_type(&self) -> Type {
+        if let Type::ImplTrait(v) = &self.output &&
+            let [GenericBound::TraitBound(PolyTrait { trait_, .. }, _ )] = &v[..]
+        {
+            let bindings = trait_.bindings().unwrap();
+            let ret_ty = bindings[0].term();
+            let ty = ret_ty.ty().expect("Unexpected constant return term");
+            ty.clone()
+        } else {
+            panic!("unexpected desugaring of async function")
         }
     }
 }
@@ -1425,21 +1422,6 @@ impl Argument {
     }
 }
 
-#[derive(Clone, PartialEq, Eq, Debug, Hash)]
-pub(crate) enum FnRetTy {
-    Return(Type),
-    DefaultReturn,
-}
-
-impl FnRetTy {
-    pub(crate) fn as_return(&self) -> Option<&Type> {
-        match self {
-            Return(ret) => Some(ret),
-            DefaultReturn => None,
-        }
-    }
-}
-
 #[derive(Clone, Debug)]
 pub(crate) struct Trait {
     pub(crate) def_id: DefId,
@@ -1641,6 +1623,10 @@ impl Type {
         matches!(self, Type::ImplTrait(_))
     }
 
+    pub(crate) fn is_unit(&self) -> bool {
+        matches!(self, Type::Tuple(v) if v.is_empty())
+    }
+
     pub(crate) fn projection(&self) -> Option<(&Type, DefId, PathSegment)> {
         if let QPath(box QPathData { self_type, trait_, assoc, .. }) = self {
             Some((self_type, trait_.as_ref()?.def_id(), assoc.clone()))
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 17aa6b38e38..366f9395296 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -193,7 +193,7 @@ pub(crate) fn build_deref_target_impls(
         };
 
         if let Some(prim) = target.primitive_type() {
-            let _prof_timer = cx.tcx.sess.prof.generic_activity("build_primitive_inherent_impls");
+            let _prof_timer = tcx.sess.prof.generic_activity("build_primitive_inherent_impls");
             for did in prim.impls(tcx).filter(|did| !did.is_local()) {
                 inline::build_impl(cx, did, None, ret);
             }
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index dfa4b091b01..9f08609a6d1 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -314,7 +314,6 @@ impl Options {
         matches: &getopts::Matches,
         args: Vec<String>,
     ) -> Result<(Options, RenderOptions), i32> {
-        let args = &args[1..];
         // Check for unstable options.
         nightly_options::check_nightly_options(matches, &opts());
 
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index c4758fd9866..8aaad8bce1b 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -147,7 +147,7 @@ impl Cache {
 
         // Cache where all our extern crates are located
         // FIXME: this part is specific to HTML so it'd be nice to remove it from the common code
-        for &crate_num in cx.tcx.crates(()) {
+        for &crate_num in tcx.crates(()) {
             let e = ExternalCrate { crate_num };
 
             let name = e.name(tcx);
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index d963d6092c4..f26d74629dd 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -1257,9 +1257,9 @@ impl clean::Impl {
                 };
                 primitive_link_fragment(f, PrimitiveType::Tuple, &format!("fn ({name}₁, {name}₂, …, {name}ₙ{ellipsis})"), "#trait-implementations-1", cx)?;
                 // Write output.
-                if let clean::FnRetTy::Return(ty) = &bare_fn.decl.output {
+                if !bare_fn.decl.output.is_unit() {
                     write!(f, " -> ")?;
-                    fmt_type(ty, f, use_absolute, cx)?;
+                    fmt_type(&bare_fn.decl.output, f, use_absolute, cx)?;
                 }
             } else if let Some(ty) = self.kind.as_blanket_ty() {
                 fmt_type(ty, f, use_absolute, cx)?;
@@ -1296,22 +1296,6 @@ impl clean::Arguments {
     }
 }
 
-impl clean::FnRetTy {
-    pub(crate) fn print<'a, 'tcx: 'a>(
-        &'a self,
-        cx: &'a Context<'tcx>,
-    ) -> impl fmt::Display + 'a + Captures<'tcx> {
-        display_fn(move |f| match self {
-            clean::Return(clean::Tuple(tys)) if tys.is_empty() => Ok(()),
-            clean::Return(ty) if f.alternate() => {
-                write!(f, " -> {:#}", ty.print(cx))
-            }
-            clean::Return(ty) => write!(f, " -&gt; {}", ty.print(cx)),
-            clean::DefaultReturn => Ok(()),
-        })
-    }
-}
-
 impl clean::BareFunctionDecl {
     fn print_hrtb_with_space<'a, 'tcx: 'a>(
         &'a self,
@@ -1366,7 +1350,7 @@ impl clean::FnDecl {
                     "({args:#}{ellipsis}){arrow:#}",
                     args = self.inputs.print(cx),
                     ellipsis = ellipsis,
-                    arrow = self.output.print(cx)
+                    arrow = self.print_output(cx)
                 )
             } else {
                 write!(
@@ -1374,7 +1358,7 @@ impl clean::FnDecl {
                     "({args}{ellipsis}){arrow}",
                     args = self.inputs.print(cx),
                     ellipsis = ellipsis,
-                    arrow = self.output.print(cx)
+                    arrow = self.print_output(cx)
                 )
             }
         })
@@ -1464,9 +1448,22 @@ impl clean::FnDecl {
             Some(n) => write!(f, "\n{})", Indent(n))?,
         };
 
-        fmt::Display::fmt(&self.output.print(cx), f)?;
+        fmt::Display::fmt(&self.print_output(cx), f)?;
         Ok(())
     }
+
+    pub(crate) fn print_output<'a, 'tcx: 'a>(
+        &'a self,
+        cx: &'a Context<'tcx>,
+    ) -> impl fmt::Display + 'a + Captures<'tcx> {
+        display_fn(move |f| match &self.output {
+            clean::Tuple(tys) if tys.is_empty() => Ok(()),
+            ty if f.alternate() => {
+                write!(f, " -> {:#}", ty.print(cx))
+            }
+            ty => write!(f, " -&gt; {}", ty.print(cx)),
+        })
+    }
 }
 
 pub(crate) fn visibility_print_with_space<'a, 'tcx: 'a>(
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 09e7ed293d4..b26a5c32ec6 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -781,7 +781,7 @@ impl<'tcx> ExtraInfo<'tcx> {
         ExtraInfo { def_id, sp, tcx }
     }
 
-    fn error_invalid_codeblock_attr(&self, msg: String, help: &str) {
+    fn error_invalid_codeblock_attr(&self, msg: String, help: &'static str) {
         if let Some(def_id) = self.def_id.as_local() {
             self.tcx.struct_span_lint_hir(
                 crate::lint::INVALID_CODEBLOCK_ATTRIBUTES,
@@ -1237,7 +1237,27 @@ pub(crate) fn plain_text_summary(md: &str, link_names: &[RenderedLink]) -> Strin
 pub(crate) struct MarkdownLink {
     pub kind: LinkType,
     pub link: String,
-    pub range: Range<usize>,
+    pub range: MarkdownLinkRange,
+}
+
+#[derive(Clone, Debug)]
+pub(crate) enum MarkdownLinkRange {
+    /// Normally, markdown link warnings point only at the destination.
+    Destination(Range<usize>),
+    /// In some cases, it's not possible to point at the destination.
+    /// Usually, this happens because backslashes `\\` are used.
+    /// When that happens, point at the whole link, and don't provide structured suggestions.
+    WholeLink(Range<usize>),
+}
+
+impl MarkdownLinkRange {
+    /// Extracts the inner range.
+    pub fn inner_range(&self) -> &Range<usize> {
+        match self {
+            MarkdownLinkRange::Destination(range) => range,
+            MarkdownLinkRange::WholeLink(range) => range,
+        }
+    }
 }
 
 pub(crate) fn markdown_links<R>(
@@ -1257,9 +1277,9 @@ pub(crate) fn markdown_links<R>(
         if md_start <= s_start && s_end <= md_end {
             let start = s_start.offset_from(md_start) as usize;
             let end = s_end.offset_from(md_start) as usize;
-            start..end
+            MarkdownLinkRange::Destination(start..end)
         } else {
-            fallback
+            MarkdownLinkRange::WholeLink(fallback)
         }
     };
 
@@ -1267,6 +1287,7 @@ pub(crate) fn markdown_links<R>(
         // For diagnostics, we want to underline the link's definition but `span` will point at
         // where the link is used. This is a problem for reference-style links, where the definition
         // is separate from the usage.
+
         match link {
             // `Borrowed` variant means the string (the link's destination) may come directly from
             // the markdown text and we can locate the original link destination.
@@ -1275,8 +1296,80 @@ pub(crate) fn markdown_links<R>(
             CowStr::Borrowed(s) => locate(s, span),
 
             // For anything else, we can only use the provided range.
-            CowStr::Boxed(_) | CowStr::Inlined(_) => span,
+            CowStr::Boxed(_) | CowStr::Inlined(_) => MarkdownLinkRange::WholeLink(span),
+        }
+    };
+
+    let span_for_offset_backward = |span: Range<usize>, open: u8, close: u8| {
+        let mut open_brace = !0;
+        let mut close_brace = !0;
+        for (i, b) in md.as_bytes()[span.clone()].iter().copied().enumerate().rev() {
+            let i = i + span.start;
+            if b == close {
+                close_brace = i;
+                break;
+            }
+        }
+        if close_brace < span.start || close_brace >= span.end {
+            return MarkdownLinkRange::WholeLink(span);
+        }
+        let mut nesting = 1;
+        for (i, b) in md.as_bytes()[span.start..close_brace].iter().copied().enumerate().rev() {
+            let i = i + span.start;
+            if b == close {
+                nesting += 1;
+            }
+            if b == open {
+                nesting -= 1;
+            }
+            if nesting == 0 {
+                open_brace = i;
+                break;
+            }
+        }
+        assert!(open_brace != close_brace);
+        if open_brace < span.start || open_brace >= span.end {
+            return MarkdownLinkRange::WholeLink(span);
+        }
+        // do not actually include braces in the span
+        let range = (open_brace + 1)..close_brace;
+        MarkdownLinkRange::Destination(range.clone())
+    };
+
+    let span_for_offset_forward = |span: Range<usize>, open: u8, close: u8| {
+        let mut open_brace = !0;
+        let mut close_brace = !0;
+        for (i, b) in md.as_bytes()[span.clone()].iter().copied().enumerate() {
+            let i = i + span.start;
+            if b == open {
+                open_brace = i;
+                break;
+            }
+        }
+        if open_brace < span.start || open_brace >= span.end {
+            return MarkdownLinkRange::WholeLink(span);
         }
+        let mut nesting = 0;
+        for (i, b) in md.as_bytes()[open_brace..span.end].iter().copied().enumerate() {
+            let i = i + open_brace;
+            if b == close {
+                nesting -= 1;
+            }
+            if b == open {
+                nesting += 1;
+            }
+            if nesting == 0 {
+                close_brace = i;
+                break;
+            }
+        }
+        assert!(open_brace != close_brace);
+        if open_brace < span.start || open_brace >= span.end {
+            return MarkdownLinkRange::WholeLink(span);
+        }
+        // do not actually include braces in the span
+        let range = (open_brace + 1)..close_brace;
+        MarkdownLinkRange::Destination(range.clone())
     };
 
     Parser::new_with_broken_link_callback(
@@ -1287,11 +1380,20 @@ pub(crate) fn markdown_links<R>(
     .into_offset_iter()
     .filter_map(|(event, span)| match event {
         Event::Start(Tag::Link(link_type, dest, _)) if may_be_doc_link(link_type) => {
-            preprocess_link(MarkdownLink {
-                kind: link_type,
-                range: span_for_link(&dest, span),
-                link: dest.into_string(),
-            })
+            let range = match link_type {
+                // Link is pulled from the link itself.
+                LinkType::ReferenceUnknown | LinkType::ShortcutUnknown => {
+                    span_for_offset_backward(span, b'[', b']')
+                }
+                LinkType::CollapsedUnknown => span_for_offset_forward(span, b'[', b']'),
+                LinkType::Inline => span_for_offset_backward(span, b'(', b')'),
+                // Link is pulled from elsewhere in the document.
+                LinkType::Reference | LinkType::Collapsed | LinkType::Shortcut => {
+                    span_for_link(&dest, span)
+                }
+                LinkType::Autolink | LinkType::Email => unreachable!(),
+            };
+            preprocess_link(MarkdownLink { kind: link_type, range, link: dest.into_string() })
         }
         _ => None,
     })
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 42e27d35a94..a5223bd6309 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -844,7 +844,7 @@ fn assoc_method(
         + name.as_str().len()
         + generics_len;
 
-    let notable_traits = d.output.as_return().and_then(|output| notable_traits_button(output, cx));
+    let notable_traits = notable_traits_button(&d.output, cx);
 
     let (indent, indent_str, end_newline) = if parent == ItemType::Trait {
         header_len += 4;
@@ -1282,6 +1282,11 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) ->
 pub(crate) fn notable_traits_button(ty: &clean::Type, cx: &mut Context<'_>) -> Option<String> {
     let mut has_notable_trait = false;
 
+    if ty.is_unit() {
+        // Very common fast path.
+        return None;
+    }
+
     let did = ty.def_id(cx.cache())?;
 
     // Box has pass-through impls for Read, Write, Iterator, and Future when the
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index 76c8e0885a0..21f61acb2c5 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -9,6 +9,8 @@ use rustc_middle::middle::stability;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{kw, sym, Symbol};
+use std::borrow::Borrow;
+use std::cell::{RefCell, RefMut};
 use std::cmp::Ordering;
 use std::fmt;
 use std::rc::Rc;
@@ -216,6 +218,53 @@ fn toggle_close(mut w: impl fmt::Write) {
     w.write_str("</details>").unwrap();
 }
 
+trait ItemTemplate<'a, 'cx: 'a>: askama::Template + fmt::Display {
+    fn item_and_mut_cx(&self) -> (&'a clean::Item, RefMut<'_, &'a mut Context<'cx>>);
+}
+
+fn item_template_document<'a: 'b, 'b, 'cx: 'a>(
+    templ: &'b impl ItemTemplate<'a, 'cx>,
+) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
+    display_fn(move |f| {
+        let (item, mut cx) = templ.item_and_mut_cx();
+        let v = document(*cx, item, None, HeadingOffset::H2);
+        write!(f, "{v}")
+    })
+}
+
+fn item_template_document_type_layout<'a: 'b, 'b, 'cx: 'a>(
+    templ: &'b impl ItemTemplate<'a, 'cx>,
+) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
+    display_fn(move |f| {
+        let (item, cx) = templ.item_and_mut_cx();
+        let def_id = item.item_id.expect_def_id();
+        let v = document_type_layout(*cx, def_id);
+        write!(f, "{v}")
+    })
+}
+
+fn item_template_render_attributes_in_pre<'a: 'b, 'b, 'cx: 'a>(
+    templ: &'b impl ItemTemplate<'a, 'cx>,
+) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
+    display_fn(move |f| {
+        let (item, cx) = templ.item_and_mut_cx();
+        let tcx = cx.tcx();
+        let v = render_attributes_in_pre(item, "", tcx);
+        write!(f, "{v}")
+    })
+}
+
+fn item_template_render_assoc_items<'a: 'b, 'b, 'cx: 'a>(
+    templ: &'b impl ItemTemplate<'a, 'cx>,
+) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
+    display_fn(move |f| {
+        let (item, mut cx) = templ.item_and_mut_cx();
+        let def_id = item.item_id.expect_def_id();
+        let v = render_assoc_items(*cx, item, def_id, AssocItemRender::All);
+        write!(f, "{v}")
+    })
+}
+
 fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: &[clean::Item]) {
     write!(w, "{}", document(cx, item, None, HeadingOffset::H2));
 
@@ -356,18 +405,18 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
 
             clean::ImportItem(ref import) => {
                 let stab_tags = if let Some(import_def_id) = import.source.did {
-                    let ast_attrs = cx.tcx().get_attrs_unchecked(import_def_id);
+                    let ast_attrs = tcx.get_attrs_unchecked(import_def_id);
                     let import_attrs = Box::new(clean::Attributes::from_ast(ast_attrs));
 
                     // Just need an item with the correct def_id and attrs
                     let import_item = clean::Item {
                         item_id: import_def_id.into(),
                         attrs: import_attrs,
-                        cfg: ast_attrs.cfg(cx.tcx(), &cx.cache().hidden_cfg),
+                        cfg: ast_attrs.cfg(tcx, &cx.cache().hidden_cfg),
                         ..myitem.clone()
                     };
 
-                    let stab_tags = Some(extra_info_tags(&import_item, item, cx.tcx()).to_string());
+                    let stab_tags = Some(extra_info_tags(&import_item, item, tcx).to_string());
                     stab_tags
                 } else {
                     None
@@ -405,8 +454,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
 
                 let unsafety_flag = match *myitem.kind {
                     clean::FunctionItem(_) | clean::ForeignFunctionItem(_)
-                        if myitem.fn_header(cx.tcx()).unwrap().unsafety
-                            == hir::Unsafety::Unsafe =>
+                        if myitem.fn_header(tcx).unwrap().unsafety == hir::Unsafety::Unsafe =>
                     {
                         "<sup title=\"unsafe function\">⚠</sup>"
                     }
@@ -439,7 +487,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
                      {docs_before}{docs}{docs_after}",
                     name = myitem.name.unwrap(),
                     visibility_emoji = visibility_emoji,
-                    stab_tags = extra_info_tags(myitem, item, cx.tcx()),
+                    stab_tags = extra_info_tags(myitem, item, tcx),
                     class = myitem.type_(),
                     unsafety_flag = unsafety_flag,
                     href = item_path(myitem.type_(), myitem.name.unwrap().as_str()),
@@ -539,8 +587,7 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle
         + name.as_str().len()
         + generics_len;
 
-    let notable_traits =
-        f.decl.output.as_return().and_then(|output| notable_traits_button(output, cx));
+    let notable_traits = notable_traits_button(&f.decl.output, cx);
 
     wrap_item(w, |w| {
         w.reserve(header_len);
@@ -886,7 +933,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
             write_small_section_header(w, "foreign-impls", "Implementations on Foreign Types", "");
 
             for implementor in foreign {
-                let provided_methods = implementor.inner_impl().provided_trait_methods(cx.tcx());
+                let provided_methods = implementor.inner_impl().provided_trait_methods(tcx);
                 let assoc_link =
                     AssocItemLink::GotoSource(implementor.impl_item.item_id, &provided_methods);
                 render_impl(
@@ -919,7 +966,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
         }
         w.write_str("</div>");
 
-        if t.is_auto(cx.tcx()) {
+        if t.is_auto(tcx) {
             write_small_section_header(
                 w,
                 "synthetic-implementors",
@@ -948,7 +995,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
             "<div id=\"implementors-list\"></div>",
         );
 
-        if t.is_auto(cx.tcx()) {
+        if t.is_auto(tcx) {
             write_small_section_header(
                 w,
                 "synthetic-implementors",
@@ -1131,32 +1178,18 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean:
     #[derive(Template)]
     #[template(path = "item_union.html")]
     struct ItemUnion<'a, 'cx> {
-        cx: std::cell::RefCell<&'a mut Context<'cx>>,
+        cx: RefCell<&'a mut Context<'cx>>,
         it: &'a clean::Item,
         s: &'a clean::Union,
     }
 
-    impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> {
-        fn render_assoc_items<'b>(
-            &'b self,
-        ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
-            display_fn(move |f| {
-                let def_id = self.it.item_id.expect_def_id();
-                let mut cx = self.cx.borrow_mut();
-                let v = render_assoc_items(*cx, self.it, def_id, AssocItemRender::All);
-                write!(f, "{v}")
-            })
-        }
-        fn document_type_layout<'b>(
-            &'b self,
-        ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
-            display_fn(move |f| {
-                let def_id = self.it.item_id.expect_def_id();
-                let cx = self.cx.borrow_mut();
-                let v = document_type_layout(*cx, def_id);
-                write!(f, "{v}")
-            })
+    impl<'a, 'cx: 'a> ItemTemplate<'a, 'cx> for ItemUnion<'a, 'cx> {
+        fn item_and_mut_cx(&self) -> (&'a clean::Item, RefMut<'_, &'a mut Context<'cx>>) {
+            (self.it, self.cx.borrow_mut())
         }
+    }
+
+    impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> {
         fn render_union<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
             display_fn(move |f| {
                 let cx = self.cx.borrow_mut();
@@ -1164,22 +1197,6 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean:
                 write!(f, "{v}")
             })
         }
-        fn render_attributes_in_pre<'b>(
-            &'b self,
-        ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
-            display_fn(move |f| {
-                let tcx = self.cx.borrow().tcx();
-                let v = render_attributes_in_pre(self.it, "", tcx);
-                write!(f, "{v}")
-            })
-        }
-        fn document<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
-            display_fn(move |f| {
-                let mut cx = self.cx.borrow_mut();
-                let v = document(*cx, self.it, None, HeadingOffset::H2);
-                write!(f, "{v}")
-            })
-        }
         fn document_field<'b>(
             &'b self,
             field: &'a clean::Item,
@@ -1219,7 +1236,7 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean:
         }
     }
 
-    ItemUnion { cx: std::cell::RefCell::new(cx), it, s }.render_into(w).unwrap();
+    ItemUnion { cx: RefCell::new(cx), it, s }.render_into(w).unwrap();
 }
 
 fn print_tuple_struct_fields<'a, 'cx: 'a>(
@@ -1402,30 +1419,36 @@ fn item_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
     write!(w, "{}", document(cx, it, None, HeadingOffset::H2))
 }
 
-fn item_proc_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, m: &clean::ProcMacro) {
-    wrap_item(w, |w| {
+fn item_proc_macro(
+    w: &mut impl fmt::Write,
+    cx: &mut Context<'_>,
+    it: &clean::Item,
+    m: &clean::ProcMacro,
+) {
+    let mut buffer = Buffer::new();
+    wrap_item(&mut buffer, |buffer| {
         let name = it.name.expect("proc-macros always have names");
         match m.kind {
             MacroKind::Bang => {
-                write!(w, "{}!() {{ /* proc-macro */ }}", name);
+                write!(buffer, "{}!() {{ /* proc-macro */ }}", name);
             }
             MacroKind::Attr => {
-                write!(w, "#[{}]", name);
+                write!(buffer, "#[{}]", name);
             }
             MacroKind::Derive => {
-                write!(w, "#[derive({})]", name);
+                write!(buffer, "#[derive({})]", name);
                 if !m.helpers.is_empty() {
-                    w.push_str("\n{\n");
-                    w.push_str("    // Attributes available to this derive:\n");
+                    buffer.push_str("\n{\n");
+                    buffer.push_str("    // Attributes available to this derive:\n");
                     for attr in &m.helpers {
-                        writeln!(w, "    #[{}]", attr);
+                        writeln!(buffer, "    #[{}]", attr);
                     }
-                    w.push_str("}\n");
+                    buffer.push_str("}\n");
                 }
             }
         }
     });
-    write!(w, "{}", document(cx, it, None, HeadingOffset::H2))
+    write!(w, "{}{}", buffer.into_inner(), document(cx, it, None, HeadingOffset::H2)).unwrap();
 }
 
 fn item_primitive(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
@@ -1541,11 +1564,12 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean
     write!(w, "{}", document_type_layout(cx, def_id));
 }
 
-fn item_static(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Static) {
-    wrap_item(w, |w| {
-        render_attributes_in_code(w, it, cx.tcx());
+fn item_static(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Static) {
+    let mut buffer = Buffer::new();
+    wrap_item(&mut buffer, |buffer| {
+        render_attributes_in_code(buffer, it, cx.tcx());
         write!(
-            w,
+            buffer,
             "{vis}static {mutability}{name}: {typ}",
             vis = visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx),
             mutability = s.mutability.print_with_space(),
@@ -1553,24 +1577,29 @@ fn item_static(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean
             typ = s.type_.print(cx)
         );
     });
-    write!(w, "{}", document(cx, it, None, HeadingOffset::H2))
+
+    write!(w, "{}", buffer.into_inner()).unwrap();
+
+    write!(w, "{}", document(cx, it, None, HeadingOffset::H2)).unwrap();
 }
 
-fn item_foreign_type(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
-    wrap_item(w, |w| {
-        w.write_str("extern {\n");
-        render_attributes_in_code(w, it, cx.tcx());
+fn item_foreign_type(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Item) {
+    let mut buffer = Buffer::new();
+    wrap_item(&mut buffer, |buffer| {
+        buffer.write_str("extern {\n");
+        render_attributes_in_code(buffer, it, cx.tcx());
         write!(
-            w,
+            buffer,
             "    {}type {};\n}}",
             visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx),
             it.name.unwrap(),
         );
     });
 
-    write!(w, "{}", document(cx, it, None, HeadingOffset::H2));
+    write!(w, "{}{}", buffer.into_inner(), document(cx, it, None, HeadingOffset::H2)).unwrap();
 
     write!(w, "{}", render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All))
+        .unwrap();
 }
 
 fn item_keyword(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs
index 846299f02e3..f34be120d29 100644
--- a/src/librustdoc/html/render/search_index.rs
+++ b/src/librustdoc/html/render/search_index.rs
@@ -7,7 +7,7 @@ use rustc_span::symbol::Symbol;
 use serde::ser::{Serialize, SerializeStruct, Serializer};
 
 use crate::clean;
-use crate::clean::types::{FnRetTy, Function, Generics, ItemId, Type, WherePredicate};
+use crate::clean::types::{Function, Generics, ItemId, Type, WherePredicate};
 use crate::formats::cache::{Cache, OrphanImplItem};
 use crate::formats::item_type::ItemType;
 use crate::html::format::join_with_double_colon;
@@ -656,22 +656,9 @@ fn get_fn_inputs_and_outputs<'tcx>(
     }
 
     let mut ret_types = Vec::new();
-    match decl.output {
-        FnRetTy::Return(ref return_type) => {
-            add_generics_and_bounds_as_types(
-                self_,
-                generics,
-                return_type,
-                tcx,
-                0,
-                &mut ret_types,
-                cache,
-            );
-            if ret_types.is_empty() {
-                ret_types.push(get_index_type(return_type, vec![]));
-            }
-        }
-        _ => {}
-    };
+    add_generics_and_bounds_as_types(self_, generics, &decl.output, tcx, 0, &mut ret_types, cache);
+    if ret_types.is_empty() {
+        ret_types.push(get_index_type(&decl.output, vec![]));
+    }
     (all_types, ret_types)
 }
diff --git a/src/librustdoc/html/render/type_layout.rs b/src/librustdoc/html/render/type_layout.rs
index 22aec623335..c9b95b1e645 100644
--- a/src/librustdoc/html/render/type_layout.rs
+++ b/src/librustdoc/html/render/type_layout.rs
@@ -54,13 +54,13 @@ pub(crate) fn document_type_layout<'a, 'cx: 'a>(
                     } else if let Primitive::Int(i, _) = tag.primitive() {
                         i.size().bytes()
                     } else {
-                        span_bug!(cx.tcx().def_span(ty_def_id), "tag is neither niche nor int")
+                        span_bug!(tcx.def_span(ty_def_id), "tag is neither niche nor int")
                     };
                 variants
                     .iter_enumerated()
                     .map(|(variant_idx, variant_layout)| {
                         let Adt(adt, _) = type_layout.ty.kind() else {
-                            span_bug!(cx.tcx().def_span(ty_def_id), "not an adt")
+                            span_bug!(tcx.def_span(ty_def_id), "not an adt")
                         };
                         let name = adt.variant(variant_idx).name;
                         let is_unsized = variant_layout.abi.is_unsized();
diff --git a/src/librustdoc/html/templates/item_union.html b/src/librustdoc/html/templates/item_union.html
index a01457971c1..c2196700513 100644
--- a/src/librustdoc/html/templates/item_union.html
+++ b/src/librustdoc/html/templates/item_union.html
@@ -1,8 +1,8 @@
 <pre class="rust item-decl"><code>
-    {{ self.render_attributes_in_pre() | safe }}
+    {{ self::item_template_render_attributes_in_pre(self.borrow()) | safe }}
     {{ self.render_union() | safe }}
 </code></pre>
-{{ self.document() | safe }}
+{{ self::item_template_document(self.borrow()) | safe }}
 {% if self.fields_iter().peek().is_some() %}
     <h2 id="fields" class="fields small-section-header">
         Fields<a href="#fields" class="anchor">§</a>
@@ -19,5 +19,5 @@
         {{ self.document_field(field) | safe }}
     {% endfor %}
 {% endif %}
-{{ self.render_assoc_items() | safe }}
-{{ self.document_type_layout() | safe }}
+{{ self::item_template_render_assoc_items(self.borrow()) | safe }}
+{{ self::item_template_document_type_layout(self.borrow()) | safe }}
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index 935bb721f18..91cd55b1113 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -624,10 +624,7 @@ impl FromWithTcx<clean::FnDecl> for FnDecl {
                 .into_iter()
                 .map(|arg| (arg.name.to_string(), arg.type_.into_tcx(tcx)))
                 .collect(),
-            output: match output {
-                clean::FnRetTy::Return(t) => Some(t.into_tcx(tcx)),
-                clean::FnRetTy::DefaultReturn => None,
-            },
+            output: if output.is_unit() { None } else { Some(output.into_tcx(tcx)) },
             c_variadic,
         }
     }
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 0a56916edcd..12c622e026f 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -712,13 +712,23 @@ fn run_renderer<'tcx, T: formats::FormatRenderer<'tcx>>(
 }
 
 fn main_args(at_args: &[String]) -> MainResult {
+    // Throw away the first argument, the name of the binary.
+    // In case of at_args being empty, as might be the case by
+    // passing empty argument array to execve under some platforms,
+    // just use an empty slice.
+    //
+    // This situation was possible before due to arg_expand_all being
+    // called before removing the argument, enabling a crash by calling
+    // the compiler with @empty_file as argv[0] and no more arguments.
+    let at_args = at_args.get(1..).unwrap_or_default();
+
     let args = rustc_driver::args::arg_expand_all(at_args);
 
     let mut options = getopts::Options::new();
     for option in opts() {
         (option.apply)(&mut options);
     }
-    let matches = match options.parse(&args[1..]) {
+    let matches = match options.parse(&args) {
         Ok(m) => m,
         Err(err) => {
             early_error(ErrorOutputType::default(), err.to_string());
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 9e6894a77df..2b0fef267e9 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -31,7 +31,7 @@ use std::ops::Range;
 use crate::clean::{self, utils::find_nearest_parent_module};
 use crate::clean::{Crate, Item, ItemLink, PrimitiveType};
 use crate::core::DocContext;
-use crate::html::markdown::{markdown_links, MarkdownLink};
+use crate::html::markdown::{markdown_links, MarkdownLink, MarkdownLinkRange};
 use crate::lint::{BROKEN_INTRA_DOC_LINKS, PRIVATE_INTRA_DOC_LINKS};
 use crate::passes::Pass;
 use crate::visit::DocVisitor;
@@ -248,7 +248,7 @@ struct DiagnosticInfo<'a> {
     item: &'a Item,
     dox: &'a str,
     ori_link: &'a str,
-    link_range: Range<usize>,
+    link_range: MarkdownLinkRange,
 }
 
 struct LinkCollector<'a, 'tcx> {
@@ -723,7 +723,7 @@ fn resolve_associated_trait_item<'a>(
         .iter()
         .flat_map(|&(impl_, trait_)| {
             filter_assoc_items_by_name_and_namespace(
-                cx.tcx,
+                tcx,
                 trait_,
                 Ident::with_dummy_span(item_name),
                 ns,
@@ -833,7 +833,7 @@ impl<'a, 'tcx> DocVisitor for LinkCollector<'a, 'tcx> {
 enum PreprocessingError {
     /// User error: `[std#x#y]` is not valid
     MultipleAnchors,
-    Disambiguator(Range<usize>, String),
+    Disambiguator(MarkdownLinkRange, String),
     MalformedGenerics(MalformedGenerics, String),
 }
 
@@ -842,7 +842,7 @@ impl PreprocessingError {
         match self {
             PreprocessingError::MultipleAnchors => report_multiple_anchors(cx, diag_info),
             PreprocessingError::Disambiguator(range, msg) => {
-                disambiguator_error(cx, diag_info, range.clone(), msg.as_str())
+                disambiguator_error(cx, diag_info, range.clone(), msg.clone())
             }
             PreprocessingError::MalformedGenerics(err, path_str) => {
                 report_malformed_generics(cx, diag_info, *err, path_str)
@@ -873,6 +873,7 @@ pub(crate) struct PreprocessedMarkdownLink(
 /// `link_buffer` is needed for lifetime reasons; it will always be overwritten and the contents ignored.
 fn preprocess_link(
     ori_link: &MarkdownLink,
+    dox: &str,
 ) -> Option<Result<PreprocessingInfo, PreprocessingError>> {
     // [] is mostly likely not supposed to be a link
     if ori_link.link.is_empty() {
@@ -906,9 +907,15 @@ fn preprocess_link(
         Err((err_msg, relative_range)) => {
             // Only report error if we would not have ignored this link. See issue #83859.
             if !should_ignore_link_with_disambiguators(link) {
-                let no_backticks_range = range_between_backticks(ori_link);
-                let disambiguator_range = (no_backticks_range.start + relative_range.start)
-                    ..(no_backticks_range.start + relative_range.end);
+                let disambiguator_range = match range_between_backticks(&ori_link.range, dox) {
+                    MarkdownLinkRange::Destination(no_backticks_range) => {
+                        MarkdownLinkRange::Destination(
+                            (no_backticks_range.start + relative_range.start)
+                                ..(no_backticks_range.start + relative_range.end),
+                        )
+                    }
+                    mdlr @ MarkdownLinkRange::WholeLink(_) => mdlr,
+                };
                 return Some(Err(PreprocessingError::Disambiguator(disambiguator_range, err_msg)));
             } else {
                 return None;
@@ -947,7 +954,7 @@ fn preprocess_link(
 
 fn preprocessed_markdown_links(s: &str) -> Vec<PreprocessedMarkdownLink> {
     markdown_links(s, |link| {
-        preprocess_link(&link).map(|pp_link| PreprocessedMarkdownLink(pp_link, link))
+        preprocess_link(&link, s).map(|pp_link| PreprocessedMarkdownLink(pp_link, link))
     })
 }
 
@@ -1060,22 +1067,12 @@ impl LinkCollector<'_, '_> {
                     // valid omission. See https://github.com/rust-lang/rust/pull/80660#discussion_r551585677
                     // for discussion on the matter.
                     let kind = self.cx.tcx.def_kind(id);
-                    self.verify_disambiguator(
-                        path_str,
-                        ori_link,
-                        kind,
-                        id,
-                        disambiguator,
-                        item,
-                        &diag_info,
-                    )?;
+                    self.verify_disambiguator(path_str, kind, id, disambiguator, item, &diag_info)?;
                 } else {
                     match disambiguator {
                         Some(Disambiguator::Primitive | Disambiguator::Namespace(_)) | None => {}
                         Some(other) => {
-                            self.report_disambiguator_mismatch(
-                                path_str, ori_link, other, res, &diag_info,
-                            );
+                            self.report_disambiguator_mismatch(path_str, other, res, &diag_info);
                             return None;
                         }
                     }
@@ -1096,7 +1093,6 @@ impl LinkCollector<'_, '_> {
                 };
                 self.verify_disambiguator(
                     path_str,
-                    ori_link,
                     kind_for_dis,
                     id_for_dis,
                     disambiguator,
@@ -1118,7 +1114,6 @@ impl LinkCollector<'_, '_> {
     fn verify_disambiguator(
         &self,
         path_str: &str,
-        ori_link: &MarkdownLink,
         kind: DefKind,
         id: DefId,
         disambiguator: Option<Disambiguator>,
@@ -1142,7 +1137,7 @@ impl LinkCollector<'_, '_> {
                 => {}
                 (actual, Some(Disambiguator::Kind(expected))) if actual == expected => {}
                 (_, Some(specified @ Disambiguator::Kind(_) | specified @ Disambiguator::Primitive)) => {
-                    self.report_disambiguator_mismatch(path_str,ori_link,specified, Res::Def(kind, id),diag_info);
+                    self.report_disambiguator_mismatch(path_str, specified, Res::Def(kind, id), diag_info);
                     return None;
                 }
             }
@@ -1164,14 +1159,13 @@ impl LinkCollector<'_, '_> {
     fn report_disambiguator_mismatch(
         &self,
         path_str: &str,
-        ori_link: &MarkdownLink,
         specified: Disambiguator,
         resolved: Res,
         diag_info: &DiagnosticInfo<'_>,
     ) {
         // The resolved item did not match the disambiguator; give a better error than 'not found'
         let msg = format!("incompatible link kind for `{}`", path_str);
-        let callback = |diag: &mut Diagnostic, sp: Option<rustc_span::Span>| {
+        let callback = |diag: &mut Diagnostic, sp: Option<rustc_span::Span>, link_range| {
             let note = format!(
                 "this link resolved to {} {}, which is not {} {}",
                 resolved.article(),
@@ -1184,14 +1178,24 @@ impl LinkCollector<'_, '_> {
             } else {
                 diag.note(note);
             }
-            suggest_disambiguator(resolved, diag, path_str, &ori_link.link, sp);
+            suggest_disambiguator(resolved, diag, path_str, link_range, sp, diag_info);
         };
         report_diagnostic(self.cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, diag_info, callback);
     }
 
-    fn report_rawptr_assoc_feature_gate(&self, dox: &str, ori_link: &Range<usize>, item: &Item) {
-        let span = super::source_span_for_markdown_range(self.cx.tcx, dox, ori_link, &item.attrs)
-            .unwrap_or_else(|| item.attr_span(self.cx.tcx));
+    fn report_rawptr_assoc_feature_gate(
+        &self,
+        dox: &str,
+        ori_link: &MarkdownLinkRange,
+        item: &Item,
+    ) {
+        let span = super::source_span_for_markdown_range(
+            self.cx.tcx,
+            dox,
+            ori_link.inner_range(),
+            &item.attrs,
+        )
+        .unwrap_or_else(|| item.attr_span(self.cx.tcx));
         rustc_session::parse::feature_err(
             &self.cx.tcx.sess.parse_sess,
             sym::intra_doc_pointers,
@@ -1371,16 +1375,23 @@ impl LinkCollector<'_, '_> {
 /// [`Foo`]
 ///   ^^^
 /// ```
-fn range_between_backticks(ori_link: &MarkdownLink) -> Range<usize> {
-    let after_first_backtick_group = ori_link.link.bytes().position(|b| b != b'`').unwrap_or(0);
-    let before_second_backtick_group = ori_link
-        .link
+///
+/// This function does nothing if `ori_link.range` is a `MarkdownLinkRange::WholeLink`.
+fn range_between_backticks(ori_link_range: &MarkdownLinkRange, dox: &str) -> MarkdownLinkRange {
+    let range = match ori_link_range {
+        mdlr @ MarkdownLinkRange::WholeLink(_) => return mdlr.clone(),
+        MarkdownLinkRange::Destination(inner) => inner.clone(),
+    };
+    let ori_link_text = &dox[range.clone()];
+    let after_first_backtick_group = ori_link_text.bytes().position(|b| b != b'`').unwrap_or(0);
+    let before_second_backtick_group = ori_link_text
         .bytes()
         .skip(after_first_backtick_group)
         .position(|b| b == b'`')
-        .unwrap_or(ori_link.link.len());
-    (ori_link.range.start + after_first_backtick_group)
-        ..(ori_link.range.start + before_second_backtick_group)
+        .unwrap_or(ori_link_text.len());
+    MarkdownLinkRange::Destination(
+        (range.start + after_first_backtick_group)..(range.start + before_second_backtick_group),
+    )
 }
 
 /// Returns true if we should ignore `link` due to it being unlikely
@@ -1530,14 +1541,23 @@ impl Suggestion {
         sp: rustc_span::Span,
     ) -> Vec<(rustc_span::Span, String)> {
         let inner_sp = match ori_link.find('(') {
+            Some(index) if index != 0 && ori_link.as_bytes()[index - 1] == b'\\' => {
+                sp.with_hi(sp.lo() + BytePos((index - 1) as _))
+            }
             Some(index) => sp.with_hi(sp.lo() + BytePos(index as _)),
             None => sp,
         };
         let inner_sp = match ori_link.find('!') {
+            Some(index) if index != 0 && ori_link.as_bytes()[index - 1] == b'\\' => {
+                sp.with_hi(sp.lo() + BytePos((index - 1) as _))
+            }
             Some(index) => inner_sp.with_hi(inner_sp.lo() + BytePos(index as _)),
             None => inner_sp,
         };
         let inner_sp = match ori_link.find('@') {
+            Some(index) if index != 0 && ori_link.as_bytes()[index - 1] == b'\\' => {
+                sp.with_hi(sp.lo() + BytePos((index - 1) as _))
+            }
             Some(index) => inner_sp.with_lo(inner_sp.lo() + BytePos(index as u32 + 1)),
             None => inner_sp,
         };
@@ -1584,7 +1604,7 @@ fn report_diagnostic(
     lint: &'static Lint,
     msg: impl Into<DiagnosticMessage> + Display,
     DiagnosticInfo { item, ori_link: _, dox, link_range }: &DiagnosticInfo<'_>,
-    decorate: impl FnOnce(&mut Diagnostic, Option<rustc_span::Span>),
+    decorate: impl FnOnce(&mut Diagnostic, Option<rustc_span::Span>, MarkdownLinkRange),
 ) {
     let Some(hir_id) = DocContext::as_local_hir_id(tcx, item.item_id)
     else {
@@ -1596,16 +1616,32 @@ fn report_diagnostic(
     let sp = item.attr_span(tcx);
 
     tcx.struct_span_lint_hir(lint, hir_id, sp, msg, |lint| {
-        let span =
-            super::source_span_for_markdown_range(tcx, dox, link_range, &item.attrs).map(|sp| {
-                if dox.as_bytes().get(link_range.start) == Some(&b'`')
-                    && dox.as_bytes().get(link_range.end - 1) == Some(&b'`')
-                {
-                    sp.with_lo(sp.lo() + BytePos(1)).with_hi(sp.hi() - BytePos(1))
-                } else {
-                    sp
-                }
-            });
+        let (span, link_range) = match link_range {
+            MarkdownLinkRange::Destination(md_range) => {
+                let mut md_range = md_range.clone();
+                let sp = super::source_span_for_markdown_range(tcx, dox, &md_range, &item.attrs)
+                    .map(|mut sp| {
+                        while dox.as_bytes().get(md_range.start) == Some(&b' ')
+                            || dox.as_bytes().get(md_range.start) == Some(&b'`')
+                        {
+                            md_range.start += 1;
+                            sp = sp.with_lo(sp.lo() + BytePos(1));
+                        }
+                        while dox.as_bytes().get(md_range.end - 1) == Some(&b' ')
+                            || dox.as_bytes().get(md_range.end - 1) == Some(&b'`')
+                        {
+                            md_range.end -= 1;
+                            sp = sp.with_hi(sp.hi() - BytePos(1));
+                        }
+                        sp
+                    });
+                (sp, MarkdownLinkRange::Destination(md_range))
+            }
+            MarkdownLinkRange::WholeLink(md_range) => (
+                super::source_span_for_markdown_range(tcx, dox, &md_range, &item.attrs),
+                link_range.clone(),
+            ),
+        };
 
         if let Some(sp) = span {
             lint.set_span(sp);
@@ -1614,21 +1650,22 @@ fn report_diagnostic(
             //                       ^     ~~~~
             //                       |     link_range
             //                       last_new_line_offset
-            let last_new_line_offset = dox[..link_range.start].rfind('\n').map_or(0, |n| n + 1);
+            let md_range = link_range.inner_range().clone();
+            let last_new_line_offset = dox[..md_range.start].rfind('\n').map_or(0, |n| n + 1);
             let line = dox[last_new_line_offset..].lines().next().unwrap_or("");
 
-            // Print the line containing the `link_range` and manually mark it with '^'s.
+            // Print the line containing the `md_range` and manually mark it with '^'s.
             lint.note(format!(
                 "the link appears in this line:\n\n{line}\n\
                      {indicator: <before$}{indicator:^<found$}",
                 line = line,
                 indicator = "",
-                before = link_range.start - last_new_line_offset,
-                found = link_range.len(),
+                before = md_range.start - last_new_line_offset,
+                found = md_range.len(),
             ));
         }
 
-        decorate(lint, span);
+        decorate(lint, span, link_range);
 
         lint
     });
@@ -1652,7 +1689,7 @@ fn resolution_failure(
         BROKEN_INTRA_DOC_LINKS,
         format!("unresolved link to `{}`", path_str),
         &diag_info,
-        |diag, sp| {
+        |diag, sp, link_range| {
             let item = |res: Res| format!("the {} `{}`", res.descr(), res.name(tcx),);
             let assoc_item_not_allowed = |res: Res| {
                 let name = res.name(tcx);
@@ -1706,7 +1743,7 @@ fn resolution_failure(
                             if let Ok(v_res) = collector.resolve(start, ns, item_id, module_id) {
                                 debug!("found partial_res={:?}", v_res);
                                 if !v_res.is_empty() {
-                                    *partial_res = Some(full_res(collector.cx.tcx, v_res[0]));
+                                    *partial_res = Some(full_res(tcx, v_res[0]));
                                     *unresolved = end.into();
                                     break 'outer;
                                 }
@@ -1845,7 +1882,14 @@ fn resolution_failure(
                 let note = match failure {
                     ResolutionFailure::NotResolved { .. } => unreachable!("handled above"),
                     ResolutionFailure::WrongNamespace { res, expected_ns } => {
-                        suggest_disambiguator(res, diag, path_str, diag_info.ori_link, sp);
+                        suggest_disambiguator(
+                            res,
+                            diag,
+                            path_str,
+                            link_range.clone(),
+                            sp,
+                            &diag_info,
+                        );
 
                         format!(
                             "this link resolves to {}, which is not in the {} namespace",
@@ -1882,7 +1926,7 @@ fn anchor_failure(
     msg: String,
     anchor_idx: usize,
 ) {
-    report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, &diag_info, |diag, sp| {
+    report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, &diag_info, |diag, sp, _link_range| {
         if let Some(mut sp) = sp {
             if let Some((fragment_offset, _)) =
                 diag_info.ori_link.char_indices().filter(|(_, x)| *x == '#').nth(anchor_idx)
@@ -1898,11 +1942,11 @@ fn anchor_failure(
 fn disambiguator_error(
     cx: &DocContext<'_>,
     mut diag_info: DiagnosticInfo<'_>,
-    disambiguator_range: Range<usize>,
+    disambiguator_range: MarkdownLinkRange,
     msg: impl Into<DiagnosticMessage> + Display,
 ) {
     diag_info.link_range = disambiguator_range;
-    report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, &diag_info, |diag, _sp| {
+    report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, &diag_info, |diag, _sp, _link_range| {
         let msg = format!(
             "see {}/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators",
             crate::DOC_RUST_LANG_ORG_CHANNEL
@@ -1922,7 +1966,7 @@ fn report_malformed_generics(
         BROKEN_INTRA_DOC_LINKS,
         format!("unresolved link to `{}`", path_str),
         &diag_info,
-        |diag, sp| {
+        |diag, sp, _link_range| {
             let note = match err {
                 MalformedGenerics::UnbalancedAngleBrackets => "unbalanced angle brackets",
                 MalformedGenerics::MissingType => "missing type for generic parameters",
@@ -1995,7 +2039,7 @@ fn ambiguity_error(
         }
     }
 
-    report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, diag_info, |diag, sp| {
+    report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, diag_info, |diag, sp, link_range| {
         if let Some(sp) = sp {
             diag.span_label(sp, "ambiguous link");
         } else {
@@ -2003,7 +2047,7 @@ fn ambiguity_error(
         }
 
         for res in kinds {
-            suggest_disambiguator(res, diag, path_str, diag_info.ori_link, sp);
+            suggest_disambiguator(res, diag, path_str, link_range.clone(), sp, diag_info);
         }
     });
     true
@@ -2015,13 +2059,19 @@ fn suggest_disambiguator(
     res: Res,
     diag: &mut Diagnostic,
     path_str: &str,
-    ori_link: &str,
+    link_range: MarkdownLinkRange,
     sp: Option<rustc_span::Span>,
+    diag_info: &DiagnosticInfo<'_>,
 ) {
     let suggestion = res.disambiguator_suggestion();
     let help = format!("to link to the {}, {}", res.descr(), suggestion.descr());
 
-    if let Some(sp) = sp {
+    let ori_link = match link_range {
+        MarkdownLinkRange::Destination(range) => Some(&diag_info.dox[range]),
+        MarkdownLinkRange::WholeLink(_) => None,
+    };
+
+    if let (Some(sp), Some(ori_link)) = (sp, ori_link) {
         let mut spans = suggestion.as_help_span(path_str, ori_link, sp);
         if spans.len() > 1 {
             diag.multipart_suggestion(help, spans, Applicability::MaybeIncorrect);
@@ -2047,7 +2097,7 @@ fn privacy_error(cx: &DocContext<'_>, diag_info: &DiagnosticInfo<'_>, path_str:
     let msg =
         format!("public documentation for `{}` links to private item `{}`", item_name, path_str);
 
-    report_diagnostic(cx.tcx, PRIVATE_INTRA_DOC_LINKS, msg, diag_info, |diag, sp| {
+    report_diagnostic(cx.tcx, PRIVATE_INTRA_DOC_LINKS, msg, diag_info, |diag, sp, _link_range| {
         if let Some(sp) = sp {
             diag.span_label(sp, "this item is private");
         }
diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs
index 8d204ddb79e..fbf827cce09 100644
--- a/src/librustdoc/passes/collect_trait_impls.rs
+++ b/src/librustdoc/passes/collect_trait_impls.rs
@@ -19,9 +19,10 @@ pub(crate) const COLLECT_TRAIT_IMPLS: Pass = Pass {
 };
 
 pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate {
+    let tcx = cx.tcx;
     // We need to check if there are errors before running this pass because it would crash when
     // we try to get auto and blanket implementations.
-    if cx.tcx.sess.diagnostic().has_errors_or_lint_errors().is_some() {
+    if tcx.sess.diagnostic().has_errors_or_lint_errors().is_some() {
         return krate;
     }
 
@@ -32,8 +33,7 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) ->
     });
 
     let local_crate = ExternalCrate { crate_num: LOCAL_CRATE };
-    let prims: FxHashSet<PrimitiveType> =
-        local_crate.primitives(cx.tcx).iter().map(|p| p.1).collect();
+    let prims: FxHashSet<PrimitiveType> = local_crate.primitives(tcx).iter().map(|p| p.1).collect();
 
     let crate_items = {
         let mut coll = ItemCollector::new();
@@ -46,9 +46,9 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) ->
 
     // External trait impls.
     {
-        let _prof_timer = cx.tcx.sess.prof.generic_activity("build_extern_trait_impls");
-        for &cnum in cx.tcx.crates(()) {
-            for &impl_def_id in cx.tcx.trait_impls_in_crate(cnum) {
+        let _prof_timer = tcx.sess.prof.generic_activity("build_extern_trait_impls");
+        for &cnum in tcx.crates(()) {
+            for &impl_def_id in tcx.trait_impls_in_crate(cnum) {
                 inline::build_impl(cx, impl_def_id, None, &mut new_items_external);
             }
         }
@@ -56,14 +56,13 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) ->
 
     // Local trait impls.
     {
-        let _prof_timer = cx.tcx.sess.prof.generic_activity("build_local_trait_impls");
+        let _prof_timer = tcx.sess.prof.generic_activity("build_local_trait_impls");
         let mut attr_buf = Vec::new();
-        for &impl_def_id in cx.tcx.trait_impls_in_crate(LOCAL_CRATE) {
-            let mut parent = Some(cx.tcx.parent(impl_def_id));
+        for &impl_def_id in tcx.trait_impls_in_crate(LOCAL_CRATE) {
+            let mut parent = Some(tcx.parent(impl_def_id));
             while let Some(did) = parent {
                 attr_buf.extend(
-                    cx.tcx
-                        .get_attrs(did, sym::doc)
+                    tcx.get_attrs(did, sym::doc)
                         .filter(|attr| {
                             if let Some([attr]) = attr.meta_item_list().as_deref() {
                                 attr.has_name(sym::cfg)
@@ -73,25 +72,24 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) ->
                         })
                         .cloned(),
                 );
-                parent = cx.tcx.opt_parent(did);
+                parent = tcx.opt_parent(did);
             }
             inline::build_impl(cx, impl_def_id, Some((&attr_buf, None)), &mut new_items_local);
             attr_buf.clear();
         }
     }
 
-    cx.tcx.sess.prof.generic_activity("build_primitive_trait_impls").run(|| {
-        for def_id in PrimitiveType::all_impls(cx.tcx) {
+    tcx.sess.prof.generic_activity("build_primitive_trait_impls").run(|| {
+        for def_id in PrimitiveType::all_impls(tcx) {
             // Try to inline primitive impls from other crates.
             if !def_id.is_local() {
                 inline::build_impl(cx, def_id, None, &mut new_items_external);
             }
         }
-        for (prim, did) in PrimitiveType::primitive_locations(cx.tcx) {
+        for (prim, did) in PrimitiveType::primitive_locations(tcx) {
             // Do not calculate blanket impl list for docs that are not going to be rendered.
             // While the `impl` blocks themselves are only in `libcore`, the module with `doc`
             // attached is directly included in `libstd` as well.
-            let tcx = cx.tcx;
             if did.is_local() {
                 for def_id in prim.impls(tcx).filter(|def_id| {
                     // Avoid including impl blocks with filled-in generics.
@@ -157,7 +155,7 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) ->
     // scan through included items ahead of time to splice in Deref targets to the "valid" sets
     for it in new_items_external.iter().chain(new_items_local.iter()) {
         if let ImplItem(box Impl { ref for_, ref trait_, ref items, .. }) = *it.kind &&
-            trait_.as_ref().map(|t| t.def_id()) == cx.tcx.lang_items().deref_trait() &&
+            trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait() &&
             cleaner.keep_impl(for_, true)
         {
             let target = items
@@ -199,7 +197,7 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) ->
         if let ImplItem(box Impl { ref for_, ref trait_, ref kind, .. }) = *it.kind {
             cleaner.keep_impl(
                 for_,
-                trait_.as_ref().map(|t| t.def_id()) == cx.tcx.lang_items().deref_trait(),
+                trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait(),
             ) || trait_.as_ref().map_or(false, |t| cleaner.keep_impl_with_def_id(t.def_id().into()))
                 || kind.is_blanket()
         } else {
diff --git a/src/librustdoc/passes/lint/bare_urls.rs b/src/librustdoc/passes/lint/bare_urls.rs
index a10d5fdb410..e9cee92d22b 100644
--- a/src/librustdoc/passes/lint/bare_urls.rs
+++ b/src/librustdoc/passes/lint/bare_urls.rs
@@ -20,19 +20,20 @@ pub(super) fn visit_item(cx: &DocContext<'_>, item: &Item) {
         };
     let dox = item.doc_value();
     if !dox.is_empty() {
-        let report_diag = |cx: &DocContext<'_>, msg: &str, url: &str, range: Range<usize>| {
-            let sp = source_span_for_markdown_range(cx.tcx, &dox, &range, &item.attrs)
-                .unwrap_or_else(|| item.attr_span(cx.tcx));
-            cx.tcx.struct_span_lint_hir(crate::lint::BARE_URLS, hir_id, sp, msg, |lint| {
-                lint.note("bare URLs are not automatically turned into clickable links")
-                    .span_suggestion(
-                        sp,
-                        "use an automatic link instead",
-                        format!("<{}>", url),
-                        Applicability::MachineApplicable,
-                    )
-            });
-        };
+        let report_diag =
+            |cx: &DocContext<'_>, msg: &'static str, url: &str, range: Range<usize>| {
+                let sp = source_span_for_markdown_range(cx.tcx, &dox, &range, &item.attrs)
+                    .unwrap_or_else(|| item.attr_span(cx.tcx));
+                cx.tcx.struct_span_lint_hir(crate::lint::BARE_URLS, hir_id, sp, msg, |lint| {
+                    lint.note("bare URLs are not automatically turned into clickable links")
+                        .span_suggestion(
+                            sp,
+                            "use an automatic link instead",
+                            format!("<{}>", url),
+                            Applicability::MachineApplicable,
+                        )
+                });
+            };
 
         let mut p = Parser::new_ext(&dox, main_body_opts()).into_offset_iter();
 
@@ -72,7 +73,7 @@ fn find_raw_urls(
     cx: &DocContext<'_>,
     text: &str,
     range: Range<usize>,
-    f: &impl Fn(&DocContext<'_>, &str, &str, Range<usize>),
+    f: &impl Fn(&DocContext<'_>, &'static str, &str, Range<usize>),
 ) {
     trace!("looking for raw urls in {}", text);
     // For now, we only check "full" URLs (meaning, starting with "http://" or "https://").
diff --git a/src/librustdoc/passes/lint/html_tags.rs b/src/librustdoc/passes/lint/html_tags.rs
index f0403647af0..5273f52bc6f 100644
--- a/src/librustdoc/passes/lint/html_tags.rs
+++ b/src/librustdoc/passes/lint/html_tags.rs
@@ -17,90 +17,96 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) {
     else { return };
     let dox = item.doc_value();
     if !dox.is_empty() {
-        let report_diag = |msg: &str, range: &Range<usize>, is_open_tag: bool| {
+        let report_diag = |msg: String, range: &Range<usize>, is_open_tag: bool| {
             let sp = match source_span_for_markdown_range(tcx, &dox, range, &item.attrs) {
                 Some(sp) => sp,
                 None => item.attr_span(tcx),
             };
-            tcx.struct_span_lint_hir(crate::lint::INVALID_HTML_TAGS, hir_id, sp, msg, |lint| {
-                use rustc_lint_defs::Applicability;
-                // If a tag looks like `<this>`, it might actually be a generic.
-                // We don't try to detect stuff `<like, this>` because that's not valid HTML,
-                // and we don't try to detect stuff `<like this>` because that's not valid Rust.
-                let mut generics_end = range.end;
-                if let Some(Some(mut generics_start)) = (is_open_tag
-                    && dox[..generics_end].ends_with('>'))
-                .then(|| extract_path_backwards(&dox, range.start))
-                {
-                    while generics_start != 0
-                        && generics_end < dox.len()
-                        && dox.as_bytes()[generics_start - 1] == b'<'
-                        && dox.as_bytes()[generics_end] == b'>'
+            tcx.struct_span_lint_hir(
+                crate::lint::INVALID_HTML_TAGS,
+                hir_id,
+                sp,
+                msg.to_string(),
+                |lint| {
+                    use rustc_lint_defs::Applicability;
+                    // If a tag looks like `<this>`, it might actually be a generic.
+                    // We don't try to detect stuff `<like, this>` because that's not valid HTML,
+                    // and we don't try to detect stuff `<like this>` because that's not valid Rust.
+                    let mut generics_end = range.end;
+                    if let Some(Some(mut generics_start)) = (is_open_tag
+                        && dox[..generics_end].ends_with('>'))
+                    .then(|| extract_path_backwards(&dox, range.start))
                     {
-                        generics_end += 1;
-                        generics_start -= 1;
-                        if let Some(new_start) = extract_path_backwards(&dox, generics_start) {
-                            generics_start = new_start;
+                        while generics_start != 0
+                            && generics_end < dox.len()
+                            && dox.as_bytes()[generics_start - 1] == b'<'
+                            && dox.as_bytes()[generics_end] == b'>'
+                        {
+                            generics_end += 1;
+                            generics_start -= 1;
+                            if let Some(new_start) = extract_path_backwards(&dox, generics_start) {
+                                generics_start = new_start;
+                            }
+                            if let Some(new_end) = extract_path_forward(&dox, generics_end) {
+                                generics_end = new_end;
+                            }
                         }
                         if let Some(new_end) = extract_path_forward(&dox, generics_end) {
                             generics_end = new_end;
                         }
+                        let generics_sp = match source_span_for_markdown_range(
+                            tcx,
+                            &dox,
+                            &(generics_start..generics_end),
+                            &item.attrs,
+                        ) {
+                            Some(sp) => sp,
+                            None => item.attr_span(tcx),
+                        };
+                        // Sometimes, we only extract part of a path. For example, consider this:
+                        //
+                        //     <[u32] as IntoIter<u32>>::Item
+                        //                       ^^^^^ unclosed HTML tag `u32`
+                        //
+                        // We don't have any code for parsing fully-qualified trait paths.
+                        // In theory, we could add it, but doing it correctly would require
+                        // parsing the entire path grammar, which is problematic because of
+                        // overlap between the path grammar and Markdown.
+                        //
+                        // The example above shows that ambiguity. Is `[u32]` intended to be an
+                        // intra-doc link to the u32 primitive, or is it intended to be a slice?
+                        //
+                        // If the below conditional were removed, we would suggest this, which is
+                        // not what the user probably wants.
+                        //
+                        //     <[u32] as `IntoIter<u32>`>::Item
+                        //
+                        // We know that the user actually wants to wrap the whole thing in a code
+                        // block, but the only reason we know that is because `u32` does not, in
+                        // fact, implement IntoIter. If the example looks like this:
+                        //
+                        //     <[Vec<i32>] as IntoIter<i32>::Item
+                        //
+                        // The ideal fix would be significantly different.
+                        if (generics_start > 0 && dox.as_bytes()[generics_start - 1] == b'<')
+                            || (generics_end < dox.len() && dox.as_bytes()[generics_end] == b'>')
+                        {
+                            return lint;
+                        }
+                        // multipart form is chosen here because ``Vec<i32>`` would be confusing.
+                        lint.multipart_suggestion(
+                            "try marking as source code",
+                            vec![
+                                (generics_sp.shrink_to_lo(), String::from("`")),
+                                (generics_sp.shrink_to_hi(), String::from("`")),
+                            ],
+                            Applicability::MaybeIncorrect,
+                        );
                     }
-                    if let Some(new_end) = extract_path_forward(&dox, generics_end) {
-                        generics_end = new_end;
-                    }
-                    let generics_sp = match source_span_for_markdown_range(
-                        tcx,
-                        &dox,
-                        &(generics_start..generics_end),
-                        &item.attrs,
-                    ) {
-                        Some(sp) => sp,
-                        None => item.attr_span(tcx),
-                    };
-                    // Sometimes, we only extract part of a path. For example, consider this:
-                    //
-                    //     <[u32] as IntoIter<u32>>::Item
-                    //                       ^^^^^ unclosed HTML tag `u32`
-                    //
-                    // We don't have any code for parsing fully-qualified trait paths.
-                    // In theory, we could add it, but doing it correctly would require
-                    // parsing the entire path grammar, which is problematic because of
-                    // overlap between the path grammar and Markdown.
-                    //
-                    // The example above shows that ambiguity. Is `[u32]` intended to be an
-                    // intra-doc link to the u32 primitive, or is it intended to be a slice?
-                    //
-                    // If the below conditional were removed, we would suggest this, which is
-                    // not what the user probably wants.
-                    //
-                    //     <[u32] as `IntoIter<u32>`>::Item
-                    //
-                    // We know that the user actually wants to wrap the whole thing in a code
-                    // block, but the only reason we know that is because `u32` does not, in
-                    // fact, implement IntoIter. If the example looks like this:
-                    //
-                    //     <[Vec<i32>] as IntoIter<i32>::Item
-                    //
-                    // The ideal fix would be significantly different.
-                    if (generics_start > 0 && dox.as_bytes()[generics_start - 1] == b'<')
-                        || (generics_end < dox.len() && dox.as_bytes()[generics_end] == b'>')
-                    {
-                        return lint;
-                    }
-                    // multipart form is chosen here because ``Vec<i32>`` would be confusing.
-                    lint.multipart_suggestion(
-                        "try marking as source code",
-                        vec![
-                            (generics_sp.shrink_to_lo(), String::from("`")),
-                            (generics_sp.shrink_to_hi(), String::from("`")),
-                        ],
-                        Applicability::MaybeIncorrect,
-                    );
-                }
 
-                lint
-            });
+                    lint
+                },
+            );
         };
 
         let mut tags = Vec::new();
@@ -147,11 +153,11 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) {
             let t = t.to_lowercase();
             !ALLOWED_UNCLOSED.contains(&t.as_str())
         }) {
-            report_diag(&format!("unclosed HTML tag `{}`", tag), range, true);
+            report_diag(format!("unclosed HTML tag `{}`", tag), range, true);
         }
 
         if let Some(range) = is_in_comment {
-            report_diag("Unclosed HTML comment", &range, false);
+            report_diag("Unclosed HTML comment".to_string(), &range, false);
         }
     }
 }
@@ -165,7 +171,7 @@ fn drop_tag(
     tags: &mut Vec<(String, Range<usize>)>,
     tag_name: String,
     range: Range<usize>,
-    f: &impl Fn(&str, &Range<usize>, bool),
+    f: &impl Fn(String, &Range<usize>, bool),
 ) {
     let tag_name_low = tag_name.to_lowercase();
     if let Some(pos) = tags.iter().rposition(|(t, _)| t.to_lowercase() == tag_name_low) {
@@ -186,14 +192,14 @@ fn drop_tag(
             // `tags` is used as a queue, meaning that everything after `pos` is included inside it.
             // So `<h2><h3></h2>` will look like `["h2", "h3"]`. So when closing `h2`, we will still
             // have `h3`, meaning the tag wasn't closed as it should have.
-            f(&format!("unclosed HTML tag `{}`", last_tag_name), &last_tag_span, true);
+            f(format!("unclosed HTML tag `{}`", last_tag_name), &last_tag_span, true);
         }
         // Remove the `tag_name` that was originally closed
         tags.pop();
     } else {
         // It can happen for example in this case: `<h2></script></h2>` (the `h2` tag isn't required
         // but it helps for the visualization).
-        f(&format!("unopened HTML tag `{}`", tag_name), &range, false);
+        f(format!("unopened HTML tag `{}`", tag_name), &range, false);
     }
 }
 
@@ -261,7 +267,7 @@ fn extract_html_tag(
     range: &Range<usize>,
     start_pos: usize,
     iter: &mut Peekable<CharIndices<'_>>,
-    f: &impl Fn(&str, &Range<usize>, bool),
+    f: &impl Fn(String, &Range<usize>, bool),
 ) {
     let mut tag_name = String::new();
     let mut is_closing = false;
@@ -347,7 +353,7 @@ fn extract_html_tag(
                     if let Some(quote_pos) = quote_pos {
                         let qr = Range { start: quote_pos, end: quote_pos };
                         f(
-                            &format!("unclosed quoted HTML attribute on tag `{}`", tag_name),
+                            format!("unclosed quoted HTML attribute on tag `{}`", tag_name),
                             &qr,
                             false,
                         );
@@ -360,7 +366,7 @@ fn extract_html_tag(
                                 at == "svg" || at == "math"
                             });
                         if !valid {
-                            f(&format!("invalid self-closing HTML tag `{}`", tag_name), &r, false);
+                            f(format!("invalid self-closing HTML tag `{}`", tag_name), &r, false);
                         }
                     } else {
                         tags.push((tag_name, r));
@@ -378,7 +384,7 @@ fn extract_tags(
     text: &str,
     range: Range<usize>,
     is_in_comment: &mut Option<Range<usize>>,
-    f: &impl Fn(&str, &Range<usize>, bool),
+    f: &impl Fn(String, &Range<usize>, bool),
 ) {
     let mut iter = text.char_indices().peekable();
 
diff --git a/src/librustdoc/passes/lint/unescaped_backticks.rs b/src/librustdoc/passes/lint/unescaped_backticks.rs
index 683c224c4be..256958d7160 100644
--- a/src/librustdoc/passes/lint/unescaped_backticks.rs
+++ b/src/librustdoc/passes/lint/unescaped_backticks.rs
@@ -56,7 +56,7 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) {
                 )
                 .unwrap_or_else(|| item.attr_span(tcx));
 
-                cx.tcx.struct_span_lint_hir(crate::lint::UNESCAPED_BACKTICKS, hir_id, span, "unescaped backtick", |lint| {
+                tcx.struct_span_lint_hir(crate::lint::UNESCAPED_BACKTICKS, hir_id, span, "unescaped backtick", |lint| {
                     let mut help_emitted = false;
 
                     match element.prev_code_guess {
@@ -373,7 +373,7 @@ fn suggest_insertion(
     lint: &mut DiagnosticBuilder<'_, ()>,
     insert_index: usize,
     suggestion: char,
-    message: &str,
+    message: &'static str,
 ) {
     /// Maximum bytes of context to show around the insertion.
     const CONTEXT_MAX_LEN: usize = 80;
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 8f8dc6b7090..abb9229fbd5 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -267,6 +267,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         let is_no_inline = use_attrs.lists(sym::doc).has_word(sym::no_inline)
             || use_attrs.lists(sym::doc).has_word(sym::hidden);
 
+        if is_no_inline {
+            return false;
+        }
+
         // For cross-crate impl inlining we need to know whether items are
         // reachable in documentation -- a previously unreachable item can be
         // made reachable by cross-crate inlining which we're checking here.
@@ -280,40 +284,57 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             return false;
         };
 
-        let is_private =
-            !self.cx.cache.effective_visibilities.is_directly_public(self.cx.tcx, ori_res_did);
-        let is_hidden = inherits_doc_hidden(self.cx.tcx, res_did, None);
+        let is_private = !self.cx.cache.effective_visibilities.is_directly_public(tcx, ori_res_did);
+        let is_hidden = tcx.is_doc_hidden(ori_res_did);
+        let item = tcx.hir().get_by_def_id(res_did);
 
-        // Only inline if requested or if the item would otherwise be stripped.
-        if (!please_inline && !is_private && !is_hidden) || is_no_inline {
-            return false;
-        }
-
-        if !please_inline &&
-            let Some(item_def_id) = reexport_chain(self.cx.tcx, def_id, res_did).iter()
+        if !please_inline {
+            let inherits_hidden = inherits_doc_hidden(tcx, res_did, None);
+            // Only inline if requested or if the item would otherwise be stripped.
+            //
+            // If it's a doc hidden module, we need to keep it in case some of its inner items
+            // are re-exported.
+            if (!is_private && !inherits_hidden) || (
+                is_hidden &&
+                !matches!(item, Node::Item(&hir::Item { kind: hir::ItemKind::Mod(_), .. }))
+            ) {
+                return false;
+            } else if let Some(item_def_id) = reexport_chain(tcx, def_id, res_did).iter()
                 .flat_map(|reexport| reexport.id()).map(|id| id.expect_local())
                 .chain(iter::once(res_did)).nth(1) &&
-            item_def_id != def_id &&
-            self
-                .cx
-                .cache
-                .effective_visibilities
-                .is_directly_public(self.cx.tcx, item_def_id.to_def_id()) &&
-            !inherits_doc_hidden(self.cx.tcx, item_def_id, None)
-        {
-            // The imported item is public and not `doc(hidden)` so no need to inline it.
-            return false;
+                item_def_id != def_id &&
+                self
+                    .cx
+                    .cache
+                    .effective_visibilities
+                    .is_directly_public(tcx, item_def_id.to_def_id()) &&
+                !inherits_doc_hidden(tcx, item_def_id, None)
+            {
+                // The imported item is public and not `doc(hidden)` so no need to inline it.
+                return false;
+            }
         }
 
-        if !self.view_item_stack.insert(res_did) {
+        let is_bang_macro = matches!(
+            item,
+            Node::Item(&hir::Item { kind: hir::ItemKind::Macro(_, MacroKind::Bang), .. })
+        );
+
+        if !self.view_item_stack.insert(res_did) && !is_bang_macro {
             return false;
         }
 
         let ret = match tcx.hir().get_by_def_id(res_did) {
+            // Bang macros are handled a bit on their because of how they are handled by the
+            // compiler. If they have `#[doc(hidden)]` and the re-export doesn't have
+            // `#[doc(inline)]`, then we don't inline it.
+            Node::Item(_) if is_bang_macro && !please_inline && renamed.is_some() && is_hidden => {
+                return false;
+            }
             Node::Item(&hir::Item { kind: hir::ItemKind::Mod(ref m), .. }) if glob => {
                 let prev = mem::replace(&mut self.inlining, true);
                 for &i in m.item_ids {
-                    let i = self.cx.tcx.hir().item(i);
+                    let i = tcx.hir().item(i);
                     self.visit_item_inner(i, None, Some(def_id));
                 }
                 self.inlining = prev;
@@ -440,6 +461,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                             is_glob,
                             please_inline,
                         ) {
+                            debug!("Inlining {:?}", item.owner_id.def_id);
                             continue;
                         }
                     }
diff --git a/src/tools/build_helper/src/lib.rs b/src/tools/build_helper/src/lib.rs
index d3d2323db85..3fa970373b3 100644
--- a/src/tools/build_helper/src/lib.rs
+++ b/src/tools/build_helper/src/lib.rs
@@ -1,2 +1,3 @@
 pub mod ci;
 pub mod git;
+pub mod util;
diff --git a/src/tools/build_helper/src/util.rs b/src/tools/build_helper/src/util.rs
new file mode 100644
index 00000000000..731095023a9
--- /dev/null
+++ b/src/tools/build_helper/src/util.rs
@@ -0,0 +1,41 @@
+use std::process::Command;
+
+/// Invokes `build_helper::util::detail_exit` with `cfg!(test)`
+#[macro_export]
+macro_rules! detail_exit_macro {
+    ($code:expr) => {
+        build_helper::util::detail_exit($code, cfg!(test));
+    };
+}
+
+/// If code is not 0 (successful exit status), exit status is 101 (rust's default error code.)
+/// If `is_test` true and code is an error code, it will cause a panic.
+pub fn detail_exit(code: i32, is_test: bool) -> ! {
+    // if in test and code is an error code, panic with status code provided
+    if is_test {
+        panic!("status code: {}", code);
+    } else {
+        // otherwise,exit with provided status code
+        std::process::exit(code);
+    }
+}
+
+pub fn fail(s: &str) -> ! {
+    eprintln!("\n\n{}\n\n", s);
+    detail_exit(1, cfg!(test));
+}
+
+pub fn try_run(cmd: &mut Command, print_cmd_on_fail: bool) -> bool {
+    let status = match cmd.status() {
+        Ok(status) => status,
+        Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", cmd, e)),
+    };
+    if !status.success() && print_cmd_on_fail {
+        println!(
+            "\n\ncommand did not execute successfully: {:?}\n\
+             expected success, got: {}\n\n",
+            cmd, status
+        );
+    }
+    status.success()
+}
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 64fb38c97ac4d3a327fc9032c862dd28c8833b1
+Subproject f7b95e31642e09c2b6eabb18ed75007dda6677a
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index 423eee47742..0ae95b045e0 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -212,7 +212,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::instant_subtraction::UNCHECKED_DURATION_SUBTRACTION_INFO,
     crate::int_plus_one::INT_PLUS_ONE_INFO,
     crate::invalid_upcast_comparisons::INVALID_UPCAST_COMPARISONS_INFO,
-    crate::invalid_utf8_in_unchecked::INVALID_UTF8_IN_UNCHECKED_INFO,
     crate::items_after_statements::ITEMS_AFTER_STATEMENTS_INFO,
     crate::items_after_test_module::ITEMS_AFTER_TEST_MODULE_INFO,
     crate::iter_not_returning_iterator::ITER_NOT_RETURNING_ITERATOR_INFO,
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index b27ffe73ffd..a1d2147cb49 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -1219,7 +1219,7 @@ fn needless_borrow_impl_arg_position<'tcx>(
                 return false;
             }
 
-            let predicate = EarlyBinder(predicate).subst(cx.tcx, &substs_with_referent_ty);
+            let predicate = EarlyBinder::bind(predicate).subst(cx.tcx, &substs_with_referent_ty);
             let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), cx.param_env, predicate);
             let infcx = cx.tcx.infer_ctxt().build();
             infcx.predicate_must_hold_modulo_regions(&obligation)
diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
index b2071f4dcb1..c919b4de65d 100644
--- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs
+++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
@@ -243,7 +243,7 @@ fn get_ufcs_type_name<'tcx>(cx: &LateContext<'tcx>, method_def_id: DefId, substs
                 | ty::Ref(..)
                 | ty::Slice(_)
                 | ty::Tuple(_) => {
-                    format!("<{}>", EarlyBinder(ty).subst(cx.tcx, substs))
+                    format!("<{}>", EarlyBinder::bind(ty).subst(cx.tcx, substs))
                 },
                 _ => ty.to_string(),
             }
diff --git a/src/tools/clippy/clippy_lints/src/invalid_utf8_in_unchecked.rs b/src/tools/clippy/clippy_lints/src/invalid_utf8_in_unchecked.rs
deleted file mode 100644
index 6a4861747d2..00000000000
--- a/src/tools/clippy/clippy_lints/src/invalid_utf8_in_unchecked.rs
+++ /dev/null
@@ -1,74 +0,0 @@
-use clippy_utils::diagnostics::span_lint;
-use clippy_utils::{match_function_call, paths};
-use rustc_ast::{BorrowKind, LitKind};
-use rustc_hir::{Expr, ExprKind};
-use rustc_lint::{LateContext, LateLintPass};
-use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::source_map::Spanned;
-use rustc_span::Span;
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for `std::str::from_utf8_unchecked` with an invalid UTF-8 literal
-    ///
-    /// ### Why is this bad?
-    /// Creating such a `str` would result in undefined behavior
-    ///
-    /// ### Example
-    /// ```rust
-    /// # #[allow(unused)]
-    /// unsafe {
-    ///     std::str::from_utf8_unchecked(b"cl\x82ippy");
-    /// }
-    /// ```
-    #[clippy::version = "1.64.0"]
-    pub INVALID_UTF8_IN_UNCHECKED,
-    correctness,
-    "using a non UTF-8 literal in `std::std::from_utf8_unchecked`"
-}
-declare_lint_pass!(InvalidUtf8InUnchecked => [INVALID_UTF8_IN_UNCHECKED]);
-
-impl<'tcx> LateLintPass<'tcx> for InvalidUtf8InUnchecked {
-    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
-        if let Some([arg]) = match_function_call(cx, expr, &paths::STR_FROM_UTF8_UNCHECKED) {
-            match &arg.kind {
-                ExprKind::Lit(Spanned { node: lit, .. }) => {
-                    if let LitKind::ByteStr(bytes, _) = &lit
-                        && std::str::from_utf8(bytes).is_err()
-                    {
-                        lint(cx, expr.span);
-                    }
-                },
-                ExprKind::AddrOf(BorrowKind::Ref, _, Expr { kind: ExprKind::Array(args), .. }) => {
-                    let elements = args.iter().map(|e|{
-                        match &e.kind {
-                            ExprKind::Lit(Spanned { node: lit, .. }) => match lit {
-                                LitKind::Byte(b) => Some(*b),
-                                #[allow(clippy::cast_possible_truncation)]
-                                LitKind::Int(b, _) => Some(*b as u8),
-                                _ => None
-                            }
-                            _ => None
-                        }
-                    }).collect::<Option<Vec<_>>>();
-
-                    if let Some(elements) = elements
-                        && std::str::from_utf8(&elements).is_err()
-                    {
-                        lint(cx, expr.span);
-                    }
-                }
-                _ => {}
-            }
-        }
-    }
-}
-
-fn lint(cx: &LateContext<'_>, span: Span) {
-    span_lint(
-        cx,
-        INVALID_UTF8_IN_UNCHECKED,
-        span,
-        "non UTF-8 literal in `std::str::from_utf8_unchecked`",
-    );
-}
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index b442a4ac5f6..fcca595c2bc 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -157,7 +157,6 @@ mod inline_fn_without_body;
 mod instant_subtraction;
 mod int_plus_one;
 mod invalid_upcast_comparisons;
-mod invalid_utf8_in_unchecked;
 mod items_after_statements;
 mod items_after_test_module;
 mod iter_not_returning_iterator;
@@ -937,7 +936,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(move |_| Box::new(manual_retain::ManualRetain::new(msrv())));
     let verbose_bit_mask_threshold = conf.verbose_bit_mask_threshold;
     store.register_late_pass(move |_| Box::new(operators::Operators::new(verbose_bit_mask_threshold)));
-    store.register_late_pass(|_| Box::new(invalid_utf8_in_unchecked::InvalidUtf8InUnchecked));
     store.register_late_pass(|_| Box::<std_instead_of_core::StdReexports>::default());
     store.register_late_pass(move |_| Box::new(instant_subtraction::InstantSubtraction::new(msrv())));
     store.register_late_pass(|_| Box::new(partialeq_to_none::PartialeqToNone));
diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
index 6841aaf626c..99f810c27cf 100644
--- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
@@ -241,7 +241,7 @@ fn is_contains_sig(cx: &LateContext<'_>, call_id: HirId, iter_expr: &Expr<'_>) -
         && let proj_ty = cx.tcx.mk_projection(iter_item.def_id, substs)
         && let Ok(item_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, proj_ty)
     {
-        item_ty == EarlyBinder(search_ty).subst(cx.tcx, cx.typeck_results().node_substs(call_id))
+        item_ty == EarlyBinder::bind(search_ty).subst(cx.tcx, cx.typeck_results().node_substs(call_id))
     } else {
         false
     }
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 67b7d3691dc..309d2157b76 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
@@ -428,7 +428,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
                                      }));
 
                         if trait_predicates.any(|predicate| {
-                            let predicate = EarlyBinder(predicate).subst(cx.tcx, new_subst);
+                            let predicate = EarlyBinder::bind(predicate).subst(cx.tcx, new_subst);
                             let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), cx.param_env, predicate);
                             !cx.tcx.infer_ctxt().build().predicate_must_hold_modulo_regions(&obligation)
                         }) {
@@ -438,7 +438,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
                         let output_ty = fn_sig.output();
                         if output_ty.contains(*param_ty) {
                             if let Ok(new_ty)  = cx.tcx.try_subst_and_normalize_erasing_regions(
-                                new_subst, cx.param_env, EarlyBinder(output_ty)) {
+                                new_subst, cx.param_env, EarlyBinder::bind(output_ty)) {
                                 expr = parent_expr;
                                 ty = new_ty;
                                 continue;
diff --git a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
index f1831a30461..3b7eccad79d 100644
--- a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
@@ -154,7 +154,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn {
 
         if let Err((span, err)) = is_min_const_fn(cx.tcx, mir, &self.msrv) {
             if cx.tcx.is_const_fn_raw(def_id.to_def_id()) {
-                cx.tcx.sess.span_err(span, err.as_ref());
+                cx.tcx.sess.span_err(span, err);
             }
         } else {
             span_lint(cx, MISSING_CONST_FOR_FN, span, "this could be a `const fn`");
diff --git a/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs
index 2abdfacd276..e6fd65f001a 100644
--- a/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs
+++ b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs
@@ -138,7 +138,7 @@ fn collect_unsafe_exprs<'tcx>(
                     .type_dependent_def_id(expr.hir_id)
                     .map(|def_id| cx.tcx.fn_sig(def_id))
                 {
-                    if sig.0.unsafety() == Unsafety::Unsafe {
+                    if sig.skip_binder().unsafety() == Unsafety::Unsafe {
                         unsafe_ops.push(("unsafe method call occurs here", expr.span));
                     }
                 }
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
index 0bb1775aae9..7d53fe65658 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
@@ -26,7 +26,6 @@ use rustc_span::{sym, Span};
 use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::traits;
 use rustc_trait_selection::traits::misc::type_allowed_to_implement_copy;
-use std::borrow::Cow;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -240,9 +239,8 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
                                         snippet_opt(cx, span)
                                             .map_or(
                                                 "change the call to".into(),
-                                                |x| Cow::from(format!("change `{x}` to")),
-                                            )
-                                            .as_ref(),
+                                                |x| format!("change `{x}` to"),
+                                            ),
                                         suggestion,
                                         Applicability::Unspecified,
                                     );
@@ -270,9 +268,8 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
                                         snippet_opt(cx, span)
                                             .map_or(
                                                 "change the call to".into(),
-                                                |x| Cow::from(format!("change `{x}` to"))
-                                            )
-                                            .as_ref(),
+                                                |x| format!("change `{x}` to")
+                                            ),
                                         suggestion,
                                         Applicability::Unspecified,
                                     );
diff --git a/src/tools/clippy/clippy_lints/src/renamed_lints.rs b/src/tools/clippy/clippy_lints/src/renamed_lints.rs
index b0db56bb417..7c2a100efda 100644
--- a/src/tools/clippy/clippy_lints/src/renamed_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/renamed_lints.rs
@@ -43,6 +43,7 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[
     ("clippy::into_iter_on_array", "array_into_iter"),
     ("clippy::invalid_atomic_ordering", "invalid_atomic_ordering"),
     ("clippy::invalid_ref", "invalid_value"),
+    ("clippy::invalid_utf8_in_unchecked", "invalid_from_utf8_unchecked"),
     ("clippy::let_underscore_drop", "let_underscore_drop"),
     ("clippy::mem_discriminant_non_enum", "enum_intrinsics_non_enums"),
     ("clippy::panic_params", "non_fmt_panics"),
diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
index 8b0e0ce5a30..5073eb02bd8 100644
--- a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
+++ b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
@@ -163,7 +163,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps {
             span_lint_and_then(cx, UNNECESSARY_WRAPS, span, lint_msg.as_str(), |diag| {
                 diag.span_suggestion(
                     fn_decl.output.span(),
-                    return_type_sugg_msg.as_str(),
+                    return_type_sugg_msg,
                     return_type_sugg,
                     Applicability::MaybeIncorrect,
                 );
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index fb772644c0d..cc3183759ae 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -462,7 +462,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
                 let substs = if self.substs.is_empty() {
                     substs
                 } else {
-                    EarlyBinder(substs).subst(self.lcx.tcx, self.substs)
+                    EarlyBinder::bind(substs).subst(self.lcx.tcx, self.substs)
                 };
 
                 let result = self
diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs
index 812f6fe71a0..edd87546a5f 100644
--- a/src/tools/clippy/clippy_utils/src/diagnostics.rs
+++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs
@@ -46,7 +46,7 @@ fn docs_link(diag: &mut Diagnostic, lint: &'static Lint) {
 ///    |     ^^^^^^^^^^^^^^^^^^^^^^^
 /// ```
 pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: impl Into<MultiSpan>, msg: &str) {
-    cx.struct_span_lint(lint, sp, msg, |diag| {
+    cx.struct_span_lint(lint, sp, msg.to_string(), |diag| {
         docs_link(diag, lint);
         diag
     });
@@ -80,11 +80,12 @@ pub fn span_lint_and_help<T: LintContext>(
     help_span: Option<Span>,
     help: &str,
 ) {
-    cx.struct_span_lint(lint, span, msg, |diag| {
+    cx.struct_span_lint(lint, span, msg.to_string(), |diag| {
+        let help = help.to_string();
         if let Some(help_span) = help_span {
-            diag.span_help(help_span, help);
+            diag.span_help(help_span, help.to_string());
         } else {
-            diag.help(help);
+            diag.help(help.to_string());
         }
         docs_link(diag, lint);
         diag
@@ -122,7 +123,8 @@ pub fn span_lint_and_note<T: LintContext>(
     note_span: Option<Span>,
     note: &str,
 ) {
-    cx.struct_span_lint(lint, span, msg, |diag| {
+    cx.struct_span_lint(lint, span, msg.to_string(), |diag| {
+        let note = note.to_string();
         if let Some(note_span) = note_span {
             diag.span_note(note_span, note);
         } else {
@@ -143,7 +145,7 @@ where
     S: Into<MultiSpan>,
     F: FnOnce(&mut Diagnostic),
 {
-    cx.struct_span_lint(lint, sp, msg, |diag| {
+    cx.struct_span_lint(lint, sp, msg.to_string(), |diag| {
         f(diag);
         docs_link(diag, lint);
         diag
@@ -151,7 +153,7 @@ where
 }
 
 pub fn span_lint_hir(cx: &LateContext<'_>, lint: &'static Lint, hir_id: HirId, sp: Span, msg: &str) {
-    cx.tcx.struct_span_lint_hir(lint, hir_id, sp, msg, |diag| {
+    cx.tcx.struct_span_lint_hir(lint, hir_id, sp, msg.to_string(), |diag| {
         docs_link(diag, lint);
         diag
     });
@@ -165,7 +167,7 @@ pub fn span_lint_hir_and_then(
     msg: &str,
     f: impl FnOnce(&mut Diagnostic),
 ) {
-    cx.tcx.struct_span_lint_hir(lint, hir_id, sp, msg, |diag| {
+    cx.tcx.struct_span_lint_hir(lint, hir_id, sp, msg.to_string(), |diag| {
         f(diag);
         docs_link(diag, lint);
         diag
@@ -202,7 +204,7 @@ pub fn span_lint_and_sugg<T: LintContext>(
     applicability: Applicability,
 ) {
     span_lint_and_then(cx, lint, sp, msg, |diag| {
-        diag.span_suggestion(sp, help, sugg, applicability);
+        diag.span_suggestion(sp, help.to_string(), sugg, applicability);
     });
 }
 
@@ -232,5 +234,5 @@ pub fn multispan_sugg_with_applicability<I>(
 ) where
     I: IntoIterator<Item = (Span, String)>,
 {
-    diag.multipart_suggestion(help_msg, sugg.into_iter().collect(), applicability);
+    diag.multipart_suggestion(help_msg.to_string(), sugg.into_iter().collect(), applicability);
 }
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index 14f7f03016f..f477524eec5 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -741,7 +741,7 @@ impl<T: LintContext> DiagnosticExt<T> for rustc_errors::Diagnostic {
         if let Some(indent) = indentation(cx, item) {
             let span = item.with_hi(item.lo());
 
-            self.span_suggestion(span, msg, format!("{attr}\n{indent}"), applicability);
+            self.span_suggestion(span, msg.to_string(), format!("{attr}\n{indent}"), applicability);
         }
     }
 
@@ -762,7 +762,7 @@ impl<T: LintContext> DiagnosticExt<T> for rustc_errors::Diagnostic {
                 })
                 .collect::<String>();
 
-            self.span_suggestion(span, msg, format!("{new_item}\n{indent}"), applicability);
+            self.span_suggestion(span, msg.to_string(), format!("{new_item}\n{indent}"), applicability);
         }
     }
 
@@ -779,7 +779,7 @@ impl<T: LintContext> DiagnosticExt<T> for rustc_errors::Diagnostic {
             }
         }
 
-        self.span_suggestion(remove_span, msg, "", applicability);
+        self.span_suggestion(remove_span, msg.to_string(), "", applicability);
     }
 }
 
diff --git a/src/tools/clippy/tests/ui/invalid_utf8_in_unchecked.rs b/src/tools/clippy/tests/ui/invalid_utf8_in_unchecked.rs
deleted file mode 100644
index 3dc096d3197..00000000000
--- a/src/tools/clippy/tests/ui/invalid_utf8_in_unchecked.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-#![warn(clippy::invalid_utf8_in_unchecked)]
-
-fn main() {
-    // Valid
-    unsafe {
-        std::str::from_utf8_unchecked(&[99, 108, 105, 112, 112, 121]);
-        std::str::from_utf8_unchecked(&[b'c', b'l', b'i', b'p', b'p', b'y']);
-        std::str::from_utf8_unchecked(b"clippy");
-
-        let x = 0xA0;
-        std::str::from_utf8_unchecked(&[0xC0, x]);
-    }
-
-    // Invalid
-    unsafe {
-        std::str::from_utf8_unchecked(&[99, 108, 130, 105, 112, 112, 121]);
-        std::str::from_utf8_unchecked(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
-        std::str::from_utf8_unchecked(b"cl\x82ippy");
-    }
-}
diff --git a/src/tools/clippy/tests/ui/invalid_utf8_in_unchecked.stderr b/src/tools/clippy/tests/ui/invalid_utf8_in_unchecked.stderr
deleted file mode 100644
index c89cd2758ee..00000000000
--- a/src/tools/clippy/tests/ui/invalid_utf8_in_unchecked.stderr
+++ /dev/null
@@ -1,22 +0,0 @@
-error: non UTF-8 literal in `std::str::from_utf8_unchecked`
-  --> $DIR/invalid_utf8_in_unchecked.rs:16:9
-   |
-LL |         std::str::from_utf8_unchecked(&[99, 108, 130, 105, 112, 112, 121]);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `-D clippy::invalid-utf8-in-unchecked` implied by `-D warnings`
-
-error: non UTF-8 literal in `std::str::from_utf8_unchecked`
-  --> $DIR/invalid_utf8_in_unchecked.rs:17:9
-   |
-LL |         std::str::from_utf8_unchecked(&[b'c', b'l', b'/x82', b'i', b'p', b'p', b'y']);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: non UTF-8 literal in `std::str::from_utf8_unchecked`
-  --> $DIR/invalid_utf8_in_unchecked.rs:18:9
-   |
-LL |         std::str::from_utf8_unchecked(b"cl/x82ippy");
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 3 previous errors
-
diff --git a/src/tools/clippy/tests/ui/rename.fixed b/src/tools/clippy/tests/ui/rename.fixed
index dfe45dec8a7..53ac65473b8 100644
--- a/src/tools/clippy/tests/ui/rename.fixed
+++ b/src/tools/clippy/tests/ui/rename.fixed
@@ -38,6 +38,7 @@
 #![allow(array_into_iter)]
 #![allow(invalid_atomic_ordering)]
 #![allow(invalid_value)]
+#![allow(invalid_from_utf8_unchecked)]
 #![allow(let_underscore_drop)]
 #![allow(enum_intrinsics_non_enums)]
 #![allow(non_fmt_panics)]
@@ -87,6 +88,7 @@
 #![warn(array_into_iter)]
 #![warn(invalid_atomic_ordering)]
 #![warn(invalid_value)]
+#![warn(invalid_from_utf8_unchecked)]
 #![warn(let_underscore_drop)]
 #![warn(enum_intrinsics_non_enums)]
 #![warn(non_fmt_panics)]
diff --git a/src/tools/clippy/tests/ui/rename.rs b/src/tools/clippy/tests/ui/rename.rs
index ce8eca5a308..722c0b3eb27 100644
--- a/src/tools/clippy/tests/ui/rename.rs
+++ b/src/tools/clippy/tests/ui/rename.rs
@@ -38,6 +38,7 @@
 #![allow(array_into_iter)]
 #![allow(invalid_atomic_ordering)]
 #![allow(invalid_value)]
+#![allow(invalid_from_utf8_unchecked)]
 #![allow(let_underscore_drop)]
 #![allow(enum_intrinsics_non_enums)]
 #![allow(non_fmt_panics)]
@@ -87,6 +88,7 @@
 #![warn(clippy::into_iter_on_array)]
 #![warn(clippy::invalid_atomic_ordering)]
 #![warn(clippy::invalid_ref)]
+#![warn(clippy::invalid_utf8_in_unchecked)]
 #![warn(clippy::let_underscore_drop)]
 #![warn(clippy::mem_discriminant_non_enum)]
 #![warn(clippy::panic_params)]
diff --git a/src/tools/clippy/tests/ui/rename.stderr b/src/tools/clippy/tests/ui/rename.stderr
index 3fca60aa2eb..1ff83917660 100644
--- a/src/tools/clippy/tests/ui/rename.stderr
+++ b/src/tools/clippy/tests/ui/rename.stderr
@@ -1,5 +1,5 @@
 error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range`
-  --> $DIR/rename.rs:49:9
+  --> $DIR/rename.rs:50:9
    |
 LL | #![warn(clippy::almost_complete_letter_range)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range`
@@ -7,286 +7,292 @@ LL | #![warn(clippy::almost_complete_letter_range)]
    = note: `-D renamed-and-removed-lints` implied by `-D warnings`
 
 error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names`
-  --> $DIR/rename.rs:50:9
+  --> $DIR/rename.rs:51:9
    |
 LL | #![warn(clippy::blacklisted_name)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names`
 
 error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions`
-  --> $DIR/rename.rs:51:9
+  --> $DIR/rename.rs:52:9
    |
 LL | #![warn(clippy::block_in_if_condition_expr)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
 
 error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions`
-  --> $DIR/rename.rs:52:9
+  --> $DIR/rename.rs:53:9
    |
 LL | #![warn(clippy::block_in_if_condition_stmt)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
 
 error: lint `clippy::box_vec` has been renamed to `clippy::box_collection`
-  --> $DIR/rename.rs:53:9
+  --> $DIR/rename.rs:54:9
    |
 LL | #![warn(clippy::box_vec)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
 
 error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
-  --> $DIR/rename.rs:54:9
+  --> $DIR/rename.rs:55:9
    |
 LL | #![warn(clippy::const_static_lifetime)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
 
 error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity`
-  --> $DIR/rename.rs:55:9
+  --> $DIR/rename.rs:56:9
    |
 LL | #![warn(clippy::cyclomatic_complexity)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
 
 error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq`
-  --> $DIR/rename.rs:56:9
+  --> $DIR/rename.rs:57:9
    |
 LL | #![warn(clippy::derive_hash_xor_eq)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq`
 
 error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods`
-  --> $DIR/rename.rs:57:9
+  --> $DIR/rename.rs:58:9
    |
 LL | #![warn(clippy::disallowed_method)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods`
 
 error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types`
-  --> $DIR/rename.rs:58:9
+  --> $DIR/rename.rs:59:9
    |
 LL | #![warn(clippy::disallowed_type)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types`
 
 error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression`
-  --> $DIR/rename.rs:59:9
+  --> $DIR/rename.rs:60:9
    |
 LL | #![warn(clippy::eval_order_dependence)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
 
 error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
-  --> $DIR/rename.rs:60:9
+  --> $DIR/rename.rs:61:9
    |
 LL | #![warn(clippy::identity_conversion)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
 
 error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
-  --> $DIR/rename.rs:61:9
+  --> $DIR/rename.rs:62:9
    |
 LL | #![warn(clippy::if_let_some_result)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
 
 error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects`
-  --> $DIR/rename.rs:62:9
+  --> $DIR/rename.rs:63:9
    |
 LL | #![warn(clippy::integer_arithmetic)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects`
 
 error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
-  --> $DIR/rename.rs:63:9
+  --> $DIR/rename.rs:64:9
    |
 LL | #![warn(clippy::logic_bug)]
    |         ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr`
 
 error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
-  --> $DIR/rename.rs:64:9
+  --> $DIR/rename.rs:65:9
    |
 LL | #![warn(clippy::new_without_default_derive)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
 
 error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
-  --> $DIR/rename.rs:65:9
+  --> $DIR/rename.rs:66:9
    |
 LL | #![warn(clippy::option_and_then_some)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
 
 error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
-  --> $DIR/rename.rs:66:9
+  --> $DIR/rename.rs:67:9
    |
 LL | #![warn(clippy::option_expect_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
 
 error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
-  --> $DIR/rename.rs:67:9
+  --> $DIR/rename.rs:68:9
    |
 LL | #![warn(clippy::option_map_unwrap_or)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
-  --> $DIR/rename.rs:68:9
+  --> $DIR/rename.rs:69:9
    |
 LL | #![warn(clippy::option_map_unwrap_or_else)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
-  --> $DIR/rename.rs:69:9
+  --> $DIR/rename.rs:70:9
    |
 LL | #![warn(clippy::option_unwrap_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
 
 error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow`
-  --> $DIR/rename.rs:70:9
+  --> $DIR/rename.rs:71:9
    |
 LL | #![warn(clippy::ref_in_deref)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow`
 
 error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
-  --> $DIR/rename.rs:71:9
+  --> $DIR/rename.rs:72:9
    |
 LL | #![warn(clippy::result_expect_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
 
 error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
-  --> $DIR/rename.rs:72:9
+  --> $DIR/rename.rs:73:9
    |
 LL | #![warn(clippy::result_map_unwrap_or_else)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
-  --> $DIR/rename.rs:73:9
+  --> $DIR/rename.rs:74:9
    |
 LL | #![warn(clippy::result_unwrap_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
 
 error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
-  --> $DIR/rename.rs:74:9
+  --> $DIR/rename.rs:75:9
    |
 LL | #![warn(clippy::single_char_push_str)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
 
 error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
-  --> $DIR/rename.rs:75:9
+  --> $DIR/rename.rs:76:9
    |
 LL | #![warn(clippy::stutter)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
 
 error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl`
-  --> $DIR/rename.rs:76:9
+  --> $DIR/rename.rs:77:9
    |
 LL | #![warn(clippy::to_string_in_display)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl`
 
 error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters`
-  --> $DIR/rename.rs:77:9
+  --> $DIR/rename.rs:78:9
    |
 LL | #![warn(clippy::zero_width_space)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
 
 error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op`
-  --> $DIR/rename.rs:78:9
+  --> $DIR/rename.rs:79:9
    |
 LL | #![warn(clippy::clone_double_ref)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op`
 
 error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
-  --> $DIR/rename.rs:79:9
+  --> $DIR/rename.rs:80:9
    |
 LL | #![warn(clippy::drop_bounds)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
 
 error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types`
-  --> $DIR/rename.rs:80:9
+  --> $DIR/rename.rs:81:9
    |
 LL | #![warn(clippy::drop_copy)]
    |         ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types`
 
 error: lint `clippy::drop_ref` has been renamed to `dropping_references`
-  --> $DIR/rename.rs:81:9
+  --> $DIR/rename.rs:82:9
    |
 LL | #![warn(clippy::drop_ref)]
    |         ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references`
 
 error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:82:9
+  --> $DIR/rename.rs:83:9
    |
 LL | #![warn(clippy::for_loop_over_option)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:83:9
+  --> $DIR/rename.rs:84:9
    |
 LL | #![warn(clippy::for_loop_over_result)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:84:9
+  --> $DIR/rename.rs:85:9
    |
 LL | #![warn(clippy::for_loops_over_fallibles)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::forget_copy` has been renamed to `forgetting_copy_types`
-  --> $DIR/rename.rs:85:9
+  --> $DIR/rename.rs:86:9
    |
 LL | #![warn(clippy::forget_copy)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types`
 
 error: lint `clippy::forget_ref` has been renamed to `forgetting_references`
-  --> $DIR/rename.rs:86:9
+  --> $DIR/rename.rs:87:9
    |
 LL | #![warn(clippy::forget_ref)]
    |         ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references`
 
 error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
-  --> $DIR/rename.rs:87:9
+  --> $DIR/rename.rs:88:9
    |
 LL | #![warn(clippy::into_iter_on_array)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
 
 error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
-  --> $DIR/rename.rs:88:9
+  --> $DIR/rename.rs:89:9
    |
 LL | #![warn(clippy::invalid_atomic_ordering)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
 
 error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
-  --> $DIR/rename.rs:89:9
+  --> $DIR/rename.rs:90:9
    |
 LL | #![warn(clippy::invalid_ref)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
 
+error: lint `clippy::invalid_utf8_in_unchecked` has been renamed to `invalid_from_utf8_unchecked`
+  --> $DIR/rename.rs:91:9
+   |
+LL | #![warn(clippy::invalid_utf8_in_unchecked)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_from_utf8_unchecked`
+
 error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
-  --> $DIR/rename.rs:90:9
+  --> $DIR/rename.rs:92:9
    |
 LL | #![warn(clippy::let_underscore_drop)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop`
 
 error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
-  --> $DIR/rename.rs:91:9
+  --> $DIR/rename.rs:93:9
    |
 LL | #![warn(clippy::mem_discriminant_non_enum)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
 
 error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
-  --> $DIR/rename.rs:92:9
+  --> $DIR/rename.rs:94:9
    |
 LL | #![warn(clippy::panic_params)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
 
 error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally`
-  --> $DIR/rename.rs:93:9
+  --> $DIR/rename.rs:95:9
    |
 LL | #![warn(clippy::positional_named_format_parameters)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
 
 error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
-  --> $DIR/rename.rs:94:9
+  --> $DIR/rename.rs:96:9
    |
 LL | #![warn(clippy::temporary_cstring_as_ptr)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
 
 error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
-  --> $DIR/rename.rs:95:9
+  --> $DIR/rename.rs:97:9
    |
 LL | #![warn(clippy::unknown_clippy_lints)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
 
 error: lint `clippy::unused_label` has been renamed to `unused_labels`
-  --> $DIR/rename.rs:96:9
+  --> $DIR/rename.rs:98:9
    |
 LL | #![warn(clippy::unused_label)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
 
-error: aborting due to 48 previous errors
+error: aborting due to 49 previous errors
 
diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml
index e5297d41a61..d2f258320f0 100644
--- a/src/tools/compiletest/Cargo.toml
+++ b/src/tools/compiletest/Cargo.toml
@@ -3,6 +3,9 @@ name = "compiletest"
 version = "0.0.0"
 edition = "2021"
 
+[lib]
+doctest = false
+
 [dependencies]
 colored = "2"
 diff = "0.1.10"
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index ba68b5ee9d5..f796c898731 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -69,6 +69,12 @@ string_enum! {
     }
 }
 
+impl Default for Mode {
+    fn default() -> Self {
+        Mode::Ui
+    }
+}
+
 impl Mode {
     pub fn disambiguator(self) -> &'static str {
         // Pretty-printing tests could run concurrently, and if they do,
@@ -125,7 +131,7 @@ pub enum PanicStrategy {
 }
 
 /// Configuration for compiletest
-#[derive(Debug, Clone)]
+#[derive(Debug, Default, Clone)]
 pub struct Config {
     /// `true` to overwrite stderr/stdout files instead of complaining about changes in output.
     pub bless: bool,
diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs
index 4a57c61406c..18b3b913a68 100644
--- a/src/tools/compiletest/src/header/needs.rs
+++ b/src/tools/compiletest/src/header/needs.rs
@@ -71,6 +71,11 @@ pub(super) fn handle_needs(
             ignore_reason: "ignored on targets without shadow call stacks",
         },
         Need {
+            name: "needs-sanitizer-safestack",
+            condition: cache.sanitizer_safestack,
+            ignore_reason: "ignored on targets without SafeStack support",
+        },
+        Need {
             name: "needs-run-enabled",
             condition: config.run_enabled(),
             ignore_reason: "ignored when running the resulting test binaries is disabled",
@@ -184,6 +189,7 @@ pub(super) struct CachedNeedsConditions {
     sanitizer_hwaddress: bool,
     sanitizer_memtag: bool,
     sanitizer_shadow_call_stack: bool,
+    sanitizer_safestack: bool,
     xray: bool,
     rust_lld: bool,
     i686_dlltool: bool,
@@ -220,6 +226,7 @@ impl CachedNeedsConditions {
             sanitizer_hwaddress: util::HWASAN_SUPPORTED_TARGETS.contains(target),
             sanitizer_memtag: util::MEMTAG_SUPPORTED_TARGETS.contains(target),
             sanitizer_shadow_call_stack: util::SHADOWCALLSTACK_SUPPORTED_TARGETS.contains(target),
+            sanitizer_safestack: util::SAFESTACK_SUPPORTED_TARGETS.contains(target),
             xray: util::XRAY_SUPPORTED_TARGETS.contains(target),
 
             // For tests using the `needs-rust-lld` directive (e.g. for `-Zgcc-ld=lld`), we need to find
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
new file mode 100644
index 00000000000..fc48d015990
--- /dev/null
+++ b/src/tools/compiletest/src/lib.rs
@@ -0,0 +1,1136 @@
+#![crate_name = "compiletest"]
+// The `test` crate is the only unstable feature
+// allowed here, just to share similar code.
+#![feature(test)]
+
+extern crate test;
+
+#[cfg(test)]
+mod tests;
+
+pub mod common;
+pub mod compute_diff;
+pub mod errors;
+pub mod header;
+mod json;
+mod raise_fd_limit;
+mod read2;
+pub mod runtest;
+pub mod util;
+
+use crate::common::{expected_output_path, output_base_dir, output_relative_path, UI_EXTENSIONS};
+use crate::common::{Config, Debugger, Mode, PassMode, TestPaths};
+use crate::util::logv;
+use build_helper::git::{get_git_modified_files, get_git_untracked_files};
+use core::panic;
+use getopts::Options;
+use lazycell::AtomicLazyCell;
+use std::collections::BTreeSet;
+use std::ffi::OsString;
+use std::fs;
+use std::io::{self, ErrorKind};
+use std::path::{Path, PathBuf};
+use std::process::{Command, Stdio};
+use std::time::SystemTime;
+use std::{env, vec};
+use test::ColorConfig;
+use tracing::*;
+use walkdir::WalkDir;
+
+use self::header::{make_test_description, EarlyProps};
+use crate::header::HeadersCache;
+use std::sync::Arc;
+
+pub fn parse_config(args: Vec<String>) -> Config {
+    let mut opts = Options::new();
+    opts.reqopt("", "compile-lib-path", "path to host shared libraries", "PATH")
+        .reqopt("", "run-lib-path", "path to target shared libraries", "PATH")
+        .reqopt("", "rustc-path", "path to rustc to use for compiling", "PATH")
+        .optopt("", "rustdoc-path", "path to rustdoc to use for compiling", "PATH")
+        .optopt("", "rust-demangler-path", "path to rust-demangler to use in tests", "PATH")
+        .reqopt("", "python", "path to python to use for doc tests", "PATH")
+        .optopt("", "jsondocck-path", "path to jsondocck to use for doc tests", "PATH")
+        .optopt("", "jsondoclint-path", "path to jsondoclint to use for doc tests", "PATH")
+        .optopt("", "valgrind-path", "path to Valgrind executable for Valgrind tests", "PROGRAM")
+        .optflag("", "force-valgrind", "fail if Valgrind tests cannot be run under Valgrind")
+        .optopt("", "run-clang-based-tests-with", "path to Clang executable", "PATH")
+        .optopt("", "llvm-filecheck", "path to LLVM's FileCheck binary", "DIR")
+        .reqopt("", "src-base", "directory to scan for test files", "PATH")
+        .reqopt("", "build-base", "directory to deposit test outputs", "PATH")
+        .reqopt("", "sysroot-base", "directory containing the compiler sysroot", "PATH")
+        .reqopt("", "stage-id", "the target-stage identifier", "stageN-TARGET")
+        .reqopt(
+            "",
+            "mode",
+            "which sort of compile tests to run",
+            "run-pass-valgrind | pretty | debug-info | codegen | rustdoc \
+            | rustdoc-json | codegen-units | incremental | run-make | ui | js-doc-test | mir-opt | assembly",
+        )
+        .reqopt(
+            "",
+            "suite",
+            "which suite of compile tests to run. used for nicer error reporting.",
+            "SUITE",
+        )
+        .optopt(
+            "",
+            "pass",
+            "force {check,build,run}-pass tests to this mode.",
+            "check | build | run",
+        )
+        .optopt("", "run", "whether to execute run-* tests", "auto | always | never")
+        .optflag("", "ignored", "run tests marked as ignored")
+        .optmulti("", "skip", "skip tests matching SUBSTRING. Can be passed multiple times", "SUBSTRING")
+        .optflag("", "exact", "filters match exactly")
+        .optopt(
+            "",
+            "runtool",
+            "supervisor program to run tests under \
+             (eg. emulator, valgrind)",
+            "PROGRAM",
+        )
+        .optmulti("", "host-rustcflags", "flags to pass to rustc for host", "FLAGS")
+        .optmulti("", "target-rustcflags", "flags to pass to rustc for target", "FLAGS")
+        .optflag("", "optimize-tests", "run tests with optimizations enabled")
+        .optflag("", "verbose", "run tests verbosely, showing all output")
+        .optflag(
+            "",
+            "bless",
+            "overwrite stderr/stdout files instead of complaining about a mismatch",
+        )
+        .optflag("", "quiet", "print one character per test instead of one line")
+        .optopt("", "color", "coloring: auto, always, never", "WHEN")
+        .optflag("", "json", "emit json output instead of plaintext output")
+        .optopt("", "logfile", "file to log test execution to", "FILE")
+        .optopt("", "target", "the target to build for", "TARGET")
+        .optopt("", "host", "the host to build for", "HOST")
+        .optopt("", "cdb", "path to CDB to use for CDB debuginfo tests", "PATH")
+        .optopt("", "gdb", "path to GDB to use for GDB debuginfo tests", "PATH")
+        .optopt("", "lldb-version", "the version of LLDB used", "VERSION STRING")
+        .optopt("", "llvm-version", "the version of LLVM used", "VERSION STRING")
+        .optflag("", "system-llvm", "is LLVM the system LLVM")
+        .optopt("", "android-cross-path", "Android NDK standalone path", "PATH")
+        .optopt("", "adb-path", "path to the android debugger", "PATH")
+        .optopt("", "adb-test-dir", "path to tests for the android debugger", "PATH")
+        .optopt("", "lldb-python-dir", "directory containing LLDB's python module", "PATH")
+        .reqopt("", "cc", "path to a C compiler", "PATH")
+        .reqopt("", "cxx", "path to a C++ compiler", "PATH")
+        .reqopt("", "cflags", "flags for the C compiler", "FLAGS")
+        .reqopt("", "cxxflags", "flags for the CXX compiler", "FLAGS")
+        .optopt("", "ar", "path to an archiver", "PATH")
+        .optopt("", "target-linker", "path to a linker for the target", "PATH")
+        .optopt("", "host-linker", "path to a linker for the host", "PATH")
+        .reqopt("", "llvm-components", "list of LLVM components built in", "LIST")
+        .optopt("", "llvm-bin-dir", "Path to LLVM's `bin` directory", "PATH")
+        .optopt("", "nodejs", "the name of nodejs", "PATH")
+        .optopt("", "npm", "the name of npm", "PATH")
+        .optopt("", "remote-test-client", "path to the remote test client", "PATH")
+        .optopt(
+            "",
+            "compare-mode",
+            "mode describing what file the actual ui output will be compared to",
+            "COMPARE MODE",
+        )
+        .optflag(
+            "",
+            "rustfix-coverage",
+            "enable this to generate a Rustfix coverage file, which is saved in \
+            `./<build_base>/rustfix_missing_coverage.txt`",
+        )
+        .optflag("", "force-rerun", "rerun tests even if the inputs are unchanged")
+        .optflag("", "only-modified", "only run tests that result been modified")
+        .optflag("", "nocapture", "")
+        .optflag("h", "help", "show this message")
+        .reqopt("", "channel", "current Rust channel", "CHANNEL")
+        .optflag("", "git-hash", "run tests which rely on commit version being compiled into the binaries")
+        .optopt("", "edition", "default Rust edition", "EDITION");
+
+    let (argv0, args_) = args.split_first().unwrap();
+    if args.len() == 1 || args[1] == "-h" || args[1] == "--help" {
+        let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0);
+        println!("{}", opts.usage(&message));
+        println!();
+        panic!()
+    }
+
+    let matches = &match opts.parse(args_) {
+        Ok(m) => m,
+        Err(f) => panic!("{:?}", f),
+    };
+
+    if matches.opt_present("h") || matches.opt_present("help") {
+        let message = format!("Usage: {} [OPTIONS]  [TESTNAME...]", argv0);
+        println!("{}", opts.usage(&message));
+        println!();
+        panic!()
+    }
+
+    fn opt_path(m: &getopts::Matches, nm: &str) -> PathBuf {
+        match m.opt_str(nm) {
+            Some(s) => PathBuf::from(&s),
+            None => panic!("no option (=path) found for {}", nm),
+        }
+    }
+
+    fn make_absolute(path: PathBuf) -> PathBuf {
+        if path.is_relative() { env::current_dir().unwrap().join(path) } else { path }
+    }
+
+    let target = opt_str2(matches.opt_str("target"));
+    let android_cross_path = opt_path(matches, "android-cross-path");
+    let (cdb, cdb_version) = analyze_cdb(matches.opt_str("cdb"), &target);
+    let (gdb, gdb_version, gdb_native_rust) =
+        analyze_gdb(matches.opt_str("gdb"), &target, &android_cross_path);
+    let (lldb_version, lldb_native_rust) = matches
+        .opt_str("lldb-version")
+        .as_deref()
+        .and_then(extract_lldb_version)
+        .map(|(v, b)| (Some(v), b))
+        .unwrap_or((None, false));
+    let color = match matches.opt_str("color").as_deref() {
+        Some("auto") | None => ColorConfig::AutoColor,
+        Some("always") => ColorConfig::AlwaysColor,
+        Some("never") => ColorConfig::NeverColor,
+        Some(x) => panic!("argument for --color must be auto, always, or never, but found `{}`", x),
+    };
+    let llvm_version =
+        matches.opt_str("llvm-version").as_deref().and_then(header::extract_llvm_version).or_else(
+            || header::extract_llvm_version_from_binary(&matches.opt_str("llvm-filecheck")?),
+        );
+
+    let src_base = opt_path(matches, "src-base");
+    let run_ignored = matches.opt_present("ignored");
+    let mode = matches.opt_str("mode").unwrap().parse().expect("invalid mode");
+    let has_tidy = if mode == Mode::Rustdoc {
+        Command::new("tidy")
+            .arg("--version")
+            .stdout(Stdio::null())
+            .status()
+            .map_or(false, |status| status.success())
+    } else {
+        // Avoid spawning an external command when we know tidy won't be used.
+        false
+    };
+    Config {
+        bless: matches.opt_present("bless"),
+        compile_lib_path: make_absolute(opt_path(matches, "compile-lib-path")),
+        run_lib_path: make_absolute(opt_path(matches, "run-lib-path")),
+        rustc_path: opt_path(matches, "rustc-path"),
+        rustdoc_path: matches.opt_str("rustdoc-path").map(PathBuf::from),
+        rust_demangler_path: matches.opt_str("rust-demangler-path").map(PathBuf::from),
+        python: matches.opt_str("python").unwrap(),
+        jsondocck_path: matches.opt_str("jsondocck-path"),
+        jsondoclint_path: matches.opt_str("jsondoclint-path"),
+        valgrind_path: matches.opt_str("valgrind-path"),
+        force_valgrind: matches.opt_present("force-valgrind"),
+        run_clang_based_tests_with: matches.opt_str("run-clang-based-tests-with"),
+        llvm_filecheck: matches.opt_str("llvm-filecheck").map(PathBuf::from),
+        llvm_bin_dir: matches.opt_str("llvm-bin-dir").map(PathBuf::from),
+        src_base,
+        build_base: opt_path(matches, "build-base"),
+        sysroot_base: opt_path(matches, "sysroot-base"),
+        stage_id: matches.opt_str("stage-id").unwrap(),
+        mode,
+        suite: matches.opt_str("suite").unwrap(),
+        debugger: None,
+        run_ignored,
+        filters: matches.free.clone(),
+        skip: matches.opt_strs("skip"),
+        filter_exact: matches.opt_present("exact"),
+        force_pass_mode: matches.opt_str("pass").map(|mode| {
+            mode.parse::<PassMode>()
+                .unwrap_or_else(|_| panic!("unknown `--pass` option `{}` given", mode))
+        }),
+        run: matches.opt_str("run").and_then(|mode| match mode.as_str() {
+            "auto" => None,
+            "always" => Some(true),
+            "never" => Some(false),
+            _ => panic!("unknown `--run` option `{}` given", mode),
+        }),
+        logfile: matches.opt_str("logfile").map(|s| PathBuf::from(&s)),
+        runtool: matches.opt_str("runtool"),
+        host_rustcflags: matches.opt_strs("host-rustcflags"),
+        target_rustcflags: matches.opt_strs("target-rustcflags"),
+        optimize_tests: matches.opt_present("optimize-tests"),
+        target,
+        host: opt_str2(matches.opt_str("host")),
+        cdb,
+        cdb_version,
+        gdb,
+        gdb_version,
+        gdb_native_rust,
+        lldb_version,
+        lldb_native_rust,
+        llvm_version,
+        system_llvm: matches.opt_present("system-llvm"),
+        android_cross_path,
+        adb_path: opt_str2(matches.opt_str("adb-path")),
+        adb_test_dir: opt_str2(matches.opt_str("adb-test-dir")),
+        adb_device_status: opt_str2(matches.opt_str("target")).contains("android")
+            && "(none)" != opt_str2(matches.opt_str("adb-test-dir"))
+            && !opt_str2(matches.opt_str("adb-test-dir")).is_empty(),
+        lldb_python_dir: matches.opt_str("lldb-python-dir"),
+        verbose: matches.opt_present("verbose"),
+        format: match (matches.opt_present("quiet"), matches.opt_present("json")) {
+            (true, true) => panic!("--quiet and --json are incompatible"),
+            (true, false) => test::OutputFormat::Terse,
+            (false, true) => test::OutputFormat::Json,
+            (false, false) => test::OutputFormat::Pretty,
+        },
+        only_modified: matches.opt_present("only-modified"),
+        color,
+        remote_test_client: matches.opt_str("remote-test-client").map(PathBuf::from),
+        compare_mode: matches
+            .opt_str("compare-mode")
+            .map(|s| s.parse().expect("invalid --compare-mode provided")),
+        rustfix_coverage: matches.opt_present("rustfix-coverage"),
+        has_tidy,
+        channel: matches.opt_str("channel").unwrap(),
+        git_hash: matches.opt_present("git-hash"),
+        edition: matches.opt_str("edition"),
+
+        cc: matches.opt_str("cc").unwrap(),
+        cxx: matches.opt_str("cxx").unwrap(),
+        cflags: matches.opt_str("cflags").unwrap(),
+        cxxflags: matches.opt_str("cxxflags").unwrap(),
+        ar: matches.opt_str("ar").unwrap_or_else(|| String::from("ar")),
+        target_linker: matches.opt_str("target-linker"),
+        host_linker: matches.opt_str("host-linker"),
+        llvm_components: matches.opt_str("llvm-components").unwrap(),
+        nodejs: matches.opt_str("nodejs"),
+        npm: matches.opt_str("npm"),
+
+        force_rerun: matches.opt_present("force-rerun"),
+
+        target_cfgs: AtomicLazyCell::new(),
+
+        nocapture: matches.opt_present("nocapture"),
+    }
+}
+
+pub fn log_config(config: &Config) {
+    let c = config;
+    logv(c, "configuration:".to_string());
+    logv(c, format!("compile_lib_path: {:?}", config.compile_lib_path));
+    logv(c, format!("run_lib_path: {:?}", config.run_lib_path));
+    logv(c, format!("rustc_path: {:?}", config.rustc_path.display()));
+    logv(c, format!("rustdoc_path: {:?}", config.rustdoc_path));
+    logv(c, format!("rust_demangler_path: {:?}", config.rust_demangler_path));
+    logv(c, format!("src_base: {:?}", config.src_base.display()));
+    logv(c, format!("build_base: {:?}", config.build_base.display()));
+    logv(c, format!("stage_id: {}", config.stage_id));
+    logv(c, format!("mode: {}", config.mode));
+    logv(c, format!("run_ignored: {}", config.run_ignored));
+    logv(c, format!("filters: {:?}", config.filters));
+    logv(c, format!("skip: {:?}", config.skip));
+    logv(c, format!("filter_exact: {}", config.filter_exact));
+    logv(
+        c,
+        format!("force_pass_mode: {}", opt_str(&config.force_pass_mode.map(|m| format!("{}", m))),),
+    );
+    logv(c, format!("runtool: {}", opt_str(&config.runtool)));
+    logv(c, format!("host-rustcflags: {:?}", config.host_rustcflags));
+    logv(c, format!("target-rustcflags: {:?}", config.target_rustcflags));
+    logv(c, format!("target: {}", config.target));
+    logv(c, format!("host: {}", config.host));
+    logv(c, format!("android-cross-path: {:?}", config.android_cross_path.display()));
+    logv(c, format!("adb_path: {:?}", config.adb_path));
+    logv(c, format!("adb_test_dir: {:?}", config.adb_test_dir));
+    logv(c, format!("adb_device_status: {}", config.adb_device_status));
+    logv(c, format!("ar: {}", config.ar));
+    logv(c, format!("target-linker: {:?}", config.target_linker));
+    logv(c, format!("host-linker: {:?}", config.host_linker));
+    logv(c, format!("verbose: {}", config.verbose));
+    logv(c, format!("format: {:?}", config.format));
+    logv(c, "\n".to_string());
+}
+
+pub fn opt_str(maybestr: &Option<String>) -> &str {
+    match *maybestr {
+        None => "(none)",
+        Some(ref s) => s,
+    }
+}
+
+pub fn opt_str2(maybestr: Option<String>) -> String {
+    match maybestr {
+        None => "(none)".to_owned(),
+        Some(s) => s,
+    }
+}
+
+pub fn run_tests(config: Arc<Config>) {
+    // If we want to collect rustfix coverage information,
+    // we first make sure that the coverage file does not exist.
+    // It will be created later on.
+    if config.rustfix_coverage {
+        let mut coverage_file_path = config.build_base.clone();
+        coverage_file_path.push("rustfix_missing_coverage.txt");
+        if coverage_file_path.exists() {
+            if let Err(e) = fs::remove_file(&coverage_file_path) {
+                panic!("Could not delete {} due to {}", coverage_file_path.display(), e)
+            }
+        }
+    }
+
+    // sadly osx needs some file descriptor limits raised for running tests in
+    // parallel (especially when we have lots and lots of child processes).
+    // For context, see #8904
+    unsafe {
+        raise_fd_limit::raise_fd_limit();
+    }
+    // Prevent issue #21352 UAC blocking .exe containing 'patch' etc. on Windows
+    // If #11207 is resolved (adding manifest to .exe) this becomes unnecessary
+    env::set_var("__COMPAT_LAYER", "RunAsInvoker");
+
+    // Let tests know which target they're running as
+    env::set_var("TARGET", &config.target);
+
+    let opts = test_opts(&config);
+
+    let mut configs = Vec::new();
+    if let Mode::DebugInfo = config.mode {
+        // Debugging emscripten code doesn't make sense today
+        if !config.target.contains("emscripten") {
+            configs.extend(configure_cdb(&config));
+            configs.extend(configure_gdb(&config));
+            configs.extend(configure_lldb(&config));
+        }
+    } else {
+        configs.push(config.clone());
+    };
+
+    let mut tests = Vec::new();
+    for c in configs {
+        let mut found_paths = BTreeSet::new();
+        make_tests(c, &mut tests, &mut found_paths);
+        check_overlapping_tests(&found_paths);
+    }
+
+    tests.sort_by(|a, b| a.desc.name.as_slice().cmp(&b.desc.name.as_slice()));
+
+    let res = test::run_tests_console(&opts, tests);
+    match res {
+        Ok(true) => {}
+        Ok(false) => {
+            // We want to report that the tests failed, but we also want to give
+            // some indication of just what tests we were running. Especially on
+            // CI, where there can be cross-compiled tests for a lot of
+            // architectures, without this critical information it can be quite
+            // easy to miss which tests failed, and as such fail to reproduce
+            // the failure locally.
+
+            println!(
+                "Some tests failed in compiletest suite={}{} mode={} host={} target={}",
+                config.suite,
+                config
+                    .compare_mode
+                    .as_ref()
+                    .map(|c| format!(" compare_mode={:?}", c))
+                    .unwrap_or_default(),
+                config.mode,
+                config.host,
+                config.target
+            );
+
+            std::process::exit(1);
+        }
+        Err(e) => {
+            // We don't know if tests passed or not, but if there was an error
+            // during testing we don't want to just succeed (we may not have
+            // tested something), so fail.
+            //
+            // This should realistically "never" happen, so don't try to make
+            // this a pretty error message.
+            panic!("I/O failure during tests: {:?}", e);
+        }
+    }
+}
+
+fn configure_cdb(config: &Config) -> Option<Arc<Config>> {
+    config.cdb.as_ref()?;
+
+    Some(Arc::new(Config { debugger: Some(Debugger::Cdb), ..config.clone() }))
+}
+
+fn configure_gdb(config: &Config) -> Option<Arc<Config>> {
+    config.gdb_version?;
+
+    if config.matches_env("msvc") {
+        return None;
+    }
+
+    if config.remote_test_client.is_some() && !config.target.contains("android") {
+        println!(
+            "WARNING: debuginfo tests are not available when \
+             testing with remote"
+        );
+        return None;
+    }
+
+    if config.target.contains("android") {
+        println!(
+            "{} debug-info test uses tcp 5039 port.\
+             please reserve it",
+            config.target
+        );
+
+        // android debug-info test uses remote debugger so, we test 1 thread
+        // at once as they're all sharing the same TCP port to communicate
+        // over.
+        //
+        // we should figure out how to lift this restriction! (run them all
+        // on different ports allocated dynamically).
+        env::set_var("RUST_TEST_THREADS", "1");
+    }
+
+    Some(Arc::new(Config { debugger: Some(Debugger::Gdb), ..config.clone() }))
+}
+
+fn configure_lldb(config: &Config) -> Option<Arc<Config>> {
+    config.lldb_python_dir.as_ref()?;
+
+    if let Some(350) = config.lldb_version {
+        println!(
+            "WARNING: The used version of LLDB (350) has a \
+             known issue that breaks debuginfo tests. See \
+             issue #32520 for more information. Skipping all \
+             LLDB-based tests!",
+        );
+        return None;
+    }
+
+    Some(Arc::new(Config { debugger: Some(Debugger::Lldb), ..config.clone() }))
+}
+
+pub fn test_opts(config: &Config) -> test::TestOpts {
+    if env::var("RUST_TEST_NOCAPTURE").is_ok() {
+        eprintln!(
+            "WARNING: RUST_TEST_NOCAPTURE is no longer used. \
+                   Use the `--nocapture` flag instead."
+        );
+    }
+
+    test::TestOpts {
+        exclude_should_panic: false,
+        filters: config.filters.clone(),
+        filter_exact: config.filter_exact,
+        run_ignored: if config.run_ignored { test::RunIgnored::Yes } else { test::RunIgnored::No },
+        format: config.format,
+        logfile: config.logfile.clone(),
+        run_tests: true,
+        bench_benchmarks: true,
+        nocapture: config.nocapture,
+        color: config.color,
+        shuffle: false,
+        shuffle_seed: None,
+        test_threads: None,
+        skip: config.skip.clone(),
+        list: false,
+        options: test::Options::new(),
+        time_options: None,
+        force_run_in_process: false,
+        fail_fast: std::env::var_os("RUSTC_TEST_FAIL_FAST").is_some(),
+    }
+}
+
+pub fn make_tests(
+    config: Arc<Config>,
+    tests: &mut Vec<test::TestDescAndFn>,
+    found_paths: &mut BTreeSet<PathBuf>,
+) {
+    debug!("making tests from {:?}", config.src_base.display());
+    let inputs = common_inputs_stamp(&config);
+    let modified_tests = modified_tests(&config, &config.src_base).unwrap_or_else(|err| {
+        panic!("modified_tests got error from dir: {}, error: {}", config.src_base.display(), err)
+    });
+
+    let cache = HeadersCache::load(&config);
+    let mut poisoned = false;
+    collect_tests_from_dir(
+        config.clone(),
+        &cache,
+        &config.src_base,
+        &PathBuf::new(),
+        &inputs,
+        tests,
+        found_paths,
+        &modified_tests,
+        &mut poisoned,
+    )
+    .unwrap_or_else(|_| panic!("Could not read tests from {}", config.src_base.display()));
+
+    if poisoned {
+        eprintln!();
+        panic!("there are errors in tests");
+    }
+}
+
+/// Returns a stamp constructed from input files common to all test cases.
+fn common_inputs_stamp(config: &Config) -> Stamp {
+    let rust_src_dir = config.find_rust_src_root().expect("Could not find Rust source root");
+
+    let mut stamp = Stamp::from_path(&config.rustc_path);
+
+    // Relevant pretty printer files
+    let pretty_printer_files = [
+        "src/etc/rust_types.py",
+        "src/etc/gdb_load_rust_pretty_printers.py",
+        "src/etc/gdb_lookup.py",
+        "src/etc/gdb_providers.py",
+        "src/etc/lldb_batchmode.py",
+        "src/etc/lldb_lookup.py",
+        "src/etc/lldb_providers.py",
+    ];
+    for file in &pretty_printer_files {
+        let path = rust_src_dir.join(file);
+        stamp.add_path(&path);
+    }
+
+    stamp.add_dir(&rust_src_dir.join("src/etc/natvis"));
+
+    stamp.add_dir(&config.run_lib_path);
+
+    if let Some(ref rustdoc_path) = config.rustdoc_path {
+        stamp.add_path(&rustdoc_path);
+        stamp.add_path(&rust_src_dir.join("src/etc/htmldocck.py"));
+    }
+
+    // Compiletest itself.
+    stamp.add_dir(&rust_src_dir.join("src/tools/compiletest/"));
+
+    stamp
+}
+
+fn modified_tests(config: &Config, dir: &Path) -> Result<Vec<PathBuf>, String> {
+    if !config.only_modified {
+        return Ok(vec![]);
+    }
+    let files =
+        get_git_modified_files(Some(dir), &vec!["rs", "stderr", "fixed"])?.unwrap_or(vec![]);
+    // Add new test cases to the list, it will be convenient in daily development.
+    let untracked_files = get_git_untracked_files(None)?.unwrap_or(vec![]);
+
+    let all_paths = [&files[..], &untracked_files[..]].concat();
+    let full_paths = {
+        let mut full_paths: Vec<PathBuf> = all_paths
+            .into_iter()
+            .map(|f| PathBuf::from(f).with_extension("").with_extension("rs"))
+            .filter_map(|f| if Path::new(&f).exists() { f.canonicalize().ok() } else { None })
+            .collect();
+        full_paths.dedup();
+        full_paths.sort_unstable();
+        full_paths
+    };
+    Ok(full_paths)
+}
+
+fn collect_tests_from_dir(
+    config: Arc<Config>,
+    cache: &HeadersCache,
+    dir: &Path,
+    relative_dir_path: &Path,
+    inputs: &Stamp,
+    tests: &mut Vec<test::TestDescAndFn>,
+    found_paths: &mut BTreeSet<PathBuf>,
+    modified_tests: &Vec<PathBuf>,
+    poisoned: &mut bool,
+) -> io::Result<()> {
+    // Ignore directories that contain a file named `compiletest-ignore-dir`.
+    if dir.join("compiletest-ignore-dir").exists() {
+        return Ok(());
+    }
+
+    if config.mode == Mode::RunMake && dir.join("Makefile").exists() {
+        let paths = TestPaths {
+            file: dir.to_path_buf(),
+            relative_dir: relative_dir_path.parent().unwrap().to_path_buf(),
+        };
+        tests.extend(make_test(config, cache, &paths, inputs, poisoned));
+        return Ok(());
+    }
+
+    // If we find a test foo/bar.rs, we have to build the
+    // output directory `$build/foo` so we can write
+    // `$build/foo/bar` into it. We do this *now* in this
+    // sequential loop because otherwise, if we do it in the
+    // tests themselves, they race for the privilege of
+    // creating the directories and sometimes fail randomly.
+    let build_dir = output_relative_path(&config, relative_dir_path);
+    fs::create_dir_all(&build_dir).unwrap();
+
+    // Add each `.rs` file as a test, and recurse further on any
+    // subdirectories we find, except for `aux` directories.
+    for file in fs::read_dir(dir)? {
+        let file = file?;
+        let file_path = file.path();
+        let file_name = file.file_name();
+        if is_test(&file_name) && (!config.only_modified || modified_tests.contains(&file_path)) {
+            debug!("found test file: {:?}", file_path.display());
+            let rel_test_path = relative_dir_path.join(file_path.file_stem().unwrap());
+            found_paths.insert(rel_test_path);
+            let paths =
+                TestPaths { file: file_path, relative_dir: relative_dir_path.to_path_buf() };
+
+            tests.extend(make_test(config.clone(), cache, &paths, inputs, poisoned))
+        } else if file_path.is_dir() {
+            let relative_file_path = relative_dir_path.join(file.file_name());
+            if &file_name != "auxiliary" {
+                debug!("found directory: {:?}", file_path.display());
+                collect_tests_from_dir(
+                    config.clone(),
+                    cache,
+                    &file_path,
+                    &relative_file_path,
+                    inputs,
+                    tests,
+                    found_paths,
+                    modified_tests,
+                    poisoned,
+                )?;
+            }
+        } else {
+            debug!("found other file/directory: {:?}", file_path.display());
+        }
+    }
+    Ok(())
+}
+
+/// Returns true if `file_name` looks like a proper test file name.
+pub fn is_test(file_name: &OsString) -> bool {
+    let file_name = file_name.to_str().unwrap();
+
+    if !file_name.ends_with(".rs") {
+        return false;
+    }
+
+    // `.`, `#`, and `~` are common temp-file prefixes.
+    let invalid_prefixes = &[".", "#", "~"];
+    !invalid_prefixes.iter().any(|p| file_name.starts_with(p))
+}
+
+fn make_test(
+    config: Arc<Config>,
+    cache: &HeadersCache,
+    testpaths: &TestPaths,
+    inputs: &Stamp,
+    poisoned: &mut bool,
+) -> Vec<test::TestDescAndFn> {
+    let test_path = if config.mode == Mode::RunMake {
+        // Parse directives in the Makefile
+        testpaths.file.join("Makefile")
+    } else {
+        PathBuf::from(&testpaths.file)
+    };
+    let early_props = EarlyProps::from_file(&config, &test_path);
+
+    // Incremental tests are special, they inherently cannot be run in parallel.
+    // `runtest::run` will be responsible for iterating over revisions.
+    let revisions = if early_props.revisions.is_empty() || config.mode == Mode::Incremental {
+        vec![None]
+    } else {
+        early_props.revisions.iter().map(Some).collect()
+    };
+
+    revisions
+        .into_iter()
+        .map(|revision| {
+            let src_file =
+                std::fs::File::open(&test_path).expect("open test file to parse ignores");
+            let cfg = revision.map(|v| &**v);
+            let test_name = crate::make_test_name(&config, testpaths, revision);
+            let mut desc = make_test_description(
+                &config, cache, test_name, &test_path, src_file, cfg, poisoned,
+            );
+            // Ignore tests that already run and are up to date with respect to inputs.
+            if !config.force_rerun {
+                desc.ignore |= is_up_to_date(
+                    &config,
+                    testpaths,
+                    &early_props,
+                    revision.map(|s| s.as_str()),
+                    inputs,
+                );
+            }
+            test::TestDescAndFn {
+                desc,
+                testfn: make_test_closure(config.clone(), testpaths, revision),
+            }
+        })
+        .collect()
+}
+
+fn stamp(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> PathBuf {
+    output_base_dir(config, testpaths, revision).join("stamp")
+}
+
+fn files_related_to_test(
+    config: &Config,
+    testpaths: &TestPaths,
+    props: &EarlyProps,
+    revision: Option<&str>,
+) -> Vec<PathBuf> {
+    let mut related = vec![];
+
+    if testpaths.file.is_dir() {
+        // run-make tests use their individual directory
+        for entry in WalkDir::new(&testpaths.file) {
+            let path = entry.unwrap().into_path();
+            if path.is_file() {
+                related.push(path);
+            }
+        }
+    } else {
+        related.push(testpaths.file.clone());
+    }
+
+    for aux in &props.aux {
+        let path = testpaths.file.parent().unwrap().join("auxiliary").join(aux);
+        related.push(path);
+    }
+
+    // UI test files.
+    for extension in UI_EXTENSIONS {
+        let path = expected_output_path(testpaths, revision, &config.compare_mode, extension);
+        related.push(path);
+    }
+
+    related
+}
+
+fn is_up_to_date(
+    config: &Config,
+    testpaths: &TestPaths,
+    props: &EarlyProps,
+    revision: Option<&str>,
+    inputs: &Stamp,
+) -> bool {
+    let stamp_name = stamp(config, testpaths, revision);
+    // Check hash.
+    let contents = match fs::read_to_string(&stamp_name) {
+        Ok(f) => f,
+        Err(ref e) if e.kind() == ErrorKind::InvalidData => panic!("Can't read stamp contents"),
+        Err(_) => return false,
+    };
+    let expected_hash = runtest::compute_stamp_hash(config);
+    if contents != expected_hash {
+        return false;
+    }
+
+    // Check timestamps.
+    let mut inputs = inputs.clone();
+    for path in files_related_to_test(config, testpaths, props, revision) {
+        inputs.add_path(&path);
+    }
+
+    inputs < Stamp::from_path(&stamp_name)
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+struct Stamp {
+    time: SystemTime,
+}
+
+impl Stamp {
+    fn from_path(path: &Path) -> Self {
+        let mut stamp = Stamp { time: SystemTime::UNIX_EPOCH };
+        stamp.add_path(path);
+        stamp
+    }
+
+    fn add_path(&mut self, path: &Path) {
+        let modified = fs::metadata(path)
+            .and_then(|metadata| metadata.modified())
+            .unwrap_or(SystemTime::UNIX_EPOCH);
+        self.time = self.time.max(modified);
+    }
+
+    fn add_dir(&mut self, path: &Path) {
+        for entry in WalkDir::new(path) {
+            let entry = entry.unwrap();
+            if entry.file_type().is_file() {
+                let modified = entry
+                    .metadata()
+                    .ok()
+                    .and_then(|metadata| metadata.modified().ok())
+                    .unwrap_or(SystemTime::UNIX_EPOCH);
+                self.time = self.time.max(modified);
+            }
+        }
+    }
+}
+
+fn make_test_name(
+    config: &Config,
+    testpaths: &TestPaths,
+    revision: Option<&String>,
+) -> test::TestName {
+    // Print the name of the file, relative to the repository root.
+    // `src_base` looks like `/path/to/rust/tests/ui`
+    let root_directory = config.src_base.parent().unwrap().parent().unwrap();
+    let path = testpaths.file.strip_prefix(root_directory).unwrap();
+    let debugger = match config.debugger {
+        Some(d) => format!("-{}", d),
+        None => String::new(),
+    };
+    let mode_suffix = match config.compare_mode {
+        Some(ref mode) => format!(" ({})", mode.to_str()),
+        None => String::new(),
+    };
+
+    test::DynTestName(format!(
+        "[{}{}{}] {}{}",
+        config.mode,
+        debugger,
+        mode_suffix,
+        path.display(),
+        revision.map_or("".to_string(), |rev| format!("#{}", rev))
+    ))
+}
+
+fn make_test_closure(
+    config: Arc<Config>,
+    testpaths: &TestPaths,
+    revision: Option<&String>,
+) -> test::TestFn {
+    let config = config.clone();
+    let testpaths = testpaths.clone();
+    let revision = revision.cloned();
+    test::DynTestFn(Box::new(move || {
+        runtest::run(config, &testpaths, revision.as_deref());
+        Ok(())
+    }))
+}
+
+/// Returns `true` if the given target is an Android target for the
+/// purposes of GDB testing.
+fn is_android_gdb_target(target: &str) -> bool {
+    matches!(
+        &target[..],
+        "arm-linux-androideabi" | "armv7-linux-androideabi" | "aarch64-linux-android"
+    )
+}
+
+/// Returns `true` if the given target is a MSVC target for the purpouses of CDB testing.
+fn is_pc_windows_msvc_target(target: &str) -> bool {
+    target.ends_with("-pc-windows-msvc")
+}
+
+fn find_cdb(target: &str) -> Option<OsString> {
+    if !(cfg!(windows) && is_pc_windows_msvc_target(target)) {
+        return None;
+    }
+
+    let pf86 = env::var_os("ProgramFiles(x86)").or_else(|| env::var_os("ProgramFiles"))?;
+    let cdb_arch = if cfg!(target_arch = "x86") {
+        "x86"
+    } else if cfg!(target_arch = "x86_64") {
+        "x64"
+    } else if cfg!(target_arch = "aarch64") {
+        "arm64"
+    } else if cfg!(target_arch = "arm") {
+        "arm"
+    } else {
+        return None; // No compatible CDB.exe in the Windows 10 SDK
+    };
+
+    let mut path = PathBuf::new();
+    path.push(pf86);
+    path.push(r"Windows Kits\10\Debuggers"); // We could check 8.1 etc. too?
+    path.push(cdb_arch);
+    path.push(r"cdb.exe");
+
+    if !path.exists() {
+        return None;
+    }
+
+    Some(path.into_os_string())
+}
+
+/// Returns Path to CDB
+fn analyze_cdb(cdb: Option<String>, target: &str) -> (Option<OsString>, Option<[u16; 4]>) {
+    let cdb = cdb.map(OsString::from).or_else(|| find_cdb(target));
+
+    let mut version = None;
+    if let Some(cdb) = cdb.as_ref() {
+        if let Ok(output) = Command::new(cdb).arg("/version").output() {
+            if let Some(first_line) = String::from_utf8_lossy(&output.stdout).lines().next() {
+                version = extract_cdb_version(&first_line);
+            }
+        }
+    }
+
+    (cdb, version)
+}
+
+fn extract_cdb_version(full_version_line: &str) -> Option<[u16; 4]> {
+    // Example full_version_line: "cdb version 10.0.18362.1"
+    let version = full_version_line.rsplit(' ').next()?;
+    let mut components = version.split('.');
+    let major: u16 = components.next().unwrap().parse().unwrap();
+    let minor: u16 = components.next().unwrap().parse().unwrap();
+    let patch: u16 = components.next().unwrap_or("0").parse().unwrap();
+    let build: u16 = components.next().unwrap_or("0").parse().unwrap();
+    Some([major, minor, patch, build])
+}
+
+/// Returns (Path to GDB, GDB Version, GDB has Rust Support)
+fn analyze_gdb(
+    gdb: Option<String>,
+    target: &str,
+    android_cross_path: &PathBuf,
+) -> (Option<String>, Option<u32>, bool) {
+    #[cfg(not(windows))]
+    const GDB_FALLBACK: &str = "gdb";
+    #[cfg(windows)]
+    const GDB_FALLBACK: &str = "gdb.exe";
+
+    const MIN_GDB_WITH_RUST: u32 = 7011010;
+
+    let fallback_gdb = || {
+        if is_android_gdb_target(target) {
+            let mut gdb_path = match android_cross_path.to_str() {
+                Some(x) => x.to_owned(),
+                None => panic!("cannot find android cross path"),
+            };
+            gdb_path.push_str("/bin/gdb");
+            gdb_path
+        } else {
+            GDB_FALLBACK.to_owned()
+        }
+    };
+
+    let gdb = match gdb {
+        None => fallback_gdb(),
+        Some(ref s) if s.is_empty() => fallback_gdb(), // may be empty if configure found no gdb
+        Some(ref s) => s.to_owned(),
+    };
+
+    let mut version_line = None;
+    if let Ok(output) = Command::new(&gdb).arg("--version").output() {
+        if let Some(first_line) = String::from_utf8_lossy(&output.stdout).lines().next() {
+            version_line = Some(first_line.to_string());
+        }
+    }
+
+    let version = match version_line {
+        Some(line) => extract_gdb_version(&line),
+        None => return (None, None, false),
+    };
+
+    let gdb_native_rust = version.map_or(false, |v| v >= MIN_GDB_WITH_RUST);
+
+    (Some(gdb), version, gdb_native_rust)
+}
+
+fn extract_gdb_version(full_version_line: &str) -> Option<u32> {
+    let full_version_line = full_version_line.trim();
+
+    // GDB versions look like this: "major.minor.patch?.yyyymmdd?", with both
+    // of the ? sections being optional
+
+    // We will parse up to 3 digits for each component, ignoring the date
+
+    // We skip text in parentheses.  This avoids accidentally parsing
+    // the openSUSE version, which looks like:
+    //  GNU gdb (GDB; openSUSE Leap 15.0) 8.1
+    // This particular form is documented in the GNU coding standards:
+    // https://www.gnu.org/prep/standards/html_node/_002d_002dversion.html#g_t_002d_002dversion
+
+    let unbracketed_part = full_version_line.split('[').next().unwrap();
+    let mut splits = unbracketed_part.trim_end().rsplit(' ');
+    let version_string = splits.next().unwrap();
+
+    let mut splits = version_string.split('.');
+    let major = splits.next().unwrap();
+    let minor = splits.next().unwrap();
+    let patch = splits.next();
+
+    let major: u32 = major.parse().unwrap();
+    let (minor, patch): (u32, u32) = match minor.find(not_a_digit) {
+        None => {
+            let minor = minor.parse().unwrap();
+            let patch: u32 = match patch {
+                Some(patch) => match patch.find(not_a_digit) {
+                    None => patch.parse().unwrap(),
+                    Some(idx) if idx > 3 => 0,
+                    Some(idx) => patch[..idx].parse().unwrap(),
+                },
+                None => 0,
+            };
+            (minor, patch)
+        }
+        // There is no patch version after minor-date (e.g. "4-2012").
+        Some(idx) => {
+            let minor = minor[..idx].parse().unwrap();
+            (minor, 0)
+        }
+    };
+
+    Some(((major * 1000) + minor) * 1000 + patch)
+}
+
+/// Returns (LLDB version, LLDB is rust-enabled)
+fn extract_lldb_version(full_version_line: &str) -> Option<(u32, bool)> {
+    // Extract the major LLDB version from the given version string.
+    // LLDB version strings are different for Apple and non-Apple platforms.
+    // The Apple variant looks like this:
+    //
+    // LLDB-179.5 (older versions)
+    // lldb-300.2.51 (new versions)
+    //
+    // We are only interested in the major version number, so this function
+    // will return `Some(179)` and `Some(300)` respectively.
+    //
+    // Upstream versions look like:
+    // lldb version 6.0.1
+    //
+    // There doesn't seem to be a way to correlate the Apple version
+    // with the upstream version, and since the tests were originally
+    // written against Apple versions, we make a fake Apple version by
+    // multiplying the first number by 100.  This is a hack, but
+    // normally fine because the only non-Apple version we test is
+    // rust-enabled.
+
+    let full_version_line = full_version_line.trim();
+
+    if let Some(apple_ver) =
+        full_version_line.strip_prefix("LLDB-").or_else(|| full_version_line.strip_prefix("lldb-"))
+    {
+        if let Some(idx) = apple_ver.find(not_a_digit) {
+            let version: u32 = apple_ver[..idx].parse().unwrap();
+            return Some((version, full_version_line.contains("rust-enabled")));
+        }
+    } else if let Some(lldb_ver) = full_version_line.strip_prefix("lldb version ") {
+        if let Some(idx) = lldb_ver.find(not_a_digit) {
+            let version: u32 = lldb_ver[..idx].parse().ok()?;
+            return Some((version * 100, full_version_line.contains("rust-enabled")));
+        }
+    }
+    None
+}
+
+fn not_a_digit(c: char) -> bool {
+    !c.is_digit(10)
+}
+
+fn check_overlapping_tests(found_paths: &BTreeSet<PathBuf>) {
+    let mut collisions = Vec::new();
+    for path in found_paths {
+        for ancestor in path.ancestors().skip(1) {
+            if found_paths.contains(ancestor) {
+                collisions.push((path, ancestor.clone()));
+            }
+        }
+    }
+    if !collisions.is_empty() {
+        let collisions: String = collisions
+            .into_iter()
+            .map(|(path, check_parent)| format!("test {path:?} clashes with {check_parent:?}\n"))
+            .collect();
+        panic!(
+            "{collisions}\n\
+            Tests cannot have overlapping names. Make sure they use unique prefixes."
+        );
+    }
+}
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index c4bef998f31..34d48559c37 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -1,45 +1,6 @@
-#![crate_name = "compiletest"]
-// The `test` crate is the only unstable feature
-// allowed here, just to share similar code.
-#![feature(test)]
+use std::{env, sync::Arc};
 
-extern crate test;
-
-use crate::common::{expected_output_path, output_base_dir, output_relative_path, UI_EXTENSIONS};
-use crate::common::{Config, Debugger, Mode, PassMode, TestPaths};
-use crate::util::logv;
-use build_helper::git::{get_git_modified_files, get_git_untracked_files};
-use core::panic;
-use getopts::Options;
-use lazycell::AtomicLazyCell;
-use std::collections::BTreeSet;
-use std::ffi::OsString;
-use std::fs;
-use std::io::{self, ErrorKind};
-use std::path::{Path, PathBuf};
-use std::process::{Command, Stdio};
-use std::time::SystemTime;
-use std::{env, vec};
-use test::ColorConfig;
-use tracing::*;
-use walkdir::WalkDir;
-
-use self::header::{make_test_description, EarlyProps};
-use crate::header::HeadersCache;
-use std::sync::Arc;
-
-#[cfg(test)]
-mod tests;
-
-pub mod common;
-pub mod compute_diff;
-pub mod errors;
-pub mod header;
-mod json;
-mod raise_fd_limit;
-mod read2;
-pub mod runtest;
-pub mod util;
+use compiletest::{common::Mode, log_config, parse_config, run_tests};
 
 fn main() {
     tracing_subscriber::fmt::init();
@@ -57,1097 +18,3 @@ fn main() {
     log_config(&config);
     run_tests(config);
 }
-
-pub fn parse_config(args: Vec<String>) -> Config {
-    let mut opts = Options::new();
-    opts.reqopt("", "compile-lib-path", "path to host shared libraries", "PATH")
-        .reqopt("", "run-lib-path", "path to target shared libraries", "PATH")
-        .reqopt("", "rustc-path", "path to rustc to use for compiling", "PATH")
-        .optopt("", "rustdoc-path", "path to rustdoc to use for compiling", "PATH")
-        .optopt("", "rust-demangler-path", "path to rust-demangler to use in tests", "PATH")
-        .reqopt("", "python", "path to python to use for doc tests", "PATH")
-        .optopt("", "jsondocck-path", "path to jsondocck to use for doc tests", "PATH")
-        .optopt("", "jsondoclint-path", "path to jsondoclint to use for doc tests", "PATH")
-        .optopt("", "valgrind-path", "path to Valgrind executable for Valgrind tests", "PROGRAM")
-        .optflag("", "force-valgrind", "fail if Valgrind tests cannot be run under Valgrind")
-        .optopt("", "run-clang-based-tests-with", "path to Clang executable", "PATH")
-        .optopt("", "llvm-filecheck", "path to LLVM's FileCheck binary", "DIR")
-        .reqopt("", "src-base", "directory to scan for test files", "PATH")
-        .reqopt("", "build-base", "directory to deposit test outputs", "PATH")
-        .reqopt("", "sysroot-base", "directory containing the compiler sysroot", "PATH")
-        .reqopt("", "stage-id", "the target-stage identifier", "stageN-TARGET")
-        .reqopt(
-            "",
-            "mode",
-            "which sort of compile tests to run",
-            "run-pass-valgrind | pretty | debug-info | codegen | rustdoc \
-            | rustdoc-json | codegen-units | incremental | run-make | ui | js-doc-test | mir-opt | assembly",
-        )
-        .reqopt(
-            "",
-            "suite",
-            "which suite of compile tests to run. used for nicer error reporting.",
-            "SUITE",
-        )
-        .optopt(
-            "",
-            "pass",
-            "force {check,build,run}-pass tests to this mode.",
-            "check | build | run",
-        )
-        .optopt("", "run", "whether to execute run-* tests", "auto | always | never")
-        .optflag("", "ignored", "run tests marked as ignored")
-        .optmulti("", "skip", "skip tests matching SUBSTRING. Can be passed multiple times", "SUBSTRING")
-        .optflag("", "exact", "filters match exactly")
-        .optopt(
-            "",
-            "runtool",
-            "supervisor program to run tests under \
-             (eg. emulator, valgrind)",
-            "PROGRAM",
-        )
-        .optmulti("", "host-rustcflags", "flags to pass to rustc for host", "FLAGS")
-        .optmulti("", "target-rustcflags", "flags to pass to rustc for target", "FLAGS")
-        .optflag("", "optimize-tests", "run tests with optimizations enabled")
-        .optflag("", "verbose", "run tests verbosely, showing all output")
-        .optflag(
-            "",
-            "bless",
-            "overwrite stderr/stdout files instead of complaining about a mismatch",
-        )
-        .optflag("", "quiet", "print one character per test instead of one line")
-        .optopt("", "color", "coloring: auto, always, never", "WHEN")
-        .optflag("", "json", "emit json output instead of plaintext output")
-        .optopt("", "logfile", "file to log test execution to", "FILE")
-        .optopt("", "target", "the target to build for", "TARGET")
-        .optopt("", "host", "the host to build for", "HOST")
-        .optopt("", "cdb", "path to CDB to use for CDB debuginfo tests", "PATH")
-        .optopt("", "gdb", "path to GDB to use for GDB debuginfo tests", "PATH")
-        .optopt("", "lldb-version", "the version of LLDB used", "VERSION STRING")
-        .optopt("", "llvm-version", "the version of LLVM used", "VERSION STRING")
-        .optflag("", "system-llvm", "is LLVM the system LLVM")
-        .optopt("", "android-cross-path", "Android NDK standalone path", "PATH")
-        .optopt("", "adb-path", "path to the android debugger", "PATH")
-        .optopt("", "adb-test-dir", "path to tests for the android debugger", "PATH")
-        .optopt("", "lldb-python-dir", "directory containing LLDB's python module", "PATH")
-        .reqopt("", "cc", "path to a C compiler", "PATH")
-        .reqopt("", "cxx", "path to a C++ compiler", "PATH")
-        .reqopt("", "cflags", "flags for the C compiler", "FLAGS")
-        .reqopt("", "cxxflags", "flags for the CXX compiler", "FLAGS")
-        .optopt("", "ar", "path to an archiver", "PATH")
-        .optopt("", "target-linker", "path to a linker for the target", "PATH")
-        .optopt("", "host-linker", "path to a linker for the host", "PATH")
-        .reqopt("", "llvm-components", "list of LLVM components built in", "LIST")
-        .optopt("", "llvm-bin-dir", "Path to LLVM's `bin` directory", "PATH")
-        .optopt("", "nodejs", "the name of nodejs", "PATH")
-        .optopt("", "npm", "the name of npm", "PATH")
-        .optopt("", "remote-test-client", "path to the remote test client", "PATH")
-        .optopt(
-            "",
-            "compare-mode",
-            "mode describing what file the actual ui output will be compared to",
-            "COMPARE MODE",
-        )
-        .optflag(
-            "",
-            "rustfix-coverage",
-            "enable this to generate a Rustfix coverage file, which is saved in \
-            `./<build_base>/rustfix_missing_coverage.txt`",
-        )
-        .optflag("", "force-rerun", "rerun tests even if the inputs are unchanged")
-        .optflag("", "only-modified", "only run tests that result been modified")
-        .optflag("", "nocapture", "")
-        .optflag("h", "help", "show this message")
-        .reqopt("", "channel", "current Rust channel", "CHANNEL")
-        .optflag("", "git-hash", "run tests which rely on commit version being compiled into the binaries")
-        .optopt("", "edition", "default Rust edition", "EDITION");
-
-    let (argv0, args_) = args.split_first().unwrap();
-    if args.len() == 1 || args[1] == "-h" || args[1] == "--help" {
-        let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0);
-        println!("{}", opts.usage(&message));
-        println!();
-        panic!()
-    }
-
-    let matches = &match opts.parse(args_) {
-        Ok(m) => m,
-        Err(f) => panic!("{:?}", f),
-    };
-
-    if matches.opt_present("h") || matches.opt_present("help") {
-        let message = format!("Usage: {} [OPTIONS]  [TESTNAME...]", argv0);
-        println!("{}", opts.usage(&message));
-        println!();
-        panic!()
-    }
-
-    fn opt_path(m: &getopts::Matches, nm: &str) -> PathBuf {
-        match m.opt_str(nm) {
-            Some(s) => PathBuf::from(&s),
-            None => panic!("no option (=path) found for {}", nm),
-        }
-    }
-
-    fn make_absolute(path: PathBuf) -> PathBuf {
-        if path.is_relative() { env::current_dir().unwrap().join(path) } else { path }
-    }
-
-    let target = opt_str2(matches.opt_str("target"));
-    let android_cross_path = opt_path(matches, "android-cross-path");
-    let (cdb, cdb_version) = analyze_cdb(matches.opt_str("cdb"), &target);
-    let (gdb, gdb_version, gdb_native_rust) =
-        analyze_gdb(matches.opt_str("gdb"), &target, &android_cross_path);
-    let (lldb_version, lldb_native_rust) = matches
-        .opt_str("lldb-version")
-        .as_deref()
-        .and_then(extract_lldb_version)
-        .map(|(v, b)| (Some(v), b))
-        .unwrap_or((None, false));
-    let color = match matches.opt_str("color").as_deref() {
-        Some("auto") | None => ColorConfig::AutoColor,
-        Some("always") => ColorConfig::AlwaysColor,
-        Some("never") => ColorConfig::NeverColor,
-        Some(x) => panic!("argument for --color must be auto, always, or never, but found `{}`", x),
-    };
-    let llvm_version =
-        matches.opt_str("llvm-version").as_deref().and_then(header::extract_llvm_version).or_else(
-            || header::extract_llvm_version_from_binary(&matches.opt_str("llvm-filecheck")?),
-        );
-
-    let src_base = opt_path(matches, "src-base");
-    let run_ignored = matches.opt_present("ignored");
-    let mode = matches.opt_str("mode").unwrap().parse().expect("invalid mode");
-    let has_tidy = if mode == Mode::Rustdoc {
-        Command::new("tidy")
-            .arg("--version")
-            .stdout(Stdio::null())
-            .status()
-            .map_or(false, |status| status.success())
-    } else {
-        // Avoid spawning an external command when we know tidy won't be used.
-        false
-    };
-    Config {
-        bless: matches.opt_present("bless"),
-        compile_lib_path: make_absolute(opt_path(matches, "compile-lib-path")),
-        run_lib_path: make_absolute(opt_path(matches, "run-lib-path")),
-        rustc_path: opt_path(matches, "rustc-path"),
-        rustdoc_path: matches.opt_str("rustdoc-path").map(PathBuf::from),
-        rust_demangler_path: matches.opt_str("rust-demangler-path").map(PathBuf::from),
-        python: matches.opt_str("python").unwrap(),
-        jsondocck_path: matches.opt_str("jsondocck-path"),
-        jsondoclint_path: matches.opt_str("jsondoclint-path"),
-        valgrind_path: matches.opt_str("valgrind-path"),
-        force_valgrind: matches.opt_present("force-valgrind"),
-        run_clang_based_tests_with: matches.opt_str("run-clang-based-tests-with"),
-        llvm_filecheck: matches.opt_str("llvm-filecheck").map(PathBuf::from),
-        llvm_bin_dir: matches.opt_str("llvm-bin-dir").map(PathBuf::from),
-        src_base,
-        build_base: opt_path(matches, "build-base"),
-        sysroot_base: opt_path(matches, "sysroot-base"),
-        stage_id: matches.opt_str("stage-id").unwrap(),
-        mode,
-        suite: matches.opt_str("suite").unwrap(),
-        debugger: None,
-        run_ignored,
-        filters: matches.free.clone(),
-        skip: matches.opt_strs("skip"),
-        filter_exact: matches.opt_present("exact"),
-        force_pass_mode: matches.opt_str("pass").map(|mode| {
-            mode.parse::<PassMode>()
-                .unwrap_or_else(|_| panic!("unknown `--pass` option `{}` given", mode))
-        }),
-        run: matches.opt_str("run").and_then(|mode| match mode.as_str() {
-            "auto" => None,
-            "always" => Some(true),
-            "never" => Some(false),
-            _ => panic!("unknown `--run` option `{}` given", mode),
-        }),
-        logfile: matches.opt_str("logfile").map(|s| PathBuf::from(&s)),
-        runtool: matches.opt_str("runtool"),
-        host_rustcflags: matches.opt_strs("host-rustcflags"),
-        target_rustcflags: matches.opt_strs("target-rustcflags"),
-        optimize_tests: matches.opt_present("optimize-tests"),
-        target,
-        host: opt_str2(matches.opt_str("host")),
-        cdb,
-        cdb_version,
-        gdb,
-        gdb_version,
-        gdb_native_rust,
-        lldb_version,
-        lldb_native_rust,
-        llvm_version,
-        system_llvm: matches.opt_present("system-llvm"),
-        android_cross_path,
-        adb_path: opt_str2(matches.opt_str("adb-path")),
-        adb_test_dir: opt_str2(matches.opt_str("adb-test-dir")),
-        adb_device_status: opt_str2(matches.opt_str("target")).contains("android")
-            && "(none)" != opt_str2(matches.opt_str("adb-test-dir"))
-            && !opt_str2(matches.opt_str("adb-test-dir")).is_empty(),
-        lldb_python_dir: matches.opt_str("lldb-python-dir"),
-        verbose: matches.opt_present("verbose"),
-        format: match (matches.opt_present("quiet"), matches.opt_present("json")) {
-            (true, true) => panic!("--quiet and --json are incompatible"),
-            (true, false) => test::OutputFormat::Terse,
-            (false, true) => test::OutputFormat::Json,
-            (false, false) => test::OutputFormat::Pretty,
-        },
-        only_modified: matches.opt_present("only-modified"),
-        color,
-        remote_test_client: matches.opt_str("remote-test-client").map(PathBuf::from),
-        compare_mode: matches
-            .opt_str("compare-mode")
-            .map(|s| s.parse().expect("invalid --compare-mode provided")),
-        rustfix_coverage: matches.opt_present("rustfix-coverage"),
-        has_tidy,
-        channel: matches.opt_str("channel").unwrap(),
-        git_hash: matches.opt_present("git-hash"),
-        edition: matches.opt_str("edition"),
-
-        cc: matches.opt_str("cc").unwrap(),
-        cxx: matches.opt_str("cxx").unwrap(),
-        cflags: matches.opt_str("cflags").unwrap(),
-        cxxflags: matches.opt_str("cxxflags").unwrap(),
-        ar: matches.opt_str("ar").unwrap_or_else(|| String::from("ar")),
-        target_linker: matches.opt_str("target-linker"),
-        host_linker: matches.opt_str("host-linker"),
-        llvm_components: matches.opt_str("llvm-components").unwrap(),
-        nodejs: matches.opt_str("nodejs"),
-        npm: matches.opt_str("npm"),
-
-        force_rerun: matches.opt_present("force-rerun"),
-
-        target_cfgs: AtomicLazyCell::new(),
-
-        nocapture: matches.opt_present("nocapture"),
-    }
-}
-
-pub fn log_config(config: &Config) {
-    let c = config;
-    logv(c, "configuration:".to_string());
-    logv(c, format!("compile_lib_path: {:?}", config.compile_lib_path));
-    logv(c, format!("run_lib_path: {:?}", config.run_lib_path));
-    logv(c, format!("rustc_path: {:?}", config.rustc_path.display()));
-    logv(c, format!("rustdoc_path: {:?}", config.rustdoc_path));
-    logv(c, format!("rust_demangler_path: {:?}", config.rust_demangler_path));
-    logv(c, format!("src_base: {:?}", config.src_base.display()));
-    logv(c, format!("build_base: {:?}", config.build_base.display()));
-    logv(c, format!("stage_id: {}", config.stage_id));
-    logv(c, format!("mode: {}", config.mode));
-    logv(c, format!("run_ignored: {}", config.run_ignored));
-    logv(c, format!("filters: {:?}", config.filters));
-    logv(c, format!("skip: {:?}", config.skip));
-    logv(c, format!("filter_exact: {}", config.filter_exact));
-    logv(
-        c,
-        format!("force_pass_mode: {}", opt_str(&config.force_pass_mode.map(|m| format!("{}", m))),),
-    );
-    logv(c, format!("runtool: {}", opt_str(&config.runtool)));
-    logv(c, format!("host-rustcflags: {:?}", config.host_rustcflags));
-    logv(c, format!("target-rustcflags: {:?}", config.target_rustcflags));
-    logv(c, format!("target: {}", config.target));
-    logv(c, format!("host: {}", config.host));
-    logv(c, format!("android-cross-path: {:?}", config.android_cross_path.display()));
-    logv(c, format!("adb_path: {:?}", config.adb_path));
-    logv(c, format!("adb_test_dir: {:?}", config.adb_test_dir));
-    logv(c, format!("adb_device_status: {}", config.adb_device_status));
-    logv(c, format!("ar: {}", config.ar));
-    logv(c, format!("target-linker: {:?}", config.target_linker));
-    logv(c, format!("host-linker: {:?}", config.host_linker));
-    logv(c, format!("verbose: {}", config.verbose));
-    logv(c, format!("format: {:?}", config.format));
-    logv(c, "\n".to_string());
-}
-
-pub fn opt_str(maybestr: &Option<String>) -> &str {
-    match *maybestr {
-        None => "(none)",
-        Some(ref s) => s,
-    }
-}
-
-pub fn opt_str2(maybestr: Option<String>) -> String {
-    match maybestr {
-        None => "(none)".to_owned(),
-        Some(s) => s,
-    }
-}
-
-pub fn run_tests(config: Arc<Config>) {
-    // If we want to collect rustfix coverage information,
-    // we first make sure that the coverage file does not exist.
-    // It will be created later on.
-    if config.rustfix_coverage {
-        let mut coverage_file_path = config.build_base.clone();
-        coverage_file_path.push("rustfix_missing_coverage.txt");
-        if coverage_file_path.exists() {
-            if let Err(e) = fs::remove_file(&coverage_file_path) {
-                panic!("Could not delete {} due to {}", coverage_file_path.display(), e)
-            }
-        }
-    }
-
-    // sadly osx needs some file descriptor limits raised for running tests in
-    // parallel (especially when we have lots and lots of child processes).
-    // For context, see #8904
-    unsafe {
-        raise_fd_limit::raise_fd_limit();
-    }
-    // Prevent issue #21352 UAC blocking .exe containing 'patch' etc. on Windows
-    // If #11207 is resolved (adding manifest to .exe) this becomes unnecessary
-    env::set_var("__COMPAT_LAYER", "RunAsInvoker");
-
-    // Let tests know which target they're running as
-    env::set_var("TARGET", &config.target);
-
-    let opts = test_opts(&config);
-
-    let mut configs = Vec::new();
-    if let Mode::DebugInfo = config.mode {
-        // Debugging emscripten code doesn't make sense today
-        if !config.target.contains("emscripten") {
-            configs.extend(configure_cdb(&config));
-            configs.extend(configure_gdb(&config));
-            configs.extend(configure_lldb(&config));
-        }
-    } else {
-        configs.push(config.clone());
-    };
-
-    let mut tests = Vec::new();
-    for c in configs {
-        let mut found_paths = BTreeSet::new();
-        make_tests(c, &mut tests, &mut found_paths);
-        check_overlapping_tests(&found_paths);
-    }
-
-    tests.sort_by(|a, b| a.desc.name.as_slice().cmp(&b.desc.name.as_slice()));
-
-    let res = test::run_tests_console(&opts, tests);
-    match res {
-        Ok(true) => {}
-        Ok(false) => {
-            // We want to report that the tests failed, but we also want to give
-            // some indication of just what tests we were running. Especially on
-            // CI, where there can be cross-compiled tests for a lot of
-            // architectures, without this critical information it can be quite
-            // easy to miss which tests failed, and as such fail to reproduce
-            // the failure locally.
-
-            println!(
-                "Some tests failed in compiletest suite={}{} mode={} host={} target={}",
-                config.suite,
-                config
-                    .compare_mode
-                    .as_ref()
-                    .map(|c| format!(" compare_mode={:?}", c))
-                    .unwrap_or_default(),
-                config.mode,
-                config.host,
-                config.target
-            );
-
-            std::process::exit(1);
-        }
-        Err(e) => {
-            // We don't know if tests passed or not, but if there was an error
-            // during testing we don't want to just succeed (we may not have
-            // tested something), so fail.
-            //
-            // This should realistically "never" happen, so don't try to make
-            // this a pretty error message.
-            panic!("I/O failure during tests: {:?}", e);
-        }
-    }
-}
-
-fn configure_cdb(config: &Config) -> Option<Arc<Config>> {
-    config.cdb.as_ref()?;
-
-    Some(Arc::new(Config { debugger: Some(Debugger::Cdb), ..config.clone() }))
-}
-
-fn configure_gdb(config: &Config) -> Option<Arc<Config>> {
-    config.gdb_version?;
-
-    if config.matches_env("msvc") {
-        return None;
-    }
-
-    if config.remote_test_client.is_some() && !config.target.contains("android") {
-        println!(
-            "WARNING: debuginfo tests are not available when \
-             testing with remote"
-        );
-        return None;
-    }
-
-    if config.target.contains("android") {
-        println!(
-            "{} debug-info test uses tcp 5039 port.\
-             please reserve it",
-            config.target
-        );
-
-        // android debug-info test uses remote debugger so, we test 1 thread
-        // at once as they're all sharing the same TCP port to communicate
-        // over.
-        //
-        // we should figure out how to lift this restriction! (run them all
-        // on different ports allocated dynamically).
-        env::set_var("RUST_TEST_THREADS", "1");
-    }
-
-    Some(Arc::new(Config { debugger: Some(Debugger::Gdb), ..config.clone() }))
-}
-
-fn configure_lldb(config: &Config) -> Option<Arc<Config>> {
-    config.lldb_python_dir.as_ref()?;
-
-    if let Some(350) = config.lldb_version {
-        println!(
-            "WARNING: The used version of LLDB (350) has a \
-             known issue that breaks debuginfo tests. See \
-             issue #32520 for more information. Skipping all \
-             LLDB-based tests!",
-        );
-        return None;
-    }
-
-    Some(Arc::new(Config { debugger: Some(Debugger::Lldb), ..config.clone() }))
-}
-
-pub fn test_opts(config: &Config) -> test::TestOpts {
-    if env::var("RUST_TEST_NOCAPTURE").is_ok() {
-        eprintln!(
-            "WARNING: RUST_TEST_NOCAPTURE is no longer used. \
-                   Use the `--nocapture` flag instead."
-        );
-    }
-
-    test::TestOpts {
-        exclude_should_panic: false,
-        filters: config.filters.clone(),
-        filter_exact: config.filter_exact,
-        run_ignored: if config.run_ignored { test::RunIgnored::Yes } else { test::RunIgnored::No },
-        format: config.format,
-        logfile: config.logfile.clone(),
-        run_tests: true,
-        bench_benchmarks: true,
-        nocapture: config.nocapture,
-        color: config.color,
-        shuffle: false,
-        shuffle_seed: None,
-        test_threads: None,
-        skip: config.skip.clone(),
-        list: false,
-        options: test::Options::new(),
-        time_options: None,
-        force_run_in_process: false,
-        fail_fast: std::env::var_os("RUSTC_TEST_FAIL_FAST").is_some(),
-    }
-}
-
-pub fn make_tests(
-    config: Arc<Config>,
-    tests: &mut Vec<test::TestDescAndFn>,
-    found_paths: &mut BTreeSet<PathBuf>,
-) {
-    debug!("making tests from {:?}", config.src_base.display());
-    let inputs = common_inputs_stamp(&config);
-    let modified_tests = modified_tests(&config, &config.src_base).unwrap_or_else(|err| {
-        panic!("modified_tests got error from dir: {}, error: {}", config.src_base.display(), err)
-    });
-
-    let cache = HeadersCache::load(&config);
-    let mut poisoned = false;
-    collect_tests_from_dir(
-        config.clone(),
-        &cache,
-        &config.src_base,
-        &PathBuf::new(),
-        &inputs,
-        tests,
-        found_paths,
-        &modified_tests,
-        &mut poisoned,
-    )
-    .unwrap_or_else(|_| panic!("Could not read tests from {}", config.src_base.display()));
-
-    if poisoned {
-        eprintln!();
-        panic!("there are errors in tests");
-    }
-}
-
-/// Returns a stamp constructed from input files common to all test cases.
-fn common_inputs_stamp(config: &Config) -> Stamp {
-    let rust_src_dir = config.find_rust_src_root().expect("Could not find Rust source root");
-
-    let mut stamp = Stamp::from_path(&config.rustc_path);
-
-    // Relevant pretty printer files
-    let pretty_printer_files = [
-        "src/etc/rust_types.py",
-        "src/etc/gdb_load_rust_pretty_printers.py",
-        "src/etc/gdb_lookup.py",
-        "src/etc/gdb_providers.py",
-        "src/etc/lldb_batchmode.py",
-        "src/etc/lldb_lookup.py",
-        "src/etc/lldb_providers.py",
-    ];
-    for file in &pretty_printer_files {
-        let path = rust_src_dir.join(file);
-        stamp.add_path(&path);
-    }
-
-    stamp.add_dir(&rust_src_dir.join("src/etc/natvis"));
-
-    stamp.add_dir(&config.run_lib_path);
-
-    if let Some(ref rustdoc_path) = config.rustdoc_path {
-        stamp.add_path(&rustdoc_path);
-        stamp.add_path(&rust_src_dir.join("src/etc/htmldocck.py"));
-    }
-
-    // Compiletest itself.
-    stamp.add_dir(&rust_src_dir.join("src/tools/compiletest/"));
-
-    stamp
-}
-
-fn modified_tests(config: &Config, dir: &Path) -> Result<Vec<PathBuf>, String> {
-    if !config.only_modified {
-        return Ok(vec![]);
-    }
-    let files =
-        get_git_modified_files(Some(dir), &vec!["rs", "stderr", "fixed"])?.unwrap_or(vec![]);
-    // Add new test cases to the list, it will be convenient in daily development.
-    let untracked_files = get_git_untracked_files(None)?.unwrap_or(vec![]);
-
-    let all_paths = [&files[..], &untracked_files[..]].concat();
-    let full_paths = {
-        let mut full_paths: Vec<PathBuf> = all_paths
-            .into_iter()
-            .map(|f| PathBuf::from(f).with_extension("").with_extension("rs"))
-            .filter_map(|f| if Path::new(&f).exists() { f.canonicalize().ok() } else { None })
-            .collect();
-        full_paths.dedup();
-        full_paths.sort_unstable();
-        full_paths
-    };
-    Ok(full_paths)
-}
-
-fn collect_tests_from_dir(
-    config: Arc<Config>,
-    cache: &HeadersCache,
-    dir: &Path,
-    relative_dir_path: &Path,
-    inputs: &Stamp,
-    tests: &mut Vec<test::TestDescAndFn>,
-    found_paths: &mut BTreeSet<PathBuf>,
-    modified_tests: &Vec<PathBuf>,
-    poisoned: &mut bool,
-) -> io::Result<()> {
-    // Ignore directories that contain a file named `compiletest-ignore-dir`.
-    if dir.join("compiletest-ignore-dir").exists() {
-        return Ok(());
-    }
-
-    if config.mode == Mode::RunMake && dir.join("Makefile").exists() {
-        let paths = TestPaths {
-            file: dir.to_path_buf(),
-            relative_dir: relative_dir_path.parent().unwrap().to_path_buf(),
-        };
-        tests.extend(make_test(config, cache, &paths, inputs, poisoned));
-        return Ok(());
-    }
-
-    // If we find a test foo/bar.rs, we have to build the
-    // output directory `$build/foo` so we can write
-    // `$build/foo/bar` into it. We do this *now* in this
-    // sequential loop because otherwise, if we do it in the
-    // tests themselves, they race for the privilege of
-    // creating the directories and sometimes fail randomly.
-    let build_dir = output_relative_path(&config, relative_dir_path);
-    fs::create_dir_all(&build_dir).unwrap();
-
-    // Add each `.rs` file as a test, and recurse further on any
-    // subdirectories we find, except for `aux` directories.
-    for file in fs::read_dir(dir)? {
-        let file = file?;
-        let file_path = file.path();
-        let file_name = file.file_name();
-        if is_test(&file_name) && (!config.only_modified || modified_tests.contains(&file_path)) {
-            debug!("found test file: {:?}", file_path.display());
-            let rel_test_path = relative_dir_path.join(file_path.file_stem().unwrap());
-            found_paths.insert(rel_test_path);
-            let paths =
-                TestPaths { file: file_path, relative_dir: relative_dir_path.to_path_buf() };
-
-            tests.extend(make_test(config.clone(), cache, &paths, inputs, poisoned))
-        } else if file_path.is_dir() {
-            let relative_file_path = relative_dir_path.join(file.file_name());
-            if &file_name != "auxiliary" {
-                debug!("found directory: {:?}", file_path.display());
-                collect_tests_from_dir(
-                    config.clone(),
-                    cache,
-                    &file_path,
-                    &relative_file_path,
-                    inputs,
-                    tests,
-                    found_paths,
-                    modified_tests,
-                    poisoned,
-                )?;
-            }
-        } else {
-            debug!("found other file/directory: {:?}", file_path.display());
-        }
-    }
-    Ok(())
-}
-
-/// Returns true if `file_name` looks like a proper test file name.
-pub fn is_test(file_name: &OsString) -> bool {
-    let file_name = file_name.to_str().unwrap();
-
-    if !file_name.ends_with(".rs") {
-        return false;
-    }
-
-    // `.`, `#`, and `~` are common temp-file prefixes.
-    let invalid_prefixes = &[".", "#", "~"];
-    !invalid_prefixes.iter().any(|p| file_name.starts_with(p))
-}
-
-fn make_test(
-    config: Arc<Config>,
-    cache: &HeadersCache,
-    testpaths: &TestPaths,
-    inputs: &Stamp,
-    poisoned: &mut bool,
-) -> Vec<test::TestDescAndFn> {
-    let test_path = if config.mode == Mode::RunMake {
-        // Parse directives in the Makefile
-        testpaths.file.join("Makefile")
-    } else {
-        PathBuf::from(&testpaths.file)
-    };
-    let early_props = EarlyProps::from_file(&config, &test_path);
-
-    // Incremental tests are special, they inherently cannot be run in parallel.
-    // `runtest::run` will be responsible for iterating over revisions.
-    let revisions = if early_props.revisions.is_empty() || config.mode == Mode::Incremental {
-        vec![None]
-    } else {
-        early_props.revisions.iter().map(Some).collect()
-    };
-
-    revisions
-        .into_iter()
-        .map(|revision| {
-            let src_file =
-                std::fs::File::open(&test_path).expect("open test file to parse ignores");
-            let cfg = revision.map(|v| &**v);
-            let test_name = crate::make_test_name(&config, testpaths, revision);
-            let mut desc = make_test_description(
-                &config, cache, test_name, &test_path, src_file, cfg, poisoned,
-            );
-            // Ignore tests that already run and are up to date with respect to inputs.
-            if !config.force_rerun {
-                desc.ignore |= is_up_to_date(
-                    &config,
-                    testpaths,
-                    &early_props,
-                    revision.map(|s| s.as_str()),
-                    inputs,
-                );
-            }
-            test::TestDescAndFn {
-                desc,
-                testfn: make_test_closure(config.clone(), testpaths, revision),
-            }
-        })
-        .collect()
-}
-
-fn stamp(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> PathBuf {
-    output_base_dir(config, testpaths, revision).join("stamp")
-}
-
-fn files_related_to_test(
-    config: &Config,
-    testpaths: &TestPaths,
-    props: &EarlyProps,
-    revision: Option<&str>,
-) -> Vec<PathBuf> {
-    let mut related = vec![];
-
-    if testpaths.file.is_dir() {
-        // run-make tests use their individual directory
-        for entry in WalkDir::new(&testpaths.file) {
-            let path = entry.unwrap().into_path();
-            if path.is_file() {
-                related.push(path);
-            }
-        }
-    } else {
-        related.push(testpaths.file.clone());
-    }
-
-    for aux in &props.aux {
-        let path = testpaths.file.parent().unwrap().join("auxiliary").join(aux);
-        related.push(path);
-    }
-
-    // UI test files.
-    for extension in UI_EXTENSIONS {
-        let path = expected_output_path(testpaths, revision, &config.compare_mode, extension);
-        related.push(path);
-    }
-
-    related
-}
-
-fn is_up_to_date(
-    config: &Config,
-    testpaths: &TestPaths,
-    props: &EarlyProps,
-    revision: Option<&str>,
-    inputs: &Stamp,
-) -> bool {
-    let stamp_name = stamp(config, testpaths, revision);
-    // Check hash.
-    let contents = match fs::read_to_string(&stamp_name) {
-        Ok(f) => f,
-        Err(ref e) if e.kind() == ErrorKind::InvalidData => panic!("Can't read stamp contents"),
-        Err(_) => return false,
-    };
-    let expected_hash = runtest::compute_stamp_hash(config);
-    if contents != expected_hash {
-        return false;
-    }
-
-    // Check timestamps.
-    let mut inputs = inputs.clone();
-    for path in files_related_to_test(config, testpaths, props, revision) {
-        inputs.add_path(&path);
-    }
-
-    inputs < Stamp::from_path(&stamp_name)
-}
-
-#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
-struct Stamp {
-    time: SystemTime,
-}
-
-impl Stamp {
-    fn from_path(path: &Path) -> Self {
-        let mut stamp = Stamp { time: SystemTime::UNIX_EPOCH };
-        stamp.add_path(path);
-        stamp
-    }
-
-    fn add_path(&mut self, path: &Path) {
-        let modified = fs::metadata(path)
-            .and_then(|metadata| metadata.modified())
-            .unwrap_or(SystemTime::UNIX_EPOCH);
-        self.time = self.time.max(modified);
-    }
-
-    fn add_dir(&mut self, path: &Path) {
-        for entry in WalkDir::new(path) {
-            let entry = entry.unwrap();
-            if entry.file_type().is_file() {
-                let modified = entry
-                    .metadata()
-                    .ok()
-                    .and_then(|metadata| metadata.modified().ok())
-                    .unwrap_or(SystemTime::UNIX_EPOCH);
-                self.time = self.time.max(modified);
-            }
-        }
-    }
-}
-
-fn make_test_name(
-    config: &Config,
-    testpaths: &TestPaths,
-    revision: Option<&String>,
-) -> test::TestName {
-    // Print the name of the file, relative to the repository root.
-    // `src_base` looks like `/path/to/rust/tests/ui`
-    let root_directory = config.src_base.parent().unwrap().parent().unwrap();
-    let path = testpaths.file.strip_prefix(root_directory).unwrap();
-    let debugger = match config.debugger {
-        Some(d) => format!("-{}", d),
-        None => String::new(),
-    };
-    let mode_suffix = match config.compare_mode {
-        Some(ref mode) => format!(" ({})", mode.to_str()),
-        None => String::new(),
-    };
-
-    test::DynTestName(format!(
-        "[{}{}{}] {}{}",
-        config.mode,
-        debugger,
-        mode_suffix,
-        path.display(),
-        revision.map_or("".to_string(), |rev| format!("#{}", rev))
-    ))
-}
-
-fn make_test_closure(
-    config: Arc<Config>,
-    testpaths: &TestPaths,
-    revision: Option<&String>,
-) -> test::TestFn {
-    let config = config.clone();
-    let testpaths = testpaths.clone();
-    let revision = revision.cloned();
-    test::DynTestFn(Box::new(move || {
-        runtest::run(config, &testpaths, revision.as_deref());
-        Ok(())
-    }))
-}
-
-/// Returns `true` if the given target is an Android target for the
-/// purposes of GDB testing.
-fn is_android_gdb_target(target: &str) -> bool {
-    matches!(
-        &target[..],
-        "arm-linux-androideabi" | "armv7-linux-androideabi" | "aarch64-linux-android"
-    )
-}
-
-/// Returns `true` if the given target is a MSVC target for the purpouses of CDB testing.
-fn is_pc_windows_msvc_target(target: &str) -> bool {
-    target.ends_with("-pc-windows-msvc")
-}
-
-fn find_cdb(target: &str) -> Option<OsString> {
-    if !(cfg!(windows) && is_pc_windows_msvc_target(target)) {
-        return None;
-    }
-
-    let pf86 = env::var_os("ProgramFiles(x86)").or_else(|| env::var_os("ProgramFiles"))?;
-    let cdb_arch = if cfg!(target_arch = "x86") {
-        "x86"
-    } else if cfg!(target_arch = "x86_64") {
-        "x64"
-    } else if cfg!(target_arch = "aarch64") {
-        "arm64"
-    } else if cfg!(target_arch = "arm") {
-        "arm"
-    } else {
-        return None; // No compatible CDB.exe in the Windows 10 SDK
-    };
-
-    let mut path = PathBuf::new();
-    path.push(pf86);
-    path.push(r"Windows Kits\10\Debuggers"); // We could check 8.1 etc. too?
-    path.push(cdb_arch);
-    path.push(r"cdb.exe");
-
-    if !path.exists() {
-        return None;
-    }
-
-    Some(path.into_os_string())
-}
-
-/// Returns Path to CDB
-fn analyze_cdb(cdb: Option<String>, target: &str) -> (Option<OsString>, Option<[u16; 4]>) {
-    let cdb = cdb.map(OsString::from).or_else(|| find_cdb(target));
-
-    let mut version = None;
-    if let Some(cdb) = cdb.as_ref() {
-        if let Ok(output) = Command::new(cdb).arg("/version").output() {
-            if let Some(first_line) = String::from_utf8_lossy(&output.stdout).lines().next() {
-                version = extract_cdb_version(&first_line);
-            }
-        }
-    }
-
-    (cdb, version)
-}
-
-fn extract_cdb_version(full_version_line: &str) -> Option<[u16; 4]> {
-    // Example full_version_line: "cdb version 10.0.18362.1"
-    let version = full_version_line.rsplit(' ').next()?;
-    let mut components = version.split('.');
-    let major: u16 = components.next().unwrap().parse().unwrap();
-    let minor: u16 = components.next().unwrap().parse().unwrap();
-    let patch: u16 = components.next().unwrap_or("0").parse().unwrap();
-    let build: u16 = components.next().unwrap_or("0").parse().unwrap();
-    Some([major, minor, patch, build])
-}
-
-/// Returns (Path to GDB, GDB Version, GDB has Rust Support)
-fn analyze_gdb(
-    gdb: Option<String>,
-    target: &str,
-    android_cross_path: &PathBuf,
-) -> (Option<String>, Option<u32>, bool) {
-    #[cfg(not(windows))]
-    const GDB_FALLBACK: &str = "gdb";
-    #[cfg(windows)]
-    const GDB_FALLBACK: &str = "gdb.exe";
-
-    const MIN_GDB_WITH_RUST: u32 = 7011010;
-
-    let fallback_gdb = || {
-        if is_android_gdb_target(target) {
-            let mut gdb_path = match android_cross_path.to_str() {
-                Some(x) => x.to_owned(),
-                None => panic!("cannot find android cross path"),
-            };
-            gdb_path.push_str("/bin/gdb");
-            gdb_path
-        } else {
-            GDB_FALLBACK.to_owned()
-        }
-    };
-
-    let gdb = match gdb {
-        None => fallback_gdb(),
-        Some(ref s) if s.is_empty() => fallback_gdb(), // may be empty if configure found no gdb
-        Some(ref s) => s.to_owned(),
-    };
-
-    let mut version_line = None;
-    if let Ok(output) = Command::new(&gdb).arg("--version").output() {
-        if let Some(first_line) = String::from_utf8_lossy(&output.stdout).lines().next() {
-            version_line = Some(first_line.to_string());
-        }
-    }
-
-    let version = match version_line {
-        Some(line) => extract_gdb_version(&line),
-        None => return (None, None, false),
-    };
-
-    let gdb_native_rust = version.map_or(false, |v| v >= MIN_GDB_WITH_RUST);
-
-    (Some(gdb), version, gdb_native_rust)
-}
-
-fn extract_gdb_version(full_version_line: &str) -> Option<u32> {
-    let full_version_line = full_version_line.trim();
-
-    // GDB versions look like this: "major.minor.patch?.yyyymmdd?", with both
-    // of the ? sections being optional
-
-    // We will parse up to 3 digits for each component, ignoring the date
-
-    // We skip text in parentheses.  This avoids accidentally parsing
-    // the openSUSE version, which looks like:
-    //  GNU gdb (GDB; openSUSE Leap 15.0) 8.1
-    // This particular form is documented in the GNU coding standards:
-    // https://www.gnu.org/prep/standards/html_node/_002d_002dversion.html#g_t_002d_002dversion
-
-    let unbracketed_part = full_version_line.split('[').next().unwrap();
-    let mut splits = unbracketed_part.trim_end().rsplit(' ');
-    let version_string = splits.next().unwrap();
-
-    let mut splits = version_string.split('.');
-    let major = splits.next().unwrap();
-    let minor = splits.next().unwrap();
-    let patch = splits.next();
-
-    let major: u32 = major.parse().unwrap();
-    let (minor, patch): (u32, u32) = match minor.find(not_a_digit) {
-        None => {
-            let minor = minor.parse().unwrap();
-            let patch: u32 = match patch {
-                Some(patch) => match patch.find(not_a_digit) {
-                    None => patch.parse().unwrap(),
-                    Some(idx) if idx > 3 => 0,
-                    Some(idx) => patch[..idx].parse().unwrap(),
-                },
-                None => 0,
-            };
-            (minor, patch)
-        }
-        // There is no patch version after minor-date (e.g. "4-2012").
-        Some(idx) => {
-            let minor = minor[..idx].parse().unwrap();
-            (minor, 0)
-        }
-    };
-
-    Some(((major * 1000) + minor) * 1000 + patch)
-}
-
-/// Returns (LLDB version, LLDB is rust-enabled)
-fn extract_lldb_version(full_version_line: &str) -> Option<(u32, bool)> {
-    // Extract the major LLDB version from the given version string.
-    // LLDB version strings are different for Apple and non-Apple platforms.
-    // The Apple variant looks like this:
-    //
-    // LLDB-179.5 (older versions)
-    // lldb-300.2.51 (new versions)
-    //
-    // We are only interested in the major version number, so this function
-    // will return `Some(179)` and `Some(300)` respectively.
-    //
-    // Upstream versions look like:
-    // lldb version 6.0.1
-    //
-    // There doesn't seem to be a way to correlate the Apple version
-    // with the upstream version, and since the tests were originally
-    // written against Apple versions, we make a fake Apple version by
-    // multiplying the first number by 100.  This is a hack, but
-    // normally fine because the only non-Apple version we test is
-    // rust-enabled.
-
-    let full_version_line = full_version_line.trim();
-
-    if let Some(apple_ver) =
-        full_version_line.strip_prefix("LLDB-").or_else(|| full_version_line.strip_prefix("lldb-"))
-    {
-        if let Some(idx) = apple_ver.find(not_a_digit) {
-            let version: u32 = apple_ver[..idx].parse().unwrap();
-            return Some((version, full_version_line.contains("rust-enabled")));
-        }
-    } else if let Some(lldb_ver) = full_version_line.strip_prefix("lldb version ") {
-        if let Some(idx) = lldb_ver.find(not_a_digit) {
-            let version: u32 = lldb_ver[..idx].parse().ok()?;
-            return Some((version * 100, full_version_line.contains("rust-enabled")));
-        }
-    }
-    None
-}
-
-fn not_a_digit(c: char) -> bool {
-    !c.is_digit(10)
-}
-
-fn check_overlapping_tests(found_paths: &BTreeSet<PathBuf>) {
-    let mut collisions = Vec::new();
-    for path in found_paths {
-        for ancestor in path.ancestors().skip(1) {
-            if found_paths.contains(ancestor) {
-                collisions.push((path, ancestor.clone()));
-            }
-        }
-    }
-    if !collisions.is_empty() {
-        let collisions: String = collisions
-            .into_iter()
-            .map(|(path, check_parent)| format!("test {path:?} clashes with {check_parent:?}\n"))
-            .collect();
-        panic!(
-            "{collisions}\n\
-            Tests cannot have overlapping names. Make sure they use unique prefixes."
-        );
-    }
-}
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 5bc4d164265..923b2e63f2e 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1939,6 +1939,17 @@ impl<'test> TestCx<'test> {
         // Use a single thread for efficiency and a deterministic error message order
         rustc.arg("-Zthreads=1");
 
+        // Hide libstd sources from ui tests to make sure we generate the stderr
+        // output that users will see.
+        // Without this, we may be producing good diagnostics in-tree but users
+        // will not see half the information.
+        //
+        // This also has the benefit of more effectively normalizing output between different
+        // compilers, so that we don't have to know the `/rustc/$sha` output to normalize after the
+        // fact.
+        rustc.arg("-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX");
+        rustc.arg("-Ztranslate-remapped-path-to-local-path=no");
+
         // Optionally prevent default --sysroot if specified in test compile-flags.
         if !self.props.compile_flags.iter().any(|flag| flag.starts_with("--sysroot")) {
             // In stage 0, make sure we use `stage0-sysroot` instead of the bootstrap sysroot.
@@ -2014,13 +2025,6 @@ impl<'test> TestCx<'test> {
                 rustc.arg("-Ccodegen-units=1");
                 // Hide line numbers to reduce churn
                 rustc.arg("-Zui-testing");
-                // Hide libstd sources from ui tests to make sure we generate the stderr
-                // output that users will see.
-                // Without this, we may be producing good diagnostics in-tree but users
-                // will not see half the information.
-                rustc.arg("-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX");
-                rustc.arg("-Ztranslate-remapped-path-to-local-path=no");
-
                 rustc.arg("-Zdeduplicate-diagnostics=no");
                 // FIXME: use this for other modes too, for perf?
                 rustc.arg("-Cstrip=debuginfo");
@@ -2045,7 +2049,10 @@ impl<'test> TestCx<'test> {
                 if let Some(pass) = &self.props.mir_unit_test {
                     rustc.args(&["-Zmir-opt-level=0", &format!("-Zmir-enable-passes=+{}", pass)]);
                 } else {
-                    rustc.arg("-Zmir-opt-level=4");
+                    rustc.args(&[
+                        "-Zmir-opt-level=4",
+                        "-Zmir-enable-passes=+ReorderBasicBlocks,+ReorderLocals",
+                    ]);
                 }
 
                 let mir_dump_dir = self.get_mir_dump_dir();
@@ -3729,28 +3736,13 @@ impl<'test> TestCx<'test> {
             normalize_path(&remapped_parent_dir, "$DIR");
         }
 
-        let source_bases = &[
-            // Source base on the current filesystem (calculated as parent of `tests/$suite`):
-            Some(self.config.src_base.parent().unwrap().parent().unwrap().into()),
-            // Source base on the sysroot (from the src components downloaded by `download-rustc`):
-            Some(self.config.sysroot_base.join("lib").join("rustlib").join("src").join("rust")),
-            // Virtual `/rustc/$sha` remapped paths (if `remap-debuginfo` is enabled):
-            option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR").map(PathBuf::from),
-            // Virtual `/rustc/$sha` coming from download-rustc:
-            std::env::var_os("FAKE_DOWNLOAD_RUSTC_PREFIX").map(PathBuf::from),
-            // Tests using -Zsimulate-remapped-rust-src-base should use this fake path
-            Some("/rustc/FAKE_PREFIX".into()),
-        ];
-        for base_dir in source_bases {
-            if let Some(base_dir) = base_dir {
-                // Paths into the libstd/libcore
-                normalize_path(&base_dir.join("library"), "$SRC_DIR");
-                // `ui-fulldeps` tests can show paths to the compiler source when testing macros from
-                // `rustc_macros`
-                // eg. /home/user/rust/compiler
-                normalize_path(&base_dir.join("compiler"), "$COMPILER_DIR");
-            }
-        }
+        let base_dir = Path::new("/rustc/FAKE_PREFIX");
+        // Paths into the libstd/libcore
+        normalize_path(&base_dir.join("library"), "$SRC_DIR");
+        // `ui-fulldeps` tests can show paths to the compiler source when testing macros from
+        // `rustc_macros`
+        // eg. /home/user/rust/compiler
+        normalize_path(&base_dir.join("compiler"), "$COMPILER_DIR");
 
         // Paths into the build directory
         let test_build_dir = &self.config.build_base;
diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs
index 748240cc94b..17bed38b65e 100644
--- a/src/tools/compiletest/src/util.rs
+++ b/src/tools/compiletest/src/util.rs
@@ -104,6 +104,8 @@ pub const XRAY_SUPPORTED_TARGETS: &[&str] = &[
     "x86_64-unknown-openbsd",
 ];
 
+pub const SAFESTACK_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu"];
+
 pub fn make_new_path(path: &str) -> String {
     assert!(cfg!(windows));
     // Windows just uses PATH as the library search path, so we have to
diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs
index d85cac7bcbb..25c8df43ee2 100644
--- a/src/tools/miri/src/concurrency/thread.rs
+++ b/src/tools/miri/src/concurrency/thread.rs
@@ -133,10 +133,15 @@ pub struct Thread<'mir, 'tcx> {
     /// The join status.
     join_status: ThreadJoinStatus,
 
-    /// The temporary used for storing the argument of
-    /// the call to `miri_start_panic` (the panic payload) when unwinding.
+    /// Stack of active panic payloads for the current thread. Used for storing
+    /// the argument of the call to `miri_start_panic` (the panic payload) when unwinding.
     /// This is pointer-sized, and matches the `Payload` type in `src/libpanic_unwind/miri.rs`.
-    pub(crate) panic_payload: Option<Scalar<Provenance>>,
+    ///
+    /// In real unwinding, the payload gets passed as an argument to the landing pad,
+    /// which then forwards it to 'Resume'. However this argument is implicit in MIR,
+    /// so we have to store it out-of-band. When there are multiple active unwinds,
+    /// the innermost one is always caught first, so we can store them as a stack.
+    pub(crate) panic_payloads: Vec<Scalar<Provenance>>,
 
     /// Last OS error location in memory. It is a 32-bit integer.
     pub(crate) last_error: Option<MPlaceTy<'tcx, Provenance>>,
@@ -206,7 +211,7 @@ impl<'mir, 'tcx> Thread<'mir, 'tcx> {
             stack: Vec::new(),
             top_user_relevant_frame: None,
             join_status: ThreadJoinStatus::Joinable,
-            panic_payload: None,
+            panic_payloads: Vec::new(),
             last_error: None,
             on_stack_empty,
         }
@@ -216,7 +221,7 @@ impl<'mir, 'tcx> Thread<'mir, 'tcx> {
 impl VisitTags for Thread<'_, '_> {
     fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) {
         let Thread {
-            panic_payload,
+            panic_payloads: panic_payload,
             last_error,
             stack,
             top_user_relevant_frame: _,
@@ -226,7 +231,9 @@ impl VisitTags for Thread<'_, '_> {
             on_stack_empty: _, // we assume the closure captures no GC-relevant state
         } = self;
 
-        panic_payload.visit_tags(visit);
+        for payload in panic_payload {
+            payload.visit_tags(visit);
+        }
         last_error.visit_tags(visit);
         for frame in stack {
             frame.visit_tags(visit)
diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs
index e3f81a78eea..14931baaadf 100644
--- a/src/tools/miri/src/diagnostics.rs
+++ b/src/tools/miri/src/diagnostics.rs
@@ -306,7 +306,7 @@ pub fn report_error<'tcx, 'mir>(
     msg.insert(0, e.to_string());
     report_msg(
         DiagLevel::Error,
-        &if let Some(title) = title { format!("{title}: {}", msg[0]) } else { msg[0].clone() },
+        if let Some(title) = title { format!("{title}: {}", msg[0]) } else { msg[0].clone() },
         msg,
         vec![],
         helps,
@@ -359,7 +359,7 @@ pub fn report_leaks<'mir, 'tcx>(
         any_pruned |= pruned;
         report_msg(
             DiagLevel::Error,
-            &format!(
+            format!(
                 "memory leaked: {id:?} ({}, size: {:?}, align: {:?}), allocated here:",
                 kind,
                 alloc.size().bytes(),
@@ -386,7 +386,7 @@ pub fn report_leaks<'mir, 'tcx>(
 /// additional `span_label` or `note` call.
 pub fn report_msg<'tcx>(
     diag_level: DiagLevel,
-    title: &str,
+    title: String,
     span_msg: Vec<String>,
     notes: Vec<(Option<SpanData>, String)>,
     helps: Vec<(Option<SpanData>, String)>,
@@ -463,15 +463,16 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
         let (stacktrace, _was_pruned) = prune_stacktrace(stacktrace, self);
 
         let (title, diag_level) = match &e {
-            RejectedIsolatedOp(_) => ("operation rejected by isolation", DiagLevel::Warning),
-            Int2Ptr { .. } => ("integer-to-pointer cast", DiagLevel::Warning),
+            RejectedIsolatedOp(_) =>
+                ("operation rejected by isolation".to_string(), DiagLevel::Warning),
+            Int2Ptr { .. } => ("integer-to-pointer cast".to_string(), DiagLevel::Warning),
             CreatedPointerTag(..)
             | PoppedPointerTag(..)
             | CreatedCallId(..)
             | CreatedAlloc(..)
             | FreedAlloc(..)
             | ProgressReport { .. }
-            | WeakMemoryOutdatedLoad => ("tracking was triggered", DiagLevel::Note),
+            | WeakMemoryOutdatedLoad => ("tracking was triggered".to_string(), DiagLevel::Note),
         };
 
         let msg = match &e {
@@ -571,7 +572,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let stacktrace = this.generate_stacktrace();
         report_msg(
             DiagLevel::Note,
-            "the place in the program where the ICE was triggered",
+            "the place in the program where the ICE was triggered".to_string(),
             vec![],
             vec![],
             vec![],
diff --git a/src/tools/miri/src/shims/panic.rs b/src/tools/miri/src/shims/panic.rs
index 18ae01a19f9..7aefdfcb976 100644
--- a/src/tools/miri/src/shims/panic.rs
+++ b/src/tools/miri/src/shims/panic.rs
@@ -63,8 +63,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let [payload] = this.check_shim(abi, Abi::Rust, link_name, args)?;
         let payload = this.read_scalar(payload)?;
         let thread = this.active_thread_mut();
-        assert!(thread.panic_payload.is_none(), "the panic runtime should avoid double-panics");
-        thread.panic_payload = Some(payload);
+        thread.panic_payloads.push(payload);
 
         // Jump to the unwind block to begin unwinding.
         this.unwind_to_block(unwind)?;
@@ -146,7 +145,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
             // The Thread's `panic_payload` holds what was passed to `miri_start_panic`.
             // This is exactly the second argument we need to pass to `catch_fn`.
-            let payload = this.active_thread_mut().panic_payload.take().unwrap();
+            let payload = this.active_thread_mut().panic_payloads.pop().unwrap();
 
             // Push the `catch_fn` stackframe.
             let f_instance = this.get_ptr_fn(catch_unwind.catch_fn)?.as_instance()?;
diff --git a/src/tools/miri/tests/fail/panic/double_panic.rs b/src/tools/miri/tests/fail/panic/double_panic.rs
index 9378adb8609..adb30714269 100644
--- a/src/tools/miri/tests/fail/panic/double_panic.rs
+++ b/src/tools/miri/tests/fail/panic/double_panic.rs
@@ -1,6 +1,4 @@
-//@error-in-other-file: the program aborted
 //@normalize-stderr-test: "\| +\^+" -> "| ^"
-//@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();"
 //@normalize-stderr-test: "\n  +[0-9]+:[^\n]+" -> "$1"
 //@normalize-stderr-test: "\n at [^\n]+" -> "$1"
 
@@ -11,6 +9,7 @@ impl Drop for Foo {
     }
 }
 fn main() {
+    //~^ERROR: panic in a function that cannot unwind
     let _foo = Foo;
     panic!("first");
 }
diff --git a/src/tools/miri/tests/fail/panic/double_panic.stderr b/src/tools/miri/tests/fail/panic/double_panic.stderr
index 77d5fc5d7ce..b6ac56f15d4 100644
--- a/src/tools/miri/tests/fail/panic/double_panic.stderr
+++ b/src/tools/miri/tests/fail/panic/double_panic.stderr
@@ -2,30 +2,17 @@ thread 'main' panicked at 'first', $DIR/double_panic.rs:LL:CC
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 thread 'main' panicked at 'second', $DIR/double_panic.rs:LL:CC
 stack backtrace:
-thread panicked while panicking. aborting.
-error: abnormal termination: the program aborted execution
-  --> RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
-   |
-LL |     ABORT();
-   | ^ the program aborted execution
-   |
-   = note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
-   = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
-   = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
-   = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
-   = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
-note: inside `<Foo as std::ops::Drop>::drop`
+error: abnormal termination: panic in a function that cannot unwind
   --> $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`
-  --> $DIR/double_panic.rs:LL:CC
+LL | / fn main() {
+LL | |
+LL | |     let _foo = Foo;
+LL | |     panic!("first");
+LL | | }
+   | |_^ panic in a function that cannot unwind
    |
-LL | }
-   | ^
-   = 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: inside `main` at $DIR/double_panic.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/pass/panic/nested_panic_caught.rs b/src/tools/miri/tests/pass/panic/nested_panic_caught.rs
new file mode 100644
index 00000000000..884813150ad
--- /dev/null
+++ b/src/tools/miri/tests/pass/panic/nested_panic_caught.rs
@@ -0,0 +1,25 @@
+//@normalize-stderr-test: "\| +\^+" -> "| ^"
+//@normalize-stderr-test: "\n  +[0-9]+:[^\n]+" -> "$1"
+//@normalize-stderr-test: "\n at [^\n]+" -> "$1"
+
+// Checks that nested panics work correctly.
+
+use std::panic::catch_unwind;
+
+fn double() {
+    struct Double;
+
+    impl Drop for Double {
+        fn drop(&mut self) {
+            let _ = catch_unwind(|| panic!("twice"));
+        }
+    }
+
+    let _d = Double;
+
+    panic!("once");
+}
+
+fn main() {
+    assert!(catch_unwind(|| double()).is_err());
+}
diff --git a/src/tools/miri/tests/pass/panic/nested_panic_caught.stderr b/src/tools/miri/tests/pass/panic/nested_panic_caught.stderr
new file mode 100644
index 00000000000..4e2593242df
--- /dev/null
+++ b/src/tools/miri/tests/pass/panic/nested_panic_caught.stderr
@@ -0,0 +1,4 @@
+thread 'main' panicked at 'once', $DIR/nested_panic_caught.rs:LL:CC
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+thread 'main' panicked at 'twice', $DIR/nested_panic_caught.rs:LL:CC
+stack backtrace:
diff --git a/src/tools/miri/tests/pass/shims/time-with-isolation2.stdout b/src/tools/miri/tests/pass/shims/time-with-isolation2.stdout
index 641e469f50c..c68b40b744b 100644
--- a/src/tools/miri/tests/pass/shims/time-with-isolation2.stdout
+++ b/src/tools/miri/tests/pass/shims/time-with-isolation2.stdout
@@ -1 +1 @@
-The loop took around 13s
+The loop took around 7s
diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/version.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/version.rs
index cf637ec359a..13f67a0128a 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-api/src/version.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/version.rs
@@ -122,7 +122,7 @@ pub fn read_version(dylib_path: &AbsPath) -> io::Result<String> {
     // https://github.com/rust-lang/rust/commit/0696e79f2740ad89309269b460579e548a5cd632
     let snappy_portion = match version {
         5 | 6 => &dot_rustc[8..],
-        7 => {
+        7 | 8 => {
             let len_bytes = &dot_rustc[8..12];
             let data_len = u32::from_be_bytes(len_bytes.try_into().unwrap()) as usize;
             &dot_rustc[12..data_len + 12]
diff --git a/src/tools/rustdoc-gui-test/Cargo.toml b/src/tools/rustdoc-gui-test/Cargo.toml
new file mode 100644
index 00000000000..4cb200ebc7c
--- /dev/null
+++ b/src/tools/rustdoc-gui-test/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "rustdoc-gui-test"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+build_helper = { path = "../build_helper" }
+compiletest = { path = "../compiletest" }
+getopts = "0.2"
+walkdir = "2"
diff --git a/src/tools/rustdoc-gui-test/src/config.rs b/src/tools/rustdoc-gui-test/src/config.rs
new file mode 100644
index 00000000000..dc4c56a5e7a
--- /dev/null
+++ b/src/tools/rustdoc-gui-test/src/config.rs
@@ -0,0 +1,62 @@
+use getopts::Options;
+use std::{env, path::PathBuf};
+
+pub(crate) struct Config {
+    pub(crate) nodejs: PathBuf,
+    pub(crate) npm: PathBuf,
+    pub(crate) rust_src: PathBuf,
+    pub(crate) out_dir: PathBuf,
+    pub(crate) initial_cargo: PathBuf,
+    pub(crate) jobs: String,
+    pub(crate) test_args: Vec<PathBuf>,
+    pub(crate) goml_files: Vec<PathBuf>,
+    pub(crate) rustc: PathBuf,
+    pub(crate) rustdoc: PathBuf,
+    pub(crate) verbose: bool,
+}
+
+impl Config {
+    pub(crate) fn from_args(args: Vec<String>) -> Self {
+        let mut opts = Options::new();
+        opts.reqopt("", "nodejs", "absolute path of nodejs", "PATH")
+            .reqopt("", "npm", "absolute path of npm", "PATH")
+            .reqopt("", "out-dir", "output path of doc compilation", "PATH")
+            .reqopt("", "rust-src", "root source of the rust source", "PATH")
+            .reqopt(
+                "",
+                "initial-cargo",
+                "path to cargo to use for compiling tests/rustdoc-gui/src/*",
+                "PATH",
+            )
+            .reqopt("", "jobs", "jobs arg of browser-ui-test", "JOBS")
+            .optflag("", "verbose", "run tests verbosely, showing all output")
+            .optmulti("", "test-arg", "args for browser-ui-test", "FLAGS")
+            .optmulti("", "goml-file", "goml files for testing with browser-ui-test", "LIST");
+
+        let (argv0, args_) = args.split_first().unwrap();
+        if args.len() == 1 || args[1] == "-h" || args[1] == "--help" {
+            let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0);
+            println!("{}", opts.usage(&message));
+            std::process::exit(1);
+        }
+
+        let matches = &match opts.parse(args_) {
+            Ok(m) => m,
+            Err(f) => panic!("{:?}", f),
+        };
+
+        Self {
+            nodejs: matches.opt_str("nodejs").map(PathBuf::from).expect("nodejs isn't available"),
+            npm: matches.opt_str("npm").map(PathBuf::from).expect("npm isn't available"),
+            rust_src: matches.opt_str("rust-src").map(PathBuf::from).unwrap(),
+            out_dir: matches.opt_str("out-dir").map(PathBuf::from).unwrap(),
+            initial_cargo: matches.opt_str("initial-cargo").map(PathBuf::from).unwrap(),
+            jobs: matches.opt_str("jobs").unwrap(),
+            goml_files: matches.opt_strs("goml-file").iter().map(PathBuf::from).collect(),
+            test_args: matches.opt_strs("test-arg").iter().map(PathBuf::from).collect(),
+            rustc: env::var("RUSTC").map(PathBuf::from).unwrap(),
+            rustdoc: env::var("RUSTDOC").map(PathBuf::from).unwrap(),
+            verbose: matches.opt_present("verbose"),
+        }
+    }
+}
diff --git a/src/tools/rustdoc-gui-test/src/main.rs b/src/tools/rustdoc-gui-test/src/main.rs
new file mode 100644
index 00000000000..3f60a90f87a
--- /dev/null
+++ b/src/tools/rustdoc-gui-test/src/main.rs
@@ -0,0 +1,156 @@
+use build_helper::util::try_run;
+use compiletest::header::TestProps;
+use config::Config;
+use std::path::{Path, PathBuf};
+use std::process::Command;
+use std::sync::Arc;
+use std::{env, fs};
+
+mod config;
+
+fn get_browser_ui_test_version_inner(npm: &Path, global: bool) -> Option<String> {
+    let mut command = Command::new(&npm);
+    command.arg("list").arg("--parseable").arg("--long").arg("--depth=0");
+    if global {
+        command.arg("--global");
+    }
+    let lines = command
+        .output()
+        .map(|output| String::from_utf8_lossy(&output.stdout).into_owned())
+        .unwrap_or(String::new());
+    lines
+        .lines()
+        .find_map(|l| l.split(':').nth(1)?.strip_prefix("browser-ui-test@"))
+        .map(|v| v.to_owned())
+}
+
+fn get_browser_ui_test_version(npm: &Path) -> Option<String> {
+    get_browser_ui_test_version_inner(npm, false)
+        .or_else(|| get_browser_ui_test_version_inner(npm, true))
+}
+
+fn compare_browser_ui_test_version(installed_version: &str, src: &Path) {
+    match fs::read_to_string(
+        src.join("src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version"),
+    ) {
+        Ok(v) => {
+            if v.trim() != installed_version {
+                eprintln!(
+                    "⚠️ Installed version of browser-ui-test (`{}`) is different than the \
+                     one used in the CI (`{}`)",
+                    installed_version, v
+                );
+                eprintln!(
+                    "You can install this version using `npm update browser-ui-test` or by using \
+                     `npm install browser-ui-test@{}`",
+                    v,
+                );
+            }
+        }
+        Err(e) => eprintln!("Couldn't find the CI browser-ui-test version: {:?}", e),
+    }
+}
+
+fn find_librs<P: AsRef<Path>>(path: P) -> Option<PathBuf> {
+    for entry in walkdir::WalkDir::new(path) {
+        let entry = entry.ok()?;
+        if entry.file_type().is_file() && entry.file_name() == "lib.rs" {
+            return Some(entry.path().to_path_buf());
+        }
+    }
+    None
+}
+
+fn main() {
+    let config = Arc::new(Config::from_args(env::args().collect()));
+
+    // The goal here is to check if the necessary packages are installed, and if not, we
+    // panic.
+    match get_browser_ui_test_version(&config.npm) {
+        Some(version) => {
+            // We also check the version currently used in CI and emit a warning if it's not the
+            // same one.
+            compare_browser_ui_test_version(&version, &config.rust_src);
+        }
+        None => {
+            eprintln!(
+                r#"
+error: rustdoc-gui test suite cannot be run because npm `browser-ui-test` dependency is missing.
+
+If you want to install the `browser-ui-test` dependency, run `npm install browser-ui-test`
+"#,
+            );
+
+            panic!("Cannot run rustdoc-gui tests");
+        }
+    }
+
+    let src_path = config.rust_src.join("tests/rustdoc-gui/src");
+    for entry in src_path.read_dir().expect("read_dir call failed") {
+        if let Ok(entry) = entry {
+            let path = entry.path();
+
+            if !path.is_dir() {
+                continue;
+            }
+
+            let mut cargo = Command::new(&config.initial_cargo);
+            cargo
+                .arg("doc")
+                .arg("--target-dir")
+                .arg(&config.out_dir)
+                .env("RUSTC_BOOTSTRAP", "1")
+                .env("RUSTDOC", &config.rustdoc)
+                .env("RUSTC", &config.rustc)
+                .current_dir(path);
+
+            if let Some(librs) = find_librs(entry.path()) {
+                let compiletest_c = compiletest::common::Config {
+                    edition: None,
+                    mode: compiletest::common::Mode::Rustdoc,
+                    ..Default::default()
+                };
+
+                let test_props = TestProps::from_file(&librs, None, &compiletest_c);
+
+                if !test_props.compile_flags.is_empty() {
+                    cargo.env("RUSTDOCFLAGS", test_props.compile_flags.join(" "));
+                }
+
+                if let Some(flags) = &test_props.run_flags {
+                    cargo.arg(flags);
+                }
+            }
+
+            try_run(&mut cargo, config.verbose);
+        }
+    }
+
+    let mut command = Command::new(&config.nodejs);
+
+    if let Ok(current_dir) = env::current_dir() {
+        let local_node_modules = current_dir.join("node_modules");
+        if local_node_modules.exists() {
+            // Link the local node_modules if exists.
+            // This is useful when we run rustdoc-gui-test from outside of the source root.
+            env::set_var("NODE_PATH", local_node_modules);
+        }
+    }
+
+    command
+        .arg(config.rust_src.join("src/tools/rustdoc-gui/tester.js"))
+        .arg("--jobs")
+        .arg(&config.jobs)
+        .arg("--doc-folder")
+        .arg(config.out_dir.join("doc"))
+        .arg("--tests-folder")
+        .arg(config.rust_src.join("tests/rustdoc-gui"));
+
+    for file in &config.goml_files {
+        command.arg("--file").arg(file);
+    }
+
+    command.args(&config.test_args);
+
+    try_run(&mut command, config.verbose);
+}
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 2e778110931..db2b7910b71 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -38,7 +38,6 @@ const LICENSES: &[&str] = &[
 const EXCEPTIONS: &[(&str, &str)] = &[
     // tidy-alphabetical-start
     ("ar_archive_writer", "Apache-2.0 WITH LLVM-exception"), // rustc
-    ("codespan-reporting", "Apache-2.0"),                    // cxx via iana-time-zone-haiku via time, only on haiku
     ("colored", "MPL-2.0"),                                  // rustfmt
     ("dissimilar", "Apache-2.0"),                            // rustdoc, rustc_lexer (few tests) via expect-test, (dev deps)
     ("fluent-langneg", "Apache-2.0"),                        // rustc (fluent translations)
diff --git a/src/tools/tidy/src/fluent_alphabetical.rs b/src/tools/tidy/src/fluent_alphabetical.rs
new file mode 100644
index 00000000000..5f8eaebf531
--- /dev/null
+++ b/src/tools/tidy/src/fluent_alphabetical.rs
@@ -0,0 +1,72 @@
+//! Checks that all Flunt files have messages in alphabetical order
+
+use crate::walk::{filter_dirs, walk};
+use std::{fs::OpenOptions, io::Write, path::Path};
+
+use regex::Regex;
+
+lazy_static::lazy_static! {
+    static ref MESSAGE: Regex = Regex::new(r#"(?m)^([a-zA-Z0-9_]+)\s*=\s*"#).unwrap();
+}
+
+fn filter_fluent(path: &Path) -> bool {
+    if let Some(ext) = path.extension() { ext.to_str() != Some("ftl") } else { true }
+}
+
+fn check_alphabetic(filename: &str, fluent: &str, bad: &mut bool) {
+    let mut matches = MESSAGE.captures_iter(fluent).peekable();
+    while let Some(m) = matches.next() {
+        if let Some(next) = matches.peek() {
+            let name = m.get(1).unwrap();
+            let next = next.get(1).unwrap();
+            if name.as_str() > next.as_str() {
+                tidy_error!(
+                    bad,
+                    "{filename}: message `{}` appears before `{}`, but is alphabetically later than it
+run tidy with `--bless` to sort the file correctly",
+                    name.as_str(),
+                    next.as_str()
+                );
+            }
+        } else {
+            break;
+        }
+    }
+}
+
+fn sort_messages(fluent: &str) -> String {
+    let mut chunks = vec![];
+    let mut cur = String::new();
+    for line in fluent.lines() {
+        if MESSAGE.is_match(line) {
+            chunks.push(std::mem::take(&mut cur));
+        }
+        cur += line;
+        cur.push('\n');
+    }
+    chunks.push(cur);
+    chunks.sort();
+    let mut out = chunks.join("");
+    out = out.trim().to_string();
+    out.push('\n');
+    out
+}
+
+pub fn check(path: &Path, bless: bool, bad: &mut bool) {
+    walk(
+        path,
+        |path, is_dir| filter_dirs(path) || (!is_dir && filter_fluent(path)),
+        &mut |ent, contents| {
+            if bless {
+                let sorted = sort_messages(contents);
+                if sorted != contents {
+                    let mut f =
+                        OpenOptions::new().write(true).truncate(true).open(ent.path()).unwrap();
+                    f.write(sorted.as_bytes()).unwrap();
+                }
+            } else {
+                check_alphabetic(ent.path().to_str().unwrap(), contents, bad);
+            }
+        },
+    );
+}
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index 35000320d1a..e467514a7a3 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -59,6 +59,7 @@ pub mod edition;
 pub mod error_codes;
 pub mod extdeps;
 pub mod features;
+pub mod fluent_alphabetical;
 pub mod mir_opt_tests;
 pub mod pal;
 pub mod primitive_docs;
diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs
index f59406c404b..1c4d96c321c 100644
--- a/src/tools/tidy/src/main.rs
+++ b/src/tools/tidy/src/main.rs
@@ -96,6 +96,7 @@ fn main() {
 
         // Checks that only make sense for the compiler.
         check!(error_codes, &root_path, &[&compiler_path, &librustdoc_path], verbose);
+        check!(fluent_alphabetical, &compiler_path, bless);
 
         // Checks that only make sense for the std libs.
         check!(pal, &library_path);
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index be3a5d3aa0f..01ef4abd3dc 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -10,8 +10,8 @@ use std::path::{Path, PathBuf};
 
 const ENTRY_LIMIT: usize = 900;
 // FIXME: The following limits should be reduced eventually.
-const ISSUES_ENTRY_LIMIT: usize = 1920;
-const ROOT_ENTRY_LIMIT: usize = 896;
+const ISSUES_ENTRY_LIMIT: usize = 1898;
+const ROOT_ENTRY_LIMIT: usize = 891;
 
 const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
     "rs",     // test source files
diff --git a/src/version b/src/version
index df484cbb1d9..0834888f558 100644
--- a/src/version
+++ b/src/version
@@ -1 +1 @@
-1.71.0
+1.72.0
diff --git a/tests/assembly/asm/mips-types.rs b/tests/assembly/asm/mips-types.rs
index 6aa28b062db..27469b22980 100644
--- a/tests/assembly/asm/mips-types.rs
+++ b/tests/assembly/asm/mips-types.rs
@@ -72,7 +72,7 @@ macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => {
 
 // mips32-LABEL: sym_static_32:
 // mips32: #APP
-// mips32: lw $3, %got(extern_static)
+// mips32: lw $3, %got(extern_static)($gp)
 // mips32: #NO_APP
 #[cfg(mips32)]
 #[no_mangle]
@@ -82,7 +82,7 @@ pub unsafe fn sym_static_32() {
 
 // mips32-LABEL: sym_fn_32:
 // mips32: #APP
-// mips32: lw $3, %got(extern_func)
+// mips32: lw $3, %got(extern_func)($gp)
 // mips32: #NO_APP
 #[cfg(mips32)]
 #[no_mangle]
@@ -92,7 +92,9 @@ pub unsafe fn sym_fn_32() {
 
 // mips64-LABEL: sym_static_64:
 // mips64: #APP
-// mips64: ld $3, %got_disp(extern_static)
+// mips64: lui    $3, %got_hi(extern_static)
+// mips64: daddu  $3, $3, $gp
+// mips64: ld     $3, %got_lo(extern_static)($3)
 // mips64: #NO_APP
 #[cfg(mips64)]
 #[no_mangle]
@@ -102,7 +104,9 @@ pub unsafe fn sym_static_64() {
 
 // mips64-LABEL: sym_fn_64:
 // mips64: #APP
-// mips64: ld $3, %got_disp(extern_func)
+// mips64: lui    $3, %got_hi(extern_func)
+// mips64: daddu  $3, $3, $gp
+// mips64: ld     $3, %got_lo(extern_func)($3)
 // mips64: #NO_APP
 #[cfg(mips64)]
 #[no_mangle]
diff --git a/tests/codegen/array-map.rs b/tests/codegen/array-map.rs
index 3706ddf99fd..24f3f43d078 100644
--- a/tests/codegen/array-map.rs
+++ b/tests/codegen/array-map.rs
@@ -4,7 +4,6 @@
 // ignore-debug (the extra assertions get in the way)
 
 #![crate_type = "lib"]
-#![feature(array_zip)]
 
 // CHECK-LABEL: @short_integer_map
 #[no_mangle]
@@ -16,16 +15,6 @@ pub fn short_integer_map(x: [u32; 8]) -> [u32; 8] {
     x.map(|x| 2 * x + 1)
 }
 
-// CHECK-LABEL: @short_integer_zip_map
-#[no_mangle]
-pub fn short_integer_zip_map(x: [u32; 8], y: [u32; 8]) -> [u32; 8] {
-    // CHECK: %[[A:.+]] = load <8 x i32>
-    // CHECK: %[[B:.+]] = load <8 x i32>
-    // CHECK: sub <8 x i32> %[[B]], %[[A]]
-    // CHECK: store <8 x i32>
-    x.zip(y).map(|(x, y)| x - y)
-}
-
 // This test is checking that LLVM can SRoA away a bunch of the overhead,
 // like fully moving the iterators to registers.  Notably, previous implementations
 // of `map` ended up `alloca`ing the whole `array::IntoIterator`, meaning both a
diff --git a/tests/codegen/autovectorize-f32x4.rs b/tests/codegen/autovectorize-f32x4.rs
index 9ecea53f1c0..54392be707f 100644
--- a/tests/codegen/autovectorize-f32x4.rs
+++ b/tests/codegen/autovectorize-f32x4.rs
@@ -1,7 +1,6 @@
 // compile-flags: -C opt-level=3 -Z merge-functions=disabled
 // only-x86_64
 #![crate_type = "lib"]
-#![feature(array_zip)]
 
 // CHECK-LABEL: @auto_vectorize_direct
 #[no_mangle]
@@ -32,12 +31,12 @@ pub fn auto_vectorize_loop(a: [f32; 4], b: [f32; 4]) -> [f32; 4] {
     c
 }
 
-// CHECK-LABEL: @auto_vectorize_array_zip_map
+// CHECK-LABEL: @auto_vectorize_array_from_fn
 #[no_mangle]
-pub fn auto_vectorize_array_zip_map(a: [f32; 4], b: [f32; 4]) -> [f32; 4] {
+pub fn auto_vectorize_array_from_fn(a: [f32; 4], b: [f32; 4]) -> [f32; 4] {
 // CHECK: load <4 x float>
 // CHECK: load <4 x float>
 // CHECK: fadd <4 x float>
 // CHECK: store <4 x float>
-    a.zip(b).map(|(a, b)| a + b)
+    std::array::from_fn(|i| a[i] + b[i])
 }
diff --git a/tests/codegen/const_scalar_pair.rs b/tests/codegen/const_scalar_pair.rs
new file mode 100644
index 00000000000..8f32c50b798
--- /dev/null
+++ b/tests/codegen/const_scalar_pair.rs
@@ -0,0 +1,8 @@
+// compile-flags: --crate-type=lib -Copt-level=0 -Zmir-opt-level=0 -C debuginfo=2
+
+#![feature(inline_const)]
+
+pub fn foo() -> (i32, i32) {
+    // CHECK: ret { i32, i32 } { i32 1, i32 2 }
+    const { (1, 2) }
+}
diff --git a/tests/codegen/sanitizer-safestack-attr-check.rs b/tests/codegen/sanitizer-safestack-attr-check.rs
new file mode 100644
index 00000000000..b73ed00e730
--- /dev/null
+++ b/tests/codegen/sanitizer-safestack-attr-check.rs
@@ -0,0 +1,11 @@
+// This tests that the safestack attribute is applied when enabling the safe-stack sanitizer.
+//
+// needs-sanitizer-safestack
+// compile-flags: -Zsanitizer=safestack
+
+#![crate_type = "lib"]
+
+// CHECK: ; Function Attrs:{{.*}}safestack
+pub fn tagged() {}
+
+// CHECK: attributes #0 = {{.*}}safestack
diff --git a/tests/incremental/issue-110457-same-span-closures/auxiliary/egui_inspect_derive.rs b/tests/incremental/issue-110457-same-span-closures/auxiliary/egui_inspect_derive.rs
new file mode 100644
index 00000000000..e7d91235e73
--- /dev/null
+++ b/tests/incremental/issue-110457-same-span-closures/auxiliary/egui_inspect_derive.rs
@@ -0,0 +1,90 @@
+// force-host
+// no-prefer-dynamic
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
+
+#[proc_macro]
+pub fn expand(_: TokenStream) -> TokenStream {
+    // Hand expansion/rewriting of
+    // ```
+    // quote! {
+    //     output_mut(|o| o.copied_text = "".into());
+    //     output_mut(|o| o.copied_text = format!("{:?}", self.tile_db));
+    // }.into()
+    // ```
+    stream([
+        ident("output_mut"),
+        group(
+            Delimiter::Parenthesis,
+            [
+                or(),
+                ident("o"),
+                or(),
+                ident("o"),
+                dot(),
+                ident("copied_text"),
+                eq(),
+                string(""),
+                dot(),
+                ident("into"),
+                group(Delimiter::Parenthesis, []),
+            ],
+        ),
+        semi(),
+        ident("output_mut"),
+        group(
+            Delimiter::Parenthesis,
+            [
+                or(),
+                ident("o"),
+                or(),
+                ident("o"),
+                dot(),
+                ident("copied_text"),
+                eq(),
+                ident("format"),
+                bang(),
+                group(
+                    Delimiter::Parenthesis,
+                    [string("{:?}"), comma(), ident("self"), dot(), ident("tile_db")],
+                ),
+            ],
+        ),
+        semi(),
+    ])
+}
+
+fn stream(s: impl IntoIterator<Item = TokenTree>) -> TokenStream {
+    s.into_iter().collect()
+}
+
+fn ident(i: &str) -> TokenTree {
+    TokenTree::Ident(Ident::new(i, Span::call_site()))
+}
+fn group(d: Delimiter, s: impl IntoIterator<Item = TokenTree>) -> TokenTree {
+    TokenTree::Group(Group::new(d, s.into_iter().collect()))
+}
+fn semi() -> TokenTree {
+    TokenTree::Punct(Punct::new(';', Spacing::Alone))
+}
+fn or() -> TokenTree {
+    TokenTree::Punct(Punct::new('|', Spacing::Alone))
+}
+fn dot() -> TokenTree {
+    TokenTree::Punct(Punct::new('.', Spacing::Alone))
+}
+fn eq() -> TokenTree {
+    TokenTree::Punct(Punct::new('=', Spacing::Alone))
+}
+fn bang() -> TokenTree {
+    TokenTree::Punct(Punct::new('!', Spacing::Alone))
+}
+fn comma() -> TokenTree {
+    TokenTree::Punct(Punct::new(',', Spacing::Alone))
+}
+fn string(s: &str) -> TokenTree {
+    TokenTree::Literal(Literal::string(s))
+}
diff --git a/tests/incremental/issue-110457-same-span-closures/main.rs b/tests/incremental/issue-110457-same-span-closures/main.rs
new file mode 100644
index 00000000000..b44fda3d36a
--- /dev/null
+++ b/tests/incremental/issue-110457-same-span-closures/main.rs
@@ -0,0 +1,47 @@
+// aux-build: egui_inspect_derive.rs
+// revisions: cpass1 cpass2
+
+extern crate egui_inspect_derive;
+
+pub struct TileDef {
+    pub layer: (),
+    #[cfg(cpass2)]
+    pub blend_graphic: String,
+}
+
+pub(crate) struct GameState {
+    pub(crate) tile_db: TileDb,
+}
+
+impl GameState {
+    fn inspect_mut(&mut self) {
+        egui_inspect_derive::expand! {}
+    }
+}
+
+fn new() -> GameState {
+    loop {}
+}
+
+fn main() {
+    let mut app = new();
+    app.inspect_mut();
+}
+// this is actually used
+pub struct TileDb {
+    unknown_bg: TileDef,
+}
+
+impl std::fmt::Debug for TileDb {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        loop {}
+    }
+}
+
+pub struct PlatformOutput {
+    pub copied_text: String,
+}
+
+pub fn output_mut<R>(writer: impl FnOnce(&mut PlatformOutput) -> R) -> R {
+    loop {}
+}
diff --git a/tests/mir-opt/deref-patterns/string.foo.PreCodegen.after.mir b/tests/mir-opt/deref-patterns/string.foo.PreCodegen.after.mir
index 97826ed19a2..bcdb12011bc 100644
--- a/tests/mir-opt/deref-patterns/string.foo.PreCodegen.after.mir
+++ b/tests/mir-opt/deref-patterns/string.foo.PreCodegen.after.mir
@@ -3,41 +3,33 @@
 fn foo(_1: Option<String>) -> i32 {
     debug s => _1;                       // in scope 0 at $DIR/string.rs:+0:12: +0:13
     let mut _0: i32;                     // return place in scope 0 at $DIR/string.rs:+0:34: +0:37
-    let mut _2: &std::string::String;    // in scope 0 at $DIR/string.rs:+2:14: +2:17
-    let mut _3: &str;                    // in scope 0 at $DIR/string.rs:+2:14: +2:17
-    let mut _4: bool;                    // in scope 0 at $DIR/string.rs:+2:14: +2:17
-    let mut _5: isize;                   // in scope 0 at $DIR/string.rs:+2:9: +2:18
-    let _6: std::option::Option<std::string::String>; // in scope 0 at $DIR/string.rs:+3:9: +3:10
-    let mut _7: bool;                    // in scope 0 at $DIR/string.rs:+5:1: +5:2
+    let mut _2: bool;                    // in scope 0 at $DIR/string.rs:+5:1: +5:2
+    let mut _3: isize;                   // in scope 0 at $DIR/string.rs:+2:9: +2:18
+    let mut _4: &std::string::String;    // in scope 0 at $DIR/string.rs:+2:14: +2:17
+    let mut _5: &str;                    // in scope 0 at $DIR/string.rs:+2:14: +2:17
+    let mut _6: bool;                    // in scope 0 at $DIR/string.rs:+2:14: +2:17
+    let _7: std::option::Option<std::string::String>; // in scope 0 at $DIR/string.rs:+3:9: +3:10
     scope 1 {
-        debug s => _6;                   // in scope 1 at $DIR/string.rs:+3:9: +3:10
+        debug s => _7;                   // in scope 1 at $DIR/string.rs:+3:9: +3:10
     }
 
     bb0: {
-        _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: bb2, otherwise: bb1]; // scope 0 at $DIR/string.rs:+1:5: +1:12
+        _2 = const false;                // scope 0 at $DIR/string.rs:+1:11: +1:12
+        _2 = const true;                 // scope 0 at $DIR/string.rs:+1:11: +1:12
+        _3 = discriminant(_1);           // scope 0 at $DIR/string.rs:+1:11: +1:12
+        switchInt(move _3) -> [1: bb1, otherwise: bb5]; // scope 0 at $DIR/string.rs:+1:5: +1:12
     }
 
     bb1: {
-        StorageLive(_6);                 // scope 0 at $DIR/string.rs:+3:9: +3:10
-        _7 = const false;                // scope 0 at $DIR/string.rs:+3:9: +3:10
-        _6 = move _1;                    // scope 0 at $DIR/string.rs:+3:9: +3:10
-        _0 = const 4321_i32;             // scope 1 at $DIR/string.rs:+3:14: +3:18
-        drop(_6) -> [return: bb6, unwind unreachable]; // scope 0 at $DIR/string.rs:+3:17: +3:18
-    }
-
-    bb2: {
-        _2 = &((_1 as Some).0: std::string::String); // scope 0 at $DIR/string.rs:+2:14: +2:17
-        _3 = <String as Deref>::deref(move _2) -> [return: bb3, unwind unreachable]; // scope 0 at $DIR/string.rs:+2:14: +2:17
+        _4 = &((_1 as Some).0: std::string::String); // scope 0 at $DIR/string.rs:+2:14: +2:17
+        _5 = <String as Deref>::deref(move _4) -> [return: bb2, unwind unreachable]; // scope 0 at $DIR/string.rs:+2:14: +2:17
                                          // mir::Constant
                                          // + span: $DIR/string.rs:9:14: 9:17
                                          // + literal: Const { ty: for<'a> fn(&'a String) -> &'a <String as Deref>::Target {<String as Deref>::deref}, val: Value(<ZST>) }
     }
 
-    bb3: {
-        _4 = <str as PartialEq>::eq(_3, const "a") -> [return: bb4, unwind unreachable]; // scope 0 at $DIR/string.rs:+2:14: +2:17
+    bb2: {
+        _6 = <str as PartialEq>::eq(_5, const "a") -> [return: bb3, unwind unreachable]; // scope 0 at $DIR/string.rs:+2:14: +2:17
                                          // mir::Constant
                                          // + span: $DIR/string.rs:9:14: 9:17
                                          // + literal: Const { ty: for<'a, 'b> fn(&'a str, &'b str) -> bool {<str as PartialEq>::eq}, val: Value(<ZST>) }
@@ -46,29 +38,37 @@ fn foo(_1: Option<String>) -> i32 {
                                          // + literal: Const { ty: &str, val: Value(Slice(..)) }
     }
 
+    bb3: {
+        switchInt(move _6) -> [0: bb5, otherwise: bb4]; // scope 0 at $DIR/string.rs:+2:14: +2:17
+    }
+
     bb4: {
-        switchInt(move _4) -> [0: bb1, otherwise: bb5]; // scope 0 at $DIR/string.rs:+2:14: +2:17
+        _0 = const 1234_i32;             // scope 0 at $DIR/string.rs:+2:22: +2:26
+        goto -> bb7;                     // scope 0 at $DIR/string.rs:+2:22: +2:26
     }
 
     bb5: {
-        _0 = const 1234_i32;             // scope 0 at $DIR/string.rs:+2:22: +2:26
-        goto -> bb9;                     // scope 0 at $DIR/string.rs:+2:22: +2:26
+        StorageLive(_7);                 // scope 0 at $DIR/string.rs:+3:9: +3:10
+        _2 = const false;                // scope 0 at $DIR/string.rs:+3:9: +3:10
+        _7 = move _1;                    // scope 0 at $DIR/string.rs:+3:9: +3:10
+        _0 = const 4321_i32;             // scope 1 at $DIR/string.rs:+3:14: +3:18
+        drop(_7) -> [return: bb6, unwind unreachable]; // scope 0 at $DIR/string.rs:+3:17: +3:18
     }
 
     bb6: {
-        StorageDead(_6);                 // scope 0 at $DIR/string.rs:+3:17: +3:18
-        goto -> bb9;                     // scope 0 at $DIR/string.rs:+3:17: +3:18
+        StorageDead(_7);                 // scope 0 at $DIR/string.rs:+3:17: +3:18
+        goto -> bb7;                     // scope 0 at $DIR/string.rs:+3:17: +3:18
     }
 
     bb7: {
-        return;                          // scope 0 at $DIR/string.rs:+5:2: +5:2
+        switchInt(_2) -> [0: bb9, otherwise: bb8]; // scope 0 at $DIR/string.rs:+5:1: +5:2
     }
 
     bb8: {
-        drop(_1) -> [return: bb7, unwind unreachable]; // scope 0 at $DIR/string.rs:+5:1: +5:2
+        drop(_1) -> [return: bb9, unwind unreachable]; // scope 0 at $DIR/string.rs:+5:1: +5:2
     }
 
     bb9: {
-        switchInt(_7) -> [0: bb7, otherwise: bb8]; // scope 0 at $DIR/string.rs:+5:1: +5:2
+        return;                          // scope 0 at $DIR/string.rs:+5:2: +5:2
     }
 }
diff --git a/tests/mir-opt/inline/cycle.g.Inline.diff b/tests/mir-opt/inline/cycle.g.Inline.diff
index 1e6e30f9e9b..53bf14a0ab6 100644
--- a/tests/mir-opt/inline/cycle.g.Inline.diff
+++ b/tests/mir-opt/inline/cycle.g.Inline.diff
@@ -8,8 +8,8 @@
 +     let mut _5: ();                      // in scope 0 at $DIR/cycle.rs:6:5: 6:8
 +     scope 1 (inlined f::<fn() {main}>) { // at $DIR/cycle.rs:12:5: 12:12
 +         debug g => _2;                   // in scope 1 at $DIR/cycle.rs:5:6: 5:7
-+         let _3: ();                      // in scope 1 at $DIR/cycle.rs:6:5: 6:8
-+         let mut _4: &fn() {main};        // in scope 1 at $DIR/cycle.rs:6:5: 6:6
++         let mut _3: &fn() {main};        // in scope 1 at $DIR/cycle.rs:6:5: 6:6
++         let _4: ();                      // in scope 1 at $DIR/cycle.rs:6:5: 6:8
 +         scope 2 (inlined <fn() {main} as Fn<()>>::call - shim(fn() {main})) { // at $DIR/cycle.rs:6:5: 6:8
 +         }
 +     }
@@ -25,16 +25,16 @@
 -                                          // mir::Constant
                                            // + span: $DIR/cycle.rs:12:7: 12:11
                                            // + literal: Const { ty: fn() {main}, val: Value(<ZST>) }
-+         StorageLive(_3);                 // scope 0 at $DIR/cycle.rs:+1:5: +1:12
-+         StorageLive(_4);                 // scope 1 at $DIR/cycle.rs:6:5: 6:6
-+         _4 = &_2;                        // scope 1 at $DIR/cycle.rs:6:5: 6:6
++         StorageLive(_4);                 // scope 0 at $DIR/cycle.rs:+1:5: +1:12
++         StorageLive(_3);                 // scope 1 at $DIR/cycle.rs:6:5: 6:6
++         _3 = &_2;                        // scope 1 at $DIR/cycle.rs:6:5: 6:6
 +         StorageLive(_5);                 // scope 1 at $DIR/cycle.rs:6:5: 6:8
 +         _5 = const ();                   // scope 1 at $DIR/cycle.rs:6:5: 6:8
-+         _3 = move (*_4)() -> [return: bb4, unwind: bb2]; // scope 2 at $SRC_DIR/core/src/ops/function.rs:LL:COL
++         _4 = move (*_3)() -> [return: bb4, unwind: bb2]; // scope 2 at $SRC_DIR/core/src/ops/function.rs:LL:COL
       }
   
       bb1: {
-+         StorageDead(_3);                 // scope 0 at $DIR/cycle.rs:+1:5: +1:12
++         StorageDead(_4);                 // scope 0 at $DIR/cycle.rs:+1:5: +1:12
 +         StorageDead(_2);                 // scope 0 at $DIR/cycle.rs:+1:5: +1:12
           StorageDead(_1);                 // scope 0 at $DIR/cycle.rs:+1:12: +1:13
           _0 = const ();                   // scope 0 at $DIR/cycle.rs:+0:8: +2:2
@@ -51,7 +51,7 @@
 + 
 +     bb4: {
 +         StorageDead(_5);                 // scope 1 at $DIR/cycle.rs:6:5: 6:8
-+         StorageDead(_4);                 // scope 1 at $DIR/cycle.rs:6:7: 6:8
++         StorageDead(_3);                 // scope 1 at $DIR/cycle.rs:6:7: 6:8
 +         drop(_2) -> bb1;                 // scope 1 at $DIR/cycle.rs:7:1: 7:2
       }
   }
diff --git a/tests/mir-opt/inline/cycle.main.Inline.diff b/tests/mir-opt/inline/cycle.main.Inline.diff
index 315634945e4..fdf6337a9be 100644
--- a/tests/mir-opt/inline/cycle.main.Inline.diff
+++ b/tests/mir-opt/inline/cycle.main.Inline.diff
@@ -8,8 +8,8 @@
 +     let mut _5: ();                      // in scope 0 at $DIR/cycle.rs:6:5: 6:8
 +     scope 1 (inlined f::<fn() {g}>) {    // at $DIR/cycle.rs:17:5: 17:9
 +         debug g => _2;                   // in scope 1 at $DIR/cycle.rs:5:6: 5:7
-+         let _3: ();                      // in scope 1 at $DIR/cycle.rs:6:5: 6:8
-+         let mut _4: &fn() {g};           // in scope 1 at $DIR/cycle.rs:6:5: 6:6
++         let mut _3: &fn() {g};           // in scope 1 at $DIR/cycle.rs:6:5: 6:6
++         let _4: ();                      // in scope 1 at $DIR/cycle.rs:6:5: 6:8
 +         scope 2 (inlined <fn() {g} as Fn<()>>::call - shim(fn() {g})) { // at $DIR/cycle.rs:6:5: 6:8
 +         }
 +     }
@@ -25,16 +25,16 @@
 -                                          // mir::Constant
                                            // + span: $DIR/cycle.rs:17:7: 17:8
                                            // + literal: Const { ty: fn() {g}, val: Value(<ZST>) }
-+         StorageLive(_3);                 // scope 0 at $DIR/cycle.rs:+1:5: +1:9
-+         StorageLive(_4);                 // scope 1 at $DIR/cycle.rs:6:5: 6:6
-+         _4 = &_2;                        // scope 1 at $DIR/cycle.rs:6:5: 6:6
++         StorageLive(_4);                 // scope 0 at $DIR/cycle.rs:+1:5: +1:9
++         StorageLive(_3);                 // scope 1 at $DIR/cycle.rs:6:5: 6:6
++         _3 = &_2;                        // scope 1 at $DIR/cycle.rs:6:5: 6:6
 +         StorageLive(_5);                 // scope 1 at $DIR/cycle.rs:6:5: 6:8
 +         _5 = const ();                   // scope 1 at $DIR/cycle.rs:6:5: 6:8
-+         _3 = move (*_4)() -> [return: bb4, unwind: bb2]; // scope 2 at $SRC_DIR/core/src/ops/function.rs:LL:COL
++         _4 = move (*_3)() -> [return: bb4, unwind: bb2]; // scope 2 at $SRC_DIR/core/src/ops/function.rs:LL:COL
       }
   
       bb1: {
-+         StorageDead(_3);                 // scope 0 at $DIR/cycle.rs:+1:5: +1:9
++         StorageDead(_4);                 // scope 0 at $DIR/cycle.rs:+1:5: +1:9
 +         StorageDead(_2);                 // scope 0 at $DIR/cycle.rs:+1:5: +1:9
           StorageDead(_1);                 // scope 0 at $DIR/cycle.rs:+1:9: +1:10
           _0 = const ();                   // scope 0 at $DIR/cycle.rs:+0:11: +2:2
@@ -51,7 +51,7 @@
 + 
 +     bb4: {
 +         StorageDead(_5);                 // scope 1 at $DIR/cycle.rs:6:5: 6:8
-+         StorageDead(_4);                 // scope 1 at $DIR/cycle.rs:6:7: 6:8
++         StorageDead(_3);                 // scope 1 at $DIR/cycle.rs:6:7: 6:8
 +         drop(_2) -> bb1;                 // scope 1 at $DIR/cycle.rs:7:1: 7:2
       }
   }
diff --git a/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir b/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir
index b36711f82f4..33bf3b73b23 100644
--- a/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir
+++ b/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir
@@ -17,10 +17,10 @@ fn foo(_1: T, _2: i32) -> (i32, T) {
             debug _q => _9;              // in scope 2 at $DIR/inline_closure_captures.rs:+1:14: +1:16
             debug q => (*((*_6).0: &i32)); // in scope 2 at $DIR/inline_closure_captures.rs:+0:23: +0:24
             debug t => (*((*_6).1: &T)); // in scope 2 at $DIR/inline_closure_captures.rs:+0:17: +0:18
-            let mut _10: i32;            // in scope 2 at $DIR/inline_closure_captures.rs:+1:19: +1:20
-            let mut _11: T;              // in scope 2 at $DIR/inline_closure_captures.rs:+1:22: +1:23
-            let mut _12: &i32;           // in scope 2 at $DIR/inline_closure_captures.rs:+1:13: +1:24
-            let mut _13: &T;             // in scope 2 at $DIR/inline_closure_captures.rs:+1:13: +1:24
+            let mut _10: &i32;           // in scope 2 at $DIR/inline_closure_captures.rs:+1:13: +1:24
+            let mut _11: i32;            // in scope 2 at $DIR/inline_closure_captures.rs:+1:19: +1:20
+            let mut _12: &T;             // in scope 2 at $DIR/inline_closure_captures.rs:+1:13: +1:24
+            let mut _13: T;              // in scope 2 at $DIR/inline_closure_captures.rs:+1:22: +1:23
         }
     }
 
@@ -49,15 +49,15 @@ fn foo(_1: T, _2: i32) -> (i32, T) {
         _7 = (move _8,);                 // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9
         StorageLive(_9);                 // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9
         _9 = move (_7.0: i32);           // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9
-        StorageLive(_10);                // scope 2 at $DIR/inline_closure_captures.rs:+1:19: +1:20
-        _12 = deref_copy ((*_6).0: &i32); // scope 2 at $DIR/inline_closure_captures.rs:+1:19: +1:20
-        _10 = (*_12);                    // scope 2 at $DIR/inline_closure_captures.rs:+1:19: +1:20
-        StorageLive(_11);                // scope 2 at $DIR/inline_closure_captures.rs:+1:22: +1:23
-        _13 = deref_copy ((*_6).1: &T);  // scope 2 at $DIR/inline_closure_captures.rs:+1:22: +1:23
-        _11 = (*_13);                    // scope 2 at $DIR/inline_closure_captures.rs:+1:22: +1:23
-        _0 = (move _10, move _11);       // scope 2 at $DIR/inline_closure_captures.rs:+1:18: +1:24
+        StorageLive(_11);                // scope 2 at $DIR/inline_closure_captures.rs:+1:19: +1:20
+        _10 = deref_copy ((*_6).0: &i32); // scope 2 at $DIR/inline_closure_captures.rs:+1:19: +1:20
+        _11 = (*_10);                    // scope 2 at $DIR/inline_closure_captures.rs:+1:19: +1:20
+        StorageLive(_13);                // scope 2 at $DIR/inline_closure_captures.rs:+1:22: +1:23
+        _12 = deref_copy ((*_6).1: &T);  // scope 2 at $DIR/inline_closure_captures.rs:+1:22: +1:23
+        _13 = (*_12);                    // scope 2 at $DIR/inline_closure_captures.rs:+1:22: +1:23
+        _0 = (move _11, move _13);       // scope 2 at $DIR/inline_closure_captures.rs:+1:18: +1:24
+        StorageDead(_13);                // scope 2 at $DIR/inline_closure_captures.rs:+1:23: +1:24
         StorageDead(_11);                // scope 2 at $DIR/inline_closure_captures.rs:+1:23: +1:24
-        StorageDead(_10);                // scope 2 at $DIR/inline_closure_captures.rs:+1:23: +1:24
         StorageDead(_9);                 // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9
         StorageDead(_8);                 // scope 1 at $DIR/inline_closure_captures.rs:+2:8: +2:9
         StorageDead(_7);                 // scope 1 at $DIR/inline_closure_captures.rs:+2:8: +2:9
diff --git a/tests/mir-opt/inline/inline_diverging.h.Inline.diff b/tests/mir-opt/inline/inline_diverging.h.Inline.diff
index d501b6ca8d2..255451e8670 100644
--- a/tests/mir-opt/inline/inline_diverging.h.Inline.diff
+++ b/tests/mir-opt/inline/inline_diverging.h.Inline.diff
@@ -8,15 +8,15 @@
 +     let mut _8: ();                      // in scope 0 at $DIR/inline_diverging.rs:27:13: 27:16
 +     scope 1 (inlined call_twice::<!, fn() -> ! {sleep}>) { // at $DIR/inline_diverging.rs:22:5: 22:22
 +         debug f => _2;                   // in scope 1 at $DIR/inline_diverging.rs:26:36: 26:37
-+         let _3: !;                       // in scope 1 at $DIR/inline_diverging.rs:27:9: 27:10
-+         let mut _4: &fn() -> ! {sleep};  // in scope 1 at $DIR/inline_diverging.rs:27:13: 27:14
++         let mut _3: &fn() -> ! {sleep};  // in scope 1 at $DIR/inline_diverging.rs:27:13: 27:14
++         let _4: !;                       // in scope 1 at $DIR/inline_diverging.rs:27:9: 27:10
 +         let mut _5: &fn() -> ! {sleep};  // in scope 1 at $DIR/inline_diverging.rs:28:13: 28:14
-+         let mut _6: !;                   // in scope 1 at $DIR/inline_diverging.rs:29:6: 29:7
-+         let mut _7: !;                   // in scope 1 at $DIR/inline_diverging.rs:29:9: 29:10
++         let mut _6: !;                   // in scope 1 at $DIR/inline_diverging.rs:29:9: 29:10
++         let mut _7: !;                   // in scope 1 at $DIR/inline_diverging.rs:29:6: 29:7
 +         scope 2 {
-+             debug a => _3;               // in scope 2 at $DIR/inline_diverging.rs:27:9: 27:10
++             debug a => _4;               // in scope 2 at $DIR/inline_diverging.rs:27:9: 27:10
 +             scope 3 {
-+                 debug b => _7;           // in scope 3 at $DIR/inline_diverging.rs:28:9: 28:10
++                 debug b => _6;           // in scope 3 at $DIR/inline_diverging.rs:28:9: 28:10
 +             }
 +         }
 +         scope 4 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) { // at $DIR/inline_diverging.rs:27:13: 27:16
@@ -34,22 +34,22 @@
 -                                          // mir::Constant
                                            // + span: $DIR/inline_diverging.rs:22:16: 22:21
                                            // + literal: Const { ty: fn() -> ! {sleep}, val: Value(<ZST>) }
-+         StorageLive(_7);                 // scope 0 at $DIR/inline_diverging.rs:+1:5: +1:22
-+         StorageLive(_3);                 // scope 1 at $DIR/inline_diverging.rs:27:9: 27:10
-+         StorageLive(_4);                 // scope 1 at $DIR/inline_diverging.rs:27:13: 27:14
-+         _4 = &_2;                        // scope 1 at $DIR/inline_diverging.rs:27:13: 27:14
++         StorageLive(_6);                 // scope 0 at $DIR/inline_diverging.rs:+1:5: +1:22
++         StorageLive(_4);                 // scope 1 at $DIR/inline_diverging.rs:27:9: 27:10
++         StorageLive(_3);                 // scope 1 at $DIR/inline_diverging.rs:27:13: 27:14
++         _3 = &_2;                        // scope 1 at $DIR/inline_diverging.rs:27:13: 27:14
 +         StorageLive(_8);                 // scope 1 at $DIR/inline_diverging.rs:27:13: 27:16
 +         _8 = const ();                   // scope 1 at $DIR/inline_diverging.rs:27:13: 27:16
-+         _3 = move (*_4)() -> [return: bb6, unwind: bb4]; // scope 4 at $SRC_DIR/core/src/ops/function.rs:LL:COL
++         _4 = move (*_3)() -> [return: bb6, unwind: bb4]; // scope 4 at $SRC_DIR/core/src/ops/function.rs:LL:COL
 +     }
 + 
 +     bb1: {
 +         StorageDead(_5);                 // scope 2 at $DIR/inline_diverging.rs:28:15: 28:16
-+         StorageLive(_6);                 // scope 3 at $DIR/inline_diverging.rs:29:6: 29:7
-+         _6 = move _3;                    // scope 3 at $DIR/inline_diverging.rs:29:6: 29:7
-+         _1 = (move _6, move _7);         // scope 3 at $DIR/inline_diverging.rs:29:5: 29:11
-+         StorageDead(_6);                 // scope 3 at $DIR/inline_diverging.rs:29:10: 29:11
-+         StorageDead(_3);                 // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2
++         StorageLive(_7);                 // scope 3 at $DIR/inline_diverging.rs:29:6: 29:7
++         _7 = move _4;                    // scope 3 at $DIR/inline_diverging.rs:29:6: 29:7
++         _1 = (move _7, move _6);         // scope 3 at $DIR/inline_diverging.rs:29:5: 29:11
++         StorageDead(_7);                 // scope 3 at $DIR/inline_diverging.rs:29:10: 29:11
++         StorageDead(_4);                 // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2
 +         drop(_2) -> bb2;                 // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2
 +     }
 + 
@@ -58,7 +58,7 @@
 +     }
 + 
 +     bb3 (cleanup): {
-+         drop(_3) -> [return: bb4, unwind terminate]; // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2
++         drop(_4) -> [return: bb4, unwind terminate]; // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2
 +     }
 + 
 +     bb4 (cleanup): {
@@ -71,10 +71,10 @@
 + 
 +     bb6: {
 +         StorageDead(_8);                 // scope 1 at $DIR/inline_diverging.rs:27:13: 27:16
-+         StorageDead(_4);                 // scope 1 at $DIR/inline_diverging.rs:27:15: 27:16
++         StorageDead(_3);                 // scope 1 at $DIR/inline_diverging.rs:27:15: 27:16
 +         StorageLive(_5);                 // scope 2 at $DIR/inline_diverging.rs:28:13: 28:14
 +         _5 = &_2;                        // scope 2 at $DIR/inline_diverging.rs:28:13: 28:14
-+         _7 = <fn() -> ! {sleep} as Fn<()>>::call(move _5, const ()) -> [return: bb1, unwind: bb3]; // scope 2 at $DIR/inline_diverging.rs:28:13: 28:16
++         _6 = <fn() -> ! {sleep} as Fn<()>>::call(move _5, const ()) -> [return: bb1, unwind: bb3]; // scope 2 at $DIR/inline_diverging.rs:28:13: 28:16
 +                                          // mir::Constant
 +                                          // + span: $DIR/inline_diverging.rs:28:13: 28:14
 +                                          // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a fn() -> ! {sleep}, ()) -> <fn() -> ! {sleep} as FnOnce<()>>::Output {<fn() -> ! {sleep} as Fn<()>>::call}, val: Value(<ZST>) }
diff --git a/tests/mir-opt/inline/inline_generator.main.Inline.diff b/tests/mir-opt/inline/inline_generator.main.Inline.diff
index c3ca2d7d42c..0dcae1e4d45 100644
--- a/tests/mir-opt/inline/inline_generator.main.Inline.diff
+++ b/tests/mir-opt/inline/inline_generator.main.Inline.diff
@@ -23,9 +23,9 @@
 +     }
 +     scope 6 (inlined g::{closure#0}) {   // at $DIR/inline_generator.rs:9:33: 9:46
 +         debug a => _5;                   // in scope 6 at $DIR/inline_generator.rs:15:6: 15:7
-+         let mut _6: i32;                 // in scope 6 at $DIR/inline_generator.rs:15:17: 15:39
++         let mut _6: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; // in scope 6 at $DIR/inline_generator.rs:15:5: 15:41
 +         let mut _7: u32;                 // in scope 6 at $DIR/inline_generator.rs:15:5: 15:41
-+         let mut _8: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; // in scope 6 at $DIR/inline_generator.rs:15:5: 15:41
++         let mut _8: i32;                 // in scope 6 at $DIR/inline_generator.rs:15:17: 15:39
 +         let mut _9: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; // in scope 6 at $DIR/inline_generator.rs:15:5: 15:41
 +         let mut _10: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; // in scope 6 at $DIR/inline_generator.rs:15:5: 15:41
 +     }
@@ -70,9 +70,9 @@
 -                                          // + literal: Const { ty: for<'a> fn(Pin<&'a mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>, bool) -> GeneratorState<<[generator@$DIR/inline_generator.rs:15:5: 15:8] as Generator<bool>>::Yield, <[generator@$DIR/inline_generator.rs:15:5: 15:8] as Generator<bool>>::Return> {<[generator@$DIR/inline_generator.rs:15:5: 15:8] as Generator<bool>>::resume}, val: Value(<ZST>) }
 +         StorageLive(_5);                 // scope 0 at $DIR/inline_generator.rs:+1:33: +1:46
 +         _5 = const false;                // scope 0 at $DIR/inline_generator.rs:+1:33: +1:46
-+         _8 = 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
-+         _7 = discriminant((*_8));        // scope 6 at $DIR/inline_generator.rs:15:5: 15:41
-+         switchInt(move _7) -> [0: bb3, 1: bb8, 3: bb7, otherwise: bb9]; // scope 6 at $DIR/inline_generator.rs:15:5: 15:41
++         _6 = 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
++         _7 = discriminant((*_6));        // scope 6 at $DIR/inline_generator.rs:15:5: 15:41
++         switchInt(move _7) -> [0: bb3, 1: bb7, 3: bb8, otherwise: bb9]; // scope 6 at $DIR/inline_generator.rs:15:5: 15:41
       }
   
 -     bb3: {
@@ -91,40 +91,40 @@
 +     }
 + 
 +     bb3: {
-+         StorageLive(_6);                 // scope 6 at $DIR/inline_generator.rs:15:17: 15:39
-+         switchInt(_5) -> [0: bb5, otherwise: bb4]; // scope 6 at $DIR/inline_generator.rs:15:20: 15:21
++         StorageLive(_8);                 // scope 6 at $DIR/inline_generator.rs:15:17: 15:39
++         switchInt(_5) -> [0: bb4, otherwise: bb5]; // scope 6 at $DIR/inline_generator.rs:15:20: 15:21
 +     }
 + 
 +     bb4: {
-+         _6 = const 7_i32;                // scope 6 at $DIR/inline_generator.rs:15:24: 15:25
++         _8 = const 13_i32;               // scope 6 at $DIR/inline_generator.rs:15:35: 15:37
 +         goto -> bb6;                     // scope 6 at $DIR/inline_generator.rs:15:17: 15:39
 +     }
 + 
 +     bb5: {
-+         _6 = const 13_i32;               // scope 6 at $DIR/inline_generator.rs:15:35: 15:37
++         _8 = const 7_i32;                // scope 6 at $DIR/inline_generator.rs:15:24: 15:25
 +         goto -> bb6;                     // scope 6 at $DIR/inline_generator.rs:15:17: 15:39
 +     }
 + 
 +     bb6: {
-+         _1 = GeneratorState::<i32, bool>::Yielded(move _6); // scope 6 at $DIR/inline_generator.rs:15:11: 15:39
++         _1 = GeneratorState::<i32, bool>::Yielded(move _8); // scope 6 at $DIR/inline_generator.rs:15:11: 15:39
 +         _9 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline_generator.rs:15:11: 15:39
 +         discriminant((*_9)) = 3;         // scope 6 at $DIR/inline_generator.rs:15:11: 15:39
 +         goto -> bb1;                     // scope 0 at $DIR/inline_generator.rs:15:11: 15:39
 +     }
 + 
 +     bb7: {
-+         StorageLive(_6);                 // scope 6 at $DIR/inline_generator.rs:15:5: 15:41
-+         StorageDead(_6);                 // scope 6 at $DIR/inline_generator.rs:15:38: 15:39
++         assert(const false, "generator resumed after completion") -> [success: bb7, unwind: bb2]; // scope 6 at $DIR/inline_generator.rs:15:5: 15:41
++     }
++ 
++     bb8: {
++         StorageLive(_8);                 // scope 6 at $DIR/inline_generator.rs:15:5: 15:41
++         StorageDead(_8);                 // scope 6 at $DIR/inline_generator.rs:15:38: 15:39
 +         _1 = GeneratorState::<i32, bool>::Complete(_5); // scope 6 at $DIR/inline_generator.rs:15:41: 15:41
 +         _10 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline_generator.rs:15:41: 15:41
 +         discriminant((*_10)) = 1;        // scope 6 at $DIR/inline_generator.rs:15:41: 15:41
 +         goto -> bb1;                     // scope 0 at $DIR/inline_generator.rs:15:41: 15:41
 +     }
 + 
-+     bb8: {
-+         assert(const false, "generator resumed after completion") -> [success: bb8, unwind: bb2]; // scope 6 at $DIR/inline_generator.rs:15:5: 15:41
-+     }
-+ 
 +     bb9: {
 +         unreachable;                     // scope 6 at $DIR/inline_generator.rs:15:5: 15:41
       }
diff --git a/tests/mir-opt/inline/issue_106141.outer.Inline.diff b/tests/mir-opt/inline/issue_106141.outer.Inline.diff
index 3aebfb69e0a..5fed54f83a7 100644
--- a/tests/mir-opt/inline/issue_106141.outer.Inline.diff
+++ b/tests/mir-opt/inline/issue_106141.outer.Inline.diff
@@ -4,9 +4,9 @@
   fn outer() -> usize {
       let mut _0: usize;                   // return place in scope 0 at $DIR/issue_106141.rs:+0:19: +0:24
 +     scope 1 (inlined inner) {            // at $DIR/issue_106141.rs:3:5: 3:12
-+         let mut _1: bool;                // in scope 1 at $DIR/issue_106141.rs:14:8: 14:21
++         let mut _1: &[bool; 1];          // in scope 1 at $DIR/issue_106141.rs:12:18: 12:25
 +         let mut _2: bool;                // in scope 1 at $DIR/issue_106141.rs:14:8: 14:21
-+         let mut _3: &[bool; 1];          // in scope 1 at $DIR/issue_106141.rs:12:18: 12:25
++         let mut _3: bool;                // in scope 1 at $DIR/issue_106141.rs:14:8: 14:21
 +         scope 2 {
 +             debug buffer => const _;     // in scope 2 at $DIR/issue_106141.rs:12:9: 12:15
 +             scope 3 {
@@ -17,8 +17,8 @@
   
       bb0: {
 -         _0 = inner() -> bb1;             // scope 0 at $DIR/issue_106141.rs:+1:5: +1:12
-+         StorageLive(_3);                 // scope 0 at $DIR/issue_106141.rs:+1:5: +1:12
-+         _3 = const _;                    // scope 1 at $DIR/issue_106141.rs:12:18: 12:25
++         StorageLive(_1);                 // scope 0 at $DIR/issue_106141.rs:+1:5: +1:12
++         _1 = const _;                    // scope 1 at $DIR/issue_106141.rs:12:18: 12:25
                                            // mir::Constant
 -                                          // + span: $DIR/issue_106141.rs:3:5: 3:10
 -                                          // + literal: Const { ty: fn() -> usize {inner}, val: Value(<ZST>) }
@@ -31,14 +31,14 @@
       }
   
       bb1: {
-+         StorageLive(_1);                 // scope 3 at $DIR/issue_106141.rs:14:8: 14:21
++         StorageLive(_3);                 // scope 3 at $DIR/issue_106141.rs:14:8: 14:21
 +         _2 = Lt(_0, const 1_usize);      // scope 3 at $DIR/issue_106141.rs:14:8: 14:21
 +         assert(move _2, "index out of bounds: the length is {} but the index is {}", const 1_usize, _0) -> bb2; // scope 3 at $DIR/issue_106141.rs:14:8: 14:21
 +     }
 + 
 +     bb2: {
-+         _1 = (*_3)[_0];                  // scope 3 at $DIR/issue_106141.rs:14:8: 14:21
-+         switchInt(move _1) -> [0: bb3, otherwise: bb4]; // scope 3 at $DIR/issue_106141.rs:14:8: 14:21
++         _3 = (*_1)[_0];                  // scope 3 at $DIR/issue_106141.rs:14:8: 14:21
++         switchInt(move _3) -> [0: bb3, otherwise: bb4]; // scope 3 at $DIR/issue_106141.rs:14:8: 14:21
 +     }
 + 
 +     bb3: {
@@ -47,8 +47,8 @@
 +     }
 + 
 +     bb4: {
-+         StorageDead(_1);                 // scope 3 at $DIR/issue_106141.rs:18:5: 18:6
-+         StorageDead(_3);                 // scope 0 at $DIR/issue_106141.rs:+1:5: +1:12
++         StorageDead(_3);                 // scope 3 at $DIR/issue_106141.rs:18:5: 18:6
++         StorageDead(_1);                 // scope 0 at $DIR/issue_106141.rs:+1:5: +1:12
           return;                          // scope 0 at $DIR/issue_106141.rs:+2:2: +2:2
       }
   }
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir
index 3c175ed1504..f4b2416eaab 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir
@@ -7,38 +7,38 @@ fn unchecked_shl_unsigned_smaller(_1: u16, _2: u32) -> u16 {
     scope 1 (inlined core::num::<impl u16>::unchecked_shl) { // at $DIR/unchecked_shifts.rs:11:7: 11:23
         debug self => _1;                // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
         debug rhs => _2;                 // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-        let mut _3: u16;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        let mut _4: (u32,);              // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        let mut _5: u32;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        let mut _3: (u32,);              // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        let mut _4: u32;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        let mut _13: u16;                // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         scope 2 {
             scope 3 (inlined core::num::<impl u16>::unchecked_shl::conv) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                debug x => _5;           // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                let mut _6: std::option::Option<u16>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                let mut _7: std::result::Result<u16, std::num::TryFromIntError>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                debug x => _4;           // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                let mut _8: std::result::Result<u16, std::num::TryFromIntError>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                let mut _11: std::option::Option<u16>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
                 scope 4 {
                     scope 5 (inlined <u32 as TryInto<u16>>::try_into) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                        debug self => _5; // in scope 5 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+                        debug self => _4; // in scope 5 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
                         scope 6 (inlined convert::num::<impl TryFrom<u32> for u16>::try_from) { // at $SRC_DIR/core/src/convert/mod.rs:LL:COL
-                            debug u => _5; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-                            let mut _8: bool; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-                            let mut _9: u32; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-                            let mut _10: u16; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                            debug u => _4; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                            let mut _5: u32; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                            let mut _6: bool; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                            let mut _7: u16; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
                         }
                     }
                     scope 7 (inlined Result::<u16, TryFromIntError>::ok) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                        debug self => _7; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
-                        let mut _11: isize; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
-                        let _12: u16;    // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+                        debug self => _8; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+                        let mut _9: isize; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+                        let _10: u16;    // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
                         scope 8 {
-                            debug x => _12; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+                            debug x => _10; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
                         }
                     }
                     scope 9 (inlined #[track_caller] Option::<u16>::unwrap_unchecked) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                        debug self => _6; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
-                        let mut _13: &std::option::Option<u16>; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
-                        let mut _14: isize; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                        debug self => _11; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                        let mut _12: isize; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                        let mut _14: &std::option::Option<u16>; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
                         scope 10 {
-                            debug val => _3; // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
+                            debug val => _13; // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
                         }
                         scope 11 {
                             scope 13 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
@@ -49,7 +49,7 @@ fn unchecked_shl_unsigned_smaller(_1: u16, _2: u32) -> u16 {
                             }
                         }
                         scope 12 (inlined Option::<u16>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
-                            debug self => _13; // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL
+                            debug self => _14; // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL
                         }
                     }
                 }
@@ -58,81 +58,81 @@ fn unchecked_shl_unsigned_smaller(_1: u16, _2: u32) -> u16 {
     }
 
     bb0: {
+        StorageLive(_13);                // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         StorageLive(_3);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _3 = (_2,);                      // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         StorageLive(_4);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        _4 = (_2,);                      // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageLive(_5);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        _5 = move (_4.0: u32);           // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageLive(_6);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageLive(_7);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageLive(_8);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        StorageLive(_9);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        _9 = const 65535_u32;            // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        _8 = Gt(_5, move _9);            // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        StorageDead(_9);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        switchInt(move _8) -> [0: bb3, otherwise: bb2]; // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _4 = move (_3.0: u32);           // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_11);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_8);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_6);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageLive(_5);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _5 = const 65535_u32;            // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _6 = Gt(_4, move _5);            // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageDead(_5);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        switchInt(move _6) -> [0: bb1, otherwise: bb2]; // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
     }
 
     bb1: {
-        StorageDead(_3);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-        return;                          // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2
+        StorageLive(_7);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _7 = _4 as u16 (IntToInt);       // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _8 = Result::<u16, TryFromIntError>::Ok(move _7); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageDead(_7);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        goto -> bb3;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
     }
 
     bb2: {
-        _7 = Result::<u16, TryFromIntError>::Err(const TryFromIntError(())); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _8 = Result::<u16, TryFromIntError>::Err(const TryFromIntError(())); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
                                          // mir::Constant
                                          // + span: no-location
                                          // + literal: Const { ty: TryFromIntError, val: Value(<ZST>) }
-        goto -> bb4;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        goto -> bb3;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
     }
 
     bb3: {
-        StorageLive(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        _10 = _5 as u16 (IntToInt);      // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        _7 = Result::<u16, TryFromIntError>::Ok(move _10); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        StorageDead(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        goto -> bb4;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageDead(_6);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageLive(_10);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _9 = discriminant(_8);           // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        switchInt(move _9) -> [0: bb4, 1: bb5, otherwise: bb9]; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
     }
 
     bb4: {
-        StorageDead(_8);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        StorageLive(_12);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        _11 = discriminant(_7);          // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
-        switchInt(move _11) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        _10 = move ((_8 as Ok).0: u16);  // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        _11 = Option::<u16>::Some(move _10); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+        goto -> bb6;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
     }
 
     bb5: {
-        _6 = Option::<u16>::None;        // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
-        goto -> bb8;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        _11 = Option::<u16>::None;       // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        goto -> bb6;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
     }
 
     bb6: {
-        unreachable;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        StorageDead(_10);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageDead(_8);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_14);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _12 = discriminant(_11);         // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+        switchInt(move _12) -> [1: bb7, otherwise: bb9]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
     }
 
     bb7: {
-        _12 = move ((_7 as Ok).0: u16);  // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
-        _6 = Option::<u16>::Some(move _12); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
-        goto -> bb8;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        _13 = move ((_11 as Some).0: u16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+        StorageDead(_14);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageDead(_11);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageDead(_4);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageDead(_3);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _0 = unchecked_shl::<u16>(_1, move _13) -> [return: bb8, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+                                         // mir::Constant
+                                         // + span: $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+                                         // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u16, u16) -> u16 {unchecked_shl::<u16>}, val: Value(<ZST>) }
     }
 
     bb8: {
-        StorageDead(_12);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageDead(_7);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageLive(_13);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        _14 = discriminant(_6);          // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
-        switchInt(move _14) -> [1: bb9, otherwise: bb6]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+        StorageDead(_13);                // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        return;                          // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2
     }
 
     bb9: {
-        _3 = move ((_6 as Some).0: u16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
-        StorageDead(_13);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageDead(_6);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageDead(_4);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        _0 = unchecked_shl::<u16>(_1, move _3) -> [return: bb1, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-                                         // mir::Constant
-                                         // + span: $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-                                         // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u16, u16) -> u16 {unchecked_shl::<u16>}, val: Value(<ZST>) }
+        unreachable;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
     }
 }
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir
index 724b3c56723..67f0fe8932f 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir
@@ -7,38 +7,38 @@ fn unchecked_shr_signed_smaller(_1: i16, _2: u32) -> i16 {
     scope 1 (inlined core::num::<impl i16>::unchecked_shr) { // at $DIR/unchecked_shifts.rs:17:7: 17:23
         debug self => _1;                // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
         debug rhs => _2;                 // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-        let mut _3: i16;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        let mut _4: (u32,);              // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        let mut _5: u32;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        let mut _3: (u32,);              // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        let mut _4: u32;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        let mut _13: i16;                // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         scope 2 {
             scope 3 (inlined core::num::<impl i16>::unchecked_shr::conv) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                debug x => _5;           // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                let mut _6: std::option::Option<i16>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                let mut _7: std::result::Result<i16, std::num::TryFromIntError>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                debug x => _4;           // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                let mut _8: std::result::Result<i16, std::num::TryFromIntError>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                let mut _11: std::option::Option<i16>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
                 scope 4 {
                     scope 5 (inlined <u32 as TryInto<i16>>::try_into) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                        debug self => _5; // in scope 5 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+                        debug self => _4; // in scope 5 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
                         scope 6 (inlined convert::num::<impl TryFrom<u32> for i16>::try_from) { // at $SRC_DIR/core/src/convert/mod.rs:LL:COL
-                            debug u => _5; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-                            let mut _8: bool; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-                            let mut _9: u32; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-                            let mut _10: i16; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                            debug u => _4; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                            let mut _5: u32; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                            let mut _6: bool; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                            let mut _7: i16; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
                         }
                     }
                     scope 7 (inlined Result::<i16, TryFromIntError>::ok) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                        debug self => _7; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
-                        let mut _11: isize; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
-                        let _12: i16;    // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+                        debug self => _8; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+                        let mut _9: isize; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+                        let _10: i16;    // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
                         scope 8 {
-                            debug x => _12; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+                            debug x => _10; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
                         }
                     }
                     scope 9 (inlined #[track_caller] Option::<i16>::unwrap_unchecked) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                        debug self => _6; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
-                        let mut _13: &std::option::Option<i16>; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
-                        let mut _14: isize; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                        debug self => _11; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                        let mut _12: isize; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                        let mut _14: &std::option::Option<i16>; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
                         scope 10 {
-                            debug val => _3; // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
+                            debug val => _13; // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
                         }
                         scope 11 {
                             scope 13 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
@@ -49,7 +49,7 @@ fn unchecked_shr_signed_smaller(_1: i16, _2: u32) -> i16 {
                             }
                         }
                         scope 12 (inlined Option::<i16>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
-                            debug self => _13; // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL
+                            debug self => _14; // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL
                         }
                     }
                 }
@@ -58,81 +58,81 @@ fn unchecked_shr_signed_smaller(_1: i16, _2: u32) -> i16 {
     }
 
     bb0: {
+        StorageLive(_13);                // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         StorageLive(_3);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _3 = (_2,);                      // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         StorageLive(_4);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        _4 = (_2,);                      // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageLive(_5);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        _5 = move (_4.0: u32);           // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageLive(_6);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageLive(_7);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageLive(_8);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        StorageLive(_9);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        _9 = const 32767_u32;            // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        _8 = Gt(_5, move _9);            // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        StorageDead(_9);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        switchInt(move _8) -> [0: bb3, otherwise: bb2]; // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _4 = move (_3.0: u32);           // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_11);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_8);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_6);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageLive(_5);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _5 = const 32767_u32;            // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _6 = Gt(_4, move _5);            // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageDead(_5);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        switchInt(move _6) -> [0: bb1, otherwise: bb2]; // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
     }
 
     bb1: {
-        StorageDead(_3);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-        return;                          // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2
+        StorageLive(_7);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _7 = _4 as i16 (IntToInt);       // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _8 = Result::<i16, TryFromIntError>::Ok(move _7); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageDead(_7);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        goto -> bb3;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
     }
 
     bb2: {
-        _7 = Result::<i16, TryFromIntError>::Err(const TryFromIntError(())); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _8 = Result::<i16, TryFromIntError>::Err(const TryFromIntError(())); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
                                          // mir::Constant
                                          // + span: no-location
                                          // + literal: Const { ty: TryFromIntError, val: Value(<ZST>) }
-        goto -> bb4;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        goto -> bb3;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
     }
 
     bb3: {
-        StorageLive(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        _10 = _5 as i16 (IntToInt);      // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        _7 = Result::<i16, TryFromIntError>::Ok(move _10); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        StorageDead(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        goto -> bb4;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageDead(_6);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageLive(_10);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _9 = discriminant(_8);           // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        switchInt(move _9) -> [0: bb4, 1: bb5, otherwise: bb9]; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
     }
 
     bb4: {
-        StorageDead(_8);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        StorageLive(_12);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        _11 = discriminant(_7);          // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
-        switchInt(move _11) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        _10 = move ((_8 as Ok).0: i16);  // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        _11 = Option::<i16>::Some(move _10); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+        goto -> bb6;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
     }
 
     bb5: {
-        _6 = Option::<i16>::None;        // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
-        goto -> bb8;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        _11 = Option::<i16>::None;       // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        goto -> bb6;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
     }
 
     bb6: {
-        unreachable;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        StorageDead(_10);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageDead(_8);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_14);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _12 = discriminant(_11);         // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+        switchInt(move _12) -> [1: bb7, otherwise: bb9]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
     }
 
     bb7: {
-        _12 = move ((_7 as Ok).0: i16);  // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
-        _6 = Option::<i16>::Some(move _12); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
-        goto -> bb8;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        _13 = move ((_11 as Some).0: i16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+        StorageDead(_14);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageDead(_11);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageDead(_4);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageDead(_3);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _0 = unchecked_shr::<i16>(_1, move _13) -> [return: bb8, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
+                                         // mir::Constant
+                                         // + span: $SRC_DIR/core/src/num/int_macros.rs:LL:COL
+                                         // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(i16, i16) -> i16 {unchecked_shr::<i16>}, val: Value(<ZST>) }
     }
 
     bb8: {
-        StorageDead(_12);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageDead(_7);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageLive(_13);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        _14 = discriminant(_6);          // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
-        switchInt(move _14) -> [1: bb9, otherwise: bb6]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+        StorageDead(_13);                // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
+        return;                          // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2
     }
 
     bb9: {
-        _3 = move ((_6 as Some).0: i16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
-        StorageDead(_13);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageDead(_6);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageDead(_4);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        _0 = unchecked_shr::<i16>(_1, move _3) -> [return: bb1, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-                                         // mir::Constant
-                                         // + span: $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-                                         // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(i16, i16) -> i16 {unchecked_shr::<i16>}, val: Value(<ZST>) }
+        unreachable;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
     }
 }
diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.mir
index c5e2469fc27..601d83702f4 100644
--- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.mir
+++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.mir
@@ -5,8 +5,8 @@ fn unwrap_unchecked(_1: Option<T>) -> T {
     let mut _0: T;                       // return place in scope 0 at $DIR/unwrap_unchecked.rs:+0:54: +0:55
     scope 1 (inlined #[track_caller] Option::<T>::unwrap_unchecked) { // at $DIR/unwrap_unchecked.rs:10:9: 10:27
         debug self => _1;                // in scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
-        let mut _2: &std::option::Option<T>; // in scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
-        let mut _3: isize;               // in scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
+        let mut _2: isize;               // in scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
+        let mut _3: &std::option::Option<T>; // in scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
         scope 2 {
             debug val => _0;             // in scope 2 at $SRC_DIR/core/src/option.rs:LL:COL
         }
@@ -19,23 +19,23 @@ fn unwrap_unchecked(_1: Option<T>) -> T {
             }
         }
         scope 4 (inlined Option::<T>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
-            debug self => _2;            // in scope 4 at $SRC_DIR/core/src/option.rs:LL:COL
+            debug self => _3;            // in scope 4 at $SRC_DIR/core/src/option.rs:LL:COL
         }
     }
 
     bb0: {
-        StorageLive(_2);                 // scope 0 at $DIR/unwrap_unchecked.rs:+1:9: +1:27
-        _3 = discriminant(_1);           // scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
-        switchInt(move _3) -> [1: bb2, otherwise: bb1]; // scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
+        StorageLive(_3);                 // scope 0 at $DIR/unwrap_unchecked.rs:+1:9: +1:27
+        _2 = discriminant(_1);           // scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
+        switchInt(move _2) -> [1: bb1, otherwise: bb2]; // scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
     }
 
     bb1: {
-        unreachable;                     // scope 6 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+        _0 = move ((_1 as Some).0: T);   // scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
+        StorageDead(_3);                 // scope 0 at $DIR/unwrap_unchecked.rs:+1:9: +1:27
+        return;                          // scope 0 at $DIR/unwrap_unchecked.rs:+2:2: +2:2
     }
 
     bb2: {
-        _0 = move ((_1 as Some).0: T);   // scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
-        StorageDead(_2);                 // scope 0 at $DIR/unwrap_unchecked.rs:+1:9: +1:27
-        return;                          // scope 0 at $DIR/unwrap_unchecked.rs:+2:2: +2:2
+        unreachable;                     // scope 6 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
     }
 }
diff --git a/tests/mir-opt/issue_101973.inner.ConstProp.diff b/tests/mir-opt/issue_101973.inner.ConstProp.diff
index d048b9e6513..2f68f65c874 100644
--- a/tests/mir-opt/issue_101973.inner.ConstProp.diff
+++ b/tests/mir-opt/issue_101973.inner.ConstProp.diff
@@ -18,8 +18,8 @@
       let mut _13: bool;                   // in scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
       scope 1 (inlined imm8) {             // at $DIR/issue_101973.rs:15:5: 15:17
           debug x => _1;                   // in scope 1 at $DIR/issue_101973.rs:6:13: 6:14
-          let mut _14: u32;                // in scope 1 at $DIR/issue_101973.rs:8:12: 8:27
-          let mut _15: u32;                // in scope 1 at $DIR/issue_101973.rs:8:12: 8:20
+          let mut _14: u32;                // in scope 1 at $DIR/issue_101973.rs:8:12: 8:20
+          let mut _15: u32;                // in scope 1 at $DIR/issue_101973.rs:8:12: 8:27
           scope 2 {
               debug out => _4;             // in scope 2 at $DIR/issue_101973.rs:7:9: 7:16
           }
@@ -33,13 +33,13 @@
           StorageLive(_2);                 // scope 0 at $DIR/issue_101973.rs:+1:5: +1:65
           StorageLive(_3);                 // scope 0 at $DIR/issue_101973.rs:+1:5: +1:58
           StorageLive(_4);                 // scope 0 at $DIR/issue_101973.rs:+1:5: +1:17
-          StorageLive(_14);                // scope 2 at $DIR/issue_101973.rs:8:12: 8:27
-          StorageLive(_15);                // scope 2 at $DIR/issue_101973.rs:8:12: 8:20
-          _15 = Shr(_1, const 0_i32);      // scope 2 at $DIR/issue_101973.rs:8:12: 8:20
-          _14 = BitAnd(move _15, const 255_u32); // scope 2 at $DIR/issue_101973.rs:8:12: 8:27
-          StorageDead(_15);                // scope 2 at $DIR/issue_101973.rs:8:26: 8:27
-          _4 = BitOr(const 0_u32, move _14); // scope 2 at $DIR/issue_101973.rs:8:5: 8:27
+          StorageLive(_15);                // scope 2 at $DIR/issue_101973.rs:8:12: 8:27
+          StorageLive(_14);                // scope 2 at $DIR/issue_101973.rs:8:12: 8:20
+          _14 = Shr(_1, const 0_i32);      // scope 2 at $DIR/issue_101973.rs:8:12: 8:20
+          _15 = BitAnd(move _14, const 255_u32); // scope 2 at $DIR/issue_101973.rs:8:12: 8:27
           StorageDead(_14);                // scope 2 at $DIR/issue_101973.rs:8:26: 8:27
+          _4 = BitOr(const 0_u32, move _15); // scope 2 at $DIR/issue_101973.rs:8:5: 8:27
+          StorageDead(_15);                // scope 2 at $DIR/issue_101973.rs:8:26: 8:27
           StorageLive(_6);                 // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
           StorageLive(_7);                 // scope 0 at $DIR/issue_101973.rs:+1:31: +1:52
           StorageLive(_8);                 // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir
index 9f955b4717b..fac4b8a2d25 100644
--- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir
+++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir
@@ -3,19 +3,19 @@
 fn num_to_digit(_1: char) -> u32 {
     debug num => _1;                     // in scope 0 at $DIR/issue_59352.rs:+0:21: +0:24
     let mut _0: u32;                     // return place in scope 0 at $DIR/issue_59352.rs:+0:35: +0:38
-    let mut _2: std::option::Option<u32>; // in scope 0 at $DIR/issue_59352.rs:+2:26: +2:41
+    let mut _5: std::option::Option<u32>; // in scope 0 at $DIR/issue_59352.rs:+2:26: +2:41
     scope 1 (inlined char::methods::<impl char>::is_digit) { // at $DIR/issue_59352.rs:15:12: 15:23
         debug self => _1;                // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
         debug radix => const 8_u32;      // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
+        let _2: std::option::Option<u32>; // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
         let mut _3: &std::option::Option<u32>; // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
-        let _4: std::option::Option<u32>; // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
         scope 2 (inlined Option::<u32>::is_some) { // at $SRC_DIR/core/src/char/methods.rs:LL:COL
             debug self => _3;            // in scope 2 at $SRC_DIR/core/src/option.rs:LL:COL
-            let mut _5: isize;           // in scope 2 at $SRC_DIR/core/src/option.rs:LL:COL
+            let mut _4: isize;           // in scope 2 at $SRC_DIR/core/src/option.rs:LL:COL
         }
     }
     scope 3 (inlined #[track_caller] Option::<u32>::unwrap) { // at $DIR/issue_59352.rs:15:42: 15:50
-        debug self => _2;                // in scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
+        debug self => _5;                // in scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
         let mut _6: isize;               // in scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
         let mut _7: !;                   // in scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
         scope 4 {
@@ -25,44 +25,35 @@ fn num_to_digit(_1: char) -> u32 {
 
     bb0: {
         StorageLive(_3);                 // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
-        StorageLive(_4);                 // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
-        _4 = char::methods::<impl char>::to_digit(_1, const 8_u32) -> bb5; // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
+        StorageLive(_2);                 // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
+        _2 = char::methods::<impl char>::to_digit(_1, const 8_u32) -> bb1; // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/char/methods.rs:LL:COL
                                          // + literal: Const { ty: fn(char, u32) -> Option<u32> {char::methods::<impl char>::to_digit}, val: Value(<ZST>) }
     }
 
     bb1: {
-        StorageLive(_2);                 // scope 0 at $DIR/issue_59352.rs:+2:26: +2:41
-        _2 = char::methods::<impl char>::to_digit(_1, const 8_u32) -> bb2; // scope 0 at $DIR/issue_59352.rs:+2:26: +2:41
-                                         // mir::Constant
-                                         // + span: $DIR/issue_59352.rs:15:30: 15:38
-                                         // + literal: Const { ty: fn(char, u32) -> Option<u32> {char::methods::<impl char>::to_digit}, val: Value(<ZST>) }
+        _3 = &_2;                        // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
+        _4 = discriminant((*_3));        // scope 2 at $SRC_DIR/core/src/option.rs:LL:COL
+        StorageDead(_3);                 // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
+        StorageDead(_2);                 // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
+        switchInt(move _4) -> [1: bb2, otherwise: bb7]; // scope 0 at $DIR/issue_59352.rs:+2:8: +2:23
     }
 
     bb2: {
-        _6 = discriminant(_2);           // scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
-        switchInt(move _6) -> [0: bb6, 1: bb8, otherwise: bb7]; // scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
+        StorageLive(_5);                 // scope 0 at $DIR/issue_59352.rs:+2:26: +2:41
+        _5 = char::methods::<impl char>::to_digit(_1, const 8_u32) -> bb3; // scope 0 at $DIR/issue_59352.rs:+2:26: +2:41
+                                         // mir::Constant
+                                         // + span: $DIR/issue_59352.rs:15:30: 15:38
+                                         // + literal: Const { ty: fn(char, u32) -> Option<u32> {char::methods::<impl char>::to_digit}, val: Value(<ZST>) }
     }
 
     bb3: {
-        _0 = const 0_u32;                // scope 0 at $DIR/issue_59352.rs:+2:60: +2:61
-        goto -> bb4;                     // scope 0 at $DIR/issue_59352.rs:+2:5: +2:63
+        _6 = discriminant(_5);           // scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
+        switchInt(move _6) -> [0: bb4, 1: bb5, otherwise: bb6]; // scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
     }
 
     bb4: {
-        return;                          // scope 0 at $DIR/issue_59352.rs:+3:2: +3:2
-    }
-
-    bb5: {
-        _3 = &_4;                        // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
-        _5 = discriminant((*_3));        // scope 2 at $SRC_DIR/core/src/option.rs:LL:COL
-        StorageDead(_3);                 // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
-        StorageDead(_4);                 // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
-        switchInt(move _5) -> [1: bb1, otherwise: bb3]; // scope 0 at $DIR/issue_59352.rs:+2:8: +2:23
-    }
-
-    bb6: {
         _7 = core::panicking::panic(const "called `Option::unwrap()` on a `None` value"); // scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/option.rs:LL:COL
@@ -72,13 +63,22 @@ fn num_to_digit(_1: char) -> u32 {
                                          // + literal: Const { ty: &str, val: Value(Slice(..)) }
     }
 
-    bb7: {
+    bb5: {
+        _0 = move ((_5 as Some).0: u32); // scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
+        StorageDead(_5);                 // scope 0 at $DIR/issue_59352.rs:+2:49: +2:50
+        goto -> bb8;                     // scope 0 at $DIR/issue_59352.rs:+2:5: +2:63
+    }
+
+    bb6: {
         unreachable;                     // scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
     }
 
+    bb7: {
+        _0 = const 0_u32;                // scope 0 at $DIR/issue_59352.rs:+2:60: +2:61
+        goto -> bb8;                     // scope 0 at $DIR/issue_59352.rs:+2:5: +2:63
+    }
+
     bb8: {
-        _0 = move ((_2 as Some).0: u32); // scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
-        StorageDead(_2);                 // scope 0 at $DIR/issue_59352.rs:+2:49: +2:50
-        goto -> bb4;                     // scope 0 at $DIR/issue_59352.rs:+2:5: +2:63
+        return;                          // scope 0 at $DIR/issue_59352.rs:+3:2: +3:2
     }
 }
diff --git a/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir
index 0e885cf94fd..6b805166ba2 100644
--- a/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir
@@ -13,15 +13,15 @@ fn ub_if_b(_1: Thing) -> Thing {
 
     bb0: {
         _2 = discriminant(_1);           // scope 0 at $DIR/duplicate_switch_targets.rs:+1:11: +1:12
-        switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/duplicate_switch_targets.rs:+1:5: +1:12
+        switchInt(move _2) -> [0: bb1, otherwise: bb2]; // scope 0 at $DIR/duplicate_switch_targets.rs:+1:5: +1:12
     }
 
     bb1: {
-        unreachable;                     // scope 2 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+        _0 = move _1;                    // scope 0 at $DIR/duplicate_switch_targets.rs:+2:21: +2:22
+        return;                          // scope 0 at $DIR/duplicate_switch_targets.rs:+5:2: +5:2
     }
 
     bb2: {
-        _0 = move _1;                    // scope 0 at $DIR/duplicate_switch_targets.rs:+2:21: +2:22
-        return;                          // scope 0 at $DIR/duplicate_switch_targets.rs:+5:2: +5:2
+        unreachable;                     // scope 2 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
     }
 }
diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.mir
index 343a4a5a6f3..693939e75f4 100644
--- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.mir
@@ -7,20 +7,33 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
     let mut _0: ();                      // return place in scope 0 at $DIR/range_iter.rs:+0:60: +0:60
     let mut _4: std::ops::Range<u32>;    // in scope 0 at $DIR/range_iter.rs:+1:14: +1:24
     let mut _5: std::ops::Range<u32>;    // in scope 0 at $DIR/range_iter.rs:+1:14: +1:24
-    let _6: ();                          // in scope 0 at $DIR/range_iter.rs:+1:14: +1:24
-    let mut _7: std::option::Option<u32>; // in scope 0 at $DIR/range_iter.rs:+1:14: +1:24
-    let mut _8: &mut std::ops::Range<u32>; // in scope 0 at $DIR/range_iter.rs:+1:14: +1:24
-    let mut _9: isize;                   // in scope 0 at $DIR/range_iter.rs:+1:5: +3:6
-    let mut _11: &impl Fn(u32);          // in scope 0 at $DIR/range_iter.rs:+2:9: +2:10
-    let mut _12: (u32,);                 // in scope 0 at $DIR/range_iter.rs:+2:9: +2:13
+    let mut _6: &mut std::ops::Range<u32>; // in scope 0 at $DIR/range_iter.rs:+1:14: +1:24
+    let mut _10: std::option::Option<u32>; // in scope 0 at $DIR/range_iter.rs:+1:14: +1:24
+    let mut _13: isize;                  // in scope 0 at $DIR/range_iter.rs:+1:5: +3:6
+    let mut _15: &impl Fn(u32);          // in scope 0 at $DIR/range_iter.rs:+2:9: +2:10
+    let mut _16: (u32,);                 // in scope 0 at $DIR/range_iter.rs:+2:9: +2:13
+    let _17: ();                         // in scope 0 at $DIR/range_iter.rs:+1:14: +1:24
     scope 1 {
         debug iter => _5;                // in scope 1 at $DIR/range_iter.rs:+1:14: +1:24
-        let _10: u32;                    // in scope 1 at $DIR/range_iter.rs:+1:9: +1:10
+        let _14: u32;                    // in scope 1 at $DIR/range_iter.rs:+1:9: +1:10
         scope 2 {
-            debug x => _10;              // in scope 2 at $DIR/range_iter.rs:+1:9: +1:10
+            debug x => _14;              // in scope 2 at $DIR/range_iter.rs:+1:9: +1:10
         }
         scope 4 (inlined iter::range::<impl Iterator for std::ops::Range<u32>>::next) { // at $DIR/range_iter.rs:21:14: 21:24
-            debug self => _8;            // in scope 4 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+            debug self => _6;            // in scope 4 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+            scope 5 (inlined <std::ops::Range<u32> as iter::range::RangeIteratorImpl>::spec_next) { // at $SRC_DIR/core/src/iter/range.rs:LL:COL
+                debug self => _6;        // in scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+                let mut _7: &u32;        // in scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+                let mut _8: &u32;        // in scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+                let mut _9: bool;        // in scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+                let _11: u32;            // in scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+                let mut _12: u32;        // in scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+                scope 6 {
+                    debug old => _11;    // in scope 6 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+                    scope 7 {
+                    }
+                }
+            }
         }
     }
     scope 3 (inlined <std::ops::Range<u32> as IntoIterator>::into_iter) { // at $DIR/range_iter.rs:21:14: 21:24
@@ -35,57 +48,92 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
     }
 
     bb1: {
-        StorageLive(_7);                 // scope 1 at $DIR/range_iter.rs:+1:14: +1:24
-        _8 = &mut _5;                    // scope 1 at $DIR/range_iter.rs:+1:14: +1:24
-        _7 = <std::ops::Range<u32> as iter::range::RangeIteratorImpl>::spec_next(_8) -> [return: bb9, unwind: bb7]; // scope 4 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        StorageLive(_10);                // scope 1 at $DIR/range_iter.rs:+1:14: +1:24
+        _6 = &mut _5;                    // scope 1 at $DIR/range_iter.rs:+1:14: +1:24
+        StorageLive(_11);                // scope 4 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        StorageLive(_9);                 // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        StorageLive(_7);                 // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        _7 = &((*_6).0: u32);            // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        StorageLive(_8);                 // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        _8 = &((*_6).1: u32);            // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        _9 = <u32 as PartialOrd>::lt(move _7, move _8) -> [return: bb2, unwind: bb12]; // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/iter/range.rs:LL:COL
-                                         // + literal: Const { ty: for<'a> fn(&'a mut std::ops::Range<u32>) -> Option<<std::ops::Range<u32> as iter::range::RangeIteratorImpl>::Item> {<std::ops::Range<u32> as iter::range::RangeIteratorImpl>::spec_next}, val: Value(<ZST>) }
+                                         // + literal: Const { ty: for<'a, 'b> fn(&'a u32, &'b u32) -> bool {<u32 as PartialOrd>::lt}, val: Value(<ZST>) }
     }
 
     bb2: {
-        _10 = ((_7 as Some).0: u32);     // scope 1 at $DIR/range_iter.rs:+1:9: +1:10
-        StorageLive(_11);                // scope 2 at $DIR/range_iter.rs:+2:9: +2:10
-        _11 = &_3;                       // scope 2 at $DIR/range_iter.rs:+2:9: +2:10
-        StorageLive(_12);                // scope 2 at $DIR/range_iter.rs:+2:9: +2:13
-        _12 = (_10,);                    // scope 2 at $DIR/range_iter.rs:+2:9: +2:13
-        _6 = <impl Fn(u32) as Fn<(u32,)>>::call(move _11, move _12) -> [return: bb5, unwind: bb7]; // scope 2 at $DIR/range_iter.rs:+2:9: +2:13
-                                         // mir::Constant
-                                         // + span: $DIR/range_iter.rs:22:9: 22:10
-                                         // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a impl Fn(u32), (u32,)) -> <impl Fn(u32) as FnOnce<(u32,)>>::Output {<impl Fn(u32) as Fn<(u32,)>>::call}, val: Value(<ZST>) }
+        StorageDead(_8);                 // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        StorageDead(_7);                 // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        switchInt(move _9) -> [0: bb3, otherwise: bb4]; // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
     }
 
     bb3: {
-        unreachable;                     // scope 1 at $DIR/range_iter.rs:+1:14: +1:24
+        _10 = Option::<u32>::None;       // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        goto -> bb6;                     // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
     }
 
     bb4: {
-        StorageDead(_7);                 // scope 1 at $DIR/range_iter.rs:+3:5: +3:6
-        StorageDead(_5);                 // scope 0 at $DIR/range_iter.rs:+3:5: +3:6
-        drop(_3) -> bb6;                 // scope 0 at $DIR/range_iter.rs:+4:1: +4:2
+        _11 = ((*_6).0: u32);            // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        StorageLive(_12);                // scope 6 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        _12 = <u32 as Step>::forward_unchecked(_11, const 1_usize) -> [return: bb5, unwind: bb12]; // scope 7 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+                                         // mir::Constant
+                                         // + span: $SRC_DIR/core/src/iter/range.rs:LL:COL
+                                         // + literal: Const { ty: unsafe fn(u32, usize) -> u32 {<u32 as Step>::forward_unchecked}, val: Value(<ZST>) }
     }
 
     bb5: {
-        StorageDead(_12);                // scope 2 at $DIR/range_iter.rs:+2:12: +2:13
-        StorageDead(_11);                // scope 2 at $DIR/range_iter.rs:+2:12: +2:13
-        StorageDead(_7);                 // scope 1 at $DIR/range_iter.rs:+3:5: +3:6
-        goto -> bb1;                     // scope 1 at $DIR/range_iter.rs:+1:5: +3:6
+        ((*_6).0: u32) = move _12;       // scope 6 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        StorageDead(_12);                // scope 6 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        _10 = Option::<u32>::Some(_11);  // scope 6 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        goto -> bb6;                     // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
     }
 
     bb6: {
-        return;                          // scope 0 at $DIR/range_iter.rs:+4:2: +4:2
+        StorageDead(_9);                 // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        StorageDead(_11);                // scope 4 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        _13 = discriminant(_10);         // scope 1 at $DIR/range_iter.rs:+1:14: +1:24
+        switchInt(move _13) -> [0: bb7, 1: bb9, otherwise: bb11]; // scope 1 at $DIR/range_iter.rs:+1:14: +1:24
     }
 
-    bb7 (cleanup): {
-        drop(_3) -> [return: bb8, unwind terminate]; // scope 0 at $DIR/range_iter.rs:+4:1: +4:2
+    bb7: {
+        StorageDead(_10);                // scope 1 at $DIR/range_iter.rs:+3:5: +3:6
+        StorageDead(_5);                 // scope 0 at $DIR/range_iter.rs:+3:5: +3:6
+        drop(_3) -> bb8;                 // scope 0 at $DIR/range_iter.rs:+4:1: +4:2
     }
 
-    bb8 (cleanup): {
-        resume;                          // scope 0 at $DIR/range_iter.rs:+0:1: +4:2
+    bb8: {
+        return;                          // scope 0 at $DIR/range_iter.rs:+4:2: +4:2
     }
 
     bb9: {
-        _9 = discriminant(_7);           // scope 1 at $DIR/range_iter.rs:+1:14: +1:24
-        switchInt(move _9) -> [0: bb4, 1: bb2, otherwise: bb3]; // scope 1 at $DIR/range_iter.rs:+1:14: +1:24
+        _14 = ((_10 as Some).0: u32);    // scope 1 at $DIR/range_iter.rs:+1:9: +1:10
+        StorageLive(_15);                // scope 2 at $DIR/range_iter.rs:+2:9: +2:10
+        _15 = &_3;                       // scope 2 at $DIR/range_iter.rs:+2:9: +2:10
+        StorageLive(_16);                // scope 2 at $DIR/range_iter.rs:+2:9: +2:13
+        _16 = (_14,);                    // scope 2 at $DIR/range_iter.rs:+2:9: +2:13
+        _17 = <impl Fn(u32) as Fn<(u32,)>>::call(move _15, move _16) -> [return: bb10, unwind: bb12]; // scope 2 at $DIR/range_iter.rs:+2:9: +2:13
+                                         // mir::Constant
+                                         // + span: $DIR/range_iter.rs:22:9: 22:10
+                                         // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a impl Fn(u32), (u32,)) -> <impl Fn(u32) as FnOnce<(u32,)>>::Output {<impl Fn(u32) as Fn<(u32,)>>::call}, val: Value(<ZST>) }
+    }
+
+    bb10: {
+        StorageDead(_16);                // scope 2 at $DIR/range_iter.rs:+2:12: +2:13
+        StorageDead(_15);                // scope 2 at $DIR/range_iter.rs:+2:12: +2:13
+        StorageDead(_10);                // scope 1 at $DIR/range_iter.rs:+3:5: +3:6
+        goto -> bb1;                     // scope 1 at $DIR/range_iter.rs:+1:5: +3:6
+    }
+
+    bb11: {
+        unreachable;                     // scope 1 at $DIR/range_iter.rs:+1:14: +1:24
+    }
+
+    bb12 (cleanup): {
+        drop(_3) -> [return: bb13, unwind terminate]; // scope 0 at $DIR/range_iter.rs:+4:1: +4:2
+    }
+
+    bb13 (cleanup): {
+        resume;                          // scope 0 at $DIR/range_iter.rs:+0:1: +4:2
     }
 }
diff --git a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.mir
index f45eabba252..a187d650a77 100644
--- a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.mir
@@ -7,20 +7,20 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
     let mut _0: ();                      // return place in scope 0 at $DIR/range_iter.rs:+0:62: +0:62
     let mut _4: std::ops::RangeInclusive<u32>; // in scope 0 at $DIR/range_iter.rs:+1:14: +1:25
     let mut _5: std::ops::RangeInclusive<u32>; // in scope 0 at $DIR/range_iter.rs:+1:14: +1:25
-    let _6: ();                          // in scope 0 at $DIR/range_iter.rs:+1:14: +1:25
+    let mut _6: &mut std::ops::RangeInclusive<u32>; // in scope 0 at $DIR/range_iter.rs:+1:14: +1:25
     let mut _7: std::option::Option<u32>; // in scope 0 at $DIR/range_iter.rs:+1:14: +1:25
-    let mut _8: &mut std::ops::RangeInclusive<u32>; // in scope 0 at $DIR/range_iter.rs:+1:14: +1:25
-    let mut _9: isize;                   // in scope 0 at $DIR/range_iter.rs:+1:5: +3:6
-    let mut _11: &impl Fn(u32);          // in scope 0 at $DIR/range_iter.rs:+2:9: +2:10
-    let mut _12: (u32,);                 // in scope 0 at $DIR/range_iter.rs:+2:9: +2:13
+    let mut _8: isize;                   // in scope 0 at $DIR/range_iter.rs:+1:5: +3:6
+    let mut _10: &impl Fn(u32);          // in scope 0 at $DIR/range_iter.rs:+2:9: +2:10
+    let mut _11: (u32,);                 // in scope 0 at $DIR/range_iter.rs:+2:9: +2:13
+    let _12: ();                         // in scope 0 at $DIR/range_iter.rs:+1:14: +1:25
     scope 1 {
         debug iter => _5;                // in scope 1 at $DIR/range_iter.rs:+1:14: +1:25
-        let _10: u32;                    // in scope 1 at $DIR/range_iter.rs:+1:9: +1:10
+        let _9: u32;                     // in scope 1 at $DIR/range_iter.rs:+1:9: +1:10
         scope 2 {
-            debug x => _10;              // in scope 2 at $DIR/range_iter.rs:+1:9: +1:10
+            debug x => _9;               // in scope 2 at $DIR/range_iter.rs:+1:9: +1:10
         }
         scope 5 (inlined iter::range::<impl Iterator for RangeInclusive<u32>>::next) { // at $DIR/range_iter.rs:28:14: 28:25
-            debug self => _8;            // in scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+            debug self => _6;            // in scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
         }
     }
     scope 3 (inlined RangeInclusive::<u32>::new) { // at $DIR/range_iter.rs:28:14: 28:25
@@ -40,56 +40,56 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
 
     bb1: {
         StorageLive(_7);                 // scope 1 at $DIR/range_iter.rs:+1:14: +1:25
-        _8 = &mut _5;                    // scope 1 at $DIR/range_iter.rs:+1:14: +1:25
-        _7 = <RangeInclusive<u32> as iter::range::RangeInclusiveIteratorImpl>::spec_next(_8) -> [return: bb9, unwind: bb7]; // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        _6 = &mut _5;                    // scope 1 at $DIR/range_iter.rs:+1:14: +1:25
+        _7 = <RangeInclusive<u32> as iter::range::RangeInclusiveIteratorImpl>::spec_next(_6) -> [return: bb2, unwind: bb8]; // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/iter/range.rs:LL:COL
                                          // + literal: Const { ty: for<'a> fn(&'a mut RangeInclusive<u32>) -> Option<<RangeInclusive<u32> as iter::range::RangeInclusiveIteratorImpl>::Item> {<RangeInclusive<u32> as iter::range::RangeInclusiveIteratorImpl>::spec_next}, val: Value(<ZST>) }
     }
 
     bb2: {
-        _10 = ((_7 as Some).0: u32);     // scope 1 at $DIR/range_iter.rs:+1:9: +1:10
-        StorageLive(_11);                // scope 2 at $DIR/range_iter.rs:+2:9: +2:10
-        _11 = &_3;                       // scope 2 at $DIR/range_iter.rs:+2:9: +2:10
-        StorageLive(_12);                // scope 2 at $DIR/range_iter.rs:+2:9: +2:13
-        _12 = (_10,);                    // scope 2 at $DIR/range_iter.rs:+2:9: +2:13
-        _6 = <impl Fn(u32) as Fn<(u32,)>>::call(move _11, move _12) -> [return: bb5, unwind: bb7]; // scope 2 at $DIR/range_iter.rs:+2:9: +2:13
-                                         // mir::Constant
-                                         // + span: $DIR/range_iter.rs:29:9: 29:10
-                                         // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a impl Fn(u32), (u32,)) -> <impl Fn(u32) as FnOnce<(u32,)>>::Output {<impl Fn(u32) as Fn<(u32,)>>::call}, val: Value(<ZST>) }
+        _8 = discriminant(_7);           // scope 1 at $DIR/range_iter.rs:+1:14: +1:25
+        switchInt(move _8) -> [0: bb3, 1: bb5, otherwise: bb7]; // scope 1 at $DIR/range_iter.rs:+1:14: +1:25
     }
 
     bb3: {
-        unreachable;                     // scope 1 at $DIR/range_iter.rs:+1:14: +1:25
+        StorageDead(_7);                 // scope 1 at $DIR/range_iter.rs:+3:5: +3:6
+        StorageDead(_5);                 // scope 0 at $DIR/range_iter.rs:+3:5: +3:6
+        drop(_3) -> bb4;                 // scope 0 at $DIR/range_iter.rs:+4:1: +4:2
     }
 
     bb4: {
-        StorageDead(_7);                 // scope 1 at $DIR/range_iter.rs:+3:5: +3:6
-        StorageDead(_5);                 // scope 0 at $DIR/range_iter.rs:+3:5: +3:6
-        drop(_3) -> bb6;                 // scope 0 at $DIR/range_iter.rs:+4:1: +4:2
+        return;                          // scope 0 at $DIR/range_iter.rs:+4:2: +4:2
     }
 
     bb5: {
-        StorageDead(_12);                // scope 2 at $DIR/range_iter.rs:+2:12: +2:13
-        StorageDead(_11);                // scope 2 at $DIR/range_iter.rs:+2:12: +2:13
-        StorageDead(_7);                 // scope 1 at $DIR/range_iter.rs:+3:5: +3:6
-        goto -> bb1;                     // scope 1 at $DIR/range_iter.rs:+1:5: +3:6
+        _9 = ((_7 as Some).0: u32);      // scope 1 at $DIR/range_iter.rs:+1:9: +1:10
+        StorageLive(_10);                // scope 2 at $DIR/range_iter.rs:+2:9: +2:10
+        _10 = &_3;                       // scope 2 at $DIR/range_iter.rs:+2:9: +2:10
+        StorageLive(_11);                // scope 2 at $DIR/range_iter.rs:+2:9: +2:13
+        _11 = (_9,);                     // scope 2 at $DIR/range_iter.rs:+2:9: +2:13
+        _12 = <impl Fn(u32) as Fn<(u32,)>>::call(move _10, move _11) -> [return: bb6, unwind: bb8]; // scope 2 at $DIR/range_iter.rs:+2:9: +2:13
+                                         // mir::Constant
+                                         // + span: $DIR/range_iter.rs:29:9: 29:10
+                                         // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a impl Fn(u32), (u32,)) -> <impl Fn(u32) as FnOnce<(u32,)>>::Output {<impl Fn(u32) as Fn<(u32,)>>::call}, val: Value(<ZST>) }
     }
 
     bb6: {
-        return;                          // scope 0 at $DIR/range_iter.rs:+4:2: +4:2
+        StorageDead(_11);                // scope 2 at $DIR/range_iter.rs:+2:12: +2:13
+        StorageDead(_10);                // scope 2 at $DIR/range_iter.rs:+2:12: +2:13
+        StorageDead(_7);                 // scope 1 at $DIR/range_iter.rs:+3:5: +3:6
+        goto -> bb1;                     // scope 1 at $DIR/range_iter.rs:+1:5: +3:6
     }
 
-    bb7 (cleanup): {
-        drop(_3) -> [return: bb8, unwind terminate]; // scope 0 at $DIR/range_iter.rs:+4:1: +4:2
+    bb7: {
+        unreachable;                     // scope 1 at $DIR/range_iter.rs:+1:14: +1:25
     }
 
     bb8 (cleanup): {
-        resume;                          // scope 0 at $DIR/range_iter.rs:+0:1: +4:2
+        drop(_3) -> [return: bb9, unwind terminate]; // scope 0 at $DIR/range_iter.rs:+4:1: +4:2
     }
 
-    bb9: {
-        _9 = discriminant(_7);           // scope 1 at $DIR/range_iter.rs:+1:14: +1:25
-        switchInt(move _9) -> [0: bb4, 1: bb2, otherwise: bb3]; // scope 1 at $DIR/range_iter.rs:+1:14: +1:25
+    bb9 (cleanup): {
+        resume;                          // scope 0 at $DIR/range_iter.rs:+0:1: +4:2
     }
 }
diff --git a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.mir
index cae46e2b0bb..668ec31c6c1 100644
--- a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.mir
@@ -5,16 +5,64 @@ fn range_iter_next(_1: &mut std::ops::Range<u32>) -> Option<u32> {
     let mut _0: std::option::Option<u32>; // return place in scope 0 at $DIR/range_iter.rs:+0:48: +0:59
     scope 1 (inlined iter::range::<impl Iterator for std::ops::Range<u32>>::next) { // at $DIR/range_iter.rs:11:8: 11:14
         debug self => _1;                // in scope 1 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        scope 2 (inlined <std::ops::Range<u32> as iter::range::RangeIteratorImpl>::spec_next) { // at $SRC_DIR/core/src/iter/range.rs:LL:COL
+            debug self => _1;            // in scope 2 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+            let mut _2: &u32;            // in scope 2 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+            let mut _3: &u32;            // in scope 2 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+            let mut _4: bool;            // in scope 2 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+            let _5: u32;                 // in scope 2 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+            let mut _6: u32;             // in scope 2 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+            scope 3 {
+                debug old => _5;         // in scope 3 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+                scope 4 {
+                }
+            }
+        }
     }
 
     bb0: {
-        _0 = <std::ops::Range<u32> as iter::range::RangeIteratorImpl>::spec_next(_1) -> bb1; // scope 1 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        StorageLive(_5);                 // scope 1 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        StorageLive(_4);                 // scope 2 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        StorageLive(_2);                 // scope 2 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        _2 = &((*_1).0: u32);            // scope 2 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        StorageLive(_3);                 // scope 2 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        _3 = &((*_1).1: u32);            // scope 2 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        _4 = <u32 as PartialOrd>::lt(move _2, move _3) -> bb1; // scope 2 at $SRC_DIR/core/src/iter/range.rs:LL:COL
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/iter/range.rs:LL:COL
-                                         // + literal: Const { ty: for<'a> fn(&'a mut std::ops::Range<u32>) -> Option<<std::ops::Range<u32> as iter::range::RangeIteratorImpl>::Item> {<std::ops::Range<u32> as iter::range::RangeIteratorImpl>::spec_next}, val: Value(<ZST>) }
+                                         // + literal: Const { ty: for<'a, 'b> fn(&'a u32, &'b u32) -> bool {<u32 as PartialOrd>::lt}, val: Value(<ZST>) }
     }
 
     bb1: {
+        StorageDead(_3);                 // scope 2 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        StorageDead(_2);                 // scope 2 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        switchInt(move _4) -> [0: bb2, otherwise: bb3]; // scope 2 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+    }
+
+    bb2: {
+        _0 = Option::<u32>::None;        // scope 2 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        goto -> bb5;                     // scope 2 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+    }
+
+    bb3: {
+        _5 = ((*_1).0: u32);             // scope 2 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        StorageLive(_6);                 // scope 3 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        _6 = <u32 as Step>::forward_unchecked(_5, const 1_usize) -> bb4; // scope 4 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+                                         // mir::Constant
+                                         // + span: $SRC_DIR/core/src/iter/range.rs:LL:COL
+                                         // + literal: Const { ty: unsafe fn(u32, usize) -> u32 {<u32 as Step>::forward_unchecked}, val: Value(<ZST>) }
+    }
+
+    bb4: {
+        ((*_1).0: u32) = move _6;        // scope 3 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        StorageDead(_6);                 // scope 3 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        _0 = Option::<u32>::Some(_5);    // scope 3 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        goto -> bb5;                     // scope 2 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+    }
+
+    bb5: {
+        StorageDead(_4);                 // scope 2 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        StorageDead(_5);                 // scope 1 at $SRC_DIR/core/src/iter/range.rs:LL:COL
         return;                          // scope 0 at $DIR/range_iter.rs:+2:2: +2:2
     }
 }
diff --git a/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir
index 986ab35886f..089b0c23e2c 100644
--- a/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir
@@ -3,18 +3,18 @@
 fn ezmap(_1: Option<i32>) -> Option<i32> {
     debug x => _1;                       // in scope 0 at $DIR/simple_option_map.rs:+0:14: +0:15
     let mut _0: std::option::Option<i32>; // return place in scope 0 at $DIR/simple_option_map.rs:+0:33: +0:44
-    let mut _6: i32;                     // in scope 0 at $DIR/simple_option_map.rs:11:25: 11:29
+    let mut _5: i32;                     // in scope 0 at $DIR/simple_option_map.rs:11:25: 11:29
     scope 1 (inlined map::<i32, i32, [closure@$DIR/simple_option_map.rs:18:12: 18:15]>) { // at $DIR/simple_option_map.rs:18:5: 18:22
         debug slf => _1;                 // in scope 1 at $DIR/simple_option_map.rs:6:17: 6:20
         debug f => const ZeroSized: [closure@$DIR/simple_option_map.rs:18:12: 18:15]; // in scope 1 at $DIR/simple_option_map.rs:6:33: 6:34
         let mut _2: isize;               // in scope 1 at $DIR/simple_option_map.rs:11:9: 11:16
         let _3: i32;                     // in scope 1 at $DIR/simple_option_map.rs:11:14: 11:15
-        let mut _4: i32;                 // in scope 1 at $DIR/simple_option_map.rs:11:25: 11:29
-        let mut _5: (i32,);              // in scope 1 at $DIR/simple_option_map.rs:11:25: 11:29
+        let mut _4: (i32,);              // in scope 1 at $DIR/simple_option_map.rs:11:25: 11:29
+        let mut _6: i32;                 // in scope 1 at $DIR/simple_option_map.rs:11:25: 11:29
         scope 2 {
             debug x => _3;               // in scope 2 at $DIR/simple_option_map.rs:11:14: 11:15
             scope 3 (inlined ezmap::{closure#0}) { // at $DIR/simple_option_map.rs:11:25: 11:29
-                debug n => _6;           // in scope 3 at $DIR/simple_option_map.rs:+1:13: +1:14
+                debug n => _5;           // in scope 3 at $DIR/simple_option_map.rs:+1:13: +1:14
             }
         }
     }
@@ -22,35 +22,35 @@ fn ezmap(_1: Option<i32>) -> Option<i32> {
     bb0: {
         StorageLive(_3);                 // scope 0 at $DIR/simple_option_map.rs:+1:5: +1:22
         _2 = discriminant(_1);           // scope 1 at $DIR/simple_option_map.rs:10:11: 10:14
-        switchInt(move _2) -> [0: bb1, 1: bb3, otherwise: bb2]; // scope 1 at $DIR/simple_option_map.rs:10:5: 10:14
+        switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb4]; // scope 1 at $DIR/simple_option_map.rs:10:5: 10:14
     }
 
     bb1: {
         _0 = Option::<i32>::None;        // scope 1 at $DIR/simple_option_map.rs:12:17: 12:21
-        goto -> bb4;                     // scope 1 at $DIR/simple_option_map.rs:12:17: 12:21
+        goto -> bb3;                     // scope 1 at $DIR/simple_option_map.rs:12:17: 12:21
     }
 
     bb2: {
-        unreachable;                     // scope 1 at $DIR/simple_option_map.rs:10:11: 10:14
-    }
-
-    bb3: {
         _3 = ((_1 as Some).0: i32);      // scope 1 at $DIR/simple_option_map.rs:11:14: 11:15
+        StorageLive(_6);                 // scope 2 at $DIR/simple_option_map.rs:11:25: 11:29
         StorageLive(_4);                 // scope 2 at $DIR/simple_option_map.rs:11:25: 11:29
+        _4 = (move _3,);                 // scope 2 at $DIR/simple_option_map.rs:11:25: 11:29
         StorageLive(_5);                 // scope 2 at $DIR/simple_option_map.rs:11:25: 11:29
-        _5 = (move _3,);                 // scope 2 at $DIR/simple_option_map.rs:11:25: 11:29
-        StorageLive(_6);                 // scope 2 at $DIR/simple_option_map.rs:11:25: 11:29
-        _6 = move (_5.0: i32);           // scope 2 at $DIR/simple_option_map.rs:11:25: 11:29
-        _4 = Add(_6, const 1_i32);       // scope 3 at $DIR/simple_option_map.rs:+1:16: +1:21
-        StorageDead(_6);                 // scope 2 at $DIR/simple_option_map.rs:11:25: 11:29
-        StorageDead(_5);                 // scope 2 at $DIR/simple_option_map.rs:11:28: 11:29
-        _0 = Option::<i32>::Some(move _4); // scope 2 at $DIR/simple_option_map.rs:11:20: 11:30
-        StorageDead(_4);                 // scope 2 at $DIR/simple_option_map.rs:11:29: 11:30
-        goto -> bb4;                     // scope 1 at $DIR/simple_option_map.rs:14:1: 14:2
+        _5 = move (_4.0: i32);           // scope 2 at $DIR/simple_option_map.rs:11:25: 11:29
+        _6 = Add(_5, const 1_i32);       // scope 3 at $DIR/simple_option_map.rs:+1:16: +1:21
+        StorageDead(_5);                 // scope 2 at $DIR/simple_option_map.rs:11:25: 11:29
+        StorageDead(_4);                 // scope 2 at $DIR/simple_option_map.rs:11:28: 11:29
+        _0 = Option::<i32>::Some(move _6); // scope 2 at $DIR/simple_option_map.rs:11:20: 11:30
+        StorageDead(_6);                 // scope 2 at $DIR/simple_option_map.rs:11:29: 11:30
+        goto -> bb3;                     // scope 1 at $DIR/simple_option_map.rs:14:1: 14:2
     }
 
-    bb4: {
+    bb3: {
         StorageDead(_3);                 // scope 0 at $DIR/simple_option_map.rs:+1:5: +1:22
         return;                          // scope 0 at $DIR/simple_option_map.rs:+2:2: +2:2
     }
+
+    bb4: {
+        unreachable;                     // scope 1 at $DIR/simple_option_map.rs:10:11: 10:14
+    }
 }
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.mir
index 715a1e3fcd4..b05d44f4d60 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.mir
@@ -10,17 +10,17 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> {
         scope 2 (inlined <usize as SliceIndex<[u32]>>::get_mut) { // at $SRC_DIR/core/src/slice/mod.rs:LL:COL
             debug self => _2;            // in scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
             debug slice => _1;           // in scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-            let mut _3: bool;            // in scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+            let mut _3: &[u32];          // in scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
             let mut _4: usize;           // in scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-            let mut _5: &[u32];          // in scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-            let mut _6: &mut u32;        // in scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-            let mut _7: *mut u32;        // in scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-            let mut _8: *mut [u32];      // in scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+            let mut _5: bool;            // in scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+            let mut _6: *mut [u32];      // in scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+            let mut _8: *mut u32;        // in scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+            let mut _9: &mut u32;        // in scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
             scope 3 {
                 scope 4 (inlined <usize as SliceIndex<[u32]>>::get_unchecked_mut) { // at $SRC_DIR/core/src/slice/index.rs:LL:COL
                     debug self => _2;    // in scope 4 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                    debug slice => _8;   // in scope 4 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                    let mut _9: *mut u32; // in scope 4 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+                    debug slice => _6;   // in scope 4 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+                    let mut _7: *mut u32; // in scope 4 at $SRC_DIR/core/src/slice/index.rs:LL:COL
                     let mut _10: usize;  // in scope 4 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
                     let mut _11: *mut [u32]; // in scope 4 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
                     scope 5 {
@@ -40,10 +40,10 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> {
                                 }
                             }
                             scope 11 (inlined ptr::mut_ptr::<impl *mut [u32]>::as_mut_ptr) { // at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                                debug self => _8; // in scope 11 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                debug self => _6; // in scope 11 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
                             }
                             scope 12 (inlined ptr::mut_ptr::<impl *mut u32>::add) { // at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                                debug self => _9; // in scope 12 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                debug self => _7; // in scope 12 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
                                 debug count => _2; // in scope 12 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
                                 scope 13 {
                                 }
@@ -56,50 +56,50 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> {
     }
 
     bb0: {
-        StorageLive(_6);                 // scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        StorageLive(_3);                 // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageLive(_4);                 // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        StorageLive(_9);                 // scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         StorageLive(_5);                 // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _5 = &(*_1);                     // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _4 = Len((*_5));                 // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _3 = Lt(_2, move _4);            // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        StorageLive(_4);                 // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        StorageLive(_3);                 // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        _3 = &(*_1);                     // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        _4 = Len((*_3));                 // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        StorageDead(_3);                 // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        _5 = Lt(_2, move _4);            // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
         StorageDead(_4);                 // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        switchInt(move _3) -> [0: bb2, otherwise: bb1]; // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        switchInt(move _5) -> [0: bb1, otherwise: bb2]; // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
     }
 
     bb1: {
-        StorageLive(_7);                 // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        _0 = const Option::<&mut u32>::None; // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+                                         // mir::Constant
+                                         // + span: no-location
+                                         // + literal: Const { ty: Option<&mut u32>, val: Value(Scalar(0x0000000000000000)) }
+        goto -> bb3;                     // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+    }
+
+    bb2: {
         StorageLive(_8);                 // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _8 = &raw mut (*_1);             // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        StorageLive(_6);                 // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        _6 = &raw mut (*_1);             // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
         StorageLive(_10);                // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
         StorageLive(_11);                // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
         StorageLive(_12);                // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageLive(_9);                 // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _9 = _8 as *mut u32 (PtrToPtr);  // scope 11 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-        _7 = Offset(_9, _2);             // scope 13 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-        StorageDead(_9);                 // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        StorageLive(_7);                 // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        _7 = _6 as *mut u32 (PtrToPtr);  // scope 11 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+        _8 = Offset(_7, _2);             // scope 13 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+        StorageDead(_7);                 // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
         StorageDead(_12);                // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
         StorageDead(_11);                // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
         StorageDead(_10);                // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageDead(_8);                 // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _6 = &mut (*_7);                 // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _0 = Option::<&mut u32>::Some(_6); // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageDead(_7);                 // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        goto -> bb3;                     // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-    }
-
-    bb2: {
-        _0 = const Option::<&mut u32>::None; // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                                         // mir::Constant
-                                         // + span: no-location
-                                         // + literal: Const { ty: Option<&mut u32>, val: Value(Scalar(0x0000000000000000)) }
+        StorageDead(_6);                 // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        _9 = &mut (*_8);                 // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        _0 = Option::<&mut u32>::Some(_9); // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        StorageDead(_8);                 // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
         goto -> bb3;                     // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
     }
 
     bb3: {
-        StorageDead(_3);                 // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageDead(_6);                 // scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        StorageDead(_9);                 // scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         return;                          // scope 0 at $DIR/slice_index.rs:+2:2: +2:2
     }
 }
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.mir
index 7a10b929ebd..6d9ec5d9a27 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.mir
@@ -8,61 +8,61 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range<usize>) ->
         debug self => _1;                // in scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         debug index => _2;               // in scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         let mut _3: *mut [u32];          // in scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        let mut _4: *mut [u32];          // in scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        let mut _15: *mut [u32];         // in scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         scope 2 {
             scope 3 (inlined <std::ops::Range<usize> as SliceIndex<[u32]>>::get_unchecked_mut) { // at $SRC_DIR/core/src/slice/mod.rs:LL:COL
                 debug self => _2;        // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                debug slice => _4;       // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                let _5: std::ops::Range<usize>; // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                let mut _7: usize;       // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+                debug slice => _3;       // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+                let mut _4: usize;       // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+                let mut _5: usize;       // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+                let mut _7: *mut u32;    // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
                 let mut _8: usize;       // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
                 let mut _9: *mut u32;    // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                let mut _10: *mut u32;   // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                let mut _11: usize;      // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                let mut _12: usize;      // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                let mut _13: std::ops::Range<usize>; // in scope 3 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
-                let mut _14: *mut [u32]; // in scope 3 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                let mut _10: usize;      // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+                let _16: std::ops::Range<usize>; // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+                let mut _17: std::ops::Range<usize>; // in scope 3 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                let mut _18: *mut [u32]; // in scope 3 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
                 scope 4 {
-                    debug this => _5;    // in scope 4 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+                    debug this => _16;   // in scope 4 at $SRC_DIR/core/src/slice/index.rs:LL:COL
                     scope 5 {
                         let _6: usize;   // in scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
                         scope 6 {
                             debug new_len => _6; // in scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
                             scope 11 (inlined ptr::mut_ptr::<impl *mut [u32]>::as_mut_ptr) { // at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                                debug self => _4; // in scope 11 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                debug self => _3; // in scope 11 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
                             }
                             scope 12 (inlined ptr::mut_ptr::<impl *mut u32>::add) { // at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                                debug self => _10; // in scope 12 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-                                debug count => _11; // in scope 12 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                debug self => _7; // in scope 12 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                debug count => _8; // in scope 12 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
                                 scope 13 {
                                 }
                             }
                             scope 14 (inlined slice_from_raw_parts_mut::<u32>) { // at $SRC_DIR/core/src/slice/index.rs:LL:COL
                                 debug data => _9; // in scope 14 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-                                debug len => _12; // in scope 14 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-                                let mut _16: *mut (); // in scope 14 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+                                debug len => _10; // in scope 14 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+                                let mut _11: *mut (); // in scope 14 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
                                 scope 15 (inlined ptr::mut_ptr::<impl *mut u32>::cast::<()>) { // at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
                                     debug self => _9; // in scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
                                 }
                                 scope 16 (inlined std::ptr::from_raw_parts_mut::<[u32]>) { // at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-                                    debug data_address => _16; // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-                                    debug metadata => _12; // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-                                    let mut _17: std::ptr::metadata::PtrRepr<[u32]>; // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-                                    let mut _18: std::ptr::metadata::PtrComponents<[u32]>; // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-                                    let mut _19: *const (); // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+                                    debug data_address => _11; // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+                                    debug metadata => _10; // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+                                    let mut _12: *const (); // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+                                    let mut _13: std::ptr::metadata::PtrComponents<[u32]>; // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+                                    let mut _14: std::ptr::metadata::PtrRepr<[u32]>; // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
                                     scope 17 {
                                     }
                                 }
                             }
                         }
                         scope 7 (inlined <std::ops::Range<usize> as SliceIndex<[T]>>::get_unchecked_mut::runtime::<u32>) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
-                            debug this => _13; // in scope 7 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
-                            debug slice => _14; // in scope 7 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                            debug this => _17; // in scope 7 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                            debug slice => _18; // in scope 7 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
                             scope 8 (inlined ptr::mut_ptr::<impl *mut [u32]>::len) { // at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                                debug self => _14; // in scope 8 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-                                let mut _15: *const [u32]; // in scope 8 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                debug self => _18; // in scope 8 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                let mut _19: *const [u32]; // in scope 8 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
                                 scope 9 (inlined std::ptr::metadata::<[u32]>) { // at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-                                    debug ptr => _15; // in scope 9 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+                                    debug ptr => _19; // in scope 9 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
                                     scope 10 {
                                     }
                                 }
@@ -75,60 +75,60 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range<usize>) ->
     }
 
     bb0: {
-        StorageLive(_3);                 // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        StorageLive(_4);                 // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        _4 = &raw mut (*_1);             // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        StorageLive(_5);                 // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        StorageLive(_13);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        StorageLive(_14);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         StorageLive(_15);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageLive(_3);                 // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        _3 = &raw mut (*_1);             // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageLive(_16);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageLive(_17);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageLive(_18);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageLive(_19);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         StorageLive(_6);                 // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageLive(_7);                 // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _7 = (_2.1: usize);              // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageLive(_8);                 // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _8 = (_2.0: usize);              // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _6 = unchecked_sub::<usize>(move _7, move _8) -> [return: bb1, unwind unreachable]; // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        StorageLive(_4);                 // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        _4 = (_2.1: usize);              // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        StorageLive(_5);                 // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        _5 = (_2.0: usize);              // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        _6 = unchecked_sub::<usize>(move _4, move _5) -> [return: bb1, unwind unreachable]; // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/slice/index.rs:LL:COL
                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(usize, usize) -> usize {unchecked_sub::<usize>}, val: Value(<ZST>) }
     }
 
     bb1: {
-        StorageDead(_8);                 // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageDead(_7);                 // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        StorageDead(_5);                 // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        StorageDead(_4);                 // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
         StorageLive(_9);                 // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        StorageLive(_7);                 // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        _7 = _3 as *mut u32 (PtrToPtr);  // scope 11 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+        StorageLive(_8);                 // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        _8 = (_2.0: usize);              // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        _9 = Offset(_7, _8);             // scope 13 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+        StorageDead(_8);                 // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        StorageDead(_7);                 // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
         StorageLive(_10);                // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _10 = _4 as *mut u32 (PtrToPtr); // scope 11 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-        StorageLive(_11);                // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _11 = (_2.0: usize);             // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _9 = Offset(_10, _11);           // scope 13 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-        StorageDead(_11);                // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        _10 = _6;                        // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        StorageLive(_11);                // scope 14 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+        _11 = _9 as *mut () (PtrToPtr);  // scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+        StorageLive(_14);                // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+        StorageLive(_13);                // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+        StorageLive(_12);                // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+        _12 = _11 as *const () (Pointer(MutToConstPointer)); // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+        _13 = ptr::metadata::PtrComponents::<[u32]> { data_address: move _12, metadata: _10 }; // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+        StorageDead(_12);                // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+        _14 = ptr::metadata::PtrRepr::<[u32]> { const_ptr: move _13 }; // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+        StorageDead(_13);                // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+        _15 = (_14.1: *mut [u32]);       // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+        StorageDead(_14);                // scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+        StorageDead(_11);                // scope 14 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
         StorageDead(_10);                // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageLive(_12);                // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _12 = _6;                        // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageLive(_16);                // scope 14 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-        _16 = _9 as *mut () (PtrToPtr);  // scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-        StorageLive(_17);                // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-        StorageLive(_18);                // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-        StorageLive(_19);                // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-        _19 = _16 as *const () (Pointer(MutToConstPointer)); // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-        _18 = ptr::metadata::PtrComponents::<[u32]> { data_address: move _19, metadata: _12 }; // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-        StorageDead(_19);                // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-        _17 = ptr::metadata::PtrRepr::<[u32]> { const_ptr: move _18 }; // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-        StorageDead(_18);                // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-        _3 = (_17.1: *mut [u32]);        // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-        StorageDead(_17);                // scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-        StorageDead(_16);                // scope 14 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-        StorageDead(_12);                // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
         StorageDead(_9);                 // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
         StorageDead(_6);                 // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageDead(_15);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        StorageDead(_14);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        StorageDead(_13);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        StorageDead(_4);                 // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        _0 = &mut (*_3);                 // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        StorageDead(_3);                 // scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageDead(_19);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageDead(_18);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageDead(_17);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageDead(_16);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageDead(_3);                 // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        _0 = &mut (*_15);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageDead(_15);                // scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         return;                          // scope 0 at $DIR/slice_index.rs:+2:2: +2:2
     }
 }
diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.mir
index 0da7e5536ae..0cf1d68d18a 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.mir
@@ -4,41 +4,41 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     debug slice => _1;                   // in scope 0 at $DIR/slice_iter.rs:+0:28: +0:33
     debug f => _2;                       // in scope 0 at $DIR/slice_iter.rs:+0:44: +0:45
     let mut _0: ();                      // return place in scope 0 at $DIR/slice_iter.rs:+0:60: +0:60
-    let mut _3: std::slice::Iter<'_, T>; // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
-    let mut _4: std::slice::Iter<'_, T>; // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
-    let _5: ();                          // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
-    let mut _6: std::option::Option<&T>; // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
-    let mut _7: &mut std::slice::Iter<'_, T>; // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
-    let mut _8: isize;                   // in scope 0 at $DIR/slice_iter.rs:+1:5: +3:6
-    let mut _10: &impl Fn(&T);           // in scope 0 at $DIR/slice_iter.rs:+2:9: +2:10
-    let mut _11: (&T,);                  // in scope 0 at $DIR/slice_iter.rs:+2:9: +2:13
+    let mut _13: std::slice::Iter<'_, T>; // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
+    let mut _14: std::slice::Iter<'_, T>; // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
+    let mut _15: &mut std::slice::Iter<'_, T>; // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
+    let mut _16: std::option::Option<&T>; // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
+    let mut _17: isize;                  // in scope 0 at $DIR/slice_iter.rs:+1:5: +3:6
+    let mut _19: &impl Fn(&T);           // in scope 0 at $DIR/slice_iter.rs:+2:9: +2:10
+    let mut _20: (&T,);                  // in scope 0 at $DIR/slice_iter.rs:+2:9: +2:13
+    let _21: ();                         // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
     scope 1 {
-        debug iter => _4;                // in scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
-        let _9: &T;                      // in scope 1 at $DIR/slice_iter.rs:+1:9: +1:10
+        debug iter => _14;               // in scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
+        let _18: &T;                     // in scope 1 at $DIR/slice_iter.rs:+1:9: +1:10
         scope 2 {
-            debug x => _9;               // in scope 2 at $DIR/slice_iter.rs:+1:9: +1:10
+            debug x => _18;              // in scope 2 at $DIR/slice_iter.rs:+1:9: +1:10
         }
     }
     scope 3 (inlined core::slice::<impl [T]>::iter) { // at $DIR/slice_iter.rs:28:20: 28:26
         debug self => _1;                // in scope 3 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         scope 4 (inlined std::slice::Iter::<'_, T>::new) { // at $SRC_DIR/core/src/slice/mod.rs:LL:COL
             debug slice => _1;           // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-            let _12: *const T;           // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-            let mut _14: bool;           // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-            let mut _15: usize;          // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-            let mut _16: usize;          // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-            let mut _17: std::ptr::NonNull<T>; // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-            let mut _18: *mut T;         // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-            let mut _19: *const T;       // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            let _4: *const T;            // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            let mut _5: bool;            // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            let mut _6: usize;           // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            let mut _8: usize;           // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            let mut _9: *mut T;          // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            let mut _11: std::ptr::NonNull<T>; // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            let mut _12: *const T;       // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
             scope 5 {
-                debug ptr => _12;        // in scope 5 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+                debug ptr => _4;         // in scope 5 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
                 scope 6 {
-                    let _13: *const T;   // in scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+                    let _7: *const T;    // in scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
                     scope 7 {
-                        debug end => _13; // in scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+                        debug end => _7; // in scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
                         scope 13 (inlined NonNull::<T>::new_unchecked) { // at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-                            debug ptr => _18; // in scope 13 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
-                            let mut _21: *const T; // in scope 13 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
+                            debug ptr => _9; // in scope 13 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
+                            let mut _10: *const T; // in scope 13 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
                             let mut _22: *mut T; // in scope 13 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
                             scope 14 {
                                 scope 15 (inlined NonNull::<T>::new_unchecked::runtime::<T>) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
@@ -65,13 +65,13 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
                         }
                     }
                     scope 9 (inlined invalid::<T>) { // at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-                        debug addr => _15; // in scope 9 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+                        debug addr => _8; // in scope 9 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
                         scope 10 {
                         }
                     }
                     scope 11 (inlined ptr::const_ptr::<impl *const T>::add) { // at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-                        debug self => _12; // in scope 11 at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-                        debug count => _16; // in scope 11 at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+                        debug self => _4; // in scope 11 at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+                        debug count => _6; // in scope 11 at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
                         scope 12 {
                         }
                     }
@@ -79,125 +79,125 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
             }
             scope 8 (inlined core::slice::<impl [T]>::as_ptr) { // at $SRC_DIR/core/src/slice/iter.rs:LL:COL
                 debug self => _1;        // in scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-                let mut _20: *const [T]; // in scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+                let mut _3: *const [T];  // in scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
             }
         }
     }
     scope 22 (inlined <std::slice::Iter<'_, T> as IntoIterator>::into_iter) { // at $DIR/slice_iter.rs:28:14: 28:26
-        debug self => _3;                // in scope 22 at $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+        debug self => _13;               // in scope 22 at $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
     }
 
     bb0: {
-        StorageLive(_12);                // scope 3 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        StorageLive(_20);                // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        _20 = &raw const (*_1);          // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        _12 = move _20 as *const T (PtrToPtr); // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        StorageDead(_20);                // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        StorageLive(_13);                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        StorageLive(_14);                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        _14 = const _;                   // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        switchInt(move _14) -> [0: bb11, otherwise: bb10]; // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_4);                 // scope 3 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageLive(_3);                 // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        _3 = &raw const (*_1);           // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        _4 = move _3 as *const T (PtrToPtr); // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageDead(_3);                 // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageLive(_7);                 // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_5);                 // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _5 = const _;                    // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        switchInt(move _5) -> [0: bb1, otherwise: bb2]; // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
     }
 
     bb1: {
-        StorageLive(_6);                 // scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
-        _7 = &mut _4;                    // scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
-        _6 = <std::slice::Iter<'_, T> as Iterator>::next(_7) -> [return: bb2, unwind: bb8]; // scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
-                                         // mir::Constant
-                                         // + span: $DIR/slice_iter.rs:28:14: 28:26
-                                         // + literal: Const { ty: for<'a> fn(&'a mut std::slice::Iter<'_, T>) -> Option<<std::slice::Iter<'_, T> as Iterator>::Item> {<std::slice::Iter<'_, T> as Iterator>::next}, val: Value(<ZST>) }
+        StorageLive(_6);                 // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _6 = Len((*_1));                 // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _7 = Offset(_4, _6);             // scope 12 at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+        StorageDead(_6);                 // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        goto -> bb3;                     // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
     }
 
     bb2: {
-        _8 = discriminant(_6);           // scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
-        switchInt(move _8) -> [0: bb5, 1: bb3, otherwise: bb4]; // scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
+        StorageLive(_8);                 // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _8 = Len((*_1));                 // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _7 = _8 as *const T (Transmute); // scope 10 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+        StorageDead(_8);                 // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        goto -> bb3;                     // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
     }
 
     bb3: {
-        _9 = ((_6 as Some).0: &T);       // scope 1 at $DIR/slice_iter.rs:+1:9: +1:10
-        StorageLive(_10);                // scope 2 at $DIR/slice_iter.rs:+2:9: +2:10
-        _10 = &_2;                       // scope 2 at $DIR/slice_iter.rs:+2:9: +2:10
-        StorageLive(_11);                // scope 2 at $DIR/slice_iter.rs:+2:9: +2:13
-        _11 = (_9,);                     // scope 2 at $DIR/slice_iter.rs:+2:9: +2:13
-        _5 = <impl Fn(&T) as Fn<(&T,)>>::call(move _10, move _11) -> [return: bb6, unwind: bb8]; // scope 2 at $DIR/slice_iter.rs:+2:9: +2:13
+        StorageDead(_5);                 // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_11);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_9);                 // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _9 = _4 as *mut T (PtrToPtr);    // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_10);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_22);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_23);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _10 = _9 as *const T (Pointer(MutToConstPointer)); // scope 14 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
+        _11 = NonNull::<T> { pointer: _10 }; // scope 14 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
+        StorageDead(_23);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageDead(_22);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageDead(_10);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageDead(_9);                 // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_12);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _12 = _7;                        // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _13 = std::slice::Iter::<'_, T> { ptr: move _11, end: move _12, _marker: const ZeroSized: PhantomData<&T> }; // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
                                          // mir::Constant
-                                         // + span: $DIR/slice_iter.rs:29:9: 29:10
-                                         // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a impl Fn(&T), (&T,)) -> <impl Fn(&T) as FnOnce<(&T,)>>::Output {<impl Fn(&T) as Fn<(&T,)>>::call}, val: Value(<ZST>) }
+                                         // + span: no-location
+                                         // + literal: Const { ty: PhantomData<&T>, val: Value(<ZST>) }
+                                         // adt
+                                         // + user_ty: UserType(1)
+        StorageDead(_12);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageDead(_11);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageDead(_7);                 // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageDead(_4);                 // scope 3 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageLive(_14);                // scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
+        _14 = move _13;                  // scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
+        goto -> bb4;                     // scope 1 at $DIR/slice_iter.rs:+1:5: +3:6
     }
 
     bb4: {
-        unreachable;                     // scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
+        StorageLive(_16);                // scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
+        _15 = &mut _14;                  // scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
+        _16 = <std::slice::Iter<'_, T> as Iterator>::next(_15) -> [return: bb5, unwind: bb11]; // scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
+                                         // mir::Constant
+                                         // + span: $DIR/slice_iter.rs:28:14: 28:26
+                                         // + literal: Const { ty: for<'a> fn(&'a mut std::slice::Iter<'_, T>) -> Option<<std::slice::Iter<'_, T> as Iterator>::Item> {<std::slice::Iter<'_, T> as Iterator>::next}, val: Value(<ZST>) }
     }
 
     bb5: {
-        StorageDead(_6);                 // scope 1 at $DIR/slice_iter.rs:+3:5: +3:6
-        StorageDead(_4);                 // scope 0 at $DIR/slice_iter.rs:+3:5: +3:6
-        drop(_2) -> bb7;                 // scope 0 at $DIR/slice_iter.rs:+4:1: +4:2
+        _17 = discriminant(_16);         // scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
+        switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10]; // scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
     }
 
     bb6: {
-        StorageDead(_11);                // scope 2 at $DIR/slice_iter.rs:+2:12: +2:13
-        StorageDead(_10);                // scope 2 at $DIR/slice_iter.rs:+2:12: +2:13
-        StorageDead(_6);                 // scope 1 at $DIR/slice_iter.rs:+3:5: +3:6
-        goto -> bb1;                     // scope 1 at $DIR/slice_iter.rs:+1:5: +3:6
+        StorageDead(_16);                // scope 1 at $DIR/slice_iter.rs:+3:5: +3:6
+        StorageDead(_14);                // scope 0 at $DIR/slice_iter.rs:+3:5: +3:6
+        drop(_2) -> bb7;                 // scope 0 at $DIR/slice_iter.rs:+4:1: +4:2
     }
 
     bb7: {
         return;                          // scope 0 at $DIR/slice_iter.rs:+4:2: +4:2
     }
 
-    bb8 (cleanup): {
-        drop(_2) -> [return: bb9, unwind terminate]; // scope 0 at $DIR/slice_iter.rs:+4:1: +4:2
+    bb8: {
+        _18 = ((_16 as Some).0: &T);     // scope 1 at $DIR/slice_iter.rs:+1:9: +1:10
+        StorageLive(_19);                // scope 2 at $DIR/slice_iter.rs:+2:9: +2:10
+        _19 = &_2;                       // scope 2 at $DIR/slice_iter.rs:+2:9: +2:10
+        StorageLive(_20);                // scope 2 at $DIR/slice_iter.rs:+2:9: +2:13
+        _20 = (_18,);                    // scope 2 at $DIR/slice_iter.rs:+2:9: +2:13
+        _21 = <impl Fn(&T) as Fn<(&T,)>>::call(move _19, move _20) -> [return: bb9, unwind: bb11]; // scope 2 at $DIR/slice_iter.rs:+2:9: +2:13
+                                         // mir::Constant
+                                         // + span: $DIR/slice_iter.rs:29:9: 29:10
+                                         // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a impl Fn(&T), (&T,)) -> <impl Fn(&T) as FnOnce<(&T,)>>::Output {<impl Fn(&T) as Fn<(&T,)>>::call}, val: Value(<ZST>) }
     }
 
-    bb9 (cleanup): {
-        resume;                          // scope 0 at $DIR/slice_iter.rs:+0:1: +4:2
+    bb9: {
+        StorageDead(_20);                // scope 2 at $DIR/slice_iter.rs:+2:12: +2:13
+        StorageDead(_19);                // scope 2 at $DIR/slice_iter.rs:+2:12: +2:13
+        StorageDead(_16);                // scope 1 at $DIR/slice_iter.rs:+3:5: +3:6
+        goto -> bb4;                     // scope 1 at $DIR/slice_iter.rs:+1:5: +3:6
     }
 
     bb10: {
-        StorageLive(_15);                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        _15 = Len((*_1));                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        _13 = _15 as *const T (Transmute); // scope 10 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-        StorageDead(_15);                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        goto -> bb12;                    // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        unreachable;                     // scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
     }
 
-    bb11: {
-        StorageLive(_16);                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        _16 = Len((*_1));                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        _13 = Offset(_12, _16);          // scope 12 at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-        StorageDead(_16);                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        goto -> bb12;                    // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+    bb11 (cleanup): {
+        drop(_2) -> [return: bb12, unwind terminate]; // scope 0 at $DIR/slice_iter.rs:+4:1: +4:2
     }
 
-    bb12: {
-        StorageDead(_14);                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        StorageLive(_17);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        StorageLive(_18);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        _18 = _12 as *mut T (PtrToPtr);  // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        StorageLive(_21);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        StorageLive(_22);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        StorageLive(_23);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        _21 = _18 as *const T (Pointer(MutToConstPointer)); // scope 14 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
-        _17 = NonNull::<T> { pointer: _21 }; // scope 14 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
-        StorageDead(_23);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        StorageDead(_22);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        StorageDead(_21);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        StorageDead(_18);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        StorageLive(_19);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        _19 = _13;                       // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        _3 = std::slice::Iter::<'_, T> { ptr: move _17, end: move _19, _marker: const ZeroSized: PhantomData<&T> }; // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-                                         // mir::Constant
-                                         // + span: no-location
-                                         // + literal: Const { ty: PhantomData<&T>, val: Value(<ZST>) }
-                                         // adt
-                                         // + user_ty: UserType(1)
-        StorageDead(_19);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        StorageDead(_17);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        StorageDead(_13);                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        StorageDead(_12);                // scope 3 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        StorageLive(_4);                 // scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
-        _4 = move _3;                    // scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
-        goto -> bb1;                     // scope 1 at $DIR/slice_iter.rs:+1:5: +3:6
+    bb12 (cleanup): {
+        resume;                          // scope 0 at $DIR/slice_iter.rs:+0:1: +4:2
     }
 }
diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.mir
index 45b41b54c8b..4fde50c6fe4 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.mir
@@ -4,61 +4,61 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     debug slice => _1;                   // in scope 0 at $DIR/slice_iter.rs:+0:28: +0:33
     debug f => _2;                       // in scope 0 at $DIR/slice_iter.rs:+0:44: +0:45
     let mut _0: ();                      // return place in scope 0 at $DIR/slice_iter.rs:+0:60: +0:60
-    let mut _3: std::iter::Rev<std::slice::Iter<'_, T>>; // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:32
-    let mut _4: std::slice::Iter<'_, T>; // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
-    let mut _5: std::iter::Rev<std::slice::Iter<'_, T>>; // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:32
-    let _6: ();                          // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:32
-    let mut _7: std::option::Option<&T>; // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:32
-    let mut _8: &mut std::iter::Rev<std::slice::Iter<'_, T>>; // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:32
-    let mut _9: isize;                   // in scope 0 at $DIR/slice_iter.rs:+1:5: +3:6
-    let mut _11: &impl Fn(&T);           // in scope 0 at $DIR/slice_iter.rs:+2:9: +2:10
-    let mut _12: (&T,);                  // in scope 0 at $DIR/slice_iter.rs:+2:9: +2:13
+    let mut _13: std::slice::Iter<'_, T>; // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
+    let mut _14: std::iter::Rev<std::slice::Iter<'_, T>>; // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:32
+    let mut _15: std::iter::Rev<std::slice::Iter<'_, T>>; // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:32
+    let mut _16: &mut std::iter::Rev<std::slice::Iter<'_, T>>; // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:32
+    let mut _18: std::option::Option<&T>; // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:32
+    let mut _19: isize;                  // in scope 0 at $DIR/slice_iter.rs:+1:5: +3:6
+    let mut _21: &impl Fn(&T);           // in scope 0 at $DIR/slice_iter.rs:+2:9: +2:10
+    let mut _22: (&T,);                  // in scope 0 at $DIR/slice_iter.rs:+2:9: +2:13
+    let _23: ();                         // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:32
     scope 1 {
-        debug iter => _5;                // in scope 1 at $DIR/slice_iter.rs:+1:14: +1:32
-        let _10: &T;                     // in scope 1 at $DIR/slice_iter.rs:+1:9: +1:10
+        debug iter => _15;               // in scope 1 at $DIR/slice_iter.rs:+1:14: +1:32
+        let _20: &T;                     // in scope 1 at $DIR/slice_iter.rs:+1:9: +1:10
         scope 2 {
-            debug x => _10;              // in scope 2 at $DIR/slice_iter.rs:+1:9: +1:10
+            debug x => _20;              // in scope 2 at $DIR/slice_iter.rs:+1:9: +1:10
         }
         scope 25 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) { // at $DIR/slice_iter.rs:35:14: 35:32
-            debug self => _8;            // in scope 25 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
-            let mut _25: &mut std::slice::Iter<'_, T>; // in scope 25 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
+            debug self => _16;           // in scope 25 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
+            let mut _17: &mut std::slice::Iter<'_, T>; // in scope 25 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
         }
     }
     scope 3 (inlined core::slice::<impl [T]>::iter) { // at $DIR/slice_iter.rs:35:20: 35:26
         debug self => _1;                // in scope 3 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         scope 4 (inlined std::slice::Iter::<'_, T>::new) { // at $SRC_DIR/core/src/slice/mod.rs:LL:COL
             debug slice => _1;           // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-            let _13: *const T;           // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-            let mut _15: bool;           // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-            let mut _16: usize;          // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-            let mut _17: usize;          // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-            let mut _18: std::ptr::NonNull<T>; // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-            let mut _19: *mut T;         // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-            let mut _20: *const T;       // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            let _4: *const T;            // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            let mut _5: bool;            // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            let mut _6: usize;           // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            let mut _8: usize;           // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            let mut _9: *mut T;          // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            let mut _11: std::ptr::NonNull<T>; // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            let mut _12: *const T;       // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
             scope 5 {
-                debug ptr => _13;        // in scope 5 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+                debug ptr => _4;         // in scope 5 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
                 scope 6 {
-                    let _14: *const T;   // in scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+                    let _7: *const T;    // in scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
                     scope 7 {
-                        debug end => _14; // in scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+                        debug end => _7; // in scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
                         scope 13 (inlined NonNull::<T>::new_unchecked) { // at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-                            debug ptr => _19; // in scope 13 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
-                            let mut _22: *const T; // in scope 13 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
-                            let mut _23: *mut T; // in scope 13 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                            debug ptr => _9; // in scope 13 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
+                            let mut _10: *const T; // in scope 13 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
+                            let mut _24: *mut T; // in scope 13 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
                             scope 14 {
                                 scope 15 (inlined NonNull::<T>::new_unchecked::runtime::<T>) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
-                                    debug ptr => _23; // in scope 15 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                                    debug ptr => _24; // in scope 15 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
                                     scope 16 (inlined ptr::mut_ptr::<impl *mut T>::is_null) { // at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
-                                        debug self => _23; // in scope 16 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-                                        let mut _24: *mut u8; // in scope 16 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                        debug self => _24; // in scope 16 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                        let mut _25: *mut u8; // in scope 16 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
                                         scope 17 {
                                             scope 18 (inlined ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) { // at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-                                                debug ptr => _24; // in scope 18 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                                debug ptr => _25; // in scope 18 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
                                                 scope 19 (inlined ptr::mut_ptr::<impl *mut u8>::addr) { // at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-                                                    debug self => _24; // in scope 19 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                                    debug self => _25; // in scope 19 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
                                                     scope 20 {
                                                         scope 21 (inlined ptr::mut_ptr::<impl *mut u8>::cast::<()>) { // at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-                                                            debug self => _24; // in scope 21 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                                            debug self => _25; // in scope 21 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
                                                         }
                                                     }
                                                 }
@@ -70,13 +70,13 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
                         }
                     }
                     scope 9 (inlined invalid::<T>) { // at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-                        debug addr => _16; // in scope 9 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+                        debug addr => _8; // in scope 9 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
                         scope 10 {
                         }
                     }
                     scope 11 (inlined ptr::const_ptr::<impl *const T>::add) { // at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-                        debug self => _13; // in scope 11 at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-                        debug count => _17; // in scope 11 at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+                        debug self => _4; // in scope 11 at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+                        debug count => _6; // in scope 11 at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
                         scope 12 {
                         }
                     }
@@ -84,137 +84,137 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
             }
             scope 8 (inlined core::slice::<impl [T]>::as_ptr) { // at $SRC_DIR/core/src/slice/iter.rs:LL:COL
                 debug self => _1;        // in scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-                let mut _21: *const [T]; // in scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+                let mut _3: *const [T];  // in scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
             }
         }
     }
     scope 22 (inlined <std::slice::Iter<'_, T> as Iterator>::rev) { // at $DIR/slice_iter.rs:35:27: 35:32
-        debug self => _4;                // in scope 22 at $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+        debug self => _13;               // in scope 22 at $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
         scope 23 (inlined Rev::<std::slice::Iter<'_, T>>::new) { // at $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-            debug iter => _4;            // in scope 23 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
+            debug iter => _13;           // in scope 23 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
         }
     }
     scope 24 (inlined <Rev<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) { // at $DIR/slice_iter.rs:35:14: 35:32
-        debug self => _3;                // in scope 24 at $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+        debug self => _14;               // in scope 24 at $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
     }
 
     bb0: {
-        StorageLive(_4);                 // scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
-        StorageLive(_13);                // scope 3 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        StorageLive(_21);                // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        _21 = &raw const (*_1);          // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        _13 = move _21 as *const T (PtrToPtr); // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        StorageDead(_21);                // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        StorageLive(_14);                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        StorageLive(_15);                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        _15 = const _;                   // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        switchInt(move _15) -> [0: bb10, otherwise: bb9]; // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_13);                // scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
+        StorageLive(_4);                 // scope 3 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageLive(_3);                 // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        _3 = &raw const (*_1);           // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        _4 = move _3 as *const T (PtrToPtr); // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageDead(_3);                 // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageLive(_7);                 // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_5);                 // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _5 = const _;                    // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        switchInt(move _5) -> [0: bb1, otherwise: bb2]; // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
     }
 
     bb1: {
-        StorageLive(_7);                 // scope 1 at $DIR/slice_iter.rs:+1:14: +1:32
-        _8 = &mut _5;                    // scope 1 at $DIR/slice_iter.rs:+1:14: +1:32
-        StorageLive(_25);                // scope 25 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
-        _25 = &mut ((*_8).0: std::slice::Iter<'_, T>); // scope 25 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
-        _7 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _25) -> [return: bb12, unwind: bb7]; // scope 25 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
-                                         // mir::Constant
-                                         // + span: $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
-                                         // + literal: Const { ty: for<'a> fn(&'a mut std::slice::Iter<'_, T>) -> Option<<std::slice::Iter<'_, T> as Iterator>::Item> {<std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back}, val: Value(<ZST>) }
+        StorageLive(_6);                 // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _6 = Len((*_1));                 // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _7 = Offset(_4, _6);             // scope 12 at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+        StorageDead(_6);                 // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        goto -> bb3;                     // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
     }
 
     bb2: {
-        _10 = ((_7 as Some).0: &T);      // scope 1 at $DIR/slice_iter.rs:+1:9: +1:10
-        StorageLive(_11);                // scope 2 at $DIR/slice_iter.rs:+2:9: +2:10
-        _11 = &_2;                       // scope 2 at $DIR/slice_iter.rs:+2:9: +2:10
-        StorageLive(_12);                // scope 2 at $DIR/slice_iter.rs:+2:9: +2:13
-        _12 = (_10,);                    // scope 2 at $DIR/slice_iter.rs:+2:9: +2:13
-        _6 = <impl Fn(&T) as Fn<(&T,)>>::call(move _11, move _12) -> [return: bb5, unwind: bb7]; // scope 2 at $DIR/slice_iter.rs:+2:9: +2:13
-                                         // mir::Constant
-                                         // + span: $DIR/slice_iter.rs:36:9: 36:10
-                                         // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a impl Fn(&T), (&T,)) -> <impl Fn(&T) as FnOnce<(&T,)>>::Output {<impl Fn(&T) as Fn<(&T,)>>::call}, val: Value(<ZST>) }
+        StorageLive(_8);                 // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _8 = Len((*_1));                 // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _7 = _8 as *const T (Transmute); // scope 10 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+        StorageDead(_8);                 // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        goto -> bb3;                     // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
     }
 
     bb3: {
-        unreachable;                     // scope 1 at $DIR/slice_iter.rs:+1:14: +1:32
+        StorageDead(_5);                 // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_11);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_9);                 // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _9 = _4 as *mut T (PtrToPtr);    // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_10);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_24);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_25);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _10 = _9 as *const T (Pointer(MutToConstPointer)); // scope 14 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
+        _11 = NonNull::<T> { pointer: _10 }; // scope 14 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
+        StorageDead(_25);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageDead(_24);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageDead(_10);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageDead(_9);                 // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_12);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _12 = _7;                        // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _13 = std::slice::Iter::<'_, T> { ptr: move _11, end: move _12, _marker: const ZeroSized: PhantomData<&T> }; // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+                                         // mir::Constant
+                                         // + span: no-location
+                                         // + literal: Const { ty: PhantomData<&T>, val: Value(<ZST>) }
+                                         // adt
+                                         // + user_ty: UserType(1)
+        StorageDead(_12);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageDead(_11);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageDead(_7);                 // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageDead(_4);                 // scope 3 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        _14 = Rev::<std::slice::Iter<'_, T>> { iter: move _13 }; // scope 23 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
+        StorageDead(_13);                // scope 0 at $DIR/slice_iter.rs:+1:31: +1:32
+        StorageLive(_15);                // scope 0 at $DIR/slice_iter.rs:+1:14: +1:32
+        _15 = move _14;                  // scope 0 at $DIR/slice_iter.rs:+1:14: +1:32
+        goto -> bb4;                     // scope 1 at $DIR/slice_iter.rs:+1:5: +3:6
     }
 
     bb4: {
-        StorageDead(_7);                 // scope 1 at $DIR/slice_iter.rs:+3:5: +3:6
-        StorageDead(_5);                 // scope 0 at $DIR/slice_iter.rs:+3:5: +3:6
-        drop(_2) -> bb6;                 // scope 0 at $DIR/slice_iter.rs:+4:1: +4:2
+        StorageLive(_18);                // scope 1 at $DIR/slice_iter.rs:+1:14: +1:32
+        _16 = &mut _15;                  // scope 1 at $DIR/slice_iter.rs:+1:14: +1:32
+        StorageLive(_17);                // scope 25 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
+        _17 = &mut ((*_16).0: std::slice::Iter<'_, T>); // scope 25 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
+        _18 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _17) -> [return: bb5, unwind: bb11]; // scope 25 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
+                                         // mir::Constant
+                                         // + span: $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
+                                         // + literal: Const { ty: for<'a> fn(&'a mut std::slice::Iter<'_, T>) -> Option<<std::slice::Iter<'_, T> as Iterator>::Item> {<std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back}, val: Value(<ZST>) }
     }
 
     bb5: {
-        StorageDead(_12);                // scope 2 at $DIR/slice_iter.rs:+2:12: +2:13
-        StorageDead(_11);                // scope 2 at $DIR/slice_iter.rs:+2:12: +2:13
-        StorageDead(_7);                 // scope 1 at $DIR/slice_iter.rs:+3:5: +3:6
-        goto -> bb1;                     // scope 1 at $DIR/slice_iter.rs:+1:5: +3:6
+        StorageDead(_17);                // scope 25 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
+        _19 = discriminant(_18);         // scope 1 at $DIR/slice_iter.rs:+1:14: +1:32
+        switchInt(move _19) -> [0: bb6, 1: bb8, otherwise: bb10]; // scope 1 at $DIR/slice_iter.rs:+1:14: +1:32
     }
 
     bb6: {
-        return;                          // scope 0 at $DIR/slice_iter.rs:+4:2: +4:2
+        StorageDead(_18);                // scope 1 at $DIR/slice_iter.rs:+3:5: +3:6
+        StorageDead(_15);                // scope 0 at $DIR/slice_iter.rs:+3:5: +3:6
+        drop(_2) -> bb7;                 // scope 0 at $DIR/slice_iter.rs:+4:1: +4:2
     }
 
-    bb7 (cleanup): {
-        drop(_2) -> [return: bb8, unwind terminate]; // scope 0 at $DIR/slice_iter.rs:+4:1: +4:2
+    bb7: {
+        return;                          // scope 0 at $DIR/slice_iter.rs:+4:2: +4:2
     }
 
-    bb8 (cleanup): {
-        resume;                          // scope 0 at $DIR/slice_iter.rs:+0:1: +4:2
+    bb8: {
+        _20 = ((_18 as Some).0: &T);     // scope 1 at $DIR/slice_iter.rs:+1:9: +1:10
+        StorageLive(_21);                // scope 2 at $DIR/slice_iter.rs:+2:9: +2:10
+        _21 = &_2;                       // scope 2 at $DIR/slice_iter.rs:+2:9: +2:10
+        StorageLive(_22);                // scope 2 at $DIR/slice_iter.rs:+2:9: +2:13
+        _22 = (_20,);                    // scope 2 at $DIR/slice_iter.rs:+2:9: +2:13
+        _23 = <impl Fn(&T) as Fn<(&T,)>>::call(move _21, move _22) -> [return: bb9, unwind: bb11]; // scope 2 at $DIR/slice_iter.rs:+2:9: +2:13
+                                         // mir::Constant
+                                         // + span: $DIR/slice_iter.rs:36:9: 36:10
+                                         // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a impl Fn(&T), (&T,)) -> <impl Fn(&T) as FnOnce<(&T,)>>::Output {<impl Fn(&T) as Fn<(&T,)>>::call}, val: Value(<ZST>) }
     }
 
     bb9: {
-        StorageLive(_16);                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        _16 = Len((*_1));                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        _14 = _16 as *const T (Transmute); // scope 10 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-        StorageDead(_16);                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        goto -> bb11;                    // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageDead(_22);                // scope 2 at $DIR/slice_iter.rs:+2:12: +2:13
+        StorageDead(_21);                // scope 2 at $DIR/slice_iter.rs:+2:12: +2:13
+        StorageDead(_18);                // scope 1 at $DIR/slice_iter.rs:+3:5: +3:6
+        goto -> bb4;                     // scope 1 at $DIR/slice_iter.rs:+1:5: +3:6
     }
 
     bb10: {
-        StorageLive(_17);                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        _17 = Len((*_1));                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        _14 = Offset(_13, _17);          // scope 12 at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-        StorageDead(_17);                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        goto -> bb11;                    // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        unreachable;                     // scope 1 at $DIR/slice_iter.rs:+1:14: +1:32
     }
 
-    bb11: {
-        StorageDead(_15);                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        StorageLive(_18);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        StorageLive(_19);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        _19 = _13 as *mut T (PtrToPtr);  // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        StorageLive(_22);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        StorageLive(_23);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        StorageLive(_24);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        _22 = _19 as *const T (Pointer(MutToConstPointer)); // scope 14 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
-        _18 = NonNull::<T> { pointer: _22 }; // scope 14 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
-        StorageDead(_24);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        StorageDead(_23);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        StorageDead(_22);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        StorageDead(_19);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        StorageLive(_20);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        _20 = _14;                       // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        _4 = std::slice::Iter::<'_, T> { ptr: move _18, end: move _20, _marker: const ZeroSized: PhantomData<&T> }; // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-                                         // mir::Constant
-                                         // + span: no-location
-                                         // + literal: Const { ty: PhantomData<&T>, val: Value(<ZST>) }
-                                         // adt
-                                         // + user_ty: UserType(1)
-        StorageDead(_20);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        StorageDead(_18);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        StorageDead(_14);                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        StorageDead(_13);                // scope 3 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        _3 = Rev::<std::slice::Iter<'_, T>> { iter: move _4 }; // scope 23 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
-        StorageDead(_4);                 // scope 0 at $DIR/slice_iter.rs:+1:31: +1:32
-        StorageLive(_5);                 // scope 0 at $DIR/slice_iter.rs:+1:14: +1:32
-        _5 = move _3;                    // scope 0 at $DIR/slice_iter.rs:+1:14: +1:32
-        goto -> bb1;                     // scope 1 at $DIR/slice_iter.rs:+1:5: +3:6
+    bb11 (cleanup): {
+        drop(_2) -> [return: bb12, unwind terminate]; // scope 0 at $DIR/slice_iter.rs:+4:1: +4:2
     }
 
-    bb12: {
-        StorageDead(_25);                // scope 25 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
-        _9 = discriminant(_7);           // scope 1 at $DIR/slice_iter.rs:+1:14: +1:32
-        switchInt(move _9) -> [0: bb4, 1: bb2, otherwise: bb3]; // scope 1 at $DIR/slice_iter.rs:+1:14: +1:32
+    bb12 (cleanup): {
+        resume;                          // scope 0 at $DIR/slice_iter.rs:+0:1: +4:2
     }
 }
diff --git a/tests/mir-opt/pre-codegen/try_identity.new.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/try_identity.new.PreCodegen.after.mir
index 53971b4cffc..c3f8745b422 100644
--- a/tests/mir-opt/pre-codegen/try_identity.new.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/try_identity.new.PreCodegen.after.mir
@@ -3,15 +3,15 @@
 fn new(_1: Result<T, E>) -> Result<T, E> {
     debug x => _1;                       // in scope 0 at $DIR/try_identity.rs:+0:14: +0:15
     let mut _0: std::result::Result<T, E>; // return place in scope 0 at $DIR/try_identity.rs:+0:34: +0:46
-    let mut _2: std::ops::ControlFlow<E, T>; // in scope 0 at $DIR/try_identity.rs:+2:15: +7:10
-    let mut _3: isize;                   // in scope 0 at $DIR/try_identity.rs:+4:17: +4:22
-    let _4: T;                           // in scope 0 at $DIR/try_identity.rs:+4:20: +4:21
+    let mut _2: isize;                   // in scope 0 at $DIR/try_identity.rs:+4:17: +4:22
+    let _3: T;                           // in scope 0 at $DIR/try_identity.rs:+4:20: +4:21
+    let mut _4: std::ops::ControlFlow<E, T>; // in scope 0 at $DIR/try_identity.rs:+2:15: +7:10
     let _5: E;                           // in scope 0 at $DIR/try_identity.rs:+5:21: +5:22
     let mut _6: isize;                   // in scope 0 at $DIR/try_identity.rs:+8:13: +8:37
     let _7: T;                           // in scope 0 at $DIR/try_identity.rs:+8:35: +8:36
     let _8: E;                           // in scope 0 at $DIR/try_identity.rs:+9:32: +9:33
     scope 1 {
-        debug v => _4;                   // in scope 1 at $DIR/try_identity.rs:+4:20: +4:21
+        debug v => _3;                   // in scope 1 at $DIR/try_identity.rs:+4:20: +4:21
     }
     scope 2 {
         debug e => _5;                   // in scope 2 at $DIR/try_identity.rs:+5:21: +5:22
@@ -24,47 +24,47 @@ fn new(_1: Result<T, E>) -> Result<T, E> {
     }
 
     bb0: {
-        StorageLive(_2);                 // scope 0 at $DIR/try_identity.rs:+2:15: +7:10
-        _3 = discriminant(_1);           // scope 0 at $DIR/try_identity.rs:+3:19: +3:20
-        switchInt(move _3) -> [0: bb3, 1: bb1, otherwise: bb2]; // scope 0 at $DIR/try_identity.rs:+3:13: +3:20
+        StorageLive(_4);                 // scope 0 at $DIR/try_identity.rs:+2:15: +7:10
+        _2 = discriminant(_1);           // scope 0 at $DIR/try_identity.rs:+3:19: +3:20
+        switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb7]; // scope 0 at $DIR/try_identity.rs:+3:13: +3:20
     }
 
     bb1: {
-        _5 = move ((_1 as Err).0: E);    // scope 0 at $DIR/try_identity.rs:+5:21: +5:22
-        _2 = ControlFlow::<E, T>::Break(move _5); // scope 2 at $DIR/try_identity.rs:+5:27: +5:48
-        goto -> bb4;                     // scope 0 at $DIR/try_identity.rs:+5:47: +5:48
+        _3 = move ((_1 as Ok).0: T);     // scope 0 at $DIR/try_identity.rs:+4:20: +4:21
+        _4 = ControlFlow::<E, T>::Continue(move _3); // scope 1 at $DIR/try_identity.rs:+4:26: +4:50
+        goto -> bb3;                     // scope 0 at $DIR/try_identity.rs:+4:49: +4:50
     }
 
     bb2: {
-        unreachable;                     // scope 0 at $DIR/try_identity.rs:+3:19: +3:20
+        _5 = move ((_1 as Err).0: E);    // scope 0 at $DIR/try_identity.rs:+5:21: +5:22
+        _4 = ControlFlow::<E, T>::Break(move _5); // scope 2 at $DIR/try_identity.rs:+5:27: +5:48
+        goto -> bb3;                     // scope 0 at $DIR/try_identity.rs:+5:47: +5:48
     }
 
     bb3: {
-        _4 = move ((_1 as Ok).0: T);     // scope 0 at $DIR/try_identity.rs:+4:20: +4:21
-        _2 = ControlFlow::<E, T>::Continue(move _4); // scope 1 at $DIR/try_identity.rs:+4:26: +4:50
-        goto -> bb4;                     // scope 0 at $DIR/try_identity.rs:+4:49: +4:50
+        _6 = discriminant(_4);           // scope 0 at $DIR/try_identity.rs:+2:15: +7:10
+        switchInt(move _6) -> [0: bb4, 1: bb5, otherwise: bb7]; // scope 0 at $DIR/try_identity.rs:+2:9: +7:10
     }
 
     bb4: {
-        _6 = discriminant(_2);           // scope 0 at $DIR/try_identity.rs:+2:15: +7:10
-        switchInt(move _6) -> [0: bb6, 1: bb5, otherwise: bb2]; // scope 0 at $DIR/try_identity.rs:+2:9: +7:10
+        _7 = move ((_4 as Continue).0: T); // scope 0 at $DIR/try_identity.rs:+8:35: +8:36
+        _0 = Result::<T, E>::Ok(move _7); // scope 0 at $DIR/try_identity.rs:+1:5: +11:6
+        StorageDead(_4);                 // scope 0 at $DIR/try_identity.rs:+12:1: +12:2
+        goto -> bb6;                     // scope 0 at $DIR/try_identity.rs:+12:1: +12:2
     }
 
     bb5: {
-        _8 = move ((_2 as Break).0: E);  // scope 0 at $DIR/try_identity.rs:+9:32: +9:33
+        _8 = move ((_4 as Break).0: E);  // scope 0 at $DIR/try_identity.rs:+9:32: +9:33
         _0 = Result::<T, E>::Err(move _8); // scope 4 at $DIR/try_identity.rs:+9:45: +9:51
-        StorageDead(_2);                 // scope 0 at $DIR/try_identity.rs:+12:1: +12:2
-        goto -> bb7;                     // scope 0 at $DIR/try_identity.rs:+12:1: +12:2
+        StorageDead(_4);                 // scope 0 at $DIR/try_identity.rs:+12:1: +12:2
+        goto -> bb6;                     // scope 0 at $DIR/try_identity.rs:+12:1: +12:2
     }
 
     bb6: {
-        _7 = move ((_2 as Continue).0: T); // scope 0 at $DIR/try_identity.rs:+8:35: +8:36
-        _0 = Result::<T, E>::Ok(move _7); // scope 0 at $DIR/try_identity.rs:+1:5: +11:6
-        StorageDead(_2);                 // scope 0 at $DIR/try_identity.rs:+12:1: +12:2
-        goto -> bb7;                     // scope 0 at $DIR/try_identity.rs:+12:1: +12:2
+        return;                          // scope 0 at $DIR/try_identity.rs:+12:2: +12:2
     }
 
     bb7: {
-        return;                          // scope 0 at $DIR/try_identity.rs:+12:2: +12:2
+        unreachable;                     // scope 0 at $DIR/try_identity.rs:+3:19: +3:20
     }
 }
diff --git a/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir
index e217d19947f..0487c6c3994 100644
--- a/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir
@@ -15,26 +15,26 @@ fn old(_1: Result<T, E>) -> Result<T, E> {
 
     bb0: {
         _2 = discriminant(_1);           // scope 0 at $DIR/try_identity.rs:+2:15: +2:16
-        switchInt(move _2) -> [0: bb3, 1: bb1, otherwise: bb2]; // scope 0 at $DIR/try_identity.rs:+2:9: +2:16
+        switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb4]; // scope 0 at $DIR/try_identity.rs:+2:9: +2:16
     }
 
     bb1: {
-        _4 = move ((_1 as Err).0: E);    // scope 0 at $DIR/try_identity.rs:+4:17: +4:18
-        _0 = Result::<T, E>::Err(move _4); // scope 2 at $DIR/try_identity.rs:+4:30: +4:36
-        goto -> bb4;                     // scope 0 at $DIR/try_identity.rs:+7:1: +7:2
+        _3 = move ((_1 as Ok).0: T);     // scope 0 at $DIR/try_identity.rs:+3:16: +3:17
+        _0 = Result::<T, E>::Ok(move _3); // scope 0 at $DIR/try_identity.rs:+1:5: +6:6
+        goto -> bb3;                     // scope 0 at $DIR/try_identity.rs:+7:1: +7:2
     }
 
     bb2: {
-        unreachable;                     // scope 0 at $DIR/try_identity.rs:+2:15: +2:16
+        _4 = move ((_1 as Err).0: E);    // scope 0 at $DIR/try_identity.rs:+4:17: +4:18
+        _0 = Result::<T, E>::Err(move _4); // scope 2 at $DIR/try_identity.rs:+4:30: +4:36
+        goto -> bb3;                     // scope 0 at $DIR/try_identity.rs:+7:1: +7:2
     }
 
     bb3: {
-        _3 = move ((_1 as Ok).0: T);     // scope 0 at $DIR/try_identity.rs:+3:16: +3:17
-        _0 = Result::<T, E>::Ok(move _3); // scope 0 at $DIR/try_identity.rs:+1:5: +6:6
-        goto -> bb4;                     // scope 0 at $DIR/try_identity.rs:+7:1: +7:2
+        return;                          // scope 0 at $DIR/try_identity.rs:+7:2: +7:2
     }
 
     bb4: {
-        return;                          // scope 0 at $DIR/try_identity.rs:+7:2: +7:2
+        unreachable;                     // scope 0 at $DIR/try_identity.rs:+2:15: +2:16
     }
 }
diff --git a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.diff b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.diff
index f908e8dd0c1..0b9ca29cedd 100644
--- a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.diff
+++ b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.diff
@@ -8,8 +8,6 @@
       let mut _3: std::option::Option<T>;  // in scope 0 at $DIR/simplify_locals_fixedpoint.rs:+1:51: +1:68
       let mut _4: isize;                   // in scope 0 at $DIR/simplify_locals_fixedpoint.rs:+1:22: +1:26
       let mut _5: isize;                   // in scope 0 at $DIR/simplify_locals_fixedpoint.rs:+1:13: +1:20
--     let mut _7: bool;                    // in scope 0 at $DIR/simplify_locals_fixedpoint.rs:+2:12: +2:20
--     let mut _8: u8;                      // in scope 0 at $DIR/simplify_locals_fixedpoint.rs:+2:12: +2:13
       scope 1 {
           debug a => _6;                   // in scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:18: +1:19
           let _6: u8;                      // in scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:18: +1:19
@@ -34,10 +32,9 @@
       }
   
       bb2: {
+          StorageLive(_6);                 // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:18: +1:19
           _6 = (((_1.0: std::option::Option<u8>) as Some).0: u8); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:18: +1:19
--         StorageLive(_7);                 // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+2:12: +2:20
--         _7 = Gt(_6, const 42_u8);        // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+2:12: +2:20
--         StorageDead(_7);                 // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+4:9: +4:10
+          StorageDead(_6);                 // scope 0 at $DIR/simplify_locals_fixedpoint.rs:+5:5: +5:6
           goto -> bb3;                     // scope 0 at $DIR/simplify_locals_fixedpoint.rs:+1:5: +5:6
       }
   
diff --git a/tests/mir-opt/switch_to_self.rs b/tests/mir-opt/switch_to_self.rs
new file mode 100644
index 00000000000..6678e4b3bd2
--- /dev/null
+++ b/tests/mir-opt/switch_to_self.rs
@@ -0,0 +1,21 @@
+// Test that MatchBranchSimplification doesn't ICE on a SwitchInt where
+// one of the targets is the block that the SwitchInt terminates.
+#![crate_type = "lib"]
+#![feature(core_intrinsics, custom_mir)]
+use std::intrinsics::mir::*;
+
+// EMIT_MIR switch_to_self.test.MatchBranchSimplification.diff
+#[custom_mir(dialect = "runtime", phase = "post-cleanup")]
+pub fn test(x: bool) {
+    mir!(
+        {
+            Goto(bb0)
+        }
+        bb0 = {
+            match x { false => bb0, _ => bb1 }
+        }
+        bb1 = {
+            match x { false => bb0, _ => bb1 }
+        }
+    )
+}
diff --git a/tests/mir-opt/switch_to_self.test.MatchBranchSimplification.diff b/tests/mir-opt/switch_to_self.test.MatchBranchSimplification.diff
new file mode 100644
index 00000000000..b0a4f9f0188
--- /dev/null
+++ b/tests/mir-opt/switch_to_self.test.MatchBranchSimplification.diff
@@ -0,0 +1,19 @@
+- // MIR for `test` before MatchBranchSimplification
++ // MIR for `test` after MatchBranchSimplification
+  
+  fn test(_1: bool) -> () {
+      let mut _0: ();                      // return place in scope 0 at $DIR/switch_to_self.rs:+0:22: +0:22
+  
+      bb0: {
+          goto -> bb1;                     // scope 0 at $DIR/switch_to_self.rs:+3:13: +3:22
+      }
+  
+      bb1: {
+          switchInt(_1) -> [0: bb1, otherwise: bb2]; // scope 0 at $DIR/switch_to_self.rs:+6:13: +6:47
+      }
+  
+      bb2: {
+          switchInt(_1) -> [0: bb1, otherwise: bb2]; // scope 0 at $DIR/switch_to_self.rs:+9:13: +9:47
+      }
+  }
+  
diff --git a/tests/mir-opt/tls_access.main.PreCodegen.after.mir b/tests/mir-opt/tls_access.main.PreCodegen.after.mir
index 09453b8ba9c..03618ae2814 100644
--- a/tests/mir-opt/tls_access.main.PreCodegen.after.mir
+++ b/tests/mir-opt/tls_access.main.PreCodegen.after.mir
@@ -2,27 +2,27 @@
 
 fn main() -> () {
     let mut _0: ();                      // return place in scope 0 at $DIR/tls_access.rs:+0:11: +0:11
-    let _2: *mut u8;                     // in scope 0 at $DIR/tls_access.rs:+2:18: +2:21
+    let _1: *mut u8;                     // in scope 0 at $DIR/tls_access.rs:+2:18: +2:21
     let mut _3: *mut u8;                 // in scope 0 at $DIR/tls_access.rs:+3:9: +3:12
     scope 1 {
-        let _1: &u8;                     // in scope 1 at $DIR/tls_access.rs:+2:13: +2:14
+        let _2: &u8;                     // in scope 1 at $DIR/tls_access.rs:+2:13: +2:14
         scope 2 {
-            debug a => _1;               // in scope 2 at $DIR/tls_access.rs:+2:13: +2:14
+            debug a => _2;               // in scope 2 at $DIR/tls_access.rs:+2:13: +2:14
         }
     }
 
     bb0: {
-        StorageLive(_1);                 // scope 1 at $DIR/tls_access.rs:+2:13: +2:14
-        StorageLive(_2);                 // scope 1 at $DIR/tls_access.rs:+2:18: +2:21
-        _2 = &/*tls*/ mut FOO;           // scope 1 at $DIR/tls_access.rs:+2:18: +2:21
-        _1 = &(*_2);                     // scope 1 at $DIR/tls_access.rs:+2:17: +2:21
+        StorageLive(_2);                 // scope 1 at $DIR/tls_access.rs:+2:13: +2:14
+        StorageLive(_1);                 // scope 1 at $DIR/tls_access.rs:+2:18: +2:21
+        _1 = &/*tls*/ mut FOO;           // scope 1 at $DIR/tls_access.rs:+2:18: +2:21
+        _2 = &(*_1);                     // scope 1 at $DIR/tls_access.rs:+2:17: +2:21
         StorageLive(_3);                 // scope 2 at $DIR/tls_access.rs:+3:9: +3:12
         _3 = &/*tls*/ mut FOO;           // scope 2 at $DIR/tls_access.rs:+3:9: +3:12
         (*_3) = const 42_u8;             // scope 2 at $DIR/tls_access.rs:+3:9: +3:17
         StorageDead(_3);                 // scope 2 at $DIR/tls_access.rs:+3:17: +3:18
         _0 = const ();                   // scope 1 at $DIR/tls_access.rs:+1:5: +4:6
-        StorageDead(_2);                 // scope 1 at $DIR/tls_access.rs:+4:5: +4:6
         StorageDead(_1);                 // scope 1 at $DIR/tls_access.rs:+4:5: +4:6
+        StorageDead(_2);                 // scope 1 at $DIR/tls_access.rs:+4:5: +4:6
         return;                          // scope 0 at $DIR/tls_access.rs:+5:2: +5:2
     }
 }
diff --git a/tests/mir-opt/while_storage.while_loop.PreCodegen.after.mir b/tests/mir-opt/while_storage.while_loop.PreCodegen.after.mir
index 811789a60c3..8922eda07ac 100644
--- a/tests/mir-opt/while_storage.while_loop.PreCodegen.after.mir
+++ b/tests/mir-opt/while_storage.while_loop.PreCodegen.after.mir
@@ -31,18 +31,18 @@ fn while_loop(_1: bool) -> () {
     }
 
     bb4: {
-        switchInt(move _3) -> [0: bb6, otherwise: bb5]; // scope 0 at $DIR/while_storage.rs:+2:12: +2:23
+        switchInt(move _3) -> [0: bb5, otherwise: bb6]; // scope 0 at $DIR/while_storage.rs:+2:12: +2:23
     }
 
     bb5: {
         StorageDead(_3);                 // scope 0 at $DIR/while_storage.rs:+4:9: +4:10
-        goto -> bb7;                     // scope 0 at no-location
+        StorageDead(_2);                 // scope 0 at $DIR/while_storage.rs:+5:5: +5:6
+        goto -> bb1;                     // scope 0 at $DIR/while_storage.rs:+1:5: +5:6
     }
 
     bb6: {
         StorageDead(_3);                 // scope 0 at $DIR/while_storage.rs:+4:9: +4:10
-        StorageDead(_2);                 // scope 0 at $DIR/while_storage.rs:+5:5: +5:6
-        goto -> bb1;                     // scope 0 at $DIR/while_storage.rs:+1:5: +5:6
+        goto -> bb7;                     // scope 0 at no-location
     }
 
     bb7: {
diff --git a/tests/rustdoc-gui/search-result-display.goml b/tests/rustdoc-gui/search-result-display.goml
index ee5598e4b21..bf096f62c48 100644
--- a/tests/rustdoc-gui/search-result-display.goml
+++ b/tests/rustdoc-gui/search-result-display.goml
@@ -57,22 +57,22 @@ define-function: (
 
 call-function: ("check-filter", {
     "theme": "ayu",
-    "border": "rgb(92, 103, 115)",
+    "border": "#5c6773",
     "filter": "invert(0.41) sepia(0.12) saturate(4.87) hue-rotate(171deg) brightness(0.94) contrast(0.94)",
-    "hover_border": "rgb(224, 224, 224)",
+    "hover_border": "#e0e0e0",
     "hover_filter": "invert(0.98) sepia(0.12) saturate(0.81) hue-rotate(343deg) brightness(1.13) contrast(0.76)",
 })
 call-function: ("check-filter", {
     "theme": "dark",
-    "border": "rgb(224, 224, 224)",
+    "border": "#e0e0e0",
     "filter": "invert(0.94) sepia(0) saturate(7.21) hue-rotate(255deg) brightness(0.9) contrast(0.9)",
-    "hover_border": "rgb(33, 150, 243)",
+    "hover_border": "#2196f3",
     "hover_filter": "invert(0.69) sepia(0.6) saturate(66.13) hue-rotate(184deg) brightness(1) contrast(0.91)",
 })
 call-function: ("check-filter", {
     "theme": "light",
-    "border": "rgb(224, 224, 224)",
+    "border": "#e0e0e0",
     "filter": "invert(1) sepia(0) saturate(42.23) hue-rotate(289deg) brightness(1.14) contrast(0.76)",
-    "hover_border": "rgb(113, 113, 113)",
+    "hover_border": "#717171",
     "hover_filter": "invert(0.44) sepia(0.18) saturate(0.23) hue-rotate(317deg) brightness(0.96) contrast(0.93)",
 })
diff --git a/tests/rustdoc-gui/source-anchor-scroll.goml b/tests/rustdoc-gui/source-anchor-scroll.goml
index 3d88d5619b1..67f1497e70c 100644
--- a/tests/rustdoc-gui/source-anchor-scroll.goml
+++ b/tests/rustdoc-gui/source-anchor-scroll.goml
@@ -8,13 +8,13 @@ set-window-size: (600, 800)
 assert-property: ("html", {"scrollTop": "0"})
 
 click: '//a[text() = "barbar"]'
-assert-property: ("html", {"scrollTop": "125"})
+assert-property: ("html", {"scrollTop": "149"})
 click: '//a[text() = "bar"]'
-assert-property: ("html", {"scrollTop": "156"})
+assert-property: ("html", {"scrollTop": "180"})
 click: '//a[text() = "sub_fn"]'
-assert-property: ("html", {"scrollTop": "53"})
+assert-property: ("html", {"scrollTop": "77"})
 
 // We now check that clicking on lines doesn't change the scroll
 // Extra information: the "sub_fn" function header is on line 1.
 click: '//*[@id="6"]'
-assert-property: ("html", {"scrollTop": "53"})
+assert-property: ("html", {"scrollTop": "77"})
diff --git a/tests/rustdoc-gui/src/extend_css/lib.rs b/tests/rustdoc-gui/src/extend_css/lib.rs
index 3a3babf8984..2308c0932fd 100644
--- a/tests/rustdoc-gui/src/extend_css/lib.rs
+++ b/tests/rustdoc-gui/src/extend_css/lib.rs
@@ -1 +1,2 @@
+// compile-flags: --extend-css extra.css
 //! <div class="extend">text in red</div>
diff --git a/tests/rustdoc-gui/src/link_to_definition/lib.rs b/tests/rustdoc-gui/src/link_to_definition/lib.rs
index 419a9cceec5..6fed79aedb8 100644
--- a/tests/rustdoc-gui/src/link_to_definition/lib.rs
+++ b/tests/rustdoc-gui/src/link_to_definition/lib.rs
@@ -1,3 +1,4 @@
+// compile-flags: -Zunstable-options --generate-link-to-definition
 pub fn sub_fn() {
     barbar();
 }
diff --git a/tests/rustdoc-gui/src/scrape_examples/src/lib.rs b/tests/rustdoc-gui/src/scrape_examples/src/lib.rs
index 88b03cf2603..6666587ad54 100644
--- a/tests/rustdoc-gui/src/scrape_examples/src/lib.rs
+++ b/tests/rustdoc-gui/src/scrape_examples/src/lib.rs
@@ -1,3 +1,4 @@
+// run-flags:-Zrustdoc-scrape-examples
 /// # Examples
 ///
 /// ```
diff --git a/tests/rustdoc-gui/target.goml b/tests/rustdoc-gui/target.goml
index 0c514fc6864..c5e7f813dd1 100644
--- a/tests/rustdoc-gui/target.goml
+++ b/tests/rustdoc-gui/target.goml
@@ -25,11 +25,11 @@ call-function: ("check-style", {
 })
 call-function: ("check-style", {
     "theme": "dark",
-    "background": "rgb(73, 74, 61)",
-    "border": "rgb(187, 116, 16)",
+    "background": "#494a3d",
+    "border": "#bb7410",
 })
 call-function: ("check-style", {
     "theme": "light",
-    "background": "rgb(253, 255, 211)",
-    "border": "rgb(173, 124, 55)",
+    "background": "#fdffd3",
+    "border": "#ad7c37",
 })
diff --git a/tests/rustdoc-ui/intra-doc/issue-110495-suffix-with-space.stderr b/tests/rustdoc-ui/intra-doc/issue-110495-suffix-with-space.stderr
index 8669b0c2086..6c834fd0a1b 100644
--- a/tests/rustdoc-ui/intra-doc/issue-110495-suffix-with-space.stderr
+++ b/tests/rustdoc-ui/intra-doc/issue-110495-suffix-with-space.stderr
@@ -36,7 +36,7 @@ LL | //! [`Clone ()`].
 help: to link to the trait, prefix with `trait@`
    |
 LL - //! [`Clone ()`].
-LL + //! [`trait@Clone (`].
+LL + //! [`trait@Clone `].
    |
 
 error: incompatible link kind for `Clone`
@@ -47,8 +47,9 @@ LL | //! [`Clone !`].
    |
 help: to link to the derive macro, prefix with `derive@`
    |
-LL | //! [`derive@Clone !`].
-   |       +++++++
+LL - //! [`Clone !`].
+LL + //! [`derive@Clone `].
+   |
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/rustdoc-ui/intra-doc/weird-syntax.rs b/tests/rustdoc-ui/intra-doc/weird-syntax.rs
new file mode 100644
index 00000000000..ca18842fb21
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/weird-syntax.rs
@@ -0,0 +1,140 @@
+// Many examples are from
+// https://github.com/rust-lang/rust/issues/110111#issuecomment-1517800781
+#![deny(rustdoc::broken_intra_doc_links)]
+
+//! This test case is closely linked to [raphlinus/pulldown-cmark#441], getting offsets of
+//! link components. In particular, pulldown-cmark doesn't provide the offsets of the contents
+//! of a link.
+//!
+//! To work around this, rustdoc parses parts of a link definition itself. This is basically a
+//! test suite for that link syntax parser.
+//!
+//! [raphlinus/pulldown-cmark#441]: https://github.com/raphlinus/pulldown-cmark/issues/441
+
+use std::clone::Clone;
+
+// Basic version //
+
+/// [`struct@Clone`] //~ERROR link
+pub struct LinkToCloneWithBackquotes;
+
+/// [```struct@Clone```] //~ERROR link
+pub struct LinkToCloneWithMultipleBackquotes;
+
+/// [  `  struct@Clone  `  ] //~ERROR link
+pub struct LinkToCloneWithSpacesAndBackquotes;
+
+/// [  `Clone ()`  ] //~ERROR link
+pub struct LinkToCloneWithSpacesBackquotesAndParens;
+
+/// [`Clone ()`  ] //~ERROR link
+pub struct LinkToCloneWithSpacesEndBackquotesAndParens;
+
+/// [  `Clone ()`] //~ERROR link
+pub struct LinkToCloneWithSpacesStartBackquotesAndParens;
+
+/// [```Clone ()```] //~ERROR link
+pub struct LinkToCloneWithMultipleBackquotesAndParens;
+
+/// [```Clone \(\)```] // not URL-shaped enough
+pub struct LinkToCloneWithMultipleBackquotesAndEscapedParens;
+
+/// [  ```  Clone ()  ```  ] //~ERROR link
+pub struct LinkToCloneWithSpacesMultipleBackquotesAndParens;
+
+/// [ x \] ] // not URL-shaped enough
+pub struct LinkWithEscapedCloseBrace;
+
+/// [ x \[ ] // not URL-shaped enough
+pub struct LinkWithEscapedOpenBrace;
+
+/// [ x \( ] // not URL-shaped enough
+pub struct LinkWithEscapedCloseParen;
+
+/// [ x \) ] // not URL-shaped enough
+pub struct LinkWithEscapedOpenParen;
+
+/// [ Clone \(\) ] // not URL-shaped enough
+pub struct LinkWithEscapedParens;
+
+// [][] version //
+
+/// [x][ struct@Clone] //~ERROR link
+pub struct XLinkToCloneWithStartSpace;
+
+/// [x][struct@Clone ] //~ERROR link
+pub struct XLinkToCloneWithEndSpace;
+
+/// [x][Clone\(\)] not URL-shaped enough
+pub struct XLinkToCloneWithEscapedParens;
+
+/// [x][`Clone`] not URL-shaped enough
+pub struct XLinkToCloneWithBackquotes;
+
+/// [x][Clone()] //~ERROR link
+pub struct XLinkToCloneWithUnescapedParens;
+
+/// [x][Clone  ()] //~ERROR link
+pub struct XLinkToCloneWithUnescapedParensAndDoubleSpace;
+
+/// [x][Clone  [] //~ERROR unresolved link to `x`
+pub struct XLinkToCloneWithUnmatchedOpenParenAndDoubleSpace;
+
+/// [x][Clone  \[] // not URL-shaped enough
+pub struct XLinkToCloneWithUnmatchedEscapedOpenParenAndDoubleSpace;
+
+/// [x][Clone  \]] // not URL-shaped enough
+pub struct XLinkToCloneWithUnmatchedEscapedCloseParenAndDoubleSpace;
+
+// []() version //
+
+/// [w]( struct@Clone) //~ERROR link
+pub struct WLinkToCloneWithStartSpace;
+
+/// [w](struct@Clone ) //~ERROR link
+pub struct WLinkToCloneWithEndSpace;
+
+/// [w](Clone\(\)) //~ERROR link
+pub struct WLinkToCloneWithEscapedParens;
+
+/// [w](`Clone`) not URL-shaped enough
+pub struct WLinkToCloneWithBackquotes;
+
+/// [w](Clone()) //~ERROR link
+pub struct WLinkToCloneWithUnescapedParens;
+
+/// [w](Clone  ()) not URL-shaped enough
+pub struct WLinkToCloneWithUnescapedParensAndDoubleSpace;
+
+/// [w](Clone  () //~ERROR unresolved link to `w`
+pub struct WLinkToCloneWithUnmatchedOpenParenAndDoubleSpace;
+
+/// [w](Clone  \() //~ERROR unresolved link to `w`
+pub struct WLinkToCloneWithUnmatchedEscapedOpenParenAndDoubleSpace;
+
+/// [w](Clone  \)) //~ERROR unresolved link to `w`
+pub struct WLinkToCloneWithUnmatchedEscapedCloseParenAndDoubleSpace;
+
+// References
+
+/// The [cln][] link here is going to be unresolved, because `Clone()` gets rejected //~ERROR link
+/// in Markdown for not being URL-shaped enough.
+///
+/// [cln]: Clone() //~ERROR link
+pub struct LinkToCloneWithParensInReference;
+
+/// The [cln][] link here is going to be unresolved, because `struct@Clone` gets //~ERROR link
+/// rejected in Markdown for not being URL-shaped enough.
+///
+/// [cln]: struct@Clone //~ERROR link
+pub struct LinkToCloneWithWrongPrefix;
+
+/// The [cln][] link here will produce a plain text suggestion //~ERROR link
+///
+/// [cln]: Clone\(\)
+pub struct LinkToCloneWithEscapedParensInReference;
+
+/// The [cln][] link here will produce a plain text suggestion //~ERROR link
+///
+/// [cln]: struct\@Clone
+pub struct LinkToCloneWithEscapedAtsInReference;
diff --git a/tests/rustdoc-ui/intra-doc/weird-syntax.stderr b/tests/rustdoc-ui/intra-doc/weird-syntax.stderr
new file mode 100644
index 00000000000..f50feb57fcc
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/weird-syntax.stderr
@@ -0,0 +1,272 @@
+error: incompatible link kind for `Clone`
+  --> $DIR/weird-syntax.rs:18:7
+   |
+LL | /// [`struct@Clone`]
+   |       ^^^^^^^^^^^^ this link resolved to a trait, which is not a struct
+   |
+note: the lint level is defined here
+  --> $DIR/weird-syntax.rs:3:9
+   |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: to link to the trait, prefix with `trait@`
+   |
+LL | /// [`trait@Clone`]
+   |       ~~~~~~
+
+error: incompatible link kind for `Clone`
+  --> $DIR/weird-syntax.rs:21:9
+   |
+LL | /// [```struct@Clone```]
+   |         ^^^^^^^^^^^^ this link resolved to a trait, which is not a struct
+   |
+help: to link to the trait, prefix with `trait@`
+   |
+LL | /// [```trait@Clone```]
+   |         ~~~~~~
+
+error: incompatible link kind for `Clone`
+  --> $DIR/weird-syntax.rs:24:11
+   |
+LL | /// [  `  struct@Clone  `  ]
+   |           ^^^^^^^^^^^^ this link resolved to a trait, which is not a struct
+   |
+help: to link to the trait, prefix with `trait@`
+   |
+LL | /// [  `  trait@Clone  `  ]
+   |           ~~~~~~
+
+error: unresolved link to `Clone`
+  --> $DIR/weird-syntax.rs:27:9
+   |
+LL | /// [  `Clone ()`  ]
+   |         ^^^^^^^^ this link resolves to the trait `Clone`, which is not in the value namespace
+   |
+help: to link to the trait, prefix with `trait@`
+   |
+LL - /// [  `Clone ()`  ]
+LL + /// [  `trait@Clone `  ]
+   |
+
+error: unresolved link to `Clone`
+  --> $DIR/weird-syntax.rs:30:7
+   |
+LL | /// [`Clone ()`  ]
+   |       ^^^^^^^^ this link resolves to the trait `Clone`, which is not in the value namespace
+   |
+help: to link to the trait, prefix with `trait@`
+   |
+LL - /// [`Clone ()`  ]
+LL + /// [`trait@Clone `  ]
+   |
+
+error: unresolved link to `Clone`
+  --> $DIR/weird-syntax.rs:33:9
+   |
+LL | /// [  `Clone ()`]
+   |         ^^^^^^^^ this link resolves to the trait `Clone`, which is not in the value namespace
+   |
+help: to link to the trait, prefix with `trait@`
+   |
+LL - /// [  `Clone ()`]
+LL + /// [  `trait@Clone `]
+   |
+
+error: unresolved link to `Clone`
+  --> $DIR/weird-syntax.rs:36:9
+   |
+LL | /// [```Clone ()```]
+   |         ^^^^^^^^ this link resolves to the trait `Clone`, which is not in the value namespace
+   |
+help: to link to the trait, prefix with `trait@`
+   |
+LL - /// [```Clone ()```]
+LL + /// [```trait@Clone ```]
+   |
+
+error: unresolved link to `Clone`
+  --> $DIR/weird-syntax.rs:42:13
+   |
+LL | /// [  ```  Clone ()  ```  ]
+   |             ^^^^^^^^ this link resolves to the trait `Clone`, which is not in the value namespace
+   |
+help: to link to the trait, prefix with `trait@`
+   |
+LL - /// [  ```  Clone ()  ```  ]
+LL + /// [  ```  trait@Clone   ```  ]
+   |
+
+error: incompatible link kind for `Clone`
+  --> $DIR/weird-syntax.rs:62:10
+   |
+LL | /// [x][ struct@Clone]
+   |          ^^^^^^^^^^^^ this link resolved to a trait, which is not a struct
+   |
+help: to link to the trait, prefix with `trait@`
+   |
+LL | /// [x][ trait@Clone]
+   |          ~~~~~~
+
+error: incompatible link kind for `Clone`
+  --> $DIR/weird-syntax.rs:65:9
+   |
+LL | /// [x][struct@Clone ]
+   |         ^^^^^^^^^^^^ this link resolved to a trait, which is not a struct
+   |
+help: to link to the trait, prefix with `trait@`
+   |
+LL | /// [x][trait@Clone ]
+   |         ~~~~~~
+
+error: unresolved link to `Clone`
+  --> $DIR/weird-syntax.rs:74:9
+   |
+LL | /// [x][Clone()]
+   |         ^^^^^^^ this link resolves to the trait `Clone`, which is not in the value namespace
+   |
+help: to link to the trait, prefix with `trait@`
+   |
+LL - /// [x][Clone()]
+LL + /// [x][trait@Clone]
+   |
+
+error: unresolved link to `Clone`
+  --> $DIR/weird-syntax.rs:77:9
+   |
+LL | /// [x][Clone  ()]
+   |         ^^^^^^^^^ this link resolves to the trait `Clone`, which is not in the value namespace
+   |
+help: to link to the trait, prefix with `trait@`
+   |
+LL - /// [x][Clone  ()]
+LL + /// [x][trait@Clone  ]
+   |
+
+error: unresolved link to `x`
+  --> $DIR/weird-syntax.rs:80:6
+   |
+LL | /// [x][Clone  []
+   |      ^ no item named `x` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: incompatible link kind for `Clone`
+  --> $DIR/weird-syntax.rs:91:10
+   |
+LL | /// [w]( struct@Clone)
+   |          ^^^^^^^^^^^^ this link resolved to a trait, which is not a struct
+   |
+help: to link to the trait, prefix with `trait@`
+   |
+LL | /// [w]( trait@Clone)
+   |          ~~~~~~
+
+error: incompatible link kind for `Clone`
+  --> $DIR/weird-syntax.rs:94:9
+   |
+LL | /// [w](struct@Clone )
+   |         ^^^^^^^^^^^^ this link resolved to a trait, which is not a struct
+   |
+help: to link to the trait, prefix with `trait@`
+   |
+LL | /// [w](trait@Clone )
+   |         ~~~~~~
+
+error: unresolved link to `Clone`
+  --> $DIR/weird-syntax.rs:97:9
+   |
+LL | /// [w](Clone\(\))
+   |         ^^^^^^^^^ this link resolves to the trait `Clone`, which is not in the value namespace
+   |
+help: to link to the trait, prefix with `trait@`
+   |
+LL - /// [w](Clone\(\))
+LL + /// [w](trait@Clone)
+   |
+
+error: unresolved link to `Clone`
+  --> $DIR/weird-syntax.rs:103:9
+   |
+LL | /// [w](Clone())
+   |         ^^^^^^^ this link resolves to the trait `Clone`, which is not in the value namespace
+   |
+help: to link to the trait, prefix with `trait@`
+   |
+LL - /// [w](Clone())
+LL + /// [w](trait@Clone)
+   |
+
+error: unresolved link to `w`
+  --> $DIR/weird-syntax.rs:109:6
+   |
+LL | /// [w](Clone  ()
+   |      ^ no item named `w` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `w`
+  --> $DIR/weird-syntax.rs:112:6
+   |
+LL | /// [w](Clone  \()
+   |      ^ no item named `w` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `w`
+  --> $DIR/weird-syntax.rs:115:6
+   |
+LL | /// [w](Clone  \))
+   |      ^ no item named `w` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `cln`
+  --> $DIR/weird-syntax.rs:120:10
+   |
+LL | /// The [cln][] link here is going to be unresolved, because `Clone()` gets rejected
+   |          ^^^ no item named `cln` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `cln`
+  --> $DIR/weird-syntax.rs:123:6
+   |
+LL | /// [cln]: Clone()
+   |      ^^^ no item named `cln` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `cln`
+  --> $DIR/weird-syntax.rs:126:10
+   |
+LL | /// The [cln][] link here is going to be unresolved, because `struct@Clone` gets
+   |          ^^^ no item named `cln` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `cln`
+  --> $DIR/weird-syntax.rs:129:6
+   |
+LL | /// [cln]: struct@Clone
+   |      ^^^ no item named `cln` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `Clone`
+  --> $DIR/weird-syntax.rs:132:9
+   |
+LL | /// The [cln][] link here will produce a plain text suggestion
+   |         ^^^^^ this link resolves to the trait `Clone`, which is not in the value namespace
+   |
+   = help: to link to the trait, prefix with `trait@`: trait@Clone
+
+error: incompatible link kind for `Clone`
+  --> $DIR/weird-syntax.rs:137:9
+   |
+LL | /// The [cln][] link here will produce a plain text suggestion
+   |         ^^^^^ this link resolved to a trait, which is not a struct
+   |
+   = help: to link to the trait, prefix with `trait@`: trait@Clone
+
+error: aborting due to 26 previous errors
+
diff --git a/tests/rustdoc/reexport-doc-hidden-inside-private.rs b/tests/rustdoc/reexport-doc-hidden-inside-private.rs
new file mode 100644
index 00000000000..1e4216d3c0c
--- /dev/null
+++ b/tests/rustdoc/reexport-doc-hidden-inside-private.rs
@@ -0,0 +1,16 @@
+// This test ensures that a re-export of  `#[doc(hidden)]` item inside a private
+// module will still be displayed (the re-export, not the item).
+
+#![crate_name = "foo"]
+
+mod private_module {
+    #[doc(hidden)]
+    pub struct Public;
+}
+
+// @has 'foo/index.html'
+// @has - '//*[@id="reexport.Foo"]/code' 'pub use crate::private_module::Public as Foo;'
+pub use crate::private_module::Public as Foo;
+// Glob re-exports with no visible items should not be displayed.
+// @count - '//*[@class="item-table"]/li' 1
+pub use crate::private_module::*;
diff --git a/tests/rustdoc/reexport-doc-hidden.rs b/tests/rustdoc/reexport-doc-hidden.rs
index 3ea5fde72f7..d9ed954868e 100644
--- a/tests/rustdoc/reexport-doc-hidden.rs
+++ b/tests/rustdoc/reexport-doc-hidden.rs
@@ -21,6 +21,5 @@ macro_rules! foo {
     () => {};
 }
 
-// This is a bug: https://github.com/rust-lang/rust/issues/59368
-// @!has - '//*[@id="reexport.Macro"]/code' 'pub use crate::foo as Macro;'
+// @has - '//*[@id="reexport.Macro"]/code' 'pub use crate::foo as Macro;'
 pub use crate::foo as Macro;
diff --git a/tests/rustdoc/reexport-hidden-macro.rs b/tests/rustdoc/reexport-hidden-macro.rs
index afcfa979616..47a21e39462 100644
--- a/tests/rustdoc/reexport-hidden-macro.rs
+++ b/tests/rustdoc/reexport-hidden-macro.rs
@@ -5,6 +5,7 @@
 
 // @has 'foo/index.html'
 // @has - '//*[@id="main-content"]//a[@href="macro.Macro2.html"]' 'Macro2'
+// @has - '//*[@id="reexport.Macro"]/code' 'pub use crate::foo as Macro;'
 
 // @has 'foo/macro.Macro2.html'
 // @has - '//*[@class="docblock"]' 'Displayed'
@@ -15,7 +16,6 @@ macro_rules! foo {
     () => {};
 }
 
-/// not displayed
 pub use crate::foo as Macro;
 /// Displayed
 #[doc(inline)]
diff --git a/tests/rustdoc/reexport-of-doc-hidden.rs b/tests/rustdoc/reexport-of-doc-hidden.rs
new file mode 100644
index 00000000000..b733716c22a
--- /dev/null
+++ b/tests/rustdoc/reexport-of-doc-hidden.rs
@@ -0,0 +1,42 @@
+// This test ensures that all re-exports of doc hidden elements are displayed.
+
+#![crate_name = "foo"]
+
+#[doc(hidden)]
+pub struct Bar;
+
+#[macro_export]
+#[doc(hidden)]
+macro_rules! foo {
+    () => {};
+}
+
+// @has 'foo/index.html'
+// @has - '//*[@id="reexport.Macro"]/code' 'pub use crate::foo as Macro;'
+pub use crate::foo as Macro;
+// @has - '//*[@id="reexport.Macro2"]/code' 'pub use crate::foo as Macro2;'
+pub use crate::foo as Macro2;
+// @has - '//*[@id="reexport.Boo"]/code' 'pub use crate::Bar as Boo;'
+pub use crate::Bar as Boo;
+// @has - '//*[@id="reexport.Boo2"]/code' 'pub use crate::Bar as Boo2;'
+pub use crate::Bar as Boo2;
+
+pub fn fofo() {}
+
+// @has - '//*[@id="reexport.f1"]/code' 'pub use crate::fofo as f1;'
+pub use crate::fofo as f1;
+// @has - '//*[@id="reexport.f2"]/code' 'pub use crate::fofo as f2;'
+pub use crate::fofo as f2;
+
+pub mod sub {
+    // @has 'foo/sub/index.html'
+    // @has - '//*[@id="reexport.Macro"]/code' 'pub use crate::foo as Macro;'
+    pub use crate::foo as Macro;
+    // @has - '//*[@id="reexport.Macro2"]/code' 'pub use crate::foo as Macro2;'
+    pub use crate::foo as Macro2;
+
+    // @has - '//*[@id="reexport.f1"]/code' 'pub use crate::fofo as f1;'
+    pub use crate::fofo as f1;
+    // @has - '//*[@id="reexport.f2"]/code' 'pub use crate::fofo as f2;'
+    pub use crate::fofo as f2;
+}
diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr
index e4b8958b4fa..8c876213ae0 100644
--- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr
+++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr
@@ -23,7 +23,7 @@ LL |     arg: NotIntoDiagnosticArg,
    |
    = help: normalized in stderr
 note: required by a bound in `Diagnostic::set_arg`
-  --> $COMPILER_DIR/rustc_errors/src/diagnostic.rs:964:5
+  --> $COMPILER_DIR/rustc_errors/src/diagnostic.rs:960:5
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/issues/issue-78115.rs b/tests/ui/async-await/issue-78115.rs
index ac18470c621..ac18470c621 100644
--- a/tests/ui/issues/issue-78115.rs
+++ b/tests/ui/async-await/issue-78115.rs
diff --git a/tests/ui/backtrace.rs b/tests/ui/backtrace.rs
index dd73dd9886a..66b378f62d6 100644
--- a/tests/ui/backtrace.rs
+++ b/tests/ui/backtrace.rs
@@ -104,13 +104,17 @@ fn runtest(me: &str) {
                 "bad output3: {}", s);
 
         // Make sure a stack trace isn't printed too many times
+        //
+        // Currently it is printed 3 times ("once", "twice" and "panic in a
+        // function that cannot unwind") but in the future the last one may be
+        // removed.
         let p = template(me).arg("double-fail")
                                     .env("RUST_BACKTRACE", "1").spawn().unwrap();
         let out = p.wait_with_output().unwrap();
         assert!(!out.status.success());
         let s = str::from_utf8(&out.stderr).unwrap();
         let mut i = 0;
-        for _ in 0..2 {
+        for _ in 0..3 {
             i += s[i + 10..].find("stack backtrace").unwrap() + 10;
         }
         assert!(s[i + 10..].find("stack backtrace").is_none(),
diff --git a/tests/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.stderr b/tests/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.stderr
index 26453b42fa9..2f397f6b585 100644
--- a/tests/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.stderr
+++ b/tests/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.stderr
@@ -4,7 +4,7 @@ error[E0712]: thread-local variable borrowed past end of function
 LL |      assert_static(&FOO);
    |                    ^^^^ thread-local variables cannot be borrowed beyond the end of the function
 LL | }
-   | - end of enclosing function is here
+   |  - end of enclosing function is here
 
 error: aborting due to previous error
 
diff --git a/tests/ui/borrowck/borrowck-vec-pattern-nesting.rs b/tests/ui/borrowck/borrowck-vec-pattern-nesting.rs
index 127a3f5b2dc..1bda7a49713 100644
--- a/tests/ui/borrowck/borrowck-vec-pattern-nesting.rs
+++ b/tests/ui/borrowck/borrowck-vec-pattern-nesting.rs
@@ -8,7 +8,6 @@ fn a() {
         //~^ NOTE `vec[_]` is borrowed here
             vec[0] = Box::new(4); //~ ERROR cannot assign
             //~^ NOTE `vec[_]` is assigned to here
-            //~| NOTE in this expansion of desugaring of drop and replace
             _a.use_ref();
             //~^ NOTE borrow later used here
         }
@@ -23,7 +22,6 @@ fn b() {
         //~^ `vec[_]` is borrowed here
             vec[0] = Box::new(4); //~ ERROR cannot assign
             //~^ NOTE `vec[_]` is assigned to here
-            //~| NOTE in this expansion of desugaring of drop and replace
             _b.use_ref();
             //~^ NOTE borrow later used here
         }
diff --git a/tests/ui/borrowck/borrowck-vec-pattern-nesting.stderr b/tests/ui/borrowck/borrowck-vec-pattern-nesting.stderr
index 5e1251b0590..70b9e4f4433 100644
--- a/tests/ui/borrowck/borrowck-vec-pattern-nesting.stderr
+++ b/tests/ui/borrowck/borrowck-vec-pattern-nesting.stderr
@@ -6,24 +6,24 @@ LL |         [box ref _a, _, _] => {
 LL |
 LL |             vec[0] = Box::new(4);
    |             ^^^^^^ `vec[_]` is assigned to here but it was already borrowed
-...
+LL |
 LL |             _a.use_ref();
    |             ------------ borrow later used here
 
 error[E0506]: cannot assign to `vec[_]` because it is borrowed
-  --> $DIR/borrowck-vec-pattern-nesting.rs:24:13
+  --> $DIR/borrowck-vec-pattern-nesting.rs:23:13
    |
 LL |         &mut [ref _b @ ..] => {
    |               ------ `vec[_]` is borrowed here
 LL |
 LL |             vec[0] = Box::new(4);
    |             ^^^^^^ `vec[_]` is assigned to here but it was already borrowed
-...
+LL |
 LL |             _b.use_ref();
    |             ------------ borrow later used here
 
 error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:36:11
+  --> $DIR/borrowck-vec-pattern-nesting.rs:34:11
    |
 LL |     match vec {
    |           ^^^ cannot move out of here
@@ -41,7 +41,7 @@ LL +         [_a,
    |
 
 error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:48:13
+  --> $DIR/borrowck-vec-pattern-nesting.rs:46:13
    |
 LL |     let a = vec[0];
    |             ^^^^^^
@@ -55,7 +55,7 @@ LL |     let a = &vec[0];
    |             +
 
 error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:57:11
+  --> $DIR/borrowck-vec-pattern-nesting.rs:55:11
    |
 LL |     match vec {
    |           ^^^ cannot move out of here
@@ -73,7 +73,7 @@ LL +         [
    |
 
 error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:67:13
+  --> $DIR/borrowck-vec-pattern-nesting.rs:65:13
    |
 LL |     let a = vec[0];
    |             ^^^^^^
@@ -87,7 +87,7 @@ LL |     let a = &vec[0];
    |             +
 
 error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:76:11
+  --> $DIR/borrowck-vec-pattern-nesting.rs:74:11
    |
 LL |     match vec {
    |           ^^^ cannot move out of here
@@ -106,7 +106,7 @@ LL +         [_a, _b, _c] => {}
    |
 
 error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:87:13
+  --> $DIR/borrowck-vec-pattern-nesting.rs:85:13
    |
 LL |     let a = vec[0];
    |             ^^^^^^
diff --git a/tests/ui/borrowck/issue-45199.rs b/tests/ui/borrowck/issue-45199.rs
index 6a6b25541f3..ded46e56e34 100644
--- a/tests/ui/borrowck/issue-45199.rs
+++ b/tests/ui/borrowck/issue-45199.rs
@@ -5,7 +5,6 @@ fn test_drop_replace() {
     b = Box::new(1);    //~ NOTE first assignment
     b = Box::new(2);    //~ ERROR cannot assign twice to immutable variable `b`
                         //~| NOTE cannot assign twice to immutable
-                        //~| NOTE in this expansion of desugaring of drop and replace
 }
 
 fn test_call() {
@@ -14,14 +13,12 @@ fn test_call() {
                             //~| SUGGESTION mut b
     b = Box::new(2);        //~ ERROR cannot assign twice to immutable variable `b`
                             //~| NOTE cannot assign twice to immutable
-                            //~| NOTE in this expansion of desugaring of drop and replace
 }
 
 fn test_args(b: Box<i32>) {  //~ HELP consider making this binding mutable
                                 //~| SUGGESTION mut b
     b = Box::new(2);            //~ ERROR cannot assign to immutable argument `b`
                                 //~| NOTE cannot assign to immutable argument
-                                //~| NOTE in this expansion of desugaring of drop and replace
 }
 
 fn main() {}
diff --git a/tests/ui/borrowck/issue-45199.stderr b/tests/ui/borrowck/issue-45199.stderr
index 163f2370ba0..47aa3090827 100644
--- a/tests/ui/borrowck/issue-45199.stderr
+++ b/tests/ui/borrowck/issue-45199.stderr
@@ -10,7 +10,7 @@ LL |     b = Box::new(2);
    |     ^ cannot assign twice to immutable variable
 
 error[E0384]: cannot assign twice to immutable variable `b`
-  --> $DIR/issue-45199.rs:15:5
+  --> $DIR/issue-45199.rs:14:5
    |
 LL |     let b = Box::new(1);
    |         -
@@ -22,7 +22,7 @@ LL |     b = Box::new(2);
    |     ^ cannot assign twice to immutable variable
 
 error[E0384]: cannot assign to immutable argument `b`
-  --> $DIR/issue-45199.rs:22:5
+  --> $DIR/issue-45199.rs:20:5
    |
 LL | fn test_args(b: Box<i32>) {
    |              - help: consider making this binding mutable: `mut b`
diff --git a/tests/ui/closures/2229_closure_analysis/unique-borrows-are-invariant-1.rs b/tests/ui/closures/2229_closure_analysis/unique-borrows-are-invariant-1.rs
new file mode 100644
index 00000000000..f21ef43fb7c
--- /dev/null
+++ b/tests/ui/closures/2229_closure_analysis/unique-borrows-are-invariant-1.rs
@@ -0,0 +1,18 @@
+// edition:2021
+
+// regression test for #112056
+
+fn extend_lifetime<'a, 'b>(x: &mut (&'a str,), y: &'b str) {
+    let mut closure = |input| x.0 = input;
+    //~^ ERROR: lifetime may not live long enough
+    closure(y);
+}
+
+fn main() {
+    let mut tuple = ("static",);
+    {
+        let x = String::from("temporary");
+        extend_lifetime(&mut tuple, &x);
+    }
+    println!("{}", tuple.0);
+}
diff --git a/tests/ui/closures/2229_closure_analysis/unique-borrows-are-invariant-1.stderr b/tests/ui/closures/2229_closure_analysis/unique-borrows-are-invariant-1.stderr
new file mode 100644
index 00000000000..730823281ab
--- /dev/null
+++ b/tests/ui/closures/2229_closure_analysis/unique-borrows-are-invariant-1.stderr
@@ -0,0 +1,14 @@
+error: lifetime may not live long enough
+  --> $DIR/unique-borrows-are-invariant-1.rs:6:31
+   |
+LL | fn extend_lifetime<'a, 'b>(x: &mut (&'a str,), y: &'b str) {
+   |                    --  -- lifetime `'b` defined here
+   |                    |
+   |                    lifetime `'a` defined here
+LL |     let mut closure = |input| x.0 = input;
+   |                               ^^^^^^^^^^^ assignment requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/closures/2229_closure_analysis/unique-borrows-are-invariant-2.rs b/tests/ui/closures/2229_closure_analysis/unique-borrows-are-invariant-2.rs
new file mode 100644
index 00000000000..dd9d986c208
--- /dev/null
+++ b/tests/ui/closures/2229_closure_analysis/unique-borrows-are-invariant-2.rs
@@ -0,0 +1,31 @@
+// edition:2021
+
+// regression test for #112056
+
+struct Spooky<'b> {
+    owned: Option<&'static u32>,
+    borrowed: &'b &'static u32,
+}
+
+impl<'b> Spooky<'b> {
+    fn create_self_reference<'a>(&'a mut self) {
+        let mut closure = || {
+            if let Some(owned) = &self.owned {
+                let borrow: &'a &'static u32 = owned;
+                self.borrowed = borrow;
+                //~^ ERROR: lifetime may not live long enough
+            }
+        };
+        closure();
+    }
+}
+
+fn main() {
+    let mut spooky: Spooky<'static> = Spooky {
+        owned: Some(&1),
+        borrowed: &&1,
+    };
+    spooky.create_self_reference();
+    spooky.owned = None;
+    println!("{}", **spooky.borrowed);
+}
diff --git a/tests/ui/closures/2229_closure_analysis/unique-borrows-are-invariant-2.stderr b/tests/ui/closures/2229_closure_analysis/unique-borrows-are-invariant-2.stderr
new file mode 100644
index 00000000000..66ba0fe3547
--- /dev/null
+++ b/tests/ui/closures/2229_closure_analysis/unique-borrows-are-invariant-2.stderr
@@ -0,0 +1,15 @@
+error: lifetime may not live long enough
+  --> $DIR/unique-borrows-are-invariant-2.rs:15:17
+   |
+LL | impl<'b> Spooky<'b> {
+   |      -- lifetime `'b` defined here
+LL |     fn create_self_reference<'a>(&'a mut self) {
+   |                              -- lifetime `'a` defined here
+...
+LL |                 self.borrowed = borrow;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/issues/issue-3794.rs b/tests/ui/coercion/issue-3794.rs
index b1f028fbccb..b1f028fbccb 100644
--- a/tests/ui/issues/issue-3794.rs
+++ b/tests/ui/coercion/issue-3794.rs
diff --git a/tests/ui/coherence/coherence-inherited-subtyping.re.stderr b/tests/ui/coherence/coherence-inherited-subtyping.re.stderr
deleted file mode 100644
index 4701bc0b139..00000000000
--- a/tests/ui/coherence/coherence-inherited-subtyping.re.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0592]: duplicate definitions with name `method1`
-  --> $DIR/coherence-inherited-subtyping.rs:14:5
-   |
-LL |     fn method1(&self) {}
-   |     ^^^^^^^^^^^^^^^^^ duplicate definitions for `method1`
-...
-LL |     fn method1(&self) {}
-   |     ----------------- other definition for `method1`
-   |
-   = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0592`.
diff --git a/tests/ui/coherence/coherence-inherited-subtyping.rs b/tests/ui/coherence/coherence-inherited-subtyping.rs
index 8587eb77950..f35cd2103da 100644
--- a/tests/ui/coherence/coherence-inherited-subtyping.rs
+++ b/tests/ui/coherence/coherence-inherited-subtyping.rs
@@ -4,8 +4,6 @@
 // Note: This scenario is currently accepted, but as part of the
 // universe transition (#56105) may eventually become an error.
 
-// revisions: old re
-
 struct Foo<T> {
     t: T,
 }
diff --git a/tests/ui/coherence/coherence-inherited-subtyping.old.stderr b/tests/ui/coherence/coherence-inherited-subtyping.stderr
index 4701bc0b139..f60b2aa2735 100644
--- a/tests/ui/coherence/coherence-inherited-subtyping.old.stderr
+++ b/tests/ui/coherence/coherence-inherited-subtyping.stderr
@@ -1,5 +1,5 @@
 error[E0592]: duplicate definitions with name `method1`
-  --> $DIR/coherence-inherited-subtyping.rs:14:5
+  --> $DIR/coherence-inherited-subtyping.rs:12:5
    |
 LL |     fn method1(&self) {}
    |     ^^^^^^^^^^^^^^^^^ duplicate definitions for `method1`
diff --git a/tests/ui/coinduction/canonicalization-rerun.rs b/tests/ui/coinduction/canonicalization-rerun.rs
index b10ba3a810f..c68895fc4e6 100644
--- a/tests/ui/coinduction/canonicalization-rerun.rs
+++ b/tests/ui/coinduction/canonicalization-rerun.rs
@@ -1,6 +1,6 @@
 // check-pass
-// revisions: old new
-//[new] compile-flags: -Ztrait-solver=next
+// revisions: old next
+//[next] compile-flags: -Ztrait-solver=next
 
 // If we use canonical goals during trait solving we have to reevaluate
 // the root goal of a cycle until we hit a fixpoint.
diff --git a/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.rs b/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.rs
index 85345d65c4a..b22cab7c7ff 100644
--- a/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.rs
+++ b/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.rs
@@ -1,7 +1,7 @@
-// check-pass
+// known-bug: #110395
 // known-bug: #97156
 
-#![feature(const_type_id, generic_const_exprs)]
+#![feature(const_type_id, const_trait_impl, generic_const_exprs)]
 #![allow(incomplete_features)]
 
 use std::any::TypeId;
@@ -26,7 +26,10 @@ impl<T: 'static> AssocCt for T {
 trait WithAssoc<U> {
     type Assoc;
 }
-impl<T: 'static> WithAssoc<()> for T where [(); <T as AssocCt>::ASSOC]: {
+impl<T: 'static> WithAssoc<()> for T
+where
+    [(); <T as AssocCt>::ASSOC]:,
+{
     type Assoc = [u8; <T as AssocCt>::ASSOC];
 }
 
@@ -38,7 +41,6 @@ where
     x
 }
 
-
 fn unsound<T>(x: <One as WithAssoc<T>>::Assoc) -> <Two as WithAssoc<T>>::Assoc
 where
     One: WithAssoc<T>,
diff --git a/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.stderr b/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.stderr
new file mode 100644
index 00000000000..8cbd1265448
--- /dev/null
+++ b/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.stderr
@@ -0,0 +1,11 @@
+error: to use a constant of type `TypeId` in a pattern, `TypeId` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/typeid-equality-by-subtyping.rs:18:9
+   |
+LL |         WHAT_A_TYPE => 0,
+   |         ^^^^^^^^^^^
+   |
+   = note: the traits must be derived, manual `impl`s are not sufficient
+   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
+
+error: aborting due to previous error
+
diff --git a/tests/ui/const-generics/transmute-fail.stderr b/tests/ui/const-generics/transmute-fail.stderr
index 41b098135e8..3d1197afd0f 100644
--- a/tests/ui/const-generics/transmute-fail.stderr
+++ b/tests/ui/const-generics/transmute-fail.stderr
@@ -4,8 +4,8 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-
 LL |     std::mem::transmute(v)
    |     ^^^^^^^^^^^^^^^^^^^
    |
-   = note: source type: `[[u32; H+1]; W]` (generic size [const expr])
-   = note: target type: `[[u32; W+1]; H]` (generic size [const expr])
+   = note: source type: `[[u32; H+1]; W]` (generic size {const expr})
+   = note: target type: `[[u32; W+1]; H]` (generic size {const expr})
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
   --> $DIR/transmute-fail.rs:16:5
@@ -34,8 +34,8 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-
 LL |     std::mem::transmute(v)
    |     ^^^^^^^^^^^^^^^^^^^
    |
-   = note: source type: `[[u32; H]; W]` (generic size [const expr])
-   = note: target type: `[u32; W * H * H]` (generic size [const expr])
+   = note: source type: `[[u32; H]; W]` (generic size {const expr})
+   = note: target type: `[u32; W * H * H]` (generic size {const expr})
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
   --> $DIR/transmute-fail.rs:30:5
diff --git a/tests/ui/consts/const_cmp_type_id.stderr b/tests/ui/consts/const_cmp_type_id.stderr
index 319d2b924a8..dc2c702d885 100644
--- a/tests/ui/consts/const_cmp_type_id.stderr
+++ b/tests/ui/consts/const_cmp_type_id.stderr
@@ -20,7 +20,6 @@ LL |     assert!(TypeId::of::<u8>() == TypeId::of::<u8>());
 note: impl defined here, but it is not `const`
   --> $SRC_DIR/core/src/any.rs:LL:COL
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-   = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: can't compare `TypeId` with `TypeId` in const contexts
   --> $DIR/const_cmp_type_id.rs:9:13
@@ -44,7 +43,6 @@ LL |     assert!(TypeId::of::<()>() != TypeId::of::<u8>());
 note: impl defined here, but it is not `const`
   --> $SRC_DIR/core/src/any.rs:LL:COL
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-   = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: can't compare `TypeId` with `TypeId` in const contexts
   --> $DIR/const_cmp_type_id.rs:10:22
diff --git a/tests/ui/issues/issue-16538.mir.stderr b/tests/ui/consts/issue-16538.mir.stderr
index e320df4b7ad..e320df4b7ad 100644
--- a/tests/ui/issues/issue-16538.mir.stderr
+++ b/tests/ui/consts/issue-16538.mir.stderr
diff --git a/tests/ui/issues/issue-16538.rs b/tests/ui/consts/issue-16538.rs
index 270fa301414..270fa301414 100644
--- a/tests/ui/issues/issue-16538.rs
+++ b/tests/ui/consts/issue-16538.rs
diff --git a/tests/ui/issues/issue-16538.thir.stderr b/tests/ui/consts/issue-16538.thir.stderr
index 4a862869274..4a862869274 100644
--- a/tests/ui/issues/issue-16538.thir.stderr
+++ b/tests/ui/consts/issue-16538.thir.stderr
diff --git a/tests/ui/issues/issue-28822.rs b/tests/ui/consts/issue-28822.rs
index 10e5d1dd0ac..10e5d1dd0ac 100644
--- a/tests/ui/issues/issue-28822.rs
+++ b/tests/ui/consts/issue-28822.rs
diff --git a/tests/ui/issues/issue-29798.rs b/tests/ui/consts/issue-29798.rs
index 5eff5d1915b..5eff5d1915b 100644
--- a/tests/ui/issues/issue-29798.rs
+++ b/tests/ui/consts/issue-29798.rs
diff --git a/tests/ui/consts/issue-73976-monomorphic.stderr b/tests/ui/consts/issue-73976-monomorphic.stderr
index 95ab78b1b23..09661d3f344 100644
--- a/tests/ui/consts/issue-73976-monomorphic.stderr
+++ b/tests/ui/consts/issue-73976-monomorphic.stderr
@@ -20,7 +20,6 @@ LL |     GetTypeId::<T>::VALUE == GetTypeId::<usize>::VALUE
 note: impl defined here, but it is not `const`
   --> $SRC_DIR/core/src/any.rs:LL:COL
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-   = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/deriving/deriving-all-codegen.stdout b/tests/ui/deriving/deriving-all-codegen.stdout
index 5bca83e87f8..d6a2c80cc06 100644
--- a/tests/ui/deriving/deriving-all-codegen.stdout
+++ b/tests/ui/deriving/deriving-all-codegen.stdout
@@ -44,6 +44,7 @@ impl ::core::default::Default for Empty {
 }
 #[automatically_derived]
 impl ::core::hash::Hash for Empty {
+    #[inline]
     fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {}
 }
 #[automatically_derived]
@@ -113,6 +114,7 @@ impl ::core::default::Default for Point {
 }
 #[automatically_derived]
 impl ::core::hash::Hash for Point {
+    #[inline]
     fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
         ::core::hash::Hash::hash(&self.x, state);
         ::core::hash::Hash::hash(&self.y, state)
@@ -198,6 +200,7 @@ impl ::core::default::Default for PackedPoint {
 }
 #[automatically_derived]
 impl ::core::hash::Hash for PackedPoint {
+    #[inline]
     fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
         ::core::hash::Hash::hash(&{ self.x }, state);
         ::core::hash::Hash::hash(&{ self.y }, state)
@@ -301,6 +304,7 @@ impl ::core::default::Default for Big {
 }
 #[automatically_derived]
 impl ::core::hash::Hash for Big {
+    #[inline]
     fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
         ::core::hash::Hash::hash(&self.b1, state);
         ::core::hash::Hash::hash(&self.b2, state);
@@ -478,6 +482,7 @@ impl ::core::fmt::Debug for Unsized {
 }
 #[automatically_derived]
 impl ::core::hash::Hash for Unsized {
+    #[inline]
     fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
         ::core::hash::Hash::hash(&self.0, state)
     }
@@ -529,6 +534,7 @@ impl ::core::fmt::Debug for PackedUnsizedU8 {
 }
 #[automatically_derived]
 impl ::core::hash::Hash for PackedUnsizedU8 {
+    #[inline]
     fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
         ::core::hash::Hash::hash(&self.0, state)
     }
@@ -584,6 +590,7 @@ impl<T: ::core::default::Default + Trait, U: ::core::default::Default>
 #[automatically_derived]
 impl<T: ::core::hash::Hash + Trait, U: ::core::hash::Hash> ::core::hash::Hash
     for Generic<T, U> where T::A: ::core::hash::Hash {
+    #[inline]
     fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
         ::core::hash::Hash::hash(&self.t, state);
         ::core::hash::Hash::hash(&self.ta, state);
@@ -701,6 +708,7 @@ impl<T: ::core::hash::Hash + ::core::marker::Copy + Trait,
     U: ::core::hash::Hash + ::core::marker::Copy> ::core::hash::Hash for
     PackedGeneric<T, U> where T::A: ::core::hash::Hash + ::core::marker::Copy
     {
+    #[inline]
     fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
         ::core::hash::Hash::hash(&{ self.0 }, state);
         ::core::hash::Hash::hash(&{ self.1 }, state);
@@ -795,6 +803,7 @@ impl ::core::fmt::Debug for Enum0 {
 }
 #[automatically_derived]
 impl ::core::hash::Hash for Enum0 {
+    #[inline]
     fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
         unsafe { ::core::intrinsics::unreachable() }
     }
@@ -861,6 +870,7 @@ impl ::core::fmt::Debug for Enum1 {
 }
 #[automatically_derived]
 impl ::core::hash::Hash for Enum1 {
+    #[inline]
     fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
         match self {
             Enum1::Single { x: __self_0 } =>
@@ -937,6 +947,7 @@ impl ::core::default::Default for Fieldless1 {
 }
 #[automatically_derived]
 impl ::core::hash::Hash for Fieldless1 {
+    #[inline]
     fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {}
 }
 #[automatically_derived]
@@ -1004,6 +1015,7 @@ impl ::core::default::Default for Fieldless {
 }
 #[automatically_derived]
 impl ::core::hash::Hash for Fieldless {
+    #[inline]
     fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
         let __self_tag = ::core::intrinsics::discriminant_value(self);
         ::core::hash::Hash::hash(&__self_tag, state)
@@ -1095,6 +1107,7 @@ impl ::core::default::Default for Mixed {
 }
 #[automatically_derived]
 impl ::core::hash::Hash for Mixed {
+    #[inline]
     fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
         let __self_tag = ::core::intrinsics::discriminant_value(self);
         ::core::hash::Hash::hash(&__self_tag, state);
@@ -1224,6 +1237,7 @@ impl ::core::fmt::Debug for Fielded {
 }
 #[automatically_derived]
 impl ::core::hash::Hash for Fielded {
+    #[inline]
     fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
         let __self_tag = ::core::intrinsics::discriminant_value(self);
         ::core::hash::Hash::hash(&__self_tag, state);
@@ -1345,6 +1359,7 @@ impl<T: ::core::fmt::Debug, U: ::core::fmt::Debug> ::core::fmt::Debug for
 #[automatically_derived]
 impl<T: ::core::hash::Hash, U: ::core::hash::Hash> ::core::hash::Hash for
     EnumGeneric<T, U> {
+    #[inline]
     fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
         let __self_tag = ::core::intrinsics::discriminant_value(self);
         ::core::hash::Hash::hash(&__self_tag, state);
diff --git a/tests/ui/editions/edition-raw-pointer-method-2018.rs b/tests/ui/editions/edition-raw-pointer-method-2018.rs
index af0b2d6bd4a..0bae65a9ae5 100644
--- a/tests/ui/editions/edition-raw-pointer-method-2018.rs
+++ b/tests/ui/editions/edition-raw-pointer-method-2018.rs
@@ -7,5 +7,5 @@ fn main() {
     let x = 0;
     let y = &x as *const _;
     let _ = y.is_null();
-    //~^ error: the type of this value must be known to call a method on a raw pointer on it [E0699]
+    //~^ error: cannot call a method on a raw pointer with an unknown pointee type [E0699]
 }
diff --git a/tests/ui/editions/edition-raw-pointer-method-2018.stderr b/tests/ui/editions/edition-raw-pointer-method-2018.stderr
index 23452495b4b..b9afa0133ca 100644
--- a/tests/ui/editions/edition-raw-pointer-method-2018.stderr
+++ b/tests/ui/editions/edition-raw-pointer-method-2018.stderr
@@ -1,4 +1,4 @@
-error[E0699]: the type of this value must be known to call a method on a raw pointer on it
+error[E0699]: cannot call a method on a raw pointer with an unknown pointee type
   --> $DIR/edition-raw-pointer-method-2018.rs:9:15
    |
 LL |     let _ = y.is_null();
diff --git a/tests/ui/issues/issue-50689.rs b/tests/ui/enum-discriminant/issue-50689.rs
index b49f2950020..b49f2950020 100644
--- a/tests/ui/issues/issue-50689.rs
+++ b/tests/ui/enum-discriminant/issue-50689.rs
diff --git a/tests/ui/issues/issue-1251.rs b/tests/ui/extern/issue-1251.rs
index c2c047c7961..c2c047c7961 100644
--- a/tests/ui/issues/issue-1251.rs
+++ b/tests/ui/extern/issue-1251.rs
diff --git a/tests/ui/issues/issue-1257.rs b/tests/ui/for-loop-while/issue-1257.rs
index de5a6d35925..de5a6d35925 100644
--- a/tests/ui/issues/issue-1257.rs
+++ b/tests/ui/for-loop-while/issue-1257.rs
diff --git a/tests/ui/higher-rank-trait-bounds/issue-95230.rs b/tests/ui/higher-rank-trait-bounds/issue-95230.rs
deleted file mode 100644
index 769b6a92537..00000000000
--- a/tests/ui/higher-rank-trait-bounds/issue-95230.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-// revisions: old new
-//[new] compile-flags: -Ztrait-solver=next
-//[old] check-pass
-//[new] known-bug: #109764
-
-
-pub struct Bar
-where
-    for<'a> &'a mut Self:;
-
-fn main() {}
diff --git a/tests/ui/higher-lifetime-bounds.rs b/tests/ui/higher-ranked/higher-lifetime-bounds.rs
index f3393347d90..f3393347d90 100644
--- a/tests/ui/higher-lifetime-bounds.rs
+++ b/tests/ui/higher-ranked/higher-lifetime-bounds.rs
diff --git a/tests/ui/higher-lifetime-bounds.stderr b/tests/ui/higher-ranked/higher-lifetime-bounds.stderr
index bc6d2288cdf..bc6d2288cdf 100644
--- a/tests/ui/higher-lifetime-bounds.stderr
+++ b/tests/ui/higher-ranked/higher-lifetime-bounds.stderr
diff --git a/tests/ui/higher-ranked/leak-check-in-selection.rs b/tests/ui/higher-ranked/leak-check-in-selection.rs
new file mode 100644
index 00000000000..e8d6cff856c
--- /dev/null
+++ b/tests/ui/higher-ranked/leak-check-in-selection.rs
@@ -0,0 +1,24 @@
+// run-pass
+// revisions: old next
+//[next] compile-flags: -Ztrait-solver=next
+#![allow(coherence_leak_check)]
+
+trait Trait: Sized {
+    fn is_higher_ranked(self) -> bool;
+}
+
+impl Trait for for<'a> fn(&'a ()) {
+    fn is_higher_ranked(self) -> bool {
+        true
+    }
+}
+impl<'a> Trait for fn(&'a ()) {
+    fn is_higher_ranked(self) -> bool {
+        false
+    }
+}
+
+fn main() {
+    let x: for<'a> fn(&'a ()) = |&()| ();
+    assert!(x.is_higher_ranked());
+}
diff --git a/tests/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr b/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr
index b7264c7e933..b7264c7e933 100644
--- a/tests/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr
+++ b/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr
diff --git a/tests/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr b/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_vs_free_x.stderr
index 2355979b0f9..2355979b0f9 100644
--- a/tests/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr
+++ b/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_vs_free_x.stderr
diff --git a/tests/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr b/tests/ui/higher-ranked/subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr
index a73c03feb87..a73c03feb87 100644
--- a/tests/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr
+++ b/tests/ui/higher-ranked/subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr
diff --git a/tests/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr b/tests/ui/higher-ranked/subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr
index 31d36d7168b..31d36d7168b 100644
--- a/tests/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr
+++ b/tests/ui/higher-ranked/subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr
diff --git a/tests/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr b/tests/ui/higher-ranked/subtype/hr-subtype.free_x_vs_free_y.stderr
index 269cde54c7e..269cde54c7e 100644
--- a/tests/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr
+++ b/tests/ui/higher-ranked/subtype/hr-subtype.free_x_vs_free_y.stderr
diff --git a/tests/ui/hr-subtype/hr-subtype.rs b/tests/ui/higher-ranked/subtype/hr-subtype.rs
index c770e0de85c..c770e0de85c 100644
--- a/tests/ui/hr-subtype/hr-subtype.rs
+++ b/tests/ui/higher-ranked/subtype/hr-subtype.rs
diff --git a/tests/ui/hr-subtype/placeholder-pattern-fail.rs b/tests/ui/higher-ranked/subtype/placeholder-pattern-fail.rs
index bd4533e0433..bd4533e0433 100644
--- a/tests/ui/hr-subtype/placeholder-pattern-fail.rs
+++ b/tests/ui/higher-ranked/subtype/placeholder-pattern-fail.rs
diff --git a/tests/ui/hr-subtype/placeholder-pattern-fail.stderr b/tests/ui/higher-ranked/subtype/placeholder-pattern-fail.stderr
index 73b0a317364..73b0a317364 100644
--- a/tests/ui/hr-subtype/placeholder-pattern-fail.stderr
+++ b/tests/ui/higher-ranked/subtype/placeholder-pattern-fail.stderr
diff --git a/tests/ui/hr-subtype/placeholder-pattern.rs b/tests/ui/higher-ranked/subtype/placeholder-pattern.rs
index 061e66e54d2..061e66e54d2 100644
--- a/tests/ui/hr-subtype/placeholder-pattern.rs
+++ b/tests/ui/higher-ranked/subtype/placeholder-pattern.rs
diff --git a/tests/ui/hr-subtype/return-static.rs b/tests/ui/higher-ranked/subtype/return-static.rs
index 6455854f34d..6455854f34d 100644
--- a/tests/ui/hr-subtype/return-static.rs
+++ b/tests/ui/higher-ranked/subtype/return-static.rs
diff --git a/tests/ui/higher-rank-trait-bounds/complex.rs b/tests/ui/higher-ranked/trait-bounds/complex.rs
index 8cdfe247e02..8cdfe247e02 100644
--- a/tests/ui/higher-rank-trait-bounds/complex.rs
+++ b/tests/ui/higher-ranked/trait-bounds/complex.rs
diff --git a/tests/ui/higher-rank-trait-bounds/due-to-where-clause.rs b/tests/ui/higher-ranked/trait-bounds/due-to-where-clause.rs
index 1afd15613b5..1afd15613b5 100644
--- a/tests/ui/higher-rank-trait-bounds/due-to-where-clause.rs
+++ b/tests/ui/higher-ranked/trait-bounds/due-to-where-clause.rs
diff --git a/tests/ui/higher-rank-trait-bounds/due-to-where-clause.stderr b/tests/ui/higher-ranked/trait-bounds/due-to-where-clause.stderr
index 520938a6335..520938a6335 100644
--- a/tests/ui/higher-rank-trait-bounds/due-to-where-clause.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/due-to-where-clause.stderr
diff --git a/tests/ui/higher-rank-trait-bounds/fn-ptr.classic.stderr b/tests/ui/higher-ranked/trait-bounds/fn-ptr.classic.stderr
index 9af6bc45c7a..9af6bc45c7a 100644
--- a/tests/ui/higher-rank-trait-bounds/fn-ptr.classic.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/fn-ptr.classic.stderr
diff --git a/tests/ui/higher-rank-trait-bounds/fn-ptr.rs b/tests/ui/higher-ranked/trait-bounds/fn-ptr.rs
index 853160f9612..853160f9612 100644
--- a/tests/ui/higher-rank-trait-bounds/fn-ptr.rs
+++ b/tests/ui/higher-ranked/trait-bounds/fn-ptr.rs
diff --git a/tests/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.rs b/tests/ui/higher-ranked/trait-bounds/hang-on-deeply-nested-dyn.rs
index d34b7a29623..d34b7a29623 100644
--- a/tests/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hang-on-deeply-nested-dyn.rs
diff --git a/tests/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.stderr b/tests/ui/higher-ranked/trait-bounds/hang-on-deeply-nested-dyn.stderr
index 3662cbfb9ba..a9d649b8285 100644
--- a/tests/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/hang-on-deeply-nested-dyn.stderr
@@ -14,7 +14,7 @@ LL |       f
    |       ^ expected `&dyn Fn(&dyn Fn(&dyn Fn(&...)))`, found `&dyn Fn(u32)`
    |
    = note: expected reference `&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&...)))))))))))`
-           the full type name has been written to '$TEST_BUILD_DIR/higher-rank-trait-bounds/hang-on-deeply-nested-dyn/hang-on-deeply-nested-dyn.long-type-hash.txt'
+           the full type name has been written to '$TEST_BUILD_DIR/higher-ranked/trait-bounds/hang-on-deeply-nested-dyn/hang-on-deeply-nested-dyn.long-type-hash.txt'
               found reference `&dyn Fn(u32)`
 
 error: aborting due to previous error
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-binder-levels-in-object-types.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-binder-levels-in-object-types.rs
index cc766c0605c..cc766c0605c 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-binder-levels-in-object-types.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-binder-levels-in-object-types.rs
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-cache-issue-54302.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-cache-issue-54302.rs
index a20d03c7747..a20d03c7747 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-cache-issue-54302.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-cache-issue-54302.rs
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-cache-issue-54302.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-cache-issue-54302.stderr
index f014eab8601..f014eab8601 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-cache-issue-54302.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-cache-issue-54302.stderr
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-conflate-regions.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.rs
index e83686404a3..e83686404a3 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-conflate-regions.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.rs
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-conflate-regions.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr
index 46f5308dd87..46f5308dd87 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-conflate-regions.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-debruijn-in-receiver.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-debruijn-in-receiver.rs
index 05d3e1a434e..05d3e1a434e 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-debruijn-in-receiver.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-debruijn-in-receiver.rs
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-debruijn-in-receiver.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-debruijn-in-receiver.stderr
index fa391ecba8a..fa391ecba8a 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-debruijn-in-receiver.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-debruijn-in-receiver.stderr
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-debruijn-object-types-in-closures.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-debruijn-object-types-in-closures.rs
index 8431226a3ec..8431226a3ec 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-debruijn-object-types-in-closures.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-debruijn-object-types-in-closures.rs
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-fn.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-fn.rs
index 56780237618..56780237618 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-fn.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-fn.rs
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-fn.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-fn.stderr
index 9914783d976..9914783d976 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-fn.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-fn.stderr
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-contravariant.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.rs
index 921061916fc..921061916fc 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-contravariant.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.rs
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-contravariant.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.stderr
index 364b613fc77..364b613fc77 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-contravariant.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.stderr
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-covariant.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.rs
index f95496a6c3c..f95496a6c3c 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-covariant.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.rs
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-invariant.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.rs
index 9b9e4496a87..9b9e4496a87 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-invariant.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.rs
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-invariant.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.stderr
index cb2ce8a4116..cb2ce8a4116 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-invariant.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.stderr
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-fn-like-trait-object.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-fn-like-trait-object.rs
index ff84ad9d298..ff84ad9d298 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-fn-like-trait-object.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-fn-like-trait-object.rs
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-fn-like-trait.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-fn-like-trait.rs
index afab9986ce2..afab9986ce2 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-fn-like-trait.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-fn-like-trait.rs
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits-transitive.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits-transitive.rs
index f9ae1429ee4..f9ae1429ee4 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits-transitive.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits-transitive.rs
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr
index b1b8ffa8c54..b1b8ffa8c54 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.rs
index 48ebe5017aa..48ebe5017aa 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.rs
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr
index 7f96909b6e7..7f96909b6e7 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-identity-fn-borrows.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-identity-fn-borrows.rs
index 89fc4705a78..89fc4705a78 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-identity-fn-borrows.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-identity-fn-borrows.rs
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-identity-fn-borrows.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-identity-fn-borrows.stderr
index 25af011e3fc..25af011e3fc 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-identity-fn-borrows.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-identity-fn-borrows.stderr
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-just-for-static.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-just-for-static.rs
index 8fb4218f8a4..8fb4218f8a4 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-just-for-static.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-just-for-static.rs
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-just-for-static.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-just-for-static.stderr
index 31e11e12835..31e11e12835 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-just-for-static.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-just-for-static.stderr
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-malformed-lifetime-generics.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-malformed-lifetime-generics.rs
index 4b096be591a..4b096be591a 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-malformed-lifetime-generics.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-malformed-lifetime-generics.rs
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-malformed-lifetime-generics.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-malformed-lifetime-generics.stderr
index e8f6d63b5ab..e8f6d63b5ab 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-malformed-lifetime-generics.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-malformed-lifetime-generics.stderr
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-opt-in-copy.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-opt-in-copy.rs
index 04519f11600..04519f11600 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-opt-in-copy.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-opt-in-copy.rs
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-parse.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-parse.rs
index 1fab9758c5c..1fab9758c5c 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-parse.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-parse.rs
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.polonius.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.polonius.stderr
index a94c80eb30b..a94c80eb30b 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.polonius.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.polonius.stderr
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.rs
index d45fa183c0c..d45fa183c0c 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.rs
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.stderr
index 727b9e6bec8..727b9e6bec8 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.stderr
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-precedence-of-plus-where-clause.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-precedence-of-plus-where-clause.rs
index 42247798f66..42247798f66 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-precedence-of-plus-where-clause.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-precedence-of-plus-where-clause.rs
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-precedence-of-plus.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-precedence-of-plus.rs
index 6834c392d4e..6834c392d4e 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-precedence-of-plus.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-precedence-of-plus.rs
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-resolve-lifetime.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-resolve-lifetime.rs
index b97fdf4df50..b97fdf4df50 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-resolve-lifetime.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-resolve-lifetime.rs
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-trait-object-paren-notation.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-trait-object-paren-notation.rs
index d8c726cdd71..d8c726cdd71 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-trait-object-paren-notation.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-trait-object-paren-notation.rs
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-trait-object-passed-to-closure.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-trait-object-passed-to-closure.rs
index 41ebb3f5a14..41ebb3f5a14 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-trait-object-passed-to-closure.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-trait-object-passed-to-closure.rs
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-type-outlives.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-type-outlives.rs
index 88d396101db..88d396101db 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-type-outlives.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-type-outlives.rs
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-unboxed-closure-trait.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-unboxed-closure-trait.rs
index a4a8a5ac6cc..a4a8a5ac6cc 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-unboxed-closure-trait.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-unboxed-closure-trait.rs
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-wrong-kind.rs
index 1a9bb252340..1a9bb252340 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-wrong-kind.rs
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-wrong-kind.stderr
index 765ea9f7854..765ea9f7854 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-wrong-kind.stderr
diff --git a/tests/ui/higher-rank-trait-bounds/issue-100689.rs b/tests/ui/higher-ranked/trait-bounds/issue-100689.rs
index 2db7f8a354c..2db7f8a354c 100644
--- a/tests/ui/higher-rank-trait-bounds/issue-100689.rs
+++ b/tests/ui/higher-ranked/trait-bounds/issue-100689.rs
diff --git a/tests/ui/higher-rank-trait-bounds/issue-102899.rs b/tests/ui/higher-ranked/trait-bounds/issue-102899.rs
index 952b81584f3..952b81584f3 100644
--- a/tests/ui/higher-rank-trait-bounds/issue-102899.rs
+++ b/tests/ui/higher-ranked/trait-bounds/issue-102899.rs
diff --git a/tests/ui/higher-rank-trait-bounds/issue-30786.rs b/tests/ui/higher-ranked/trait-bounds/issue-30786.rs
index 4a6399c8f62..4a6399c8f62 100644
--- a/tests/ui/higher-rank-trait-bounds/issue-30786.rs
+++ b/tests/ui/higher-ranked/trait-bounds/issue-30786.rs
diff --git a/tests/ui/higher-rank-trait-bounds/issue-30786.stderr b/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr
index 6ec34d11a7e..f32ba57200d 100644
--- a/tests/ui/higher-rank-trait-bounds/issue-30786.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr
@@ -31,7 +31,7 @@ LL | pub struct Filter<S, F> {
 LL |     let count = filter.countx();
    |                        ^^^^^^ method cannot be called due to unsatisfied trait bounds
    |
-   = note: the full type name has been written to '$TEST_BUILD_DIR/higher-rank-trait-bounds/issue-30786/issue-30786.long-type-hash.txt'
+   = note: the full type name has been written to '$TEST_BUILD_DIR/higher-ranked/trait-bounds/issue-30786/issue-30786.long-type-hash.txt'
 note: the following trait bounds were not satisfied:
       `&'a mut &Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:131:30: 131:37]>: Stream`
       `&'a mut &mut Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:131:30: 131:37]>: Stream`
diff --git a/tests/ui/higher-rank-trait-bounds/issue-36139-normalize-closure-sig.rs b/tests/ui/higher-ranked/trait-bounds/issue-36139-normalize-closure-sig.rs
index 2d49151ffcc..2d49151ffcc 100644
--- a/tests/ui/higher-rank-trait-bounds/issue-36139-normalize-closure-sig.rs
+++ b/tests/ui/higher-ranked/trait-bounds/issue-36139-normalize-closure-sig.rs
diff --git a/tests/ui/higher-rank-trait-bounds/issue-39292.rs b/tests/ui/higher-ranked/trait-bounds/issue-39292.rs
index 968cf08916f..968cf08916f 100644
--- a/tests/ui/higher-rank-trait-bounds/issue-39292.rs
+++ b/tests/ui/higher-ranked/trait-bounds/issue-39292.rs
diff --git a/tests/ui/higher-rank-trait-bounds/issue-42114.rs b/tests/ui/higher-ranked/trait-bounds/issue-42114.rs
index 01515fdc9d2..01515fdc9d2 100644
--- a/tests/ui/higher-rank-trait-bounds/issue-42114.rs
+++ b/tests/ui/higher-ranked/trait-bounds/issue-42114.rs
diff --git a/tests/ui/higher-rank-trait-bounds/issue-43623.rs b/tests/ui/higher-ranked/trait-bounds/issue-43623.rs
index cedcf7c361c..cedcf7c361c 100644
--- a/tests/ui/higher-rank-trait-bounds/issue-43623.rs
+++ b/tests/ui/higher-ranked/trait-bounds/issue-43623.rs
diff --git a/tests/ui/higher-rank-trait-bounds/issue-46989.rs b/tests/ui/higher-ranked/trait-bounds/issue-46989.rs
index 4a09f4be156..4a09f4be156 100644
--- a/tests/ui/higher-rank-trait-bounds/issue-46989.rs
+++ b/tests/ui/higher-ranked/trait-bounds/issue-46989.rs
diff --git a/tests/ui/higher-rank-trait-bounds/issue-46989.stderr b/tests/ui/higher-ranked/trait-bounds/issue-46989.stderr
index 3f874220a27..3f874220a27 100644
--- a/tests/ui/higher-rank-trait-bounds/issue-46989.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/issue-46989.stderr
diff --git a/tests/ui/higher-rank-trait-bounds/issue-57639.rs b/tests/ui/higher-ranked/trait-bounds/issue-57639.rs
index 392e7233b56..392e7233b56 100644
--- a/tests/ui/higher-rank-trait-bounds/issue-57639.rs
+++ b/tests/ui/higher-ranked/trait-bounds/issue-57639.rs
diff --git a/tests/ui/higher-rank-trait-bounds/issue-58451.rs b/tests/ui/higher-ranked/trait-bounds/issue-58451.rs
index 6006a108c5c..6006a108c5c 100644
--- a/tests/ui/higher-rank-trait-bounds/issue-58451.rs
+++ b/tests/ui/higher-ranked/trait-bounds/issue-58451.rs
diff --git a/tests/ui/higher-rank-trait-bounds/issue-58451.stderr b/tests/ui/higher-ranked/trait-bounds/issue-58451.stderr
index 0f051be2128..0f051be2128 100644
--- a/tests/ui/higher-rank-trait-bounds/issue-58451.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/issue-58451.stderr
diff --git a/tests/ui/higher-rank-trait-bounds/issue-59311.rs b/tests/ui/higher-ranked/trait-bounds/issue-59311.rs
index 3ad548450e5..3ad548450e5 100644
--- a/tests/ui/higher-rank-trait-bounds/issue-59311.rs
+++ b/tests/ui/higher-ranked/trait-bounds/issue-59311.rs
diff --git a/tests/ui/higher-rank-trait-bounds/issue-59311.stderr b/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr
index c01ab8e347c..c01ab8e347c 100644
--- a/tests/ui/higher-rank-trait-bounds/issue-59311.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr
diff --git a/tests/ui/higher-rank-trait-bounds/issue-60283.rs b/tests/ui/higher-ranked/trait-bounds/issue-60283.rs
index 05315b3f9f5..05315b3f9f5 100644
--- a/tests/ui/higher-rank-trait-bounds/issue-60283.rs
+++ b/tests/ui/higher-ranked/trait-bounds/issue-60283.rs
diff --git a/tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.rs b/tests/ui/higher-ranked/trait-bounds/issue-62203-hrtb-ice.rs
index e70f6fc3430..e70f6fc3430 100644
--- a/tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.rs
+++ b/tests/ui/higher-ranked/trait-bounds/issue-62203-hrtb-ice.rs
diff --git a/tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr b/tests/ui/higher-ranked/trait-bounds/issue-62203-hrtb-ice.stderr
index 4d470ae7022..4d470ae7022 100644
--- a/tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/issue-62203-hrtb-ice.stderr
diff --git a/tests/ui/higher-rank-trait-bounds/issue-88446.rs b/tests/ui/higher-ranked/trait-bounds/issue-88446.rs
index 571b8531757..571b8531757 100644
--- a/tests/ui/higher-rank-trait-bounds/issue-88446.rs
+++ b/tests/ui/higher-ranked/trait-bounds/issue-88446.rs
diff --git a/tests/ui/higher-rank-trait-bounds/issue-88586-hr-self-outlives-in-trait-def.rs b/tests/ui/higher-ranked/trait-bounds/issue-88586-hr-self-outlives-in-trait-def.rs
index 92b7c5deb81..92b7c5deb81 100644
--- a/tests/ui/higher-rank-trait-bounds/issue-88586-hr-self-outlives-in-trait-def.rs
+++ b/tests/ui/higher-ranked/trait-bounds/issue-88586-hr-self-outlives-in-trait-def.rs
diff --git a/tests/ui/higher-rank-trait-bounds/issue-90177.rs b/tests/ui/higher-ranked/trait-bounds/issue-90177.rs
index b151a9d3ab6..b151a9d3ab6 100644
--- a/tests/ui/higher-rank-trait-bounds/issue-90177.rs
+++ b/tests/ui/higher-ranked/trait-bounds/issue-90177.rs
diff --git a/tests/ui/higher-rank-trait-bounds/issue-95034.rs b/tests/ui/higher-ranked/trait-bounds/issue-95034.rs
index af4946a187f..af4946a187f 100644
--- a/tests/ui/higher-rank-trait-bounds/issue-95034.rs
+++ b/tests/ui/higher-ranked/trait-bounds/issue-95034.rs
diff --git a/tests/ui/higher-rank-trait-bounds/issue-95230.new.stderr b/tests/ui/higher-ranked/trait-bounds/issue-95230.next.stderr
index d4bc5b67220..d4bc5b67220 100644
--- a/tests/ui/higher-rank-trait-bounds/issue-95230.new.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/issue-95230.next.stderr
diff --git a/tests/ui/higher-ranked/trait-bounds/issue-95230.rs b/tests/ui/higher-ranked/trait-bounds/issue-95230.rs
new file mode 100644
index 00000000000..49a1584d54e
--- /dev/null
+++ b/tests/ui/higher-ranked/trait-bounds/issue-95230.rs
@@ -0,0 +1,11 @@
+// revisions: old next
+//[next] compile-flags: -Ztrait-solver=next
+//[old] check-pass
+//[next] known-bug: #109764
+
+
+pub struct Bar
+where
+    for<'a> &'a mut Self:;
+
+fn main() {}
diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-44005.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-44005.rs
index f255eac0c4b..f255eac0c4b 100644
--- a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-44005.rs
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-44005.rs
diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-56556.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-56556.rs
index 4d38cb19e9b..4d38cb19e9b 100644
--- a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-56556.rs
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-56556.rs
diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-1.rs
index c6f29fa5908..c6f29fa5908 100644
--- a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-1.rs
diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-2.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-2.rs
index 00205473291..00205473291 100644
--- a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-2.rs
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-2.rs
diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.rs
index d84e30f4984..d84e30f4984 100644
--- a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.rs
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.rs
diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr
index b30dd36d2ad..b30dd36d2ad 100644
--- a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr
diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-4.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-4.rs
index 8c2a59868ca..8c2a59868ca 100644
--- a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-4.rs
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-4.rs
diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-5.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-5.rs
index 03f257a029c..03f257a029c 100644
--- a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-5.rs
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-5.rs
diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-6.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-6.rs
index 74a4785e478..74a4785e478 100644
--- a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-6.rs
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-6.rs
diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-70120.rs
index 3ced40230f0..3ced40230f0 100644
--- a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.rs
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-70120.rs
diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.migrate.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.migrate.stderr
index 0f38f8e3283..0f38f8e3283 100644
--- a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.migrate.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.migrate.stderr
diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.rs
index 1d90226a3f4..1d90226a3f4 100644
--- a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.rs
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.rs
diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr
index 4ef96cd9541..4ef96cd9541 100644
--- a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr
diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-74261.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-74261.rs
index 93ccb42684c..93ccb42684c 100644
--- a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-74261.rs
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-74261.rs
diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-76956.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-76956.rs
index 583470080a2..583470080a2 100644
--- a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-76956.rs
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-76956.rs
diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80706.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-80706.rs
index 00a866f220b..00a866f220b 100644
--- a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80706.rs
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-80706.rs
diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80956.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-80956.rs
index 6316ceea156..6316ceea156 100644
--- a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80956.rs
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-80956.rs
diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-81809.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-81809.rs
index f6ab9c203b5..f6ab9c203b5 100644
--- a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-81809.rs
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-81809.rs
diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-85455.rs
index 8aa29926d4f..8aa29926d4f 100644
--- a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-85455.rs
diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-85455.stderr
index 3240518fbbe..3240518fbbe 100644
--- a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-85455.stderr
diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89118.rs
index fffb54f86ca..fffb54f86ca 100644
--- a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.rs
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89118.rs
diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89118.stderr
index edef6ccd34e..edef6ccd34e 100644
--- a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89118.stderr
diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89436.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89436.rs
index f7e467b3786..f7e467b3786 100644
--- a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89436.rs
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89436.rs
diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90612.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90612.rs
index effc329456d..effc329456d 100644
--- a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90612.rs
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90612.rs
diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90638.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90638.rs
index 628b5cba104..628b5cba104 100644
--- a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90638.rs
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90638.rs
diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90875.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90875.rs
index ffd6857d84a..ffd6857d84a 100644
--- a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90875.rs
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90875.rs
diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90950.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90950.rs
index ab9d9a7ce6f..ab9d9a7ce6f 100644
--- a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90950.rs
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90950.rs
diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90950.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90950.stderr
index 5be33bccdc3..5be33bccdc3 100644
--- a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90950.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90950.stderr
diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/norm-before-method-resolution.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution.rs
index 7693b118247..7693b118247 100644
--- a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/norm-before-method-resolution.rs
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution.rs
diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/norm-before-method-resolution.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution.stderr
index 73388a72574..73388a72574 100644
--- a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/norm-before-method-resolution.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution.stderr
diff --git a/tests/ui/impl-trait/autoderef.rs b/tests/ui/impl-trait/autoderef.rs
index 5e4f4995447..0d07a549640 100644
--- a/tests/ui/impl-trait/autoderef.rs
+++ b/tests/ui/impl-trait/autoderef.rs
@@ -1,3 +1,5 @@
+// revisions: current next
+//[next] compile-flag: -Ztrait-solver=next
 // check-pass
 
 use std::path::Path;
diff --git a/tests/ui/impl-trait/multiple-defining-usages-in-body.rs b/tests/ui/impl-trait/multiple-defining-usages-in-body.rs
new file mode 100644
index 00000000000..c3a6f09f86d
--- /dev/null
+++ b/tests/ui/impl-trait/multiple-defining-usages-in-body.rs
@@ -0,0 +1,12 @@
+trait Trait {}
+impl Trait for () {}
+
+fn foo<T: Trait, U: Trait>() -> impl Trait {
+    //~^ WARN function cannot return without recursing [unconditional_recursion]
+    let a: T = foo::<T, U>();
+    //~^ ERROR concrete type differs from previous defining opaque type use
+    loop {}
+    let _: T = foo::<U, T>();
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/multiple-defining-usages-in-body.stderr b/tests/ui/impl-trait/multiple-defining-usages-in-body.stderr
new file mode 100644
index 00000000000..06991749bfa
--- /dev/null
+++ b/tests/ui/impl-trait/multiple-defining-usages-in-body.stderr
@@ -0,0 +1,26 @@
+warning: function cannot return without recursing
+  --> $DIR/multiple-defining-usages-in-body.rs:4:1
+   |
+LL | fn foo<T: Trait, U: Trait>() -> impl Trait {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
+LL |
+LL |     let a: T = foo::<T, U>();
+   |                ------------- recursive call site
+   |
+   = help: a `loop` may express intention better if this is on purpose
+   = note: `#[warn(unconditional_recursion)]` on by default
+
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/multiple-defining-usages-in-body.rs:6:16
+   |
+LL |     let a: T = foo::<T, U>();
+   |                ^^^^^^^^^^^^^ expected `U`, got `T`
+   |
+note: previous use here
+  --> $DIR/multiple-defining-usages-in-body.rs:9:16
+   |
+LL |     let _: T = foo::<U, T>();
+   |                ^^^^^^^^^^^^^
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/tests/ui/imports/issue-55884-2.rs b/tests/ui/imports/issue-55884-2.rs
index 75bb4206f97..6f8d0cf8ae2 100644
--- a/tests/ui/imports/issue-55884-2.rs
+++ b/tests/ui/imports/issue-55884-2.rs
@@ -6,6 +6,7 @@ mod parser {
     pub use options::*;
     // Private single import shadows public glob import, but arrives too late for initial
     // resolution of `use parser::ParseOptions` because it depends on that resolution itself.
+    #[allow(hidden_glob_reexports)]
     use ParseOptions;
 }
 
diff --git a/tests/ui/imports/issue-55884-2.stderr b/tests/ui/imports/issue-55884-2.stderr
index 5adbc4b66d1..67d4114149a 100644
--- a/tests/ui/imports/issue-55884-2.stderr
+++ b/tests/ui/imports/issue-55884-2.stderr
@@ -1,16 +1,16 @@
 error[E0603]: struct import `ParseOptions` is private
-  --> $DIR/issue-55884-2.rs:12:17
+  --> $DIR/issue-55884-2.rs:13:17
    |
 LL | pub use parser::ParseOptions;
    |                 ^^^^^^^^^^^^ private struct import
    |
 note: the struct import `ParseOptions` is defined here...
-  --> $DIR/issue-55884-2.rs:9:9
+  --> $DIR/issue-55884-2.rs:10:9
    |
 LL |     use ParseOptions;
    |         ^^^^^^^^^^^^
 note: ...and refers to the struct import `ParseOptions` which is defined here...
-  --> $DIR/issue-55884-2.rs:12:9
+  --> $DIR/issue-55884-2.rs:13:9
    |
 LL | pub use parser::ParseOptions;
    |         ^^^^^^^^^^^^^^^^^^^^ consider importing it directly
diff --git a/tests/ui/issues/issue-17954.stderr b/tests/ui/issues/issue-17954.stderr
index e08375fee1f..3e3706bcb7d 100644
--- a/tests/ui/issues/issue-17954.stderr
+++ b/tests/ui/issues/issue-17954.stderr
@@ -5,7 +5,7 @@ LL |     let a = &FOO;
    |             ^^^^ thread-local variables cannot be borrowed beyond the end of the function
 ...
 LL | }
-   | - end of enclosing function is here
+   |  - end of enclosing function is here
 
 error: aborting due to previous error
 
diff --git a/tests/ui/issues/issue-52049.stderr b/tests/ui/issues/issue-52049.stderr
index b25dbd1cb8b..0812976cf40 100644
--- a/tests/ui/issues/issue-52049.stderr
+++ b/tests/ui/issues/issue-52049.stderr
@@ -2,12 +2,10 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/issue-52049.rs:6:10
    |
 LL |     foo(&unpromotable(5u32));
-   |     -----^^^^^^^^^^^^^^^^^^-
+   |     -----^^^^^^^^^^^^^^^^^^-- temporary value is freed at the end of this statement
    |     |    |
    |     |    creates a temporary value which is freed while still in use
    |     argument requires that borrow lasts for `'static`
-LL | }
-   | - temporary value is freed at the end of this statement
 
 error: aborting due to previous error
 
diff --git a/tests/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr b/tests/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr
index 3602de8dd95..598f1424191 100644
--- a/tests/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr
+++ b/tests/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr
@@ -10,7 +10,7 @@ LL |     let read = &refcell as &RefCell<dyn Read>;
    |                -------- cast requires that `foo` is borrowed for `'static`
 ...
 LL | }
-   | - `foo` dropped here while still borrowed
+   |  - `foo` dropped here while still borrowed
 
 error: lifetime may not live long enough
   --> $DIR/issue-90600-expected-return-static-indirect.rs:9:16
diff --git a/tests/ui/lint/invalid_from_utf8.rs b/tests/ui/lint/invalid_from_utf8.rs
new file mode 100644
index 00000000000..9c8c636812e
--- /dev/null
+++ b/tests/ui/lint/invalid_from_utf8.rs
@@ -0,0 +1,93 @@
+// check-pass
+
+#![feature(concat_bytes)]
+#![warn(invalid_from_utf8_unchecked)]
+#![warn(invalid_from_utf8)]
+
+pub fn from_utf8_unchecked_mut() {
+    // Valid
+    unsafe {
+        std::str::from_utf8_unchecked_mut(&mut [99, 108, 105, 112, 112, 121]);
+        std::str::from_utf8_unchecked_mut(&mut [b'c', b'l', b'i', b'p', b'p', b'y']);
+
+        let x = 0xA0;
+        std::str::from_utf8_unchecked_mut(&mut [0xC0, x]);
+    }
+
+    // Invalid
+    unsafe {
+        std::str::from_utf8_unchecked_mut(&mut [99, 108, 130, 105, 112, 112, 121]);
+        //~^ WARN calls to `std::str::from_utf8_unchecked_mut`
+        std::str::from_utf8_unchecked_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
+        //~^ WARN calls to `std::str::from_utf8_unchecked_mut`
+    }
+}
+
+pub fn from_utf8_unchecked() {
+    // Valid
+    unsafe {
+        std::str::from_utf8_unchecked(&[99, 108, 105, 112, 112, 121]);
+        std::str::from_utf8_unchecked(&[b'c', b'l', b'i', b'p', b'p', b'y']);
+        std::str::from_utf8_unchecked(b"clippy");
+
+        let x = 0xA0;
+        std::str::from_utf8_unchecked(&[0xC0, x]);
+    }
+
+    // Invalid
+    unsafe {
+        std::str::from_utf8_unchecked(&[99, 108, 130, 105, 112, 112, 121]);
+        //~^ WARN calls to `std::str::from_utf8_unchecked`
+        std::str::from_utf8_unchecked(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
+        //~^ WARN calls to `std::str::from_utf8_unchecked`
+        std::str::from_utf8_unchecked(b"cl\x82ippy");
+        //~^ WARN calls to `std::str::from_utf8_unchecked`
+        std::str::from_utf8_unchecked(concat_bytes!(b"cl", b"\x82ippy"));
+        //~^ WARN calls to `std::str::from_utf8_unchecked`
+    }
+}
+
+pub fn from_utf8_mut() {
+    // Valid
+    {
+        std::str::from_utf8_mut(&mut [99, 108, 105, 112, 112, 121]);
+        std::str::from_utf8_mut(&mut [b'c', b'l', b'i', b'p', b'p', b'y']);
+
+        let x = 0xa0;
+        std::str::from_utf8_mut(&mut [0xc0, x]);
+    }
+
+    // Invalid
+    {
+        std::str::from_utf8_mut(&mut [99, 108, 130, 105, 112, 112, 121]);
+        //~^ WARN calls to `std::str::from_utf8_mut`
+        std::str::from_utf8_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
+        //~^ WARN calls to `std::str::from_utf8_mut`
+    }
+}
+
+pub fn from_utf8() {
+    // Valid
+    {
+        std::str::from_utf8(&[99, 108, 105, 112, 112, 121]);
+        std::str::from_utf8(&[b'c', b'l', b'i', b'p', b'p', b'y']);
+        std::str::from_utf8(b"clippy");
+
+        let x = 0xA0;
+        std::str::from_utf8(&[0xC0, x]);
+    }
+
+    // Invalid
+    {
+        std::str::from_utf8(&[99, 108, 130, 105, 112, 112, 121]);
+        //~^ WARN calls to `std::str::from_utf8`
+        std::str::from_utf8(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
+        //~^ WARN calls to `std::str::from_utf8`
+        std::str::from_utf8(b"cl\x82ippy");
+        //~^ WARN calls to `std::str::from_utf8`
+        std::str::from_utf8(concat_bytes!(b"cl", b"\x82ippy"));
+        //~^ WARN calls to `std::str::from_utf8`
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/lint/invalid_from_utf8.stderr b/tests/ui/lint/invalid_from_utf8.stderr
new file mode 100644
index 00000000000..8e00d3bf872
--- /dev/null
+++ b/tests/ui/lint/invalid_from_utf8.stderr
@@ -0,0 +1,110 @@
+warning: calls to `std::str::from_utf8_unchecked_mut` with a invalid literal are undefined behavior
+  --> $DIR/invalid_from_utf8.rs:19:9
+   |
+LL |         std::str::from_utf8_unchecked_mut(&mut [99, 108, 130, 105, 112, 112, 121]);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------------^
+   |                                           |
+   |                                           the literal was valid UTF-8 up to the 2 bytes
+   |
+note: the lint level is defined here
+  --> $DIR/invalid_from_utf8.rs:4:9
+   |
+LL | #![warn(invalid_from_utf8_unchecked)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: calls to `std::str::from_utf8_unchecked_mut` with a invalid literal are undefined behavior
+  --> $DIR/invalid_from_utf8.rs:21:9
+   |
+LL |         std::str::from_utf8_unchecked_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--------------------------------------------------^
+   |                                           |
+   |                                           the literal was valid UTF-8 up to the 2 bytes
+
+warning: calls to `std::str::from_utf8_unchecked` with a invalid literal are undefined behavior
+  --> $DIR/invalid_from_utf8.rs:39:9
+   |
+LL |         std::str::from_utf8_unchecked(&[99, 108, 130, 105, 112, 112, 121]);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------------------------^
+   |                                       |
+   |                                       the literal was valid UTF-8 up to the 2 bytes
+
+warning: calls to `std::str::from_utf8_unchecked` with a invalid literal are undefined behavior
+  --> $DIR/invalid_from_utf8.rs:41:9
+   |
+LL |         std::str::from_utf8_unchecked(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------------------^
+   |                                       |
+   |                                       the literal was valid UTF-8 up to the 2 bytes
+
+warning: calls to `std::str::from_utf8_unchecked` with a invalid literal are undefined behavior
+  --> $DIR/invalid_from_utf8.rs:43:9
+   |
+LL |         std::str::from_utf8_unchecked(b"cl\x82ippy");
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------------^
+   |                                       |
+   |                                       the literal was valid UTF-8 up to the 2 bytes
+
+warning: calls to `std::str::from_utf8_unchecked` with a invalid literal are undefined behavior
+  --> $DIR/invalid_from_utf8.rs:45:9
+   |
+LL |         std::str::from_utf8_unchecked(concat_bytes!(b"cl", b"\x82ippy"));
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------^
+   |                                       |
+   |                                       the literal was valid UTF-8 up to the 2 bytes
+
+warning: calls to `std::str::from_utf8_mut` with a invalid literal always return an error
+  --> $DIR/invalid_from_utf8.rs:62:9
+   |
+LL |         std::str::from_utf8_mut(&mut [99, 108, 130, 105, 112, 112, 121]);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------------^
+   |                                 |
+   |                                 the literal was valid UTF-8 up to the 2 bytes
+   |
+note: the lint level is defined here
+  --> $DIR/invalid_from_utf8.rs:5:9
+   |
+LL | #![warn(invalid_from_utf8)]
+   |         ^^^^^^^^^^^^^^^^^
+
+warning: calls to `std::str::from_utf8_mut` with a invalid literal always return an error
+  --> $DIR/invalid_from_utf8.rs:64:9
+   |
+LL |         std::str::from_utf8_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^--------------------------------------------------^
+   |                                 |
+   |                                 the literal was valid UTF-8 up to the 2 bytes
+
+warning: calls to `std::str::from_utf8` with a invalid literal always return an error
+  --> $DIR/invalid_from_utf8.rs:82:9
+   |
+LL |         std::str::from_utf8(&[99, 108, 130, 105, 112, 112, 121]);
+   |         ^^^^^^^^^^^^^^^^^^^^-----------------------------------^
+   |                             |
+   |                             the literal was valid UTF-8 up to the 2 bytes
+
+warning: calls to `std::str::from_utf8` with a invalid literal always return an error
+  --> $DIR/invalid_from_utf8.rs:84:9
+   |
+LL |         std::str::from_utf8(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
+   |         ^^^^^^^^^^^^^^^^^^^^----------------------------------------------^
+   |                             |
+   |                             the literal was valid UTF-8 up to the 2 bytes
+
+warning: calls to `std::str::from_utf8` with a invalid literal always return an error
+  --> $DIR/invalid_from_utf8.rs:86:9
+   |
+LL |         std::str::from_utf8(b"cl\x82ippy");
+   |         ^^^^^^^^^^^^^^^^^^^^-------------^
+   |                             |
+   |                             the literal was valid UTF-8 up to the 2 bytes
+
+warning: calls to `std::str::from_utf8` with a invalid literal always return an error
+  --> $DIR/invalid_from_utf8.rs:88:9
+   |
+LL |         std::str::from_utf8(concat_bytes!(b"cl", b"\x82ippy"));
+   |         ^^^^^^^^^^^^^^^^^^^^---------------------------------^
+   |                             |
+   |                             the literal was valid UTF-8 up to the 2 bytes
+
+warning: 12 warnings emitted
+
diff --git a/tests/ui/lint/rfc-2383-lint-reason/root-attribute-confusion.rs b/tests/ui/lint/rfc-2383-lint-reason/root-attribute-confusion.rs
new file mode 100644
index 00000000000..0cade7fef02
--- /dev/null
+++ b/tests/ui/lint/rfc-2383-lint-reason/root-attribute-confusion.rs
@@ -0,0 +1,7 @@
+// check-pass
+// compile-flags: -Dunused_attributes
+
+#![deny(unused_crate_dependencies)]
+#![feature(lint_reasons)]
+
+fn main() {}
diff --git a/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.rs b/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.rs
index 293fdca1cc9..c9b16e43910 100644
--- a/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.rs
+++ b/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.rs
@@ -5,7 +5,6 @@ fn test() {
     drop(b);
     b = Box::new(2); //~ ERROR cannot assign twice to immutable variable `b`
                      //~| NOTE cannot assign twice to immutable
-                     //~| NOTE in this expansion of desugaring of drop and replace
     drop(b);
 }
 
diff --git a/tests/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs b/tests/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs
index e88e24482cc..b1db05afd08 100644
--- a/tests/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs
+++ b/tests/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs
@@ -5,7 +5,7 @@
 // needs-unwind Asserting on contents of error message
 
 #![allow(path_statements, unused_allocation)]
-#![feature(core_intrinsics, generic_assert, generic_assert_internals)]
+#![feature(core_intrinsics, generic_assert)]
 
 macro_rules! test {
   (
@@ -51,6 +51,7 @@ macro_rules! tests {
 
 const FOO: Foo = Foo { bar: 1 };
 
+
 #[derive(Clone, Copy, Debug, PartialEq)]
 struct Foo {
   bar: i32
@@ -83,9 +84,18 @@ fn main() {
     // cast
     [ elem as i32 == 3 ] => "Assertion failed: elem as i32 == 3\nWith captures:\n  elem = 1\n"
 
+    // if
+    [ if elem == 3 { true } else { false } ] => "Assertion failed: if elem == 3 { true } else { false }\nWith captures:\n  elem = 1\n"
+
     // index
     [ [1i32, 1][elem as usize] == 3 ] => "Assertion failed: [1i32, 1][elem as usize] == 3\nWith captures:\n  elem = 1\n"
 
+    // let
+    [ if let 3 = elem { true } else { false } ] => "Assertion failed: if let 3 = elem { true } else { false }\nWith captures:\n  elem = 1\n"
+
+    // match
+    [ match elem { 3 => true, _ => false, } ] => "Assertion failed: match elem { 3 => true, _ => false, }\nWith captures:\n  elem = 1\n"
+
     // method call
     [ FOO.add(elem, elem) == 3 ] => "Assertion failed: FOO.add(elem, elem) == 3\nWith captures:\n  elem = 1\n"
 
@@ -107,77 +117,4 @@ fn main() {
     // unary
     [ -elem == -3 ] => "Assertion failed: -elem == -3\nWith captures:\n  elem = 1\n"
   );
-
-  // ***** Disallowed *****
-
-  tests!(
-    let mut elem = 1i32;
-
-    // assign
-    [ { let local = elem; local } == 3 ] => "Assertion failed: { let local = elem; local } == 3"
-
-    // assign op
-    [ { elem += 1; elem } == 3 ] => "Assertion failed: { elem += 1; elem } == 3"
-
-    // async
-    [ { let _ = async { elem }; elem } == 3 ] => "Assertion failed: { let _ = async { elem }; elem } == 3"
-
-    // await
-
-    // block
-    [ { elem } == 3 ] => "Assertion failed: { elem } == 3"
-
-    // break
-    [ loop { break elem; } ==  3 ] => "Assertion failed: loop { break elem; } == 3"
-
-    // closure
-    [(|| elem)() ==  3 ] => "Assertion failed: (|| elem)() == 3"
-
-    // const block
-
-    // continue
-
-    // err
-
-    // field
-    [ FOO.bar ==  3 ] => "Assertion failed: FOO.bar == 3"
-
-    // for loop
-    [ { for _ in 0..elem { elem; } elem } ==  3 ] => "Assertion failed: { for _ in 0..elem { elem; } elem } == 3"
-
-    // if
-    [ if true { elem } else { elem } == 3 ] => "Assertion failed: if true { elem } else { elem } == 3"
-
-    // inline asm
-
-    // let
-    [ if let true = true { elem } else { elem } == 3 ] => "Assertion failed: if let true = true { elem } else { elem } == 3"
-
-    // lit
-
-    // loop
-    [ loop { elem; break elem; } == 3 ] => "Assertion failed: loop { elem; break elem; } == 3"
-
-    // mac call
-
-    // match
-    [ match elem { _ => elem } == 3 ] => "Assertion failed: (match elem { _ => elem, }) == 3"
-
-    // ret
-    [ (|| { return elem; })() == 3 ] => "Assertion failed: (|| { return elem; })() == 3"
-
-    // try
-    [ (|| { Some(Some(elem)?) })() == Some(3) ] => "Assertion failed: (|| { Some(Some(elem)?) })() == Some(3)"
-
-    // try block
-
-    // underscore
-
-    // while
-    [ { while false { elem; break; } elem } == 3 ] => "Assertion failed: { while false { elem; break; } elem } == 3"
-
-    // yeet
-
-    // yield
-  );
 }
diff --git a/tests/ui/macros/rfc-2011-nicer-assert-messages/all-not-available-cases.rs b/tests/ui/macros/rfc-2011-nicer-assert-messages/all-not-available-cases.rs
index d46f396ee29..fcf4f367d04 100644
--- a/tests/ui/macros/rfc-2011-nicer-assert-messages/all-not-available-cases.rs
+++ b/tests/ui/macros/rfc-2011-nicer-assert-messages/all-not-available-cases.rs
@@ -4,7 +4,7 @@
 // run-pass
 // needs-unwind Asserting on contents of error message
 
-#![feature(core_intrinsics, generic_assert, generic_assert_internals)]
+#![feature(core_intrinsics, generic_assert)]
 
 extern crate common;
 
diff --git a/tests/ui/macros/rfc-2011-nicer-assert-messages/assert-with-custom-errors-does-not-create-unnecessary-code.rs b/tests/ui/macros/rfc-2011-nicer-assert-messages/assert-with-custom-errors-does-not-create-unnecessary-code.rs
index 6a1435f792b..c8408d16fbb 100644
--- a/tests/ui/macros/rfc-2011-nicer-assert-messages/assert-with-custom-errors-does-not-create-unnecessary-code.rs
+++ b/tests/ui/macros/rfc-2011-nicer-assert-messages/assert-with-custom-errors-does-not-create-unnecessary-code.rs
@@ -1,7 +1,7 @@
 // compile-flags: --test
 // run-pass
 
-#![feature(core_intrinsics, generic_assert, generic_assert_internals)]
+#![feature(core_intrinsics, generic_assert)]
 
 #[should_panic(expected = "Custom user message")]
 #[test]
diff --git a/tests/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs b/tests/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs
index 1f5a29ab524..0e3c14a5770 100644
--- a/tests/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs
+++ b/tests/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs
@@ -3,7 +3,7 @@
 // run-pass
 // needs-unwind Asserting on contents of error message
 
-#![feature(core_intrinsics, generic_assert, generic_assert_internals)]
+#![feature(core_intrinsics, generic_assert)]
 
 extern crate common;
 
diff --git a/tests/ui/macros/rfc-2011-nicer-assert-messages/feature-gate-generic_assert.rs b/tests/ui/macros/rfc-2011-nicer-assert-messages/feature-gate-generic_assert.rs
index 01860adaac2..0d2518dc253 100644
--- a/tests/ui/macros/rfc-2011-nicer-assert-messages/feature-gate-generic_assert.rs
+++ b/tests/ui/macros/rfc-2011-nicer-assert-messages/feature-gate-generic_assert.rs
@@ -2,7 +2,7 @@
 // ignore-tidy-linelength
 // run-pass
 
-#![feature(core_intrinsics, generic_assert, generic_assert_internals)]
+#![feature(core_intrinsics, generic_assert)]
 
 use std::fmt::{Debug, Formatter};
 
diff --git a/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.rs b/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.rs
index 5ec84b08ff8..57b79a56b7b 100644
--- a/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.rs
+++ b/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.rs
@@ -1,7 +1,7 @@
 // check-pass
 // compile-flags: -Z unpretty=expanded
 
-#![feature(core_intrinsics, generic_assert, generic_assert_internals)]
+#![feature(core_intrinsics, generic_assert)]
 
 fn arbitrary_consuming_method_for_demonstration_purposes() {
     let elem = 1i32;
diff --git a/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout b/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout
index b69b5bc3b53..66321bc35f0 100644
--- a/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout
+++ b/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout
@@ -3,7 +3,7 @@
 // check-pass
 // compile-flags: -Z unpretty=expanded
 
-#![feature(core_intrinsics, generic_assert, generic_assert_internals)]
+#![feature(core_intrinsics, generic_assert)]
 #[prelude_import]
 use ::std::prelude::rust_2015::*;
 #[macro_use]
diff --git a/tests/ui/methods/call_method_unknown_pointee.rs b/tests/ui/methods/call_method_unknown_pointee.rs
new file mode 100644
index 00000000000..fe4275f5367
--- /dev/null
+++ b/tests/ui/methods/call_method_unknown_pointee.rs
@@ -0,0 +1,28 @@
+// edition: 2018
+
+// tests that the pointee type of a raw pointer must be known to call methods on it
+// see also: `tests/ui/editions/edition-raw-pointer-method-2018.rs`
+
+fn main() {
+    let val = 1_u32;
+    let ptr = &val as *const u32;
+    unsafe {
+        let _a: i32 = (ptr as *const _).read();
+        //~^ ERROR cannot call a method on a raw pointer with an unknown pointee type [E0699]
+        let b = ptr as *const _;
+        let _b: u8 = b.read();
+        //~^ ERROR cannot call a method on a raw pointer with an unknown pointee type [E0699]
+        let _c = (ptr as *const u8).read(); // we know the type here
+    }
+
+    let mut val = 2_u32;
+    let ptr = &mut val as *mut u32;
+    unsafe {
+        let _a: i32 = (ptr as *mut _).read();
+        //~^ ERROR cannot call a method on a raw pointer with an unknown pointee type [E0699]
+        let b = ptr as *mut _;
+        b.write(10);
+        //~^ ERROR cannot call a method on a raw pointer with an unknown pointee type [E0699]
+        (ptr as *mut i32).write(1000); // we know the type here
+    }
+}
diff --git a/tests/ui/methods/call_method_unknown_pointee.stderr b/tests/ui/methods/call_method_unknown_pointee.stderr
new file mode 100644
index 00000000000..84ecf046e7a
--- /dev/null
+++ b/tests/ui/methods/call_method_unknown_pointee.stderr
@@ -0,0 +1,27 @@
+error[E0699]: cannot call a method on a raw pointer with an unknown pointee type
+  --> $DIR/call_method_unknown_pointee.rs:10:41
+   |
+LL |         let _a: i32 = (ptr as *const _).read();
+   |                                         ^^^^
+
+error[E0699]: cannot call a method on a raw pointer with an unknown pointee type
+  --> $DIR/call_method_unknown_pointee.rs:13:24
+   |
+LL |         let _b: u8 = b.read();
+   |                        ^^^^
+
+error[E0699]: cannot call a method on a raw pointer with an unknown pointee type
+  --> $DIR/call_method_unknown_pointee.rs:21:39
+   |
+LL |         let _a: i32 = (ptr as *mut _).read();
+   |                                       ^^^^
+
+error[E0699]: cannot call a method on a raw pointer with an unknown pointee type
+  --> $DIR/call_method_unknown_pointee.rs:24:11
+   |
+LL |         b.write(10);
+   |           ^^^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0699`.
diff --git a/tests/ui/mir/addrof_alignment.rs b/tests/ui/mir/addrof_alignment.rs
new file mode 100644
index 00000000000..892638bfb92
--- /dev/null
+++ b/tests/ui/mir/addrof_alignment.rs
@@ -0,0 +1,15 @@
+// run-pass
+// ignore-wasm32-bare: No panic messages
+// compile-flags: -C debug-assertions
+
+struct Misalignment {
+    a: u32,
+}
+
+fn main() {
+    let items: [Misalignment; 2] = [Misalignment { a: 0 }, Misalignment { a: 1 }];
+    unsafe {
+        let ptr: *const Misalignment = items.as_ptr().cast::<u8>().add(1).cast::<Misalignment>();
+        let _ptr = core::ptr::addr_of!((*ptr).a);
+    }
+}
diff --git a/tests/ui/mismatched_types/E0053.stderr b/tests/ui/mismatched_types/E0053.stderr
index 154f2fcbee0..d0bd5b46cf5 100644
--- a/tests/ui/mismatched_types/E0053.stderr
+++ b/tests/ui/mismatched_types/E0053.stderr
@@ -22,7 +22,7 @@ LL |     fn bar(&mut self) { }
    |            ^^^^^^^^^
    |            |
    |            types differ in mutability
-   |            help: change the self-receiver type to match the trait: `self: &Bar`
+   |            help: change the self-receiver type to match the trait: `&self`
    |
 note: type in trait
   --> $DIR/E0053.rs:3:12
diff --git a/tests/ui/mismatched_types/issue-112036.rs b/tests/ui/mismatched_types/issue-112036.rs
new file mode 100644
index 00000000000..e63471e9747
--- /dev/null
+++ b/tests/ui/mismatched_types/issue-112036.rs
@@ -0,0 +1,7 @@
+struct Foo;
+
+impl Drop for Foo {
+    fn drop(self) {} //~ ERROR method `drop` has an incompatible type for trait
+}
+
+fn main() {}
diff --git a/tests/ui/mismatched_types/issue-112036.stderr b/tests/ui/mismatched_types/issue-112036.stderr
new file mode 100644
index 00000000000..a883aba35bf
--- /dev/null
+++ b/tests/ui/mismatched_types/issue-112036.stderr
@@ -0,0 +1,15 @@
+error[E0053]: method `drop` has an incompatible type for trait
+  --> $DIR/issue-112036.rs:4:13
+   |
+LL |     fn drop(self) {}
+   |             ^^^^
+   |             |
+   |             expected `&mut Foo`, found `Foo`
+   |             help: change the self-receiver type to match the trait: `&mut self`
+   |
+   = note: expected signature `fn(&mut Foo)`
+              found signature `fn(Foo)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/tests/ui/offset-of/offset-of-unsized.rs b/tests/ui/offset-of/offset-of-unsized.rs
new file mode 100644
index 00000000000..666387e615e
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-unsized.rs
@@ -0,0 +1,15 @@
+// build-pass
+// regression test for #112051
+
+#![feature(offset_of)]
+
+struct S<T: ?Sized> {
+    a: u64,
+    b: T,
+}
+trait Tr {}
+
+fn main() {
+    let _a = core::mem::offset_of!(S<dyn Tr>, a);
+    let _b = core::mem::offset_of!((u64, dyn Tr), 0);
+}
diff --git a/tests/ui/panics/nested_panic_caught.rs b/tests/ui/panics/nested_panic_caught.rs
new file mode 100644
index 00000000000..d43886e8095
--- /dev/null
+++ b/tests/ui/panics/nested_panic_caught.rs
@@ -0,0 +1,24 @@
+// run-pass
+// needs-unwind
+
+// Checks that nested panics work correctly.
+
+use std::panic::catch_unwind;
+
+fn double() {
+    struct Double;
+
+    impl Drop for Double {
+        fn drop(&mut self) {
+            let _ = catch_unwind(|| panic!("twice"));
+        }
+    }
+
+    let _d = Double;
+
+    panic!("once");
+}
+
+fn main() {
+    assert!(catch_unwind(|| double()).is_err());
+}
diff --git a/tests/ui/parser/issues/issue-111148.rs b/tests/ui/parser/issues/issue-111148.rs
new file mode 100644
index 00000000000..2502beab443
--- /dev/null
+++ b/tests/ui/parser/issues/issue-111148.rs
@@ -0,0 +1,2 @@
+fn a<<i<Y<w<>#
+//~^ ERROR expected one of `#`, `>`, `const`, identifier, or lifetime, found `<`
diff --git a/tests/ui/parser/issues/issue-111148.stderr b/tests/ui/parser/issues/issue-111148.stderr
new file mode 100644
index 00000000000..e6595a5cbcc
--- /dev/null
+++ b/tests/ui/parser/issues/issue-111148.stderr
@@ -0,0 +1,8 @@
+error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `<`
+  --> $DIR/issue-111148.rs:1:6
+   |
+LL | fn a<<i<Y<w<>#
+   |      ^ expected one of `#`, `>`, `const`, identifier, or lifetime
+
+error: aborting due to previous error
+
diff --git a/tests/ui/parser/typod-const-in-const-param-def.rs b/tests/ui/parser/typod-const-in-const-param-def.rs
new file mode 100644
index 00000000000..85d3ebba57a
--- /dev/null
+++ b/tests/ui/parser/typod-const-in-const-param-def.rs
@@ -0,0 +1,16 @@
+pub fn foo<Const N: u8>() {}
+//~^ ERROR `const` keyword was mistyped as `Const`
+
+pub fn bar<Const>() {}
+// OK
+
+pub fn baz<Const N: u8, T>() {}
+//~^ ERROR `const` keyword was mistyped as `Const`
+
+pub fn qux<T, Const N: u8>() {}
+//~^ ERROR `const` keyword was mistyped as `Const`
+
+pub fn quux<T, Const N: u8, U>() {}
+//~^ ERROR `const` keyword was mistyped as `Const`
+
+fn main() {}
diff --git a/tests/ui/parser/typod-const-in-const-param-def.stderr b/tests/ui/parser/typod-const-in-const-param-def.stderr
new file mode 100644
index 00000000000..75d73c6ea87
--- /dev/null
+++ b/tests/ui/parser/typod-const-in-const-param-def.stderr
@@ -0,0 +1,46 @@
+error: `const` keyword was mistyped as `Const`
+  --> $DIR/typod-const-in-const-param-def.rs:1:12
+   |
+LL | pub fn foo<Const N: u8>() {}
+   |            ^^^^^
+   |
+help: use the `const` keyword
+   |
+LL | pub fn foo<const N: u8>() {}
+   |            ~~~~~
+
+error: `const` keyword was mistyped as `Const`
+  --> $DIR/typod-const-in-const-param-def.rs:7:12
+   |
+LL | pub fn baz<Const N: u8, T>() {}
+   |            ^^^^^
+   |
+help: use the `const` keyword
+   |
+LL | pub fn baz<const N: u8, T>() {}
+   |            ~~~~~
+
+error: `const` keyword was mistyped as `Const`
+  --> $DIR/typod-const-in-const-param-def.rs:10:15
+   |
+LL | pub fn qux<T, Const N: u8>() {}
+   |               ^^^^^
+   |
+help: use the `const` keyword
+   |
+LL | pub fn qux<T, const N: u8>() {}
+   |               ~~~~~
+
+error: `const` keyword was mistyped as `Const`
+  --> $DIR/typod-const-in-const-param-def.rs:13:16
+   |
+LL | pub fn quux<T, Const N: u8, U>() {}
+   |                ^^^^^
+   |
+help: use the `const` keyword
+   |
+LL | pub fn quux<T, const N: u8, U>() {}
+   |                ~~~~~
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/issue-94866.rs b/tests/ui/pattern/issue-94866.rs
index c4203487936..c4203487936 100644
--- a/tests/ui/issue-94866.rs
+++ b/tests/ui/pattern/issue-94866.rs
diff --git a/tests/ui/issue-94866.stderr b/tests/ui/pattern/issue-94866.stderr
index b3c17ce8974..b3c17ce8974 100644
--- a/tests/ui/issue-94866.stderr
+++ b/tests/ui/pattern/issue-94866.stderr
diff --git a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr
index 5a145efce94..49b6dfca62e 100644
--- a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr
+++ b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr
@@ -1,5 +1,5 @@
 error: unreachable pattern
-  --> $DIR/empty-match.rs:37:9
+  --> $DIR/empty-match.rs:58:9
    |
 LL |         _ => {},
    |         ^
@@ -11,37 +11,52 @@ LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:40:9
+  --> $DIR/empty-match.rs:61:9
    |
 LL |         _ if false => {},
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:47:9
+  --> $DIR/empty-match.rs:68:9
    |
 LL |         _ => {},
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:50:9
+  --> $DIR/empty-match.rs:71:9
    |
 LL |         _ if false => {},
    |         ^
 
+error[E0005]: refutable pattern in local binding
+  --> $DIR/empty-match.rs:76:9
+   |
+LL |     let None = x;
+   |         ^^^^ pattern `Some(_)` not covered
+   |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+   = note: pattern `Some(_)` is currently uninhabited, but this variant contains private fields which may become inhabited in the future
+   = note: the matched value is of type `Option<SecretlyUninhabitedForeignStruct>`
+help: you might want to use `if let` to ignore the variant that isn't matched
+   |
+LL |     if let None = x { todo!() };
+   |     ++              +++++++++++
+
 error: unreachable pattern
-  --> $DIR/empty-match.rs:57:9
+  --> $DIR/empty-match.rs:88:9
    |
 LL |         _ => {},
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:60:9
+  --> $DIR/empty-match.rs:91:9
    |
 LL |         _ if false => {},
    |         ^
 
 error[E0004]: non-exhaustive patterns: type `u8` is non-empty
-  --> $DIR/empty-match.rs:78:20
+  --> $DIR/empty-match.rs:109:20
    |
 LL |     match_no_arms!(0u8);
    |                    ^^^
@@ -50,13 +65,13 @@ LL |     match_no_arms!(0u8);
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty
-  --> $DIR/empty-match.rs:79:20
+  --> $DIR/empty-match.rs:111:20
    |
 LL |     match_no_arms!(NonEmptyStruct1);
    |                    ^^^^^^^^^^^^^^^
    |
 note: `NonEmptyStruct1` defined here
-  --> $DIR/empty-match.rs:14:8
+  --> $DIR/empty-match.rs:15:8
    |
 LL | struct NonEmptyStruct1;
    |        ^^^^^^^^^^^^^^^
@@ -64,13 +79,13 @@ LL | struct NonEmptyStruct1;
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty
-  --> $DIR/empty-match.rs:80:20
+  --> $DIR/empty-match.rs:113:20
    |
 LL |     match_no_arms!(NonEmptyStruct2(true));
    |                    ^^^^^^^^^^^^^^^^^^^^^
    |
 note: `NonEmptyStruct2` defined here
-  --> $DIR/empty-match.rs:15:8
+  --> $DIR/empty-match.rs:18:8
    |
 LL | struct NonEmptyStruct2(bool);
    |        ^^^^^^^^^^^^^^^
@@ -78,13 +93,13 @@ LL | struct NonEmptyStruct2(bool);
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty
-  --> $DIR/empty-match.rs:81:20
+  --> $DIR/empty-match.rs:115:20
    |
 LL |     match_no_arms!((NonEmptyUnion1 { foo: () }));
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `NonEmptyUnion1` defined here
-  --> $DIR/empty-match.rs:16:7
+  --> $DIR/empty-match.rs:21:7
    |
 LL | union NonEmptyUnion1 {
    |       ^^^^^^^^^^^^^^
@@ -92,13 +107,13 @@ LL | union NonEmptyUnion1 {
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty
-  --> $DIR/empty-match.rs:82:20
+  --> $DIR/empty-match.rs:117:20
    |
 LL |     match_no_arms!((NonEmptyUnion2 { foo: () }));
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `NonEmptyUnion2` defined here
-  --> $DIR/empty-match.rs:19:7
+  --> $DIR/empty-match.rs:26:7
    |
 LL | union NonEmptyUnion2 {
    |       ^^^^^^^^^^^^^^
@@ -106,13 +121,13 @@ LL | union NonEmptyUnion2 {
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered
-  --> $DIR/empty-match.rs:83:20
+  --> $DIR/empty-match.rs:119:20
    |
 LL |     match_no_arms!(NonEmptyEnum1::Foo(true));
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered
    |
 note: `NonEmptyEnum1` defined here
-  --> $DIR/empty-match.rs:24:5
+  --> $DIR/empty-match.rs:33:5
    |
 LL | enum NonEmptyEnum1 {
    |      -------------
@@ -122,31 +137,32 @@ LL |     Foo(bool),
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
-  --> $DIR/empty-match.rs:84:20
+  --> $DIR/empty-match.rs:122:20
    |
 LL |     match_no_arms!(NonEmptyEnum2::Foo(true));
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
    |
 note: `NonEmptyEnum2` defined here
-  --> $DIR/empty-match.rs:27:5
+  --> $DIR/empty-match.rs:40:5
    |
 LL | enum NonEmptyEnum2 {
    |      -------------
 LL |     Foo(bool),
    |     ^^^ not covered
+...
 LL |     Bar,
    |     ^^^ not covered
    = note: the matched value is of type `NonEmptyEnum2`
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
-  --> $DIR/empty-match.rs:85:20
+  --> $DIR/empty-match.rs:125:20
    |
 LL |     match_no_arms!(NonEmptyEnum5::V1);
    |                    ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
    |
 note: `NonEmptyEnum5` defined here
-  --> $DIR/empty-match.rs:30:6
+  --> $DIR/empty-match.rs:49:6
    |
 LL | enum NonEmptyEnum5 {
    |      ^^^^^^^^^^^^^
@@ -154,7 +170,7 @@ LL | enum NonEmptyEnum5 {
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
 
 error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/empty-match.rs:87:24
+  --> $DIR/empty-match.rs:129:24
    |
 LL |     match_guarded_arm!(0u8);
    |                        ^^^ pattern `_` not covered
@@ -167,13 +183,13 @@ LL +             _ => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered
-  --> $DIR/empty-match.rs:88:24
+  --> $DIR/empty-match.rs:133:24
    |
 LL |     match_guarded_arm!(NonEmptyStruct1);
    |                        ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered
    |
 note: `NonEmptyStruct1` defined here
-  --> $DIR/empty-match.rs:14:8
+  --> $DIR/empty-match.rs:15:8
    |
 LL | struct NonEmptyStruct1;
    |        ^^^^^^^^^^^^^^^
@@ -185,13 +201,13 @@ LL +             NonEmptyStruct1 => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered
-  --> $DIR/empty-match.rs:89:24
+  --> $DIR/empty-match.rs:137:24
    |
 LL |     match_guarded_arm!(NonEmptyStruct2(true));
    |                        ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered
    |
 note: `NonEmptyStruct2` defined here
-  --> $DIR/empty-match.rs:15:8
+  --> $DIR/empty-match.rs:18:8
    |
 LL | struct NonEmptyStruct2(bool);
    |        ^^^^^^^^^^^^^^^
@@ -203,13 +219,13 @@ LL +             NonEmptyStruct2(_) => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered
-  --> $DIR/empty-match.rs:90:24
+  --> $DIR/empty-match.rs:141:24
    |
 LL |     match_guarded_arm!((NonEmptyUnion1 { foo: () }));
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered
    |
 note: `NonEmptyUnion1` defined here
-  --> $DIR/empty-match.rs:16:7
+  --> $DIR/empty-match.rs:21:7
    |
 LL | union NonEmptyUnion1 {
    |       ^^^^^^^^^^^^^^
@@ -221,13 +237,13 @@ LL +             NonEmptyUnion1 { .. } => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered
-  --> $DIR/empty-match.rs:91:24
+  --> $DIR/empty-match.rs:145:24
    |
 LL |     match_guarded_arm!((NonEmptyUnion2 { foo: () }));
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered
    |
 note: `NonEmptyUnion2` defined here
-  --> $DIR/empty-match.rs:19:7
+  --> $DIR/empty-match.rs:26:7
    |
 LL | union NonEmptyUnion2 {
    |       ^^^^^^^^^^^^^^
@@ -239,13 +255,13 @@ LL +             NonEmptyUnion2 { .. } => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered
-  --> $DIR/empty-match.rs:92:24
+  --> $DIR/empty-match.rs:149:24
    |
 LL |     match_guarded_arm!(NonEmptyEnum1::Foo(true));
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered
    |
 note: `NonEmptyEnum1` defined here
-  --> $DIR/empty-match.rs:24:5
+  --> $DIR/empty-match.rs:33:5
    |
 LL | enum NonEmptyEnum1 {
    |      -------------
@@ -259,18 +275,19 @@ LL +             NonEmptyEnum1::Foo(_) => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
-  --> $DIR/empty-match.rs:93:24
+  --> $DIR/empty-match.rs:153:24
    |
 LL |     match_guarded_arm!(NonEmptyEnum2::Foo(true));
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
    |
 note: `NonEmptyEnum2` defined here
-  --> $DIR/empty-match.rs:27:5
+  --> $DIR/empty-match.rs:40:5
    |
 LL | enum NonEmptyEnum2 {
    |      -------------
 LL |     Foo(bool),
    |     ^^^ not covered
+...
 LL |     Bar,
    |     ^^^ not covered
    = note: the matched value is of type `NonEmptyEnum2`
@@ -281,13 +298,13 @@ LL +             NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
-  --> $DIR/empty-match.rs:94:24
+  --> $DIR/empty-match.rs:157:24
    |
 LL |     match_guarded_arm!(NonEmptyEnum5::V1);
    |                        ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
    |
 note: `NonEmptyEnum5` defined here
-  --> $DIR/empty-match.rs:30:6
+  --> $DIR/empty-match.rs:49:6
    |
 LL | enum NonEmptyEnum5 {
    |      ^^^^^^^^^^^^^
@@ -298,6 +315,7 @@ LL ~             _ if false => {},
 LL +             _ => todo!()
    |
 
-error: aborting due to 22 previous errors
+error: aborting due to 23 previous errors
 
-For more information about this error, try `rustc --explain E0004`.
+Some errors have detailed explanations: E0004, E0005.
+For more information about an error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/empty-match.normal.stderr b/tests/ui/pattern/usefulness/empty-match.normal.stderr
index 5a145efce94..f54a3f3364f 100644
--- a/tests/ui/pattern/usefulness/empty-match.normal.stderr
+++ b/tests/ui/pattern/usefulness/empty-match.normal.stderr
@@ -1,5 +1,5 @@
 error: unreachable pattern
-  --> $DIR/empty-match.rs:37:9
+  --> $DIR/empty-match.rs:58:9
    |
 LL |         _ => {},
    |         ^
@@ -11,37 +11,51 @@ LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:40:9
+  --> $DIR/empty-match.rs:61:9
    |
 LL |         _ if false => {},
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:47:9
+  --> $DIR/empty-match.rs:68:9
    |
 LL |         _ => {},
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:50:9
+  --> $DIR/empty-match.rs:71:9
    |
 LL |         _ if false => {},
    |         ^
 
+error[E0005]: refutable pattern in local binding
+  --> $DIR/empty-match.rs:76:9
+   |
+LL |     let None = x;
+   |         ^^^^ pattern `Some(_)` not covered
+   |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+   = note: the matched value is of type `Option<SecretlyUninhabitedForeignStruct>`
+help: you might want to use `if let` to ignore the variant that isn't matched
+   |
+LL |     if let None = x { todo!() };
+   |     ++              +++++++++++
+
 error: unreachable pattern
-  --> $DIR/empty-match.rs:57:9
+  --> $DIR/empty-match.rs:88:9
    |
 LL |         _ => {},
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:60:9
+  --> $DIR/empty-match.rs:91:9
    |
 LL |         _ if false => {},
    |         ^
 
 error[E0004]: non-exhaustive patterns: type `u8` is non-empty
-  --> $DIR/empty-match.rs:78:20
+  --> $DIR/empty-match.rs:109:20
    |
 LL |     match_no_arms!(0u8);
    |                    ^^^
@@ -50,13 +64,13 @@ LL |     match_no_arms!(0u8);
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty
-  --> $DIR/empty-match.rs:79:20
+  --> $DIR/empty-match.rs:111:20
    |
 LL |     match_no_arms!(NonEmptyStruct1);
    |                    ^^^^^^^^^^^^^^^
    |
 note: `NonEmptyStruct1` defined here
-  --> $DIR/empty-match.rs:14:8
+  --> $DIR/empty-match.rs:15:8
    |
 LL | struct NonEmptyStruct1;
    |        ^^^^^^^^^^^^^^^
@@ -64,13 +78,13 @@ LL | struct NonEmptyStruct1;
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty
-  --> $DIR/empty-match.rs:80:20
+  --> $DIR/empty-match.rs:113:20
    |
 LL |     match_no_arms!(NonEmptyStruct2(true));
    |                    ^^^^^^^^^^^^^^^^^^^^^
    |
 note: `NonEmptyStruct2` defined here
-  --> $DIR/empty-match.rs:15:8
+  --> $DIR/empty-match.rs:18:8
    |
 LL | struct NonEmptyStruct2(bool);
    |        ^^^^^^^^^^^^^^^
@@ -78,13 +92,13 @@ LL | struct NonEmptyStruct2(bool);
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty
-  --> $DIR/empty-match.rs:81:20
+  --> $DIR/empty-match.rs:115:20
    |
 LL |     match_no_arms!((NonEmptyUnion1 { foo: () }));
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `NonEmptyUnion1` defined here
-  --> $DIR/empty-match.rs:16:7
+  --> $DIR/empty-match.rs:21:7
    |
 LL | union NonEmptyUnion1 {
    |       ^^^^^^^^^^^^^^
@@ -92,13 +106,13 @@ LL | union NonEmptyUnion1 {
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty
-  --> $DIR/empty-match.rs:82:20
+  --> $DIR/empty-match.rs:117:20
    |
 LL |     match_no_arms!((NonEmptyUnion2 { foo: () }));
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `NonEmptyUnion2` defined here
-  --> $DIR/empty-match.rs:19:7
+  --> $DIR/empty-match.rs:26:7
    |
 LL | union NonEmptyUnion2 {
    |       ^^^^^^^^^^^^^^
@@ -106,13 +120,13 @@ LL | union NonEmptyUnion2 {
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered
-  --> $DIR/empty-match.rs:83:20
+  --> $DIR/empty-match.rs:119:20
    |
 LL |     match_no_arms!(NonEmptyEnum1::Foo(true));
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered
    |
 note: `NonEmptyEnum1` defined here
-  --> $DIR/empty-match.rs:24:5
+  --> $DIR/empty-match.rs:33:5
    |
 LL | enum NonEmptyEnum1 {
    |      -------------
@@ -122,31 +136,32 @@ LL |     Foo(bool),
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
-  --> $DIR/empty-match.rs:84:20
+  --> $DIR/empty-match.rs:122:20
    |
 LL |     match_no_arms!(NonEmptyEnum2::Foo(true));
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
    |
 note: `NonEmptyEnum2` defined here
-  --> $DIR/empty-match.rs:27:5
+  --> $DIR/empty-match.rs:40:5
    |
 LL | enum NonEmptyEnum2 {
    |      -------------
 LL |     Foo(bool),
    |     ^^^ not covered
+...
 LL |     Bar,
    |     ^^^ not covered
    = note: the matched value is of type `NonEmptyEnum2`
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
-  --> $DIR/empty-match.rs:85:20
+  --> $DIR/empty-match.rs:125:20
    |
 LL |     match_no_arms!(NonEmptyEnum5::V1);
    |                    ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
    |
 note: `NonEmptyEnum5` defined here
-  --> $DIR/empty-match.rs:30:6
+  --> $DIR/empty-match.rs:49:6
    |
 LL | enum NonEmptyEnum5 {
    |      ^^^^^^^^^^^^^
@@ -154,7 +169,7 @@ LL | enum NonEmptyEnum5 {
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
 
 error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/empty-match.rs:87:24
+  --> $DIR/empty-match.rs:129:24
    |
 LL |     match_guarded_arm!(0u8);
    |                        ^^^ pattern `_` not covered
@@ -167,13 +182,13 @@ LL +             _ => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered
-  --> $DIR/empty-match.rs:88:24
+  --> $DIR/empty-match.rs:133:24
    |
 LL |     match_guarded_arm!(NonEmptyStruct1);
    |                        ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered
    |
 note: `NonEmptyStruct1` defined here
-  --> $DIR/empty-match.rs:14:8
+  --> $DIR/empty-match.rs:15:8
    |
 LL | struct NonEmptyStruct1;
    |        ^^^^^^^^^^^^^^^
@@ -185,13 +200,13 @@ LL +             NonEmptyStruct1 => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered
-  --> $DIR/empty-match.rs:89:24
+  --> $DIR/empty-match.rs:137:24
    |
 LL |     match_guarded_arm!(NonEmptyStruct2(true));
    |                        ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered
    |
 note: `NonEmptyStruct2` defined here
-  --> $DIR/empty-match.rs:15:8
+  --> $DIR/empty-match.rs:18:8
    |
 LL | struct NonEmptyStruct2(bool);
    |        ^^^^^^^^^^^^^^^
@@ -203,13 +218,13 @@ LL +             NonEmptyStruct2(_) => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered
-  --> $DIR/empty-match.rs:90:24
+  --> $DIR/empty-match.rs:141:24
    |
 LL |     match_guarded_arm!((NonEmptyUnion1 { foo: () }));
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered
    |
 note: `NonEmptyUnion1` defined here
-  --> $DIR/empty-match.rs:16:7
+  --> $DIR/empty-match.rs:21:7
    |
 LL | union NonEmptyUnion1 {
    |       ^^^^^^^^^^^^^^
@@ -221,13 +236,13 @@ LL +             NonEmptyUnion1 { .. } => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered
-  --> $DIR/empty-match.rs:91:24
+  --> $DIR/empty-match.rs:145:24
    |
 LL |     match_guarded_arm!((NonEmptyUnion2 { foo: () }));
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered
    |
 note: `NonEmptyUnion2` defined here
-  --> $DIR/empty-match.rs:19:7
+  --> $DIR/empty-match.rs:26:7
    |
 LL | union NonEmptyUnion2 {
    |       ^^^^^^^^^^^^^^
@@ -239,13 +254,13 @@ LL +             NonEmptyUnion2 { .. } => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered
-  --> $DIR/empty-match.rs:92:24
+  --> $DIR/empty-match.rs:149:24
    |
 LL |     match_guarded_arm!(NonEmptyEnum1::Foo(true));
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered
    |
 note: `NonEmptyEnum1` defined here
-  --> $DIR/empty-match.rs:24:5
+  --> $DIR/empty-match.rs:33:5
    |
 LL | enum NonEmptyEnum1 {
    |      -------------
@@ -259,18 +274,19 @@ LL +             NonEmptyEnum1::Foo(_) => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
-  --> $DIR/empty-match.rs:93:24
+  --> $DIR/empty-match.rs:153:24
    |
 LL |     match_guarded_arm!(NonEmptyEnum2::Foo(true));
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
    |
 note: `NonEmptyEnum2` defined here
-  --> $DIR/empty-match.rs:27:5
+  --> $DIR/empty-match.rs:40:5
    |
 LL | enum NonEmptyEnum2 {
    |      -------------
 LL |     Foo(bool),
    |     ^^^ not covered
+...
 LL |     Bar,
    |     ^^^ not covered
    = note: the matched value is of type `NonEmptyEnum2`
@@ -281,13 +297,13 @@ LL +             NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
-  --> $DIR/empty-match.rs:94:24
+  --> $DIR/empty-match.rs:157:24
    |
 LL |     match_guarded_arm!(NonEmptyEnum5::V1);
    |                        ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
    |
 note: `NonEmptyEnum5` defined here
-  --> $DIR/empty-match.rs:30:6
+  --> $DIR/empty-match.rs:49:6
    |
 LL | enum NonEmptyEnum5 {
    |      ^^^^^^^^^^^^^
@@ -298,6 +314,7 @@ LL ~             _ if false => {},
 LL +             _ => todo!()
    |
 
-error: aborting due to 22 previous errors
+error: aborting due to 23 previous errors
 
-For more information about this error, try `rustc --explain E0004`.
+Some errors have detailed explanations: E0004, E0005.
+For more information about an error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/empty-match.rs b/tests/ui/pattern/usefulness/empty-match.rs
index 9cdc0413ba1..062241faa4c 100644
--- a/tests/ui/pattern/usefulness/empty-match.rs
+++ b/tests/ui/pattern/usefulness/empty-match.rs
@@ -6,28 +6,49 @@
 #![feature(never_type_fallback)]
 #![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))]
 #![deny(unreachable_patterns)]
+//~^ NOTE the lint level is defined here
 
 extern crate empty;
 
 enum EmptyEnum {}
 
 struct NonEmptyStruct1;
+//~^ NOTE `NonEmptyStruct1` defined here
+//~| NOTE `NonEmptyStruct1` defined here
 struct NonEmptyStruct2(bool);
+//~^ NOTE `NonEmptyStruct2` defined here
+//~| NOTE `NonEmptyStruct2` defined here
 union NonEmptyUnion1 {
+    //~^ NOTE `NonEmptyUnion1` defined here
+    //~| NOTE `NonEmptyUnion1` defined here
     foo: (),
 }
 union NonEmptyUnion2 {
+    //~^ NOTE `NonEmptyUnion2` defined here
+    //~| NOTE `NonEmptyUnion2` defined here
     foo: (),
     bar: (),
 }
 enum NonEmptyEnum1 {
     Foo(bool),
+    //~^ NOTE `NonEmptyEnum1` defined here
+    //~| NOTE `NonEmptyEnum1` defined here
+    //~| NOTE not covered
+    //~| NOTE not covered
 }
 enum NonEmptyEnum2 {
     Foo(bool),
+    //~^ NOTE `NonEmptyEnum2` defined here
+    //~| NOTE `NonEmptyEnum2` defined here
+    //~| NOTE not covered
+    //~| NOTE not covered
     Bar,
+    //~^ NOTE not covered
+    //~| NOTE not covered
 }
 enum NonEmptyEnum5 {
+    //~^ NOTE `NonEmptyEnum5` defined here
+    //~| NOTE `NonEmptyEnum5` defined here
     V1, V2, V3, V4, V5,
 }
 
@@ -51,6 +72,16 @@ fn empty_foreign_enum(x: empty::EmptyForeignEnum) {
     }
 }
 
+fn empty_foreign_enum_private(x: Option<empty::SecretlyUninhabitedForeignStruct>) {
+    let None = x;
+    //~^ ERROR refutable pattern in local binding
+    //~| NOTE `let` bindings require an "irrefutable pattern"
+    //~| NOTE for more information, visit
+    //~| NOTE the matched value is of type
+    //~| NOTE pattern `Some(_)` not covered
+    //[exhaustive_patterns]~| NOTE currently uninhabited, but this variant contains private fields
+}
+
 fn never(x: !) {
     match x {} // ok
     match x {
@@ -76,20 +107,55 @@ macro_rules! match_guarded_arm {
 
 fn main() {
     match_no_arms!(0u8); //~ ERROR type `u8` is non-empty
+                         //~| NOTE the matched value is of type
     match_no_arms!(NonEmptyStruct1); //~ ERROR type `NonEmptyStruct1` is non-empty
+                                     //~| NOTE the matched value is of type
     match_no_arms!(NonEmptyStruct2(true)); //~ ERROR type `NonEmptyStruct2` is non-empty
+                                           //~| NOTE the matched value is of type
     match_no_arms!((NonEmptyUnion1 { foo: () })); //~ ERROR type `NonEmptyUnion1` is non-empty
+                                                  //~| NOTE the matched value is of type
     match_no_arms!((NonEmptyUnion2 { foo: () })); //~ ERROR type `NonEmptyUnion2` is non-empty
+                                                  //~| NOTE the matched value is of type
     match_no_arms!(NonEmptyEnum1::Foo(true)); //~ ERROR `NonEmptyEnum1::Foo(_)` not covered
+                                              //~| NOTE pattern `NonEmptyEnum1::Foo(_)` not covered
+                                              //~| NOTE the matched value is of type
     match_no_arms!(NonEmptyEnum2::Foo(true)); //~ ERROR `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
+                                              //~| NOTE patterns `NonEmptyEnum2::Foo(_)` and
+                                              //~| NOTE the matched value is of type
     match_no_arms!(NonEmptyEnum5::V1); //~ ERROR `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
+                                       //~| NOTE patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`
+                                       //~| NOTE the matched value is of type
 
     match_guarded_arm!(0u8); //~ ERROR `_` not covered
+                             //~| NOTE the matched value is of type
+                             //~| NOTE pattern `_` not covered
+                             //~| NOTE in this expansion of match_guarded_arm!
     match_guarded_arm!(NonEmptyStruct1); //~ ERROR `NonEmptyStruct1` not covered
+                                         //~| NOTE pattern `NonEmptyStruct1` not covered
+                                         //~| NOTE the matched value is of type
+                                         //~| NOTE in this expansion of match_guarded_arm!
     match_guarded_arm!(NonEmptyStruct2(true)); //~ ERROR `NonEmptyStruct2(_)` not covered
+                                               //~| NOTE the matched value is of type
+                                               //~| NOTE pattern `NonEmptyStruct2(_)` not covered
+                                               //~| NOTE in this expansion of match_guarded_arm!
     match_guarded_arm!((NonEmptyUnion1 { foo: () })); //~ ERROR `NonEmptyUnion1 { .. }` not covered
+                                                      //~| NOTE the matched value is of type
+                                                      //~| NOTE pattern `NonEmptyUnion1 { .. }` not covered
+                                                      //~| NOTE in this expansion of match_guarded_arm!
     match_guarded_arm!((NonEmptyUnion2 { foo: () })); //~ ERROR `NonEmptyUnion2 { .. }` not covered
+                                                      //~| NOTE the matched value is of type
+                                                      //~| NOTE pattern `NonEmptyUnion2 { .. }` not covered
+                                                      //~| NOTE in this expansion of match_guarded_arm!
     match_guarded_arm!(NonEmptyEnum1::Foo(true)); //~ ERROR `NonEmptyEnum1::Foo(_)` not covered
+                                                  //~| NOTE the matched value is of type
+                                                  //~| NOTE pattern `NonEmptyEnum1::Foo(_)` not covered
+                                                  //~| NOTE in this expansion of match_guarded_arm!
     match_guarded_arm!(NonEmptyEnum2::Foo(true)); //~ ERROR `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
+                                                  //~| NOTE the matched value is of type
+                                                  //~| NOTE patterns `NonEmptyEnum2::Foo(_)` and
+                                                  //~| NOTE in this expansion of match_guarded_arm!
     match_guarded_arm!(NonEmptyEnum5::V1); //~ ERROR `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
+                                           //~| NOTE the matched value is of type
+                                           //~| NOTE patterns `NonEmptyEnum5::V1`,
+                                           //~| NOTE in this expansion of match_guarded_arm!
 }
diff --git a/tests/ui/privacy/issue-111220-2-tuple-struct-fields-projection.rs b/tests/ui/privacy/issue-111220-2-tuple-struct-fields-projection.rs
new file mode 100644
index 00000000000..f413b502778
--- /dev/null
+++ b/tests/ui/privacy/issue-111220-2-tuple-struct-fields-projection.rs
@@ -0,0 +1,33 @@
+mod b {
+    pub struct A(u32);
+}
+
+trait Id {
+    type Assoc;
+}
+impl Id for b::A {
+    type Assoc = b::A;
+}
+impl Id for u32 {
+    type Assoc = u32;
+}
+
+
+trait Trait<T> {
+    fn method(&self)
+    where
+        T: Id<Assoc = b::A>;
+}
+
+impl<T: Id> Trait<T> for <T as Id>::Assoc {
+    fn method(&self)
+    where
+        T: Id<Assoc = b::A>,
+    {
+        let Self(a) = self;
+        //~^ ERROR: tuple struct constructor `A` is private
+        println!("{a}");
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/privacy/issue-111220-2-tuple-struct-fields-projection.stderr b/tests/ui/privacy/issue-111220-2-tuple-struct-fields-projection.stderr
new file mode 100644
index 00000000000..231a4da8b5f
--- /dev/null
+++ b/tests/ui/privacy/issue-111220-2-tuple-struct-fields-projection.stderr
@@ -0,0 +1,9 @@
+error[E0603]: tuple struct constructor `A` is private
+  --> $DIR/issue-111220-2-tuple-struct-fields-projection.rs:27:13
+   |
+LL |         let Self(a) = self;
+   |             ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/tests/ui/privacy/issue-111220-tuple-struct-fields.rs b/tests/ui/privacy/issue-111220-tuple-struct-fields.rs
new file mode 100644
index 00000000000..78d35fd96da
--- /dev/null
+++ b/tests/ui/privacy/issue-111220-tuple-struct-fields.rs
@@ -0,0 +1,46 @@
+mod b {
+    #[derive(Default)]
+    pub struct A(u32);
+}
+
+impl b::A {
+    fn inherent_bypass(&self) {
+        let Self(x) = self;
+        //~^ ERROR: tuple struct constructor `A` is private
+        println!("{x}");
+    }
+}
+
+pub trait B {
+    fn f(&self);
+}
+
+impl B for b::A {
+    fn f(&self) {
+        let Self(a) = self;
+        //~^ ERROR: tuple struct constructor `A` is private
+        println!("{}", a);
+    }
+}
+
+pub trait Projector {
+    type P;
+}
+
+impl Projector for () {
+    type P = b::A;
+}
+
+pub trait Bypass2 {
+    fn f2(&self);
+}
+
+impl Bypass2 for <() as Projector>::P {
+    fn f2(&self) {
+        let Self(a) = self;
+        //~^ ERROR: tuple struct constructor `A` is private
+        println!("{}", a);
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/privacy/issue-111220-tuple-struct-fields.stderr b/tests/ui/privacy/issue-111220-tuple-struct-fields.stderr
new file mode 100644
index 00000000000..17a32379cc0
--- /dev/null
+++ b/tests/ui/privacy/issue-111220-tuple-struct-fields.stderr
@@ -0,0 +1,21 @@
+error[E0603]: tuple struct constructor `A` is private
+  --> $DIR/issue-111220-tuple-struct-fields.rs:8:13
+   |
+LL |         let Self(x) = self;
+   |             ^^^^^^^
+
+error[E0603]: tuple struct constructor `A` is private
+  --> $DIR/issue-111220-tuple-struct-fields.rs:20:13
+   |
+LL |         let Self(a) = self;
+   |             ^^^^^^^
+
+error[E0603]: tuple struct constructor `A` is private
+  --> $DIR/issue-111220-tuple-struct-fields.rs:40:13
+   |
+LL |         let Self(a) = self;
+   |             ^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/tests/ui/process/process-panic-after-fork.rs b/tests/ui/process/process-panic-after-fork.rs
index da268312173..7c2fc296bb0 100644
--- a/tests/ui/process/process-panic-after-fork.rs
+++ b/tests/ui/process/process-panic-after-fork.rs
@@ -11,6 +11,8 @@
 #![feature(never_type)]
 #![feature(panic_always_abort)]
 
+#![allow(invalid_from_utf8)]
+
 extern crate libc;
 
 use std::alloc::{GlobalAlloc, Layout};
diff --git a/tests/ui/resolve/hidden_glob_reexports.rs b/tests/ui/resolve/hidden_glob_reexports.rs
new file mode 100644
index 00000000000..361243fcd7b
--- /dev/null
+++ b/tests/ui/resolve/hidden_glob_reexports.rs
@@ -0,0 +1,52 @@
+// check-pass
+
+pub mod upstream_a {
+    mod inner {
+        pub struct Foo {}
+        pub struct Bar {}
+    }
+
+    pub use self::inner::*;
+
+    struct Foo;
+    //~^ WARN private item shadows public glob re-export
+}
+
+pub mod upstream_b {
+    mod inner {
+        pub struct Foo {}
+        pub struct Qux {}
+    }
+
+    mod other {
+        pub struct Foo;
+    }
+
+    pub use self::inner::*;
+
+    use self::other::Foo;
+    //~^ WARN private item shadows public glob re-export
+}
+
+pub mod upstream_c {
+    mod no_def_id {
+        #![allow(non_camel_case_types)]
+        pub struct u8;
+        pub struct World;
+    }
+
+    pub use self::no_def_id::*;
+
+    use std::primitive::u8;
+    //~^ WARN private item shadows public glob re-export
+}
+
+// Downstream crate
+// mod downstream {
+//     fn proof() {
+//         let _ = crate::upstream_a::Foo;
+//         let _ = crate::upstream_b::Foo;
+//     }
+// }
+
+pub fn main() {}
diff --git a/tests/ui/resolve/hidden_glob_reexports.stderr b/tests/ui/resolve/hidden_glob_reexports.stderr
new file mode 100644
index 00000000000..ddf7bcda827
--- /dev/null
+++ b/tests/ui/resolve/hidden_glob_reexports.stderr
@@ -0,0 +1,31 @@
+warning: private item shadows public glob re-export
+  --> $DIR/hidden_glob_reexports.rs:11:5
+   |
+LL |     pub use self::inner::*;
+   |             -------------- the name `Foo` in the type namespace is supposed to be publicly re-exported here
+LL |
+LL |     struct Foo;
+   |     ^^^^^^^^^^^ but the private item here shadows it
+   |
+   = note: `#[warn(hidden_glob_reexports)]` on by default
+
+warning: private item shadows public glob re-export
+  --> $DIR/hidden_glob_reexports.rs:27:9
+   |
+LL |     pub use self::inner::*;
+   |             -------------- the name `Foo` in the type namespace is supposed to be publicly re-exported here
+LL |
+LL |     use self::other::Foo;
+   |         ^^^^^^^^^^^^^^^^ but the private item here shadows it
+
+warning: private item shadows public glob re-export
+  --> $DIR/hidden_glob_reexports.rs:40:9
+   |
+LL |     pub use self::no_def_id::*;
+   |             ------------------ the name `u8` in the type namespace is supposed to be publicly re-exported here
+LL |
+LL |     use std::primitive::u8;
+   |         ^^^^^^^^^^^^^^^^^^ but the private item here shadows it
+
+warning: 3 warnings emitted
+
diff --git a/tests/ui/issues/issue-3008-1.rs b/tests/ui/structs-enums/issue-3008-1.rs
index 1124969e6d0..1124969e6d0 100644
--- a/tests/ui/issues/issue-3008-1.rs
+++ b/tests/ui/structs-enums/issue-3008-1.rs
diff --git a/tests/ui/issues/issue-3008-1.stderr b/tests/ui/structs-enums/issue-3008-1.stderr
index be25b9091d5..be25b9091d5 100644
--- a/tests/ui/issues/issue-3008-1.stderr
+++ b/tests/ui/structs-enums/issue-3008-1.stderr
diff --git a/tests/ui/issues/issue-3008-2.rs b/tests/ui/structs-enums/issue-3008-2.rs
index 5846c69da41..5846c69da41 100644
--- a/tests/ui/issues/issue-3008-2.rs
+++ b/tests/ui/structs-enums/issue-3008-2.rs
diff --git a/tests/ui/issues/issue-3008-2.stderr b/tests/ui/structs-enums/issue-3008-2.stderr
index 858a8fd6af8..858a8fd6af8 100644
--- a/tests/ui/issues/issue-3008-2.stderr
+++ b/tests/ui/structs-enums/issue-3008-2.stderr
diff --git a/tests/ui/issues/issue-3008-3.rs b/tests/ui/structs-enums/issue-3008-3.rs
index 212eb2eb8e0..212eb2eb8e0 100644
--- a/tests/ui/issues/issue-3008-3.rs
+++ b/tests/ui/structs-enums/issue-3008-3.rs
diff --git a/tests/ui/issues/issue-3008-3.stderr b/tests/ui/structs-enums/issue-3008-3.stderr
index a1a81e29367..a1a81e29367 100644
--- a/tests/ui/issues/issue-3008-3.stderr
+++ b/tests/ui/structs-enums/issue-3008-3.stderr
diff --git a/tests/ui/suggestions/issue-103646.rs b/tests/ui/suggestions/issue-103646.rs
new file mode 100644
index 00000000000..f679640c5dc
--- /dev/null
+++ b/tests/ui/suggestions/issue-103646.rs
@@ -0,0 +1,11 @@
+trait Cat {
+    fn nya() {}
+}
+
+fn uwu<T: Cat>(c: T) {
+    c.nya();
+    //~^ ERROR no method named `nya` found for type parameter `T` in the current scope
+    //~| Suggestion T::nya()
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-103646.stderr b/tests/ui/suggestions/issue-103646.stderr
new file mode 100644
index 00000000000..3ae9813d491
--- /dev/null
+++ b/tests/ui/suggestions/issue-103646.stderr
@@ -0,0 +1,21 @@
+error[E0599]: no method named `nya` found for type parameter `T` in the current scope
+  --> $DIR/issue-103646.rs:6:7
+   |
+LL | fn uwu<T: Cat>(c: T) {
+   |        - method `nya` not found for this type parameter
+LL |     c.nya();
+   |     --^^^--
+   |     | |
+   |     | this is an associated function, not a method
+   |     help: use associated function syntax instead: `T::nya()`
+   |
+   = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
+note: the candidate is defined in the trait `Cat`
+  --> $DIR/issue-103646.rs:2:5
+   |
+LL |     fn nya() {}
+   |     ^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/thir-print/thir-flat.stdout b/tests/ui/thir-print/thir-flat.stdout
index 9d467f73d09..b0aa44b56aa 100644
--- a/tests/ui/thir-print/thir-flat.stdout
+++ b/tests/ui/thir-print/thir-flat.stdout
@@ -1,7 +1,7 @@
 DefId(0:3 ~ thir_flat[7b97]::main):
 Thir {
     body_type: Fn(
-        ([]; c_variadic: false)->(),
+        fn(),
     ),
     arms: [],
     blocks: [
diff --git a/tests/ui/track-diagnostics/track6.stderr b/tests/ui/track-diagnostics/track6.stderr
index 89438aea9ad..583b02555b4 100644
--- a/tests/ui/track-diagnostics/track6.stderr
+++ b/tests/ui/track-diagnostics/track6.stderr
@@ -3,7 +3,7 @@ error[E0658]: specialization is unstable
    |
 LL |     default fn bar() {}
    |     ^^^^^^^^^^^^^^^^^^^
--Ztrack-diagnostics: created at $COMPILER_DIR/rustc_session/src/parse.rs:LL:CC
+-Ztrack-diagnostics: created at compiler/rustc_ast_passes/src/feature_gate.rs:LL:CC
    |
    = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
    = help: add `#![feature(specialization)]` to the crate attributes to enable
diff --git a/tests/ui/traits/new-solver/leak-check-coinductive-cycle.rs b/tests/ui/traits/new-solver/leak-check-coinductive-cycle.rs
new file mode 100644
index 00000000000..1f7d4a49c90
--- /dev/null
+++ b/tests/ui/traits/new-solver/leak-check-coinductive-cycle.rs
@@ -0,0 +1,33 @@
+// check-pass
+// compile-flags: -Ztrait-solver=next
+#![feature(rustc_attrs)]
+
+#[rustc_coinductive]
+trait Trait<T> {}
+impl<'a, 'b, T> Trait<T> for (&'a (), &'b ())
+where
+    'b: 'a,
+    &'a (): Trait<T>,
+{}
+
+impl Trait<i32> for &'static () {}
+impl<'a> Trait<u32> for &'a ()
+where
+    for<'b> (&'a (), &'b ()): Trait<u32>,
+{}
+
+
+fn impls_trait<T: Trait<U>, U>() {}
+
+fn main() {
+    // This infers to `impls_trait::<(&'static (), &'static ()), i32>();`
+    //
+    // In the first attempt we have 2 candidates for `&'a (): Trait<_>`
+    // and we get ambiguity. The result is therefore ambiguity with a `'b: 'a`
+    // constraint. The next attempt then uses that provisional result when
+    // trying to apply `impl<'a> Trait<u32> for &'a ()`. This means we get a
+    // `for<'b> 'b: 'a` bound which fails the leak check. Because of this we
+    // end up with a single impl for `&'a (): Trait<_>` which infers `_` to `i32`
+    // and succeeds.
+    impls_trait::<(&(), &()), _>();
+}
diff --git a/tests/ui/type-alias-impl-trait/coherence_different_hidden_ty.rs b/tests/ui/type-alias-impl-trait/coherence_different_hidden_ty.rs
new file mode 100644
index 00000000000..39b3d535ad4
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/coherence_different_hidden_ty.rs
@@ -0,0 +1,25 @@
+// When checking whether these two impls overlap, we could detect that we
+// would require the hidden type of `TAIT` to be equal to both `u32` and `i32`
+// and therefore accept them as disjoint. That is annoying to implement with
+// the current system because we would have to add the following to each
+// returning branch in coherence.
+//
+//    let _ = infcx.take_opaque_types();
+//
+// @lcnr: Because of this I decided to not bother and cause this to fail instead.
+// In the future we can definitely modify the compiler to accept this
+// again.
+#![feature(type_alias_impl_trait)]
+
+trait Trait {}
+
+type TAIT = impl Sized;
+
+impl Trait for (TAIT, TAIT) {}
+
+impl Trait for (u32, i32) {}
+//~^ ERROR conflicting implementations of trait `Trait` for type `(TAIT, TAIT)`
+
+fn define() -> TAIT {}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/coherence_different_hidden_ty.stderr b/tests/ui/type-alias-impl-trait/coherence_different_hidden_ty.stderr
new file mode 100644
index 00000000000..f2aee798608
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/coherence_different_hidden_ty.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `Trait` for type `(TAIT, TAIT)`
+  --> $DIR/coherence_different_hidden_ty.rs:20:1
+   |
+LL | impl Trait for (TAIT, TAIT) {}
+   | --------------------------- first implementation here
+LL |
+LL | impl Trait for (u32, i32) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(TAIT, TAIT)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/type-alias-impl-trait/coherence_generalization.rs b/tests/ui/type-alias-impl-trait/coherence_generalization.rs
index 5c9ad9498b6..679b2b0f188 100644
--- a/tests/ui/type-alias-impl-trait/coherence_generalization.rs
+++ b/tests/ui/type-alias-impl-trait/coherence_generalization.rs
@@ -1,5 +1,7 @@
 // check-pass
 
+// FIXME(type_alias_impl_trait): What does this test? This needs a comment
+// explaining what we're worried about here.
 #![feature(type_alias_impl_trait)]
 trait Trait {}
 type Opaque<T> = impl Sized;
diff --git a/tests/ui/typeck/issue-106929.rs b/tests/ui/typeck/issue-106929.rs
new file mode 100644
index 00000000000..91342229ae1
--- /dev/null
+++ b/tests/ui/typeck/issue-106929.rs
@@ -0,0 +1,13 @@
+struct Client;
+
+impl Client {
+    fn post<T: std::ops::Add>(&self, _: T, _: T) {}
+}
+
+fn f() {
+    let c = Client;
+    post(c, ());
+    //~^ ERROR cannot find function `post` in this scope
+}
+
+fn main() {}
diff --git a/tests/ui/typeck/issue-106929.stderr b/tests/ui/typeck/issue-106929.stderr
new file mode 100644
index 00000000000..f744e5a41f0
--- /dev/null
+++ b/tests/ui/typeck/issue-106929.stderr
@@ -0,0 +1,15 @@
+error[E0425]: cannot find function `post` in this scope
+  --> $DIR/issue-106929.rs:9:5
+   |
+LL |     post(c, ());
+   |     ^^^^ not found in this scope
+   |
+help: use the `.` operator to call the method `post` on `&Client`
+   |
+LL -     post(c, ());
+LL +     c.post(());
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/issues/issue-1871.rs b/tests/ui/typeck/issue-1871.rs
index f7a2bdd5659..f7a2bdd5659 100644
--- a/tests/ui/issues/issue-1871.rs
+++ b/tests/ui/typeck/issue-1871.rs
diff --git a/tests/ui/issues/issue-1871.stderr b/tests/ui/typeck/issue-1871.stderr
index b774ca22dd7..b774ca22dd7 100644
--- a/tests/ui/issues/issue-1871.stderr
+++ b/tests/ui/typeck/issue-1871.stderr
diff --git a/tests/ui/issues/issue-2063-resource.rs b/tests/ui/typeck/issue-2063-resource.rs
index 1d0527447ba..1d0527447ba 100644
--- a/tests/ui/issues/issue-2063-resource.rs
+++ b/tests/ui/typeck/issue-2063-resource.rs
diff --git a/tests/ui/issues/issue-2063.rs b/tests/ui/typeck/issue-2063.rs
index f08f9d4cfe4..f08f9d4cfe4 100644
--- a/tests/ui/issues/issue-2063.rs
+++ b/tests/ui/typeck/issue-2063.rs
diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.rs b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.rs
index a6c86311b37..e7f7fdc513b 100644
--- a/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.rs
+++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.rs
@@ -2,7 +2,7 @@
 
 trait One<A> { fn foo(&self) -> A; }
 
-fn foo(_: &dyn One()) //~ ERROR associated type `Output` not found for `One<()>`
+fn foo(_: &dyn One()) //~ ERROR associated type `Output` not found for `One`
 {}
 
 fn main() { }
diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.stderr b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.stderr
index 59e7bc8c832..e4772478bd9 100644
--- a/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.stderr
+++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.stderr
@@ -1,4 +1,4 @@
-error[E0220]: associated type `Output` not found for `One<()>`
+error[E0220]: associated type `Output` not found for `One`
   --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters-1.rs:5:16
    |
 LL | fn foo(_: &dyn One())
diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr
index 5d7fe3fa533..eb18b121957 100644
--- a/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr
+++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr
@@ -12,7 +12,7 @@ note: trait defined here, with 3 generic parameters: `A`, `B`, `C`
 LL | trait Three<A,B,C> { fn dummy(&self) -> (A,B,C); }
    |       ^^^^^ - - -
 
-error[E0220]: associated type `Output` not found for `Three<(), [type error], [type error]>`
+error[E0220]: associated type `Output` not found for `Three`
   --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs:5:16
    |
 LL | fn foo(_: &dyn Three())
diff --git a/tests/ui/issues/issue-50825-1.rs b/tests/ui/where-clauses/issue-50825-1.rs
index ee4316029a8..ee4316029a8 100644
--- a/tests/ui/issues/issue-50825-1.rs
+++ b/tests/ui/where-clauses/issue-50825-1.rs
diff --git a/tests/ui/issues/issue-50825.rs b/tests/ui/where-clauses/issue-50825.rs
index 1ece2e9fc84..1ece2e9fc84 100644
--- a/tests/ui/issues/issue-50825.rs
+++ b/tests/ui/where-clauses/issue-50825.rs
diff --git a/triagebot.toml b/triagebot.toml
index d7cd3ea1275..c160c83cc95 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -190,6 +190,7 @@ trigger_files = [
     "src/stage0.json",
     "src/tools/compiletest",
     "src/tools/tidy",
+    "src/tools/rustdoc-gui-test",
 ]
 
 [autolabel."T-infra"]
@@ -640,3 +641,4 @@ style-team = [
 "/src/tools/rustdoc-themes" =                ["rustdoc"]
 "/src/tools/tidy" =                          ["bootstrap"]
 "/src/tools/x" =                             ["bootstrap"]
+"/src/tools/rustdoc-gui-test" =              ["bootstrap", "@ozkanonur"]