about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2024-05-12 15:44:24 +0200
committerRalf Jung <post@ralfj.de>2024-05-12 15:44:24 +0200
commit1e7fba9e06965b6db8a173cb497068401eea3bae (patch)
treef3ada808f56974250673700372722ba24596027f
parent7d565dfa0fa40991df9e3567f991284b4912ab0b (diff)
parentf8433a82b4a4120e34de236a68d0cfeaea6e60c3 (diff)
downloadrust-1e7fba9e06965b6db8a173cb497068401eea3bae.tar.gz
rust-1e7fba9e06965b6db8a173cb497068401eea3bae.zip
Merge from rustc
-rw-r--r--.github/workflows/dependencies.yml2
-rw-r--r--Cargo.lock452
-rw-r--r--compiler/rustc_abi/src/lib.rs9
-rw-r--r--compiler/rustc_ast/src/ast.rs1
-rw-r--r--compiler/rustc_ast/src/ast_traits.rs2
-rw-r--r--compiler/rustc_ast/src/attr/mod.rs2
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs10
-rw-r--r--compiler/rustc_ast/src/token.rs100
-rw-r--r--compiler/rustc_ast/src/tokenstream.rs25
-rw-r--r--compiler/rustc_ast/src/util/classify.rs98
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs15
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs84
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/expr.rs2
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/fixup.rs57
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs3
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs5
-rw-r--r--compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml8
-rw-r--r--compiler/rustc_codegen_cranelift/.github/workflows/main.yml16
-rw-r--r--compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml4
-rw-r--r--compiler/rustc_codegen_cranelift/.gitignore4
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/Cargo.toml3
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs37
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/main.rs8
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/tests.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs10
-rw-r--r--compiler/rustc_codegen_cranelift/example/std_example.rs29
-rw-r--r--compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml4
-rw-r--r--compiler/rustc_codegen_cranelift/rust-toolchain2
-rwxr-xr-xcompiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh4
-rw-r--r--compiler/rustc_codegen_cranelift/src/abi/mod.rs6
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs37
-rw-r--r--compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs21
-rw-r--r--compiler/rustc_codegen_cranelift/src/config.rs9
-rw-r--r--compiler/rustc_codegen_cranelift/src/constant.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/discriminant.rs45
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/aot.rs72
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/jit.rs23
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/mod.rs16
-rw-r--r--compiler/rustc_codegen_cranelift/src/global_asm.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/inline_asm.rs201
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs52
-rw-r--r--compiler/rustc_codegen_cranelift/src/lib.rs6
-rw-r--r--compiler/rustc_codegen_cranelift/src/main_shim.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/value_and_place.rs8
-rw-r--r--compiler/rustc_codegen_cranelift/y.cmd4
-rwxr-xr-x[-rw-r--r--]compiler/rustc_codegen_cranelift/y.ps17
-rwxr-xr-xcompiler/rustc_codegen_cranelift/y.sh3
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs15
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/intrinsic.rs15
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/operand.rs60
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/place.rs87
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs74
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/builder.rs61
-rw-r--r--compiler/rustc_const_eval/src/const_eval/dummy_machine.rs5
-rw-r--r--compiler/rustc_const_eval/src/const_eval/error.rs1
-rw-r--r--compiler/rustc_const_eval/src/const_eval/eval_queries.rs3
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs6
-rw-r--r--compiler/rustc_const_eval/src/const_eval/mod.rs1
-rw-r--r--compiler/rustc_const_eval/src/const_eval/valtrees.rs1
-rw-r--r--compiler/rustc_const_eval/src/interpret/cast.rs4
-rw-r--r--compiler/rustc_const_eval/src/interpret/discriminant.rs5
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs8
-rw-r--r--compiler/rustc_const_eval/src/interpret/intern.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs8
-rw-r--r--compiler/rustc_const_eval/src/interpret/machine.rs6
-rw-r--r--compiler/rustc_const_eval/src/interpret/memory.rs8
-rw-r--r--compiler/rustc_const_eval/src/interpret/operand.rs7
-rw-r--r--compiler/rustc_const_eval/src/interpret/operator.rs3
-rw-r--r--compiler/rustc_const_eval/src/interpret/place.rs8
-rw-r--r--compiler/rustc_const_eval/src/interpret/projection.rs6
-rw-r--r--compiler/rustc_const_eval/src/interpret/step.rs1
-rw-r--r--compiler/rustc_const_eval/src/interpret/terminator.rs6
-rw-r--r--compiler/rustc_const_eval/src/interpret/util.rs3
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs7
-rw-r--r--compiler/rustc_const_eval/src/interpret/visitor.rs2
-rw-r--r--compiler/rustc_const_eval/src/lib.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs5
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/mod.rs1
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/ops.rs1
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs1
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs1
-rw-r--r--compiler/rustc_const_eval/src/util/caller_location.rs1
-rw-r--r--compiler/rustc_const_eval/src/util/check_validity_requirement.rs1
-rw-r--r--compiler/rustc_const_eval/src/util/type_name.rs1
-rw-r--r--compiler/rustc_data_structures/Cargo.toml2
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs5
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0457.md2
-rw-r--r--compiler/rustc_errors/src/diagnostic_impls.rs6
-rw-r--r--compiler/rustc_expand/src/config.rs15
-rw-r--r--compiler/rustc_expand/src/mbe/diagnostics.rs6
-rw-r--r--compiler/rustc_expand/src/mbe/macro_parser.rs11
-rw-r--r--compiler/rustc_expand/src/mbe/transcribe.rs10
-rw-r--r--compiler/rustc_expand/src/proc_macro.rs2
-rw-r--r--compiler/rustc_expand/src/proc_macro_server.rs27
-rw-r--r--compiler/rustc_hir/src/hir.rs11
-rw-r--r--compiler/rustc_hir/src/intravisit.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs14
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/check/entry.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsicck.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/check/region.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/orphan.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/collect/item_bounds.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs5
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/constrained_generic_params.rs5
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs20
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs25
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs9
-rw-r--r--compiler/rustc_hir_analysis/src/hir_wf_check.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs17
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/test.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/utils.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/variance/constraints.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/variance/mod.rs3
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs8
-rw-r--r--compiler/rustc_hir_typeck/messages.ftl4
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs11
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/errors.rs7
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/expr_use_visitor.rs1351
-rw-r--r--compiler/rustc_hir_typeck/src/fallback.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs7
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs7
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/intrinsicck.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs5
-rw-r--r--compiler/rustc_hir_typeck/src/mem_categorization.rs774
-rw-r--r--compiler/rustc_hir_typeck/src/method/confirm.rs17
-rw-r--r--compiler/rustc_hir_typeck/src/method/mod.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/method/prelude2021.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs21
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs30
-rw-r--r--compiler/rustc_hir_typeck/src/op.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs405
-rw-r--r--compiler/rustc_hir_typeck/src/place_op.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/rvalue_scopes.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs18
-rw-r--r--compiler/rustc_infer/src/errors/note_and_explain.rs1
-rw-r--r--compiler/rustc_infer/src/infer/at.rs15
-rw-r--r--compiler/rustc_infer/src/infer/canonical/canonicalizer.rs1
-rw-r--r--compiler/rustc_infer/src/infer/canonical/instantiate.rs1
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs1
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs8
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs1
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs8
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs8
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note.rs11
-rw-r--r--compiler/rustc_infer/src/infer/freshen.rs1
-rw-r--r--compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs1
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs3
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types/table.rs1
-rw-r--r--compiler/rustc_infer/src/infer/outlives/env.rs1
-rw-r--r--compiler/rustc_infer/src/infer/outlives/obligations.rs9
-rw-r--r--compiler/rustc_infer/src/infer/projection.rs4
-rw-r--r--compiler/rustc_infer/src/infer/region_constraints/leak_check.rs1
-rw-r--r--compiler/rustc_infer/src/infer/region_constraints/mod.rs1
-rw-r--r--compiler/rustc_infer/src/infer/relate/combine.rs1
-rw-r--r--compiler/rustc_infer/src/infer/relate/generalize.rs3
-rw-r--r--compiler/rustc_infer/src/infer/resolve.rs1
-rw-r--r--compiler/rustc_infer/src/infer/type_variable.rs1
-rw-r--r--compiler/rustc_infer/src/lib.rs2
-rw-r--r--compiler/rustc_infer/src/traits/mod.rs2
-rw-r--r--compiler/rustc_infer/src/traits/project.rs31
-rw-r--r--compiler/rustc_lint/messages.ftl11
-rw-r--r--compiler/rustc_lint/src/impl_trait_overcaptures.rs425
-rw-r--r--compiler/rustc_lint/src/lib.rs3
-rw-r--r--compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs16
-rw-r--r--compiler/rustc_lint/src/reference_casting.rs6
-rw-r--r--compiler/rustc_lint/src/unused.rs27
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs38
-rw-r--r--compiler/rustc_metadata/src/creader.rs1
-rw-r--r--compiler/rustc_metadata/src/dependency_format.rs1
-rw-r--r--compiler/rustc_metadata/src/lib.rs3
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs1
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs1
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs1
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs1
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs121
-rw-r--r--compiler/rustc_middle/src/mir/interpret/mod.rs121
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs25
-rw-r--r--compiler/rustc_middle/src/ty/context.rs16
-rw-r--r--compiler/rustc_middle/src/ty/flags.rs10
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs86
-rw-r--r--compiler/rustc_middle/src/ty/predicate.rs284
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs134
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs66
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs27
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs260
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs19
-rw-r--r--compiler/rustc_middle/src/ty/util.rs2
-rw-r--r--compiler/rustc_mir_build/Cargo.toml1
-rw-r--r--compiler/rustc_mir_build/messages.ftl2
-rw-r--r--compiler/rustc_mir_build/src/build/block.rs1
-rw-r--r--compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs1
-rw-r--r--compiler/rustc_mir_build/src/build/custom/mod.rs1
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_constant.rs1
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_place.rs1
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs1
-rw-r--r--compiler/rustc_mir_build/src/build/expr/into.rs1
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs1
-rw-r--r--compiler/rustc_mir_build/src/build/matches/test.rs1
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs1
-rw-r--r--compiler/rustc_mir_build/src/build/scope.rs1
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs1
-rw-r--r--compiler/rustc_mir_build/src/errors.rs27
-rw-r--r--compiler/rustc_mir_build/src/lib.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/constant.rs1
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs1
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/mod.rs1
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs12
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs1
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs91
-rw-r--r--compiler/rustc_mir_build/src/thir/util.rs1
-rw-r--r--compiler/rustc_mir_transform/src/abort_unwinding_calls.rs1
-rw-r--r--compiler/rustc_mir_transform/src/check_packed_ref.rs1
-rw-r--r--compiler/rustc_mir_transform/src/coroutine.rs1
-rw-r--r--compiler/rustc_mir_transform/src/coroutine/by_move_body.rs1
-rw-r--r--compiler/rustc_mir_transform/src/coverage/counters.rs1
-rw-r--r--compiler/rustc_mir_transform/src/coverage/graph.rs1
-rw-r--r--compiler/rustc_mir_transform/src/coverage/spans.rs1
-rw-r--r--compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs1
-rw-r--r--compiler/rustc_mir_transform/src/coverage/tests.rs1
-rw-r--r--compiler/rustc_mir_transform/src/dataflow_const_prop.rs1
-rw-r--r--compiler/rustc_mir_transform/src/dead_store_elimination.rs1
-rw-r--r--compiler/rustc_mir_transform/src/dest_prop.rs1
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_box_derefs.rs1
-rw-r--r--compiler/rustc_mir_transform/src/ffi_unwind_calls.rs1
-rw-r--r--compiler/rustc_mir_transform/src/gvn.rs1
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs1
-rw-r--r--compiler/rustc_mir_transform/src/instsimplify.rs1
-rw-r--r--compiler/rustc_mir_transform/src/jump_threading.rs1
-rw-r--r--compiler/rustc_mir_transform/src/known_panics_lint.rs1
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs3
-rw-r--r--compiler/rustc_mir_transform/src/lower_intrinsics.rs1
-rw-r--r--compiler/rustc_mir_transform/src/nrvo.rs1
-rw-r--r--compiler/rustc_mir_transform/src/promote_consts.rs1
-rw-r--r--compiler/rustc_mir_transform/src/ref_prop.rs1
-rw-r--r--compiler/rustc_mir_transform/src/shim.rs1
-rw-r--r--compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs4
-rw-r--r--compiler/rustc_mir_transform/src/simplify_comparison_integral.rs1
-rw-r--r--compiler/rustc_mir_transform/src/sroa.rs1
-rw-r--r--compiler/rustc_mir_transform/src/ssa.rs1
-rw-r--r--compiler/rustc_mir_transform/src/unreachable_enum_branching.rs1
-rw-r--r--compiler/rustc_mir_transform/src/unreachable_prop.rs1
-rw-r--r--compiler/rustc_parse/src/errors.rs2
-rw-r--r--compiler/rustc_parse/src/lexer/tokentrees.rs2
-rw-r--r--compiler/rustc_parse/src/parser/attr.rs2
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs99
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs42
-rw-r--r--compiler/rustc_parse/src/parser/item.rs58
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs32
-rw-r--r--compiler/rustc_parse/src/parser/nonterminal.rs69
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs2
-rw-r--r--compiler/rustc_parse/src/parser/path.rs2
-rw-r--r--compiler/rustc_parse/src/parser/stmt.rs4
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs58
-rw-r--r--compiler/rustc_privacy/src/lib.rs11
-rw-r--r--compiler/rustc_query_impl/src/lib.rs5
-rw-r--r--compiler/rustc_query_impl/src/plumbing.rs5
-rw-r--r--compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs3
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/ty.rs14
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs5
-rw-r--r--compiler/rustc_target/src/spec/base/apple/mod.rs83
-rw-r--r--compiler/rustc_target/src/spec/mod.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs6
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs6
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs6
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs6
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs6
-rw-r--r--compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/i386_apple_ios.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs6
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs6
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs9
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_none.rs25
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs4
-rw-r--r--compiler/rustc_trait_selection/src/lib.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/alias_relate.rs10
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/mod.rs15
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs15
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs11
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs37
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs1
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs1
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill.rs3
-rw-r--r--compiler/rustc_trait_selection/src/solve/inspect/build.rs1
-rw-r--r--compiler/rustc_trait_selection/src/solve/mod.rs23
-rw-r--r--compiler/rustc_trait_selection/src/solve/normalize.rs15
-rw-r--r--compiler/rustc_trait_selection/src/solve/normalizes_to/anon_const.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/normalizes_to/inherent.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs44
-rw-r--r--compiler/rustc_trait_selection/src/solve/project_goals.rs16
-rw-r--r--compiler/rustc_trait_selection/src/solve/search_graph.rs4
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals.rs5
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs12
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs5
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs67
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs76
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs5
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs3
-rw-r--r--compiler/rustc_trait_selection/src/traits/normalize.rs10
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs5
-rw-r--r--compiler/rustc_trait_selection/src/traits/outlives_bounds.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs170
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/normalize.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs3
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs11
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/mod.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/structural_match.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/util.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/vtable.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs24
-rw-r--r--compiler/rustc_traits/src/normalize_projection_ty.rs10
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs1
-rw-r--r--compiler/rustc_ty_utils/src/assoc.rs1
-rw-r--r--compiler/rustc_ty_utils/src/consts.rs1
-rw-r--r--compiler/rustc_ty_utils/src/implied_bounds.rs1
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs1
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs1
-rw-r--r--compiler/rustc_ty_utils/src/layout_sanity_check.rs1
-rw-r--r--compiler/rustc_ty_utils/src/lib.rs2
-rw-r--r--compiler/rustc_ty_utils/src/needs_drop.rs1
-rw-r--r--compiler/rustc_ty_utils/src/opaque_types.rs1
-rw-r--r--compiler/rustc_ty_utils/src/representability.rs1
-rw-r--r--compiler/rustc_ty_utils/src/sig_types.rs1
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs3
-rw-r--r--compiler/rustc_type_ir/Cargo.toml3
-rw-r--r--compiler/rustc_type_ir/src/canonical.rs151
-rw-r--r--compiler/rustc_type_ir/src/const_kind.rs4
-rw-r--r--compiler/rustc_type_ir/src/inherent.rs26
-rw-r--r--compiler/rustc_type_ir/src/interner.rs27
-rw-r--r--compiler/rustc_type_ir/src/ir_print.rs24
-rw-r--r--compiler/rustc_type_ir/src/lib.rs6
-rw-r--r--compiler/rustc_type_ir/src/macros.rs1
-rw-r--r--compiler/rustc_type_ir/src/predicate.rs469
-rw-r--r--compiler/rustc_type_ir/src/predicate_kind.rs127
-rw-r--r--compiler/rustc_type_ir/src/region_kind.rs5
-rw-r--r--compiler/rustc_type_ir/src/trait_ref.rs109
-rw-r--r--compiler/rustc_type_ir/src/ty_kind.rs46
-rw-r--r--compiler/rustc_type_ir_macros/Cargo.toml15
-rw-r--r--compiler/rustc_type_ir_macros/src/lib.rs159
-rw-r--r--compiler/stable_mir/src/ty.rs8
-rw-r--r--config.example.toml6
-rw-r--r--library/alloc/src/fmt.rs6
-rw-r--r--library/alloc/src/rc.rs49
-rw-r--r--library/alloc/src/sync.rs16
-rw-r--r--library/core/src/fmt/fmt_trait_method_doc.md8
-rw-r--r--library/core/src/fmt/mod.rs42
-rw-r--r--library/core/src/mem/manually_drop.rs2
-rw-r--r--library/core/src/primitive_docs.rs3
-rw-r--r--library/core/src/ptr/mod.rs38
-rw-r--r--library/core/src/slice/ascii.rs21
-rw-r--r--library/core/src/str/mod.rs15
-rw-r--r--library/std/Cargo.toml5
-rw-r--r--library/std/src/io/mod.rs9
-rw-r--r--library/std/src/sys/pal/unix/alloc.rs2
-rw-r--r--library/std/src/sys/pal/unix/rand.rs13
-rw-r--r--src/bootstrap/bootstrap.py38
-rw-r--r--src/bootstrap/src/core/builder.rs3
-rw-r--r--src/bootstrap/src/core/builder/tests.rs20
-rw-r--r--src/bootstrap/src/core/config/config.rs38
-rw-r--r--src/bootstrap/src/core/download.rs8
-rw-r--r--src/ci/docker/host-x86_64/dist-armv7-linux/Dockerfile2
-rw-r--r--src/doc/rustc/src/SUMMARY.md1
-rw-r--r--src/doc/rustc/src/platform-support.md1
-rw-r--r--src/doc/rustc/src/platform-support/fuchsia.md25
-rw-r--r--src/doc/rustc/src/platform-support/x86_64-unknown-linux-none.md40
-rw-r--r--src/doc/rustc/src/symbol-mangling/v0.md2
-rw-r--r--src/doc/rustdoc/src/command-line-arguments.md2
-rw-r--r--src/doc/style-guide/src/editions.md1
-rw-r--r--src/doc/style-guide/src/items.md30
-rw-r--r--src/librustdoc/clean/mod.rs33
-rw-r--r--src/librustdoc/doctest.rs4
-rw-r--r--src/librustdoc/passes/mod.rs5
-rw-r--r--src/librustdoc/passes/strip_aliased_non_local.rs57
-rw-r--r--src/stage0447
-rw-r--r--src/stage0.json456
-rw-r--r--src/tools/build_helper/src/lib.rs1
-rw-r--r--src/tools/build_helper/src/stage0_parser.rs76
-rw-r--r--src/tools/bump-stage0/Cargo.toml2
-rw-r--r--src/tools/bump-stage0/src/main.rs143
-rw-r--r--src/tools/clippy/clippy_lints/src/escape.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs23
-rw-r--r--src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unwrap.rs14
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs1
-rw-r--r--src/tools/clippy/clippy_utils/src/sugg.rs6
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/usage.rs13
-rw-r--r--src/tools/run-make-support/src/lib.rs9
-rw-r--r--src/tools/run-make-support/src/rustc.rs9
-rw-r--r--src/tools/run-make-support/src/rustdoc.rs44
-rw-r--r--src/tools/tidy/src/allowed_run_make_makefiles.txt7
-rw-r--r--src/tools/tidy/src/deps.rs1
-rw-r--r--tests/assembly/targets/targets-elf.rs3
-rw-r--r--tests/auxiliary/rust_test_helpers.c6
-rw-r--r--tests/codegen-units/partitioning/extern-drop-glue.rs5
-rw-r--r--tests/codegen-units/partitioning/extern-generic.rs4
-rw-r--r--tests/codegen-units/partitioning/incremental-merging.rs3
-rw-r--r--tests/codegen-units/partitioning/inlining-from-extern-crate.rs4
-rw-r--r--tests/codegen-units/partitioning/local-drop-glue.rs4
-rw-r--r--tests/codegen-units/partitioning/local-generic.rs3
-rw-r--r--tests/codegen-units/partitioning/local-inlining-but-not-all.rs4
-rw-r--r--tests/codegen-units/partitioning/local-inlining.rs4
-rw-r--r--tests/codegen-units/partitioning/local-transitive-inlining.rs4
-rw-r--r--tests/codegen-units/partitioning/methods-are-with-self-type.rs4
-rw-r--r--tests/codegen-units/partitioning/regular-modules.rs3
-rw-r--r--tests/codegen-units/partitioning/shared-generics.rs1
-rw-r--r--tests/codegen-units/partitioning/statics.rs3
-rw-r--r--tests/codegen-units/partitioning/vtable-through-const.rs5
-rw-r--r--tests/codegen/mir-aggregate-no-alloca.rs2
-rw-r--r--tests/codegen/option-niche-eq.rs12
-rw-r--r--tests/codegen/sanitizer/no-sanitize-inlining.rs2
-rw-r--r--tests/codegen/simd/issue-120720-reduce-nan.rs2
-rw-r--r--tests/crashes/123901.rs8
-rw-r--r--tests/run-make/alloc-no-oom-handling/Makefile7
-rw-r--r--tests/run-make/alloc-no-oom-handling/rmake.rs15
-rw-r--r--tests/run-make/alloc-no-rc/Makefile7
-rw-r--r--tests/run-make/alloc-no-rc/rmake.rs15
-rw-r--r--tests/run-make/alloc-no-sync/Makefile7
-rw-r--r--tests/run-make/alloc-no-sync/rmake.rs15
-rw-r--r--tests/run-make/c-link-to-rust-va-list-fn/Makefile7
-rw-r--r--tests/run-make/c-link-to-rust-va-list-fn/rmake.rs18
-rw-r--r--tests/run-make/core-no-fp-fmt-parse/rmake.rs1
-rw-r--r--tests/run-make/rustdoc-scrape-examples-ordering/Makefile5
-rw-r--r--tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs55
-rw-r--r--tests/run-make/rustdoc-shared-flags/Makefile18
-rw-r--r--tests/run-make/rustdoc-shared-flags/rmake.rs14
-rw-r--r--tests/run-make/rustdoc-target-spec-json-path/Makefile9
-rw-r--r--tests/run-make/rustdoc-target-spec-json-path/rmake.rs14
-rw-r--r--tests/rustdoc-ui/issues/issue-91713.stdout2
-rw-r--r--tests/rustdoc/inline_cross/assoc-const-equality.rs1
-rw-r--r--tests/rustdoc/private-non-local-fields-2.rs11
-rw-r--r--tests/rustdoc/private-non-local-fields.rs9
-rw-r--r--tests/ui/abi/extern/auxiliary/extern-crosscrate-source.rs25
-rw-r--r--tests/ui/abi/extern/extern-call-deep.rs28
-rw-r--r--tests/ui/abi/extern/extern-call-deep2.rs29
-rw-r--r--tests/ui/abi/extern/extern-call-indirect.rs26
-rw-r--r--tests/ui/abi/extern/extern-call-scrub.rs30
-rw-r--r--tests/ui/abi/extern/extern-crosscrate.rs9
-rw-r--r--tests/ui/abi/foreign/foreign-call-no-runtime.rs60
-rw-r--r--tests/ui/associated-consts/issue-105330.rs4
-rw-r--r--tests/ui/associated-consts/issue-105330.stderr38
-rw-r--r--tests/ui/async-await/async-closures/ambiguous-arg.rs15
-rw-r--r--tests/ui/async-await/async-closures/ambiguous-arg.stderr13
-rw-r--r--tests/ui/cast/ice-cast-type-with-error-124848.rs18
-rw-r--r--tests/ui/cast/ice-cast-type-with-error-124848.stderr63
-rw-r--r--tests/ui/coercion/pin-dyn-dispatch-sound.rs19
-rw-r--r--tests/ui/coercion/pin-dyn-dispatch-sound.stderr9
-rw-r--r--tests/ui/higher-ranked/trait-bounds/issue-59311.stderr26
-rw-r--r--tests/ui/higher-ranked/trait-bounds/trivial-does-not-hold.rs11
-rw-r--r--tests/ui/higher-ranked/trait-bounds/trivial-does-not-hold.stderr10
-rw-r--r--tests/ui/impl-trait/precise-capturing/apit.stderr2
-rw-r--r--tests/ui/impl-trait/precise-capturing/overcaptures-2024.fixed29
-rw-r--r--tests/ui/impl-trait/precise-capturing/overcaptures-2024.rs29
-rw-r--r--tests/ui/impl-trait/precise-capturing/overcaptures-2024.stderr75
-rw-r--r--tests/ui/impl-trait/precise-capturing/redundant.rs25
-rw-r--r--tests/ui/impl-trait/precise-capturing/redundant.stderr45
-rw-r--r--tests/ui/lint/lint-unnecessary-parens.fixed31
-rw-r--r--tests/ui/lint/lint-unnecessary-parens.rs31
-rw-r--r--tests/ui/lint/lint-unnecessary-parens.stderr74
-rw-r--r--tests/ui/lint/reference_casting.rs7
-rw-r--r--tests/ui/macros/nonterminal-matching.stderr2
-rw-r--r--tests/ui/macros/stringify.rs45
-rw-r--r--tests/ui/macros/trace_faulty_macros.stderr8
-rw-r--r--tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024.rs6
-rw-r--r--tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs12
-rw-r--r--tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr45
-rw-r--r--tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.rs3
-rw-r--r--tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.stderr11
-rw-r--r--tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_ref_mut_inside_and.fixed30
-rw-r--r--tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_ref_mut_inside_and.rs30
-rw-r--r--tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_ref_mut_inside_and.stderr43
-rw-r--r--tests/ui/match/ref_pat_everywhere-fail.rs (renamed from tests/ui/match/ref_pat_everywhere-mutability-mismatch.rs)6
-rw-r--r--tests/ui/match/ref_pat_everywhere-fail.stderr38
-rw-r--r--tests/ui/match/ref_pat_everywhere-mutability-mismatch.stderr44
-rw-r--r--tests/ui/match/ref_pat_everywhere.rs6
-rw-r--r--tests/ui/parser/else-no-if.rs30
-rw-r--r--tests/ui/parser/else-no-if.stderr56
-rw-r--r--tests/ui/parser/macro/statement-boundaries.rs104
-rw-r--r--tests/ui/pattern/auxiliary/match_ergonomics_2024_macros.rs12
-rw-r--r--tests/ui/pattern/match_ergonomics_2024.fixed57
-rw-r--r--tests/ui/pattern/match_ergonomics_2024.rs57
-rw-r--r--tests/ui/pattern/match_ergonomics_2024.stderr97
-rw-r--r--tests/ui/pattern/mut_preserve_binding_mode_2024_lint.rs16
-rw-r--r--tests/ui/pattern/mut_preserve_binding_mode_2024_lint.stderr31
-rw-r--r--tests/ui/suggestions/recover-from-semicolon-trailing-item.stderr4
-rw-r--r--tests/ui/symbol-names/types.legacy.stderr194
-rw-r--r--tests/ui/symbol-names/types.rs267
-rw-r--r--tests/ui/symbol-names/types.v0.stderr506
-rw-r--r--tests/ui/symbol-names/types.verbose-legacy.stderr194
-rw-r--r--tests/ui/traits/next-solver/typeck/normalize-in-upvar-collection.rs19
-rw-r--r--tests/ui/type-alias-impl-trait/static-lifetime-through-closure-issue-122775.rs17
-rw-r--r--tests/ui/unpretty/let-else-hir.rs (renamed from tests/ui/unpretty/pretty-let-else.rs)0
-rw-r--r--tests/ui/unpretty/let-else-hir.stdout (renamed from tests/ui/unpretty/pretty-let-else.stdout)0
-rw-r--r--tests/ui/unpretty/let-else.rs11
-rw-r--r--tests/ui/unpretty/let-else.stdout15
-rw-r--r--tests/ui/write-fmt-errors.rs29
-rw-r--r--triagebot.toml13
545 files changed, 9068 insertions, 5303 deletions
diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml
index f4e409e0d49..03584aed08d 100644
--- a/.github/workflows/dependencies.yml
+++ b/.github/workflows/dependencies.yml
@@ -56,7 +56,7 @@ jobs:
       - name: install the bootstrap toolchain
         run: |
           # Extract the stage0 version
-          TOOLCHAIN=$(jq -r '.compiler | {version,date} | join("-")' -- src/stage0.json)
+          TOOLCHAIN=$(awk -F= '{a[$1]=$2} END {print(a["compiler_version"] "-" a["compiler_date"])}' src/stage0)
           # Install and set as default
           rustup toolchain install --no-self-update --profile minimal $TOOLCHAIN
           rustup default $TOOLCHAIN
diff --git a/Cargo.lock b/Cargo.lock
index aa73df55cb9..df4e4f32613 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -68,9 +68,9 @@ dependencies = [
 
 [[package]]
 name = "allocator-api2"
-version = "0.2.16"
+version = "0.2.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
+checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
 
 [[package]]
 name = "ammonia"
@@ -141,56 +141,57 @@ dependencies = [
 
 [[package]]
 name = "anstream"
-version = "0.6.13"
+version = "0.6.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb"
+checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b"
 dependencies = [
  "anstyle",
  "anstyle-parse",
  "anstyle-query",
  "anstyle-wincon",
  "colorchoice",
+ "is_terminal_polyfill",
  "utf8parse",
 ]
 
 [[package]]
 name = "anstyle"
-version = "1.0.6"
+version = "1.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc"
+checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b"
 
 [[package]]
 name = "anstyle-lossy"
-version = "1.1.0"
+version = "1.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9a0444767dbd4aea9355cb47a370eb184dbfe918875e127eff52cb9d1638181"
+checksum = "6fcff6599f06e21b0165c85052ccd6e67dc388ddd1c516a9dc5f55dc8cacf004"
 dependencies = [
  "anstyle",
 ]
 
 [[package]]
 name = "anstyle-parse"
-version = "0.2.3"
+version = "0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
+checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
 dependencies = [
  "utf8parse",
 ]
 
 [[package]]
 name = "anstyle-query"
-version = "1.0.2"
+version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
+checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5"
 dependencies = [
  "windows-sys 0.52.0",
 ]
 
 [[package]]
 name = "anstyle-svg"
-version = "0.1.3"
+version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b6ddad447b448d6d5db36b31cbd3ff27c7af071619501998eeceab01968287a"
+checksum = "bbbf0bf947d663010f0b4132f28ca08da9151f3b9035fa7578a38de521c1d1aa"
 dependencies = [
  "anstream",
  "anstyle",
@@ -201,9 +202,9 @@ dependencies = [
 
 [[package]]
 name = "anstyle-wincon"
-version = "3.0.2"
+version = "3.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
+checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19"
 dependencies = [
  "anstyle",
  "windows-sys 0.52.0",
@@ -211,9 +212,9 @@ dependencies = [
 
 [[package]]
 name = "anyhow"
-version = "1.0.81"
+version = "1.0.83"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247"
+checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3"
 dependencies = [
  "backtrace",
 ]
@@ -256,7 +257,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "serde",
- "syn 2.0.58",
+ "syn 2.0.62",
 ]
 
 [[package]]
@@ -276,9 +277,9 @@ dependencies = [
 
 [[package]]
 name = "autocfg"
-version = "1.2.0"
+version = "1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
+checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
 
 [[package]]
 name = "backtrace"
@@ -380,27 +381,24 @@ name = "bump-stage0"
 version = "0.1.0"
 dependencies = [
  "anyhow",
+ "build_helper",
  "curl",
  "indexmap",
  "serde",
- "serde_json",
  "toml 0.5.11",
 ]
 
 [[package]]
 name = "bumpalo"
-version = "3.15.4"
+version = "3.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa"
+checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
 
 [[package]]
 name = "bytecount"
-version = "0.6.7"
+version = "0.6.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e1e5f035d16fc623ae5f74981db80a439803888314e3a555fd6f04acd51a3205"
-dependencies = [
- "packed_simd",
-]
+checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce"
 
 [[package]]
 name = "byteorder"
@@ -509,7 +507,7 @@ dependencies = [
  "iana-time-zone",
  "num-traits",
  "serde",
- "windows-targets 0.52.4",
+ "windows-targets 0.52.5",
 ]
 
 [[package]]
@@ -579,9 +577,9 @@ dependencies = [
 
 [[package]]
 name = "clap_complete"
-version = "4.5.1"
+version = "4.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "885e4d7d5af40bfb99ae6f9433e292feac98d452dcb3ec3d25dfe7552b77da8c"
+checksum = "dd79504325bf38b10165b02e89b4347300f855f273c4cb30c4a3209e6583275e"
 dependencies = [
  "clap",
 ]
@@ -595,7 +593,7 @@ dependencies = [
  "heck 0.5.0",
  "proc-macro2",
  "quote",
- "syn 2.0.58",
+ "syn 2.0.62",
 ]
 
 [[package]]
@@ -622,7 +620,7 @@ dependencies = [
  "regex",
  "rustc_tools_util",
  "serde",
- "syn 2.0.58",
+ "syn 2.0.62",
  "tempfile",
  "termize",
  "tokio",
@@ -716,23 +714,23 @@ dependencies = [
 
 [[package]]
 name = "color-print"
-version = "0.3.5"
+version = "0.3.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a858372ff14bab9b1b30ea504f2a4bc534582aee3e42ba2d41d2a7baba63d5d"
+checksum = "1ee543c60ff3888934877a5671f45494dd27ed4ba25c6670b9a7576b7ed7a8c0"
 dependencies = [
  "color-print-proc-macro",
 ]
 
 [[package]]
 name = "color-print-proc-macro"
-version = "0.3.5"
+version = "0.3.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57e37866456a721d0a404439a1adae37a31be4e0055590d053dfe6981e05003f"
+checksum = "77ff1a80c5f3cb1ca7c06ffdd71b6a6dd6d8f896c42141fbd43f50ed28dcdb93"
 dependencies = [
  "nom",
  "proc-macro2",
  "quote",
- "syn 1.0.109",
+ "syn 2.0.62",
 ]
 
 [[package]]
@@ -749,9 +747,9 @@ dependencies = [
 
 [[package]]
 name = "colorchoice"
-version = "1.0.0"
+version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
+checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
 
 [[package]]
 name = "colored"
@@ -978,7 +976,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "strsim 0.10.0",
- "syn 2.0.58",
+ "syn 2.0.62",
 ]
 
 [[package]]
@@ -989,7 +987,7 @@ checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f"
 dependencies = [
  "darling_core",
  "quote",
- "syn 2.0.58",
+ "syn 2.0.62",
 ]
 
 [[package]]
@@ -1004,7 +1002,7 @@ version = "0.1.80"
 dependencies = [
  "itertools 0.12.1",
  "quote",
- "syn 2.0.58",
+ "syn 2.0.62",
 ]
 
 [[package]]
@@ -1045,7 +1043,7 @@ dependencies = [
  "darling",
  "proc-macro2",
  "quote",
- "syn 2.0.58",
+ "syn 2.0.62",
 ]
 
 [[package]]
@@ -1055,7 +1053,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b"
 dependencies = [
  "derive_builder_core",
- "syn 2.0.58",
+ "syn 2.0.62",
 ]
 
 [[package]]
@@ -1078,7 +1076,7 @@ dependencies = [
  "darling",
  "proc-macro2",
  "quote",
- "syn 2.0.58",
+ "syn 2.0.62",
 ]
 
 [[package]]
@@ -1167,14 +1165,14 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.58",
+ "syn 2.0.62",
 ]
 
 [[package]]
 name = "dissimilar"
-version = "1.0.7"
+version = "1.0.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86e3bdc80eee6e16b2b6b0f87fbc98c04bee3455e35174c0de1a125d0688c632"
+checksum = "59f8e79d1fbf76bdfbde321e902714bf6c49df88a7dda6fc682fc2979226962d"
 
 [[package]]
 name = "dlmalloc"
@@ -1191,9 +1189,9 @@ dependencies = [
 
 [[package]]
 name = "either"
-version = "1.10.0"
+version = "1.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a"
+checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2"
 
 [[package]]
 name = "elasticlunr-rs"
@@ -1218,9 +1216,9 @@ dependencies = [
 
 [[package]]
 name = "ena"
-version = "0.14.2"
+version = "0.14.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c533630cf40e9caa44bd91aadc88a75d75a4c3a12b4cfde353cbed41daa1e1f1"
+checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5"
 dependencies = [
  "log",
 ]
@@ -1233,9 +1231,9 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
 
 [[package]]
 name = "encoding_rs"
-version = "0.8.33"
+version = "0.8.34"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1"
+checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59"
 dependencies = [
  "cfg-if",
 ]
@@ -1271,9 +1269,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
 
 [[package]]
 name = "errno"
-version = "0.3.8"
+version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
+checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
 dependencies = [
  "libc",
  "windows-sys 0.52.0",
@@ -1314,9 +1312,9 @@ checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649"
 
 [[package]]
 name = "fastrand"
-version = "2.0.2"
+version = "2.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984"
+checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a"
 
 [[package]]
 name = "field-offset"
@@ -1336,15 +1334,15 @@ checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd"
 dependencies = [
  "cfg-if",
  "libc",
- "redox_syscall",
+ "redox_syscall 0.4.1",
  "windows-sys 0.52.0",
 ]
 
 [[package]]
 name = "flate2"
-version = "1.0.28"
+version = "1.0.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e"
+checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae"
 dependencies = [
  "crc32fast",
  "miniz_oxide",
@@ -1352,9 +1350,9 @@ dependencies = [
 
 [[package]]
 name = "fluent-bundle"
-version = "0.15.2"
+version = "0.15.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e242c601dec9711505f6d5bbff5bedd4b61b2469f2e8bb8e57ee7c9747a87ffd"
+checksum = "7fe0a21ee80050c678013f82edf4b705fe2f26f1f9877593d13198612503f493"
 dependencies = [
  "fluent-langneg",
  "fluent-syntax",
@@ -1377,9 +1375,9 @@ dependencies = [
 
 [[package]]
 name = "fluent-syntax"
-version = "0.11.0"
+version = "0.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0abed97648395c902868fee9026de96483933faa54ea3b40d652f7dfe61ca78"
+checksum = "2a530c4694a6a8d528794ee9bbd8ba0122e779629ac908d15ad5a7ae7763a33d"
 dependencies = [
  "thiserror",
 ]
@@ -1505,7 +1503,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.58",
+ "syn 2.0.62",
 ]
 
 [[package]]
@@ -1577,9 +1575,9 @@ dependencies = [
 
 [[package]]
 name = "getrandom"
-version = "0.2.13"
+version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a06fddc2749e0528d2813f95e050e87e52c8cbbae56223b9babf73b3e53b0cc6"
+checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c"
 dependencies = [
  "cfg-if",
  "libc",
@@ -1663,9 +1661,9 @@ dependencies = [
 
 [[package]]
 name = "hashbrown"
-version = "0.14.3"
+version = "0.14.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
+checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
 dependencies = [
  "ahash",
  "allocator-api2",
@@ -1943,7 +1941,7 @@ checksum = "d2abdd3a62551e8337af119c5899e600ca0c88ec8f23a46c60ba216c803dcf1a"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.58",
+ "syn 2.0.62",
 ]
 
 [[package]]
@@ -2055,9 +2053,9 @@ dependencies = [
 
 [[package]]
 name = "intl-memoizer"
-version = "0.5.1"
+version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c310433e4a310918d6ed9243542a6b83ec1183df95dff8f23f87bb88a264a66f"
+checksum = "fe22e020fce238ae18a6d5d8c502ee76a52a6e880d99477657e6acc30ec57bda"
 dependencies = [
  "type-map",
  "unic-langid",
@@ -2079,6 +2077,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
 
 [[package]]
+name = "is_terminal_polyfill"
+version = "1.70.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
+
+[[package]]
 name = "itertools"
 version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2114,9 +2118,9 @@ dependencies = [
 
 [[package]]
 name = "jobserver"
-version = "0.1.28"
+version = "0.1.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6"
+checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e"
 dependencies = [
  "libc",
 ]
@@ -2219,7 +2223,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19"
 dependencies = [
  "cfg-if",
- "windows-targets 0.52.4",
+ "windows-targets 0.52.5",
 ]
 
 [[package]]
@@ -2296,9 +2300,9 @@ dependencies = [
 
 [[package]]
 name = "lock_api"
-version = "0.4.11"
+version = "0.4.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
+checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
 dependencies = [
  "autocfg",
  "scopeguard",
@@ -2384,7 +2388,7 @@ dependencies = [
  "memchr",
  "once_cell",
  "opener",
- "pulldown-cmark 0.10.2",
+ "pulldown-cmark 0.10.3",
  "regex",
  "serde",
  "serde_json",
@@ -2615,12 +2619,11 @@ checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
 
 [[package]]
 name = "num-traits"
-version = "0.2.18"
+version = "0.2.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
+checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
 dependencies = [
  "autocfg",
- "libm",
 ]
 
 [[package]]
@@ -2717,7 +2720,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.58",
+ "syn 2.0.62",
 ]
 
 [[package]]
@@ -2783,16 +2786,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
 
 [[package]]
-name = "packed_simd"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f9f08af0c877571712e2e3e686ad79efad9657dbf0f7c3c8ba943ff6c38932d"
-dependencies = [
- "cfg-if",
- "num-traits",
-]
-
-[[package]]
 name = "pad"
 version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2837,9 +2830,9 @@ dependencies = [
 
 [[package]]
 name = "parking_lot"
-version = "0.12.1"
+version = "0.12.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
+checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb"
 dependencies = [
  "lock_api",
  "parking_lot_core",
@@ -2847,15 +2840,15 @@ dependencies = [
 
 [[package]]
 name = "parking_lot_core"
-version = "0.9.9"
+version = "0.9.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
+checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
 dependencies = [
  "cfg-if",
  "libc",
- "redox_syscall",
+ "redox_syscall 0.5.1",
  "smallvec",
- "windows-targets 0.48.5",
+ "windows-targets 0.52.5",
 ]
 
 [[package]]
@@ -2890,9 +2883,9 @@ dependencies = [
 
 [[package]]
 name = "pest"
-version = "2.7.9"
+version = "2.7.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "311fb059dee1a7b802f036316d790138c613a4e8b180c822e3925a662e9f0c95"
+checksum = "560131c633294438da9f7c4b08189194b20946c8274c6b9e38881a7874dc8ee8"
 dependencies = [
  "memchr",
  "thiserror",
@@ -2901,9 +2894,9 @@ dependencies = [
 
 [[package]]
 name = "pest_derive"
-version = "2.7.9"
+version = "2.7.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f73541b156d32197eecda1a4014d7f868fd2bcb3c550d5386087cfba442bf69c"
+checksum = "26293c9193fbca7b1a3bf9b79dc1e388e927e6cacaa78b4a3ab705a1d3d41459"
 dependencies = [
  "pest",
  "pest_generator",
@@ -2911,22 +2904,22 @@ dependencies = [
 
 [[package]]
 name = "pest_generator"
-version = "2.7.9"
+version = "2.7.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c35eeed0a3fab112f75165fdc026b3913f4183133f19b49be773ac9ea966e8bd"
+checksum = "3ec22af7d3fb470a85dd2ca96b7c577a1eb4ef6f1683a9fe9a8c16e136c04687"
 dependencies = [
  "pest",
  "pest_meta",
  "proc-macro2",
  "quote",
- "syn 2.0.58",
+ "syn 2.0.62",
 ]
 
 [[package]]
 name = "pest_meta"
-version = "2.7.9"
+version = "2.7.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2adbf29bb9776f28caece835398781ab24435585fe0d4dc1374a61db5accedca"
+checksum = "d7a240022f37c361ec1878d646fc5b7d7c4d28d5946e1a80ad5a7a4f4ca0bdcd"
 dependencies = [
  "once_cell",
  "pest",
@@ -3080,9 +3073,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.79"
+version = "1.0.82"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e"
+checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b"
 dependencies = [
  "unicode-ident",
 ]
@@ -3126,9 +3119,9 @@ dependencies = [
 
 [[package]]
 name = "pulldown-cmark"
-version = "0.10.2"
+version = "0.10.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f0530d13d87d1f549b66a3e8d0c688952abe5994e204ed62615baaf25dc029c"
+checksum = "76979bea66e7875e7509c4ec5300112b316af87fa7a252ca91c448b32dfe3993"
 dependencies = [
  "bitflags 2.5.0",
  "memchr",
@@ -3138,9 +3131,9 @@ dependencies = [
 
 [[package]]
 name = "pulldown-cmark-escape"
-version = "0.10.0"
+version = "0.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d5d8f9aa0e3cbcfaf8bf00300004ee3b72f74770f9cbac93f6928771f613276b"
+checksum = "bd348ff538bc9caeda7ee8cad2d1d48236a1f443c1fa3913c6a02fe0043b1dd3"
 
 [[package]]
 name = "punycode"
@@ -3156,9 +3149,9 @@ checksum = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45"
 
 [[package]]
 name = "quote"
-version = "1.0.35"
+version = "1.0.36"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
+checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
 dependencies = [
  "proc-macro2",
 ]
@@ -3262,6 +3255,15 @@ dependencies = [
 ]
 
 [[package]]
+name = "redox_syscall"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e"
+dependencies = [
+ "bitflags 2.5.0",
+]
+
+[[package]]
 name = "redox_users"
 version = "0.4.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3436,9 +3438,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-demangle"
-version = "0.1.23"
+version = "0.1.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
+checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
 dependencies = [
  "compiler_builtins",
  "rustc-std-workspace-core",
@@ -3999,7 +4001,7 @@ dependencies = [
  "fluent-syntax",
  "proc-macro2",
  "quote",
- "syn 2.0.58",
+ "syn 2.0.62",
  "unic-langid",
 ]
 
@@ -4133,7 +4135,7 @@ version = "0.0.0"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.58",
+ "syn 2.0.62",
  "synstructure",
 ]
 
@@ -4280,7 +4282,7 @@ version = "0.0.0"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.58",
+ "syn 2.0.62",
  "synstructure",
 ]
 
@@ -4367,6 +4369,7 @@ dependencies = [
  "rustc_hir",
  "rustc_index",
  "rustc_infer",
+ "rustc_lint",
  "rustc_macros",
  "rustc_middle",
  "rustc_pattern_analysis",
@@ -4835,10 +4838,21 @@ dependencies = [
  "rustc_macros",
  "rustc_serialize",
  "rustc_span",
+ "rustc_type_ir_macros",
  "smallvec",
 ]
 
 [[package]]
+name = "rustc_type_ir_macros"
+version = "0.0.0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.62",
+ "synstructure",
+]
+
+[[package]]
 name = "rustc_version"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4932,7 +4946,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "serde",
- "syn 2.0.58",
+ "syn 2.0.62",
 ]
 
 [[package]]
@@ -4967,9 +4981,9 @@ dependencies = [
 
 [[package]]
 name = "rustix"
-version = "0.38.32"
+version = "0.38.34"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89"
+checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
 dependencies = [
  "bitflags 2.5.0",
  "errno",
@@ -4989,9 +5003,9 @@ dependencies = [
 
 [[package]]
 name = "rustversion"
-version = "1.0.15"
+version = "1.0.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47"
+checksum = "092474d1a01ea8278f69e6a358998405fae5b8b963ddaeb2b0b04a128bf1dfb0"
 
 [[package]]
 name = "ruzstd"
@@ -5017,9 +5031,9 @@ dependencies = [
 
 [[package]]
 name = "ryu"
-version = "1.0.17"
+version = "1.0.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
+checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
 
 [[package]]
 name = "same-file"
@@ -5053,11 +5067,11 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
 
 [[package]]
 name = "security-framework"
-version = "2.10.0"
+version = "2.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6"
+checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0"
 dependencies = [
- "bitflags 1.3.2",
+ "bitflags 2.5.0",
  "core-foundation",
  "core-foundation-sys",
  "libc",
@@ -5066,9 +5080,9 @@ dependencies = [
 
 [[package]]
 name = "security-framework-sys"
-version = "2.10.0"
+version = "2.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef"
+checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7"
 dependencies = [
  "core-foundation-sys",
  "libc",
@@ -5080,49 +5094,49 @@ version = "0.10.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e14e4d63b804dc0c7ec4a1e52bcb63f02c7ac94476755aa579edac21e01f915d"
 dependencies = [
- "self_cell 1.0.3",
+ "self_cell 1.0.4",
 ]
 
 [[package]]
 name = "self_cell"
-version = "1.0.3"
+version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58bf37232d3bb9a2c4e641ca2a11d83b5062066f88df7fed36c28772046d65ba"
+checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a"
 
 [[package]]
 name = "semver"
-version = "1.0.22"
+version = "1.0.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca"
+checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
 dependencies = [
  "serde",
 ]
 
 [[package]]
 name = "serde"
-version = "1.0.197"
+version = "1.0.201"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
+checksum = "780f1cebed1629e4753a1a38a3c72d30b97ec044f0aef68cb26650a3c5cf363c"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.197"
+version = "1.0.201"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
+checksum = "c5e405930b9796f1c00bee880d03fc7e0bb4b9a11afc776885ffe84320da2865"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.58",
+ "syn 2.0.62",
 ]
 
 [[package]]
 name = "serde_json"
-version = "1.0.115"
+version = "1.0.117"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd"
+checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3"
 dependencies = [
  "indexmap",
  "itoa",
@@ -5229,9 +5243,9 @@ checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b"
 
 [[package]]
 name = "socket2"
-version = "0.5.6"
+version = "0.5.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871"
+checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c"
 dependencies = [
  "libc",
  "windows-sys 0.52.0",
@@ -5427,9 +5441,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.58"
+version = "2.0.62"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687"
+checksum = "9f660c3bfcefb88c538776b6685a0c472e3128b51e74d48793dc2a488196e8eb"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -5450,14 +5464,14 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.58",
+ "syn 2.0.62",
 ]
 
 [[package]]
 name = "sysinfo"
-version = "0.30.8"
+version = "0.30.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b1a378e48fb3ce3a5cf04359c456c9c98ff689bcf1c1bc6e6a31f247686f275"
+checksum = "732ffa00f53e6b2af46208fba5718d9662a421049204e156328b66791ffa15ae"
 dependencies = [
  "cfg-if",
  "core-foundation-sys",
@@ -5601,22 +5615,22 @@ checksum = "a38c90d48152c236a3ab59271da4f4ae63d678c5d7ad6b7714d7cb9760be5e4b"
 
 [[package]]
 name = "thiserror"
-version = "1.0.58"
+version = "1.0.60"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297"
+checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.58"
+version = "1.0.60"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7"
+checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.58",
+ "syn 2.0.62",
 ]
 
 [[package]]
@@ -5751,16 +5765,15 @@ dependencies = [
 
 [[package]]
 name = "tokio-util"
-version = "0.7.10"
+version = "0.7.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15"
+checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1"
 dependencies = [
  "bytes",
  "futures-core",
  "futures-sink",
  "pin-project-lite",
  "tokio",
- "tracing",
 ]
 
 [[package]]
@@ -5838,7 +5851,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.58",
+ "syn 2.0.62",
 ]
 
 [[package]]
@@ -5922,9 +5935,9 @@ dependencies = [
 
 [[package]]
 name = "type-map"
-version = "0.4.0"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6d3364c5e96cb2ad1603037ab253ddd34d7fb72a58bdddf4b7350760fc69a46"
+checksum = "deb68604048ff8fa93347f02441e4487594adc20bb8a084f9e564d2b827a0a9f"
 dependencies = [
  "rustc-hash",
 ]
@@ -6007,9 +6020,9 @@ dependencies = [
 
 [[package]]
 name = "unic-langid"
-version = "0.9.4"
+version = "0.9.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "238722e6d794ed130f91f4ea33e01fcff4f188d92337a21297892521c72df516"
+checksum = "23dd9d1e72a73b25e07123a80776aae3e7b0ec461ef94f9151eed6ec88005a44"
 dependencies = [
  "unic-langid-impl",
  "unic-langid-macros",
@@ -6017,18 +6030,18 @@ dependencies = [
 
 [[package]]
 name = "unic-langid-impl"
-version = "0.9.4"
+version = "0.9.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4bd55a2063fdea4ef1f8633243a7b0524cbeef1905ae04c31a1c9b9775c55bc6"
+checksum = "0a5422c1f65949306c99240b81de9f3f15929f5a8bfe05bb44b034cc8bf593e5"
 dependencies = [
  "tinystr",
 ]
 
 [[package]]
 name = "unic-langid-macros"
-version = "0.9.4"
+version = "0.9.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c854cefb82ff2816410ce606acbad1b3af065140907b29be9229040752b83ec"
+checksum = "0da1cd2c042d3c7569a1008806b02039e7a4a2bdf8f8e96bd3c792434a0e275e"
 dependencies = [
  "proc-macro-hack",
  "tinystr",
@@ -6038,13 +6051,13 @@ dependencies = [
 
 [[package]]
 name = "unic-langid-macros-impl"
-version = "0.9.4"
+version = "0.9.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fea2a4c80deb4fb3ca51f66b5e2dd91e3642bbce52234bcf22e41668281208e4"
+checksum = "1ed7f4237ba393424195053097c1516bd4590dc82b84f2f97c5c69e12704555b"
 dependencies = [
  "proc-macro-hack",
  "quote",
- "syn 2.0.58",
+ "syn 2.0.62",
  "unic-langid-impl",
 ]
 
@@ -6115,9 +6128,9 @@ checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
 
 [[package]]
 name = "unicode-width"
-version = "0.1.11"
+version = "0.1.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
+checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6"
 dependencies = [
  "compiler_builtins",
  "rustc-std-workspace-core",
@@ -6276,7 +6289,7 @@ dependencies = [
  "once_cell",
  "proc-macro2",
  "quote",
- "syn 2.0.58",
+ "syn 2.0.62",
  "wasm-bindgen-shared",
 ]
 
@@ -6310,7 +6323,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.58",
+ "syn 2.0.62",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
@@ -6368,11 +6381,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
 
 [[package]]
 name = "winapi-util"
-version = "0.1.6"
+version = "0.1.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
+checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b"
 dependencies = [
- "winapi",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]
@@ -6388,7 +6401,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
 dependencies = [
  "windows-core",
- "windows-targets 0.52.4",
+ "windows-targets 0.52.5",
 ]
 
 [[package]]
@@ -6401,7 +6414,7 @@ dependencies = [
  "rayon",
  "serde",
  "serde_json",
- "syn 2.0.58",
+ "syn 2.0.62",
  "windows-metadata",
 ]
 
@@ -6411,7 +6424,7 @@ version = "0.52.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
 dependencies = [
- "windows-targets 0.52.4",
+ "windows-targets 0.52.5",
 ]
 
 [[package]]
@@ -6435,7 +6448,7 @@ version = "0.52.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
 dependencies = [
- "windows-targets 0.52.4",
+ "windows-targets 0.52.5",
 ]
 
 [[package]]
@@ -6455,17 +6468,18 @@ dependencies = [
 
 [[package]]
 name = "windows-targets"
-version = "0.52.4"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
+checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
 dependencies = [
- "windows_aarch64_gnullvm 0.52.4",
- "windows_aarch64_msvc 0.52.4",
- "windows_i686_gnu 0.52.4",
- "windows_i686_msvc 0.52.4",
- "windows_x86_64_gnu 0.52.4",
- "windows_x86_64_gnullvm 0.52.4",
- "windows_x86_64_msvc 0.52.4",
+ "windows_aarch64_gnullvm 0.52.5",
+ "windows_aarch64_msvc 0.52.5",
+ "windows_i686_gnu 0.52.5",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc 0.52.5",
+ "windows_x86_64_gnu 0.52.5",
+ "windows_x86_64_gnullvm 0.52.5",
+ "windows_x86_64_msvc 0.52.5",
 ]
 
 [[package]]
@@ -6476,9 +6490,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
 
 [[package]]
 name = "windows_aarch64_gnullvm"
-version = "0.52.4"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
+checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
 
 [[package]]
 name = "windows_aarch64_msvc"
@@ -6488,9 +6502,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
 
 [[package]]
 name = "windows_aarch64_msvc"
-version = "0.52.4"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
+checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
 
 [[package]]
 name = "windows_i686_gnu"
@@ -6500,9 +6514,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
 
 [[package]]
 name = "windows_i686_gnu"
-version = "0.52.4"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
+checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
 
 [[package]]
 name = "windows_i686_msvc"
@@ -6512,9 +6532,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
 
 [[package]]
 name = "windows_i686_msvc"
-version = "0.52.4"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
+checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
 
 [[package]]
 name = "windows_x86_64_gnu"
@@ -6524,9 +6544,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
 
 [[package]]
 name = "windows_x86_64_gnu"
-version = "0.52.4"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
+checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
 
 [[package]]
 name = "windows_x86_64_gnullvm"
@@ -6536,9 +6556,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
 
 [[package]]
 name = "windows_x86_64_gnullvm"
-version = "0.52.4"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
+checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
 
 [[package]]
 name = "windows_x86_64_msvc"
@@ -6548,9 +6568,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
 
 [[package]]
 name = "windows_x86_64_msvc"
-version = "0.52.4"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
+checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
 
 [[package]]
 name = "winnow"
@@ -6626,28 +6646,28 @@ checksum = "9e6936f0cce458098a201c245a11bef556c6a0181129c7034d10d76d1ec3a2b8"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.58",
+ "syn 2.0.62",
  "synstructure",
 ]
 
 [[package]]
 name = "zerocopy"
-version = "0.7.32"
+version = "0.7.34"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"
+checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087"
 dependencies = [
  "zerocopy-derive",
 ]
 
 [[package]]
 name = "zerocopy-derive"
-version = "0.7.32"
+version = "0.7.34"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
+checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.58",
+ "syn 2.0.62",
 ]
 
 [[package]]
@@ -6667,7 +6687,7 @@ checksum = "e6a647510471d372f2e6c2e6b7219e44d8c574d24fdc11c610a61455782f18c3"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.58",
+ "syn 2.0.62",
  "synstructure",
 ]
 
@@ -6690,7 +6710,7 @@ checksum = "7b4e5997cbf58990550ef1f0e5124a05e47e1ebd33a84af25739be6031a62c20"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.58",
+ "syn 2.0.62",
 ]
 
 [[package]]
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index a8d019c9804..9f2788c87c3 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -1255,7 +1255,7 @@ impl<FieldIdx: Idx> FieldsShape<FieldIdx> {
 
     /// Gets source indices of the fields by increasing offsets.
     #[inline]
-    pub fn index_by_increasing_offset(&self) -> impl Iterator<Item = usize> + '_ {
+    pub fn index_by_increasing_offset(&self) -> impl ExactSizeIterator<Item = usize> + '_ {
         let mut inverse_small = [0u8; 64];
         let mut inverse_big = IndexVec::new();
         let use_small = self.count() <= inverse_small.len();
@@ -1271,7 +1271,12 @@ impl<FieldIdx: Idx> FieldsShape<FieldIdx> {
             }
         }
 
-        (0..self.count()).map(move |i| match *self {
+        // Primitives don't really have fields in the way that structs do,
+        // but having this return an empty iterator for them is unhelpful
+        // since that makes them look kinda like ZSTs, which they're not.
+        let pseudofield_count = if let FieldsShape::Primitive = self { 1 } else { self.count() };
+
+        (0..pseudofield_count).map(move |i| match *self {
             FieldsShape::Primitive | FieldsShape::Union(_) | FieldsShape::Array { .. } => i,
             FieldsShape::Arbitrary { .. } => {
                 if use_small {
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 7951b7e7b75..56d4f53f9ee 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -3250,6 +3250,7 @@ pub enum ItemKind {
 }
 
 impl ItemKind {
+    /// "a" or "an"
     pub fn article(&self) -> &'static str {
         use ItemKind::*;
         match self {
diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs
index a0486227f2a..2cf811e9122 100644
--- a/compiler/rustc_ast/src/ast_traits.rs
+++ b/compiler/rustc_ast/src/ast_traits.rs
@@ -240,7 +240,6 @@ impl HasTokens for Nonterminal {
             Nonterminal::NtPath(path) => path.tokens(),
             Nonterminal::NtVis(vis) => vis.tokens(),
             Nonterminal::NtBlock(block) => block.tokens(),
-            Nonterminal::NtIdent(..) | Nonterminal::NtLifetime(..) => None,
         }
     }
     fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
@@ -254,7 +253,6 @@ impl HasTokens for Nonterminal {
             Nonterminal::NtPath(path) => path.tokens_mut(),
             Nonterminal::NtVis(vis) => vis.tokens_mut(),
             Nonterminal::NtBlock(block) => block.tokens_mut(),
-            Nonterminal::NtIdent(..) | Nonterminal::NtLifetime(..) => None,
         }
     }
 }
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs
index 0f12fd31975..0684163617f 100644
--- a/compiler/rustc_ast/src/attr/mod.rs
+++ b/compiler/rustc_ast/src/attr/mod.rs
@@ -345,7 +345,7 @@ impl MetaItem {
                 let span = span.with_hi(segments.last().unwrap().ident.span.hi());
                 Path { span, segments, tokens: None }
             }
-            Some(TokenTree::Token(Token { kind: token::Interpolated(nt), .. }, _)) => match &nt.0 {
+            Some(TokenTree::Token(Token { kind: token::Interpolated(nt), .. }, _)) => match &**nt {
                 token::Nonterminal::NtMeta(item) => return item.meta(item.path.span),
                 token::Nonterminal::NtPath(path) => (**path).clone(),
                 _ => return None,
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 379c2e273eb..5c4162295bb 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -781,10 +781,14 @@ pub fn visit_token<T: MutVisitor>(t: &mut Token, vis: &mut T) {
             *span = ident.span;
             return; // Avoid visiting the span for the second time.
         }
+        token::NtIdent(ident, _is_raw) => {
+            vis.visit_ident(ident);
+        }
+        token::NtLifetime(ident) => {
+            vis.visit_ident(ident);
+        }
         token::Interpolated(nt) => {
             let nt = Lrc::make_mut(nt);
-            let (nt, sp) = (&mut nt.0, &mut nt.1);
-            vis.visit_span(sp);
             visit_nonterminal(nt, vis);
         }
         _ => {}
@@ -834,8 +838,6 @@ fn visit_nonterminal<T: MutVisitor>(nt: &mut token::Nonterminal, vis: &mut T) {
         token::NtPat(pat) => vis.visit_pat(pat),
         token::NtExpr(expr) => vis.visit_expr(expr),
         token::NtTy(ty) => vis.visit_ty(ty),
-        token::NtIdent(ident, _is_raw) => vis.visit_ident(ident),
-        token::NtLifetime(ident) => vis.visit_ident(ident),
         token::NtLiteral(expr) => vis.visit_expr(expr),
         token::NtMeta(item) => {
             let AttrItem { path, args, tokens } = item.deref_mut();
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index 72f89737f99..d00352ea2e1 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -111,7 +111,7 @@ impl Lit {
             Ident(name, IdentIsRaw::No) if name.is_bool_lit() => Some(Lit::new(Bool, name, None)),
             Literal(token_lit) => Some(token_lit),
             Interpolated(ref nt)
-                if let NtExpr(expr) | NtLiteral(expr) = &nt.0
+                if let NtExpr(expr) | NtLiteral(expr) = &**nt
                     && let ast::ExprKind::Lit(token_lit) = expr.kind =>
             {
                 Some(token_lit)
@@ -318,11 +318,20 @@ pub enum TokenKind {
     /// It's recommended to use `Token::(ident,uninterpolate,uninterpolated_span)` to
     /// treat regular and interpolated identifiers in the same way.
     Ident(Symbol, IdentIsRaw),
+    /// This identifier (and its span) is the identifier passed to the
+    /// declarative macro. The span in the surrounding `Token` is the span of
+    /// the `ident` metavariable in the macro's RHS.
+    NtIdent(Ident, IdentIsRaw),
+
     /// Lifetime identifier token.
     /// Do not forget about `NtLifetime` when you want to match on lifetime identifiers.
     /// It's recommended to use `Token::(lifetime,uninterpolate,uninterpolated_span)` to
     /// treat regular and interpolated lifetime identifiers in the same way.
     Lifetime(Symbol),
+    /// This identifier (and its span) is the lifetime passed to the
+    /// declarative macro. The span in the surrounding `Token` is the span of
+    /// the `lifetime` metavariable in the macro's RHS.
+    NtLifetime(Ident),
 
     /// An embedded AST node, as produced by a macro. This only exists for
     /// historical reasons. We'd like to get rid of it, for multiple reasons.
@@ -333,7 +342,11 @@ pub enum TokenKind {
     /// - It prevents `Token` from implementing `Copy`.
     /// It adds complexity and likely slows things down. Please don't add new
     /// occurrences of this token kind!
-    Interpolated(Lrc<(Nonterminal, Span)>),
+    ///
+    /// The span in the surrounding `Token` is that of the metavariable in the
+    /// macro's RHS. The span within the Nonterminal is that of the fragment
+    /// passed to the macro at the call site.
+    Interpolated(Lrc<Nonterminal>),
 
     /// A doc comment token.
     /// `Symbol` is the doc comment's data excluding its "quotes" (`///`, `/**`, etc)
@@ -440,8 +453,9 @@ impl Token {
     /// Note that keywords are also identifiers, so they should use this
     /// if they keep spans or perform edition checks.
     pub fn uninterpolated_span(&self) -> Span {
-        match &self.kind {
-            Interpolated(nt) => nt.0.use_span(),
+        match self.kind {
+            NtIdent(ident, _) | NtLifetime(ident) => ident.span,
+            Interpolated(ref nt) => nt.use_span(),
             _ => self.span,
         }
     }
@@ -459,7 +473,7 @@ impl Token {
             }
 
             OpenDelim(..) | CloseDelim(..) | Literal(..) | DocComment(..) | Ident(..)
-            | Lifetime(..) | Interpolated(..) | Eof => false,
+            | NtIdent(..) | Lifetime(..) | NtLifetime(..) | Interpolated(..) | Eof => false,
         }
     }
 
@@ -486,7 +500,7 @@ impl Token {
             PathSep                            | // global path
             Lifetime(..)                      | // labeled loop
             Pound                             => true, // expression attributes
-            Interpolated(ref nt) => matches!(&nt.0, NtLiteral(..) |
+            Interpolated(ref nt) => matches!(&**nt, NtLiteral(..) |
                 NtExpr(..)    |
                 NtBlock(..)   |
                 NtPath(..)),
@@ -510,7 +524,7 @@ impl Token {
             | DotDot | DotDotDot | DotDotEq      // ranges
             | Lt | BinOp(Shl)                    // associated path
             | PathSep                    => true, // global path
-            Interpolated(ref nt) => matches!(&nt.0, NtLiteral(..) |
+            Interpolated(ref nt) => matches!(&**nt, NtLiteral(..) |
                 NtPat(..)     |
                 NtBlock(..)   |
                 NtPath(..)),
@@ -533,7 +547,7 @@ impl Token {
             Lifetime(..)                | // lifetime bound in trait object
             Lt | BinOp(Shl)             | // associated path
             PathSep                      => true, // global path
-            Interpolated(ref nt) => matches!(&nt.0, NtTy(..) | NtPath(..)),
+            Interpolated(ref nt) => matches!(&**nt, NtTy(..) | NtPath(..)),
             // For anonymous structs or unions, which only appear in specific positions
             // (type of struct fields or union fields), we don't consider them as regular types
             _ => false,
@@ -544,7 +558,7 @@ impl Token {
     pub fn can_begin_const_arg(&self) -> bool {
         match self.kind {
             OpenDelim(Delimiter::Brace) => true,
-            Interpolated(ref nt) => matches!(&nt.0, NtExpr(..) | NtBlock(..) | NtLiteral(..)),
+            Interpolated(ref nt) => matches!(&**nt, NtExpr(..) | NtBlock(..) | NtLiteral(..)),
             _ => self.can_begin_literal_maybe_minus(),
         }
     }
@@ -589,7 +603,7 @@ impl Token {
         match self.uninterpolate().kind {
             Literal(..) | BinOp(Minus) => true,
             Ident(name, IdentIsRaw::No) if name.is_bool_lit() => true,
-            Interpolated(ref nt) => match &nt.0 {
+            Interpolated(ref nt) => match &**nt {
                 NtLiteral(_) => true,
                 NtExpr(e) => match &e.kind {
                     ast::ExprKind::Lit(_) => true,
@@ -609,14 +623,9 @@ impl Token {
     /// into the regular identifier or lifetime token it refers to,
     /// otherwise returns the original token.
     pub fn uninterpolate(&self) -> Cow<'_, Token> {
-        match &self.kind {
-            Interpolated(nt) => match &nt.0 {
-                NtIdent(ident, is_raw) => {
-                    Cow::Owned(Token::new(Ident(ident.name, *is_raw), ident.span))
-                }
-                NtLifetime(ident) => Cow::Owned(Token::new(Lifetime(ident.name), ident.span)),
-                _ => Cow::Borrowed(self),
-            },
+        match self.kind {
+            NtIdent(ident, is_raw) => Cow::Owned(Token::new(Ident(ident.name, is_raw), ident.span)),
+            NtLifetime(ident) => Cow::Owned(Token::new(Lifetime(ident.name), ident.span)),
             _ => Cow::Borrowed(self),
         }
     }
@@ -625,12 +634,9 @@ impl Token {
     #[inline]
     pub fn ident(&self) -> Option<(Ident, IdentIsRaw)> {
         // We avoid using `Token::uninterpolate` here because it's slow.
-        match &self.kind {
-            &Ident(name, is_raw) => Some((Ident::new(name, self.span), is_raw)),
-            Interpolated(nt) => match &nt.0 {
-                NtIdent(ident, is_raw) => Some((*ident, *is_raw)),
-                _ => None,
-            },
+        match self.kind {
+            Ident(name, is_raw) => Some((Ident::new(name, self.span), is_raw)),
+            NtIdent(ident, is_raw) => Some((ident, is_raw)),
             _ => None,
         }
     }
@@ -639,12 +645,9 @@ impl Token {
     #[inline]
     pub fn lifetime(&self) -> Option<Ident> {
         // We avoid using `Token::uninterpolate` here because it's slow.
-        match &self.kind {
-            &Lifetime(name) => Some(Ident::new(name, self.span)),
-            Interpolated(nt) => match &nt.0 {
-                NtLifetime(ident) => Some(*ident),
-                _ => None,
-            },
+        match self.kind {
+            Lifetime(name) => Some(Ident::new(name, self.span)),
+            NtLifetime(ident) => Some(ident),
             _ => None,
         }
     }
@@ -668,7 +671,7 @@ impl Token {
     /// Returns `true` if the token is an interpolated path.
     fn is_whole_path(&self) -> bool {
         if let Interpolated(nt) = &self.kind
-            && let NtPath(..) = &nt.0
+            && let NtPath(..) = &**nt
         {
             return true;
         }
@@ -681,7 +684,7 @@ impl Token {
     /// (which happens while parsing the result of macro expansion)?
     pub fn is_whole_expr(&self) -> bool {
         if let Interpolated(nt) = &self.kind
-            && let NtExpr(_) | NtLiteral(_) | NtPath(_) | NtBlock(_) = &nt.0
+            && let NtExpr(_) | NtLiteral(_) | NtPath(_) | NtBlock(_) = &**nt
         {
             return true;
         }
@@ -692,7 +695,7 @@ impl Token {
     /// Is the token an interpolated block (`$b:block`)?
     pub fn is_whole_block(&self) -> bool {
         if let Interpolated(nt) = &self.kind
-            && let NtBlock(..) = &nt.0
+            && let NtBlock(..) = &**nt
         {
             return true;
         }
@@ -833,8 +836,10 @@ impl Token {
 
             Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | BinOpEq(..) | At | DotDotDot
             | DotDotEq | Comma | Semi | PathSep | RArrow | LArrow | FatArrow | Pound | Dollar
-            | Question | OpenDelim(..) | CloseDelim(..) | Literal(..) | Ident(..)
-            | Lifetime(..) | Interpolated(..) | DocComment(..) | Eof => return None,
+            | Question | OpenDelim(..) | CloseDelim(..) | Literal(..) | Ident(..) | NtIdent(..)
+            | Lifetime(..) | NtLifetime(..) | Interpolated(..) | DocComment(..) | Eof => {
+                return None;
+            }
         };
 
         Some(Token::new(kind, self.span.to(joint.span)))
@@ -857,8 +862,6 @@ pub enum Nonterminal {
     NtPat(P<ast::Pat>),
     NtExpr(P<ast::Expr>),
     NtTy(P<ast::Ty>),
-    NtIdent(Ident, IdentIsRaw),
-    NtLifetime(Ident),
     NtLiteral(P<ast::Expr>),
     /// Stuff inside brackets for attributes
     NtMeta(P<ast::AttrItem>),
@@ -953,7 +956,6 @@ impl Nonterminal {
             NtPat(pat) => pat.span,
             NtExpr(expr) | NtLiteral(expr) => expr.span,
             NtTy(ty) => ty.span,
-            NtIdent(ident, _) | NtLifetime(ident) => ident.span,
             NtMeta(attr_item) => attr_item.span(),
             NtPath(path) => path.span,
             NtVis(vis) => vis.span,
@@ -969,8 +971,6 @@ impl Nonterminal {
             NtExpr(..) => "expression",
             NtLiteral(..) => "literal",
             NtTy(..) => "type",
-            NtIdent(..) => "identifier",
-            NtLifetime(..) => "lifetime",
             NtMeta(..) => "attribute",
             NtPath(..) => "path",
             NtVis(..) => "visibility",
@@ -979,18 +979,12 @@ impl Nonterminal {
 }
 
 impl PartialEq for Nonterminal {
-    fn eq(&self, rhs: &Self) -> bool {
-        match (self, rhs) {
-            (NtIdent(ident_lhs, is_raw_lhs), NtIdent(ident_rhs, is_raw_rhs)) => {
-                ident_lhs == ident_rhs && is_raw_lhs == is_raw_rhs
-            }
-            (NtLifetime(ident_lhs), NtLifetime(ident_rhs)) => ident_lhs == ident_rhs,
-            // FIXME: Assume that all "complex" nonterminal are not equal, we can't compare them
-            // correctly based on data from AST. This will prevent them from matching each other
-            // in macros. The comparison will become possible only when each nonterminal has an
-            // attached token stream from which it was parsed.
-            _ => false,
-        }
+    fn eq(&self, _rhs: &Self) -> bool {
+        // FIXME: Assume that all nonterminals are not equal, we can't compare them
+        // correctly based on data from AST. This will prevent them from matching each other
+        // in macros. The comparison will become possible only when each nonterminal has an
+        // attached token stream from which it was parsed.
+        false
     }
 }
 
@@ -1003,12 +997,10 @@ impl fmt::Debug for Nonterminal {
             NtPat(..) => f.pad("NtPat(..)"),
             NtExpr(..) => f.pad("NtExpr(..)"),
             NtTy(..) => f.pad("NtTy(..)"),
-            NtIdent(..) => f.pad("NtIdent(..)"),
             NtLiteral(..) => f.pad("NtLiteral(..)"),
             NtMeta(..) => f.pad("NtMeta(..)"),
             NtPath(..) => f.pad("NtPath(..)"),
             NtVis(..) => f.pad("NtVis(..)"),
-            NtLifetime(..) => f.pad("NtLifetime(..)"),
         }
     }
 }
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index 8e80161af1b..fb666550e93 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -466,12 +466,6 @@ impl TokenStream {
 
     pub fn from_nonterminal_ast(nt: &Nonterminal) -> TokenStream {
         match nt {
-            Nonterminal::NtIdent(ident, is_raw) => {
-                TokenStream::token_alone(token::Ident(ident.name, *is_raw), ident.span)
-            }
-            Nonterminal::NtLifetime(ident) => {
-                TokenStream::token_alone(token::Lifetime(ident.name), ident.span)
-            }
             Nonterminal::NtItem(item) => TokenStream::from_ast(item),
             Nonterminal::NtBlock(block) => TokenStream::from_ast(block),
             Nonterminal::NtStmt(stmt) if let StmtKind::Empty = stmt.kind => {
@@ -489,15 +483,21 @@ impl TokenStream {
     }
 
     fn flatten_token(token: &Token, spacing: Spacing) -> TokenTree {
-        match &token.kind {
-            token::Interpolated(nt) if let token::NtIdent(ident, is_raw) = nt.0 => {
+        match token.kind {
+            token::NtIdent(ident, is_raw) => {
                 TokenTree::Token(Token::new(token::Ident(ident.name, is_raw), ident.span), spacing)
             }
-            token::Interpolated(nt) => TokenTree::Delimited(
+            token::NtLifetime(ident) => TokenTree::Delimited(
+                DelimSpan::from_single(token.span),
+                DelimSpacing::new(Spacing::JointHidden, spacing),
+                Delimiter::Invisible,
+                TokenStream::token_alone(token::Lifetime(ident.name), ident.span),
+            ),
+            token::Interpolated(ref nt) => TokenTree::Delimited(
                 DelimSpan::from_single(token.span),
                 DelimSpacing::new(Spacing::JointHidden, spacing),
                 Delimiter::Invisible,
-                TokenStream::from_nonterminal_ast(&nt.0).flattened(),
+                TokenStream::from_nonterminal_ast(&nt).flattened(),
             ),
             _ => TokenTree::Token(token.clone(), spacing),
         }
@@ -516,7 +516,10 @@ impl TokenStream {
     pub fn flattened(&self) -> TokenStream {
         fn can_skip(stream: &TokenStream) -> bool {
             stream.trees().all(|tree| match tree {
-                TokenTree::Token(token, _) => !matches!(token.kind, token::Interpolated(_)),
+                TokenTree::Token(token, _) => !matches!(
+                    token.kind,
+                    token::NtIdent(..) | token::NtLifetime(..) | token::Interpolated(..)
+                ),
                 TokenTree::Delimited(.., inner) => can_skip(inner),
             })
         }
diff --git a/compiler/rustc_ast/src/util/classify.rs b/compiler/rustc_ast/src/util/classify.rs
index f21a9cabb81..f6e9e1a87c4 100644
--- a/compiler/rustc_ast/src/util/classify.rs
+++ b/compiler/rustc_ast/src/util/classify.rs
@@ -1,34 +1,88 @@
-//! Routines the parser uses to classify AST nodes
-
-// Predicates on exprs and stmts that the pretty-printer and parser use
+//! Routines the parser and pretty-printer use to classify AST nodes.
 
+use crate::ast::ExprKind::*;
 use crate::{ast, token::Delimiter};
 
-/// Does this expression require a semicolon to be treated
-/// as a statement? The negation of this: 'can this expression
-/// be used as a statement without a semicolon' -- is used
-/// as an early-bail-out in the parser so that, for instance,
-///     if true {...} else {...}
-///      |x| 5
-/// isn't parsed as (if true {...} else {...} | x) | 5
-pub fn expr_requires_semi_to_be_stmt(e: &ast::Expr) -> bool {
-    !matches!(
+/// This classification determines whether various syntactic positions break out
+/// of parsing the current expression (true) or continue parsing more of the
+/// same expression (false).
+///
+/// For example, it's relevant in the parsing of match arms:
+///
+/// ```ignore (illustrative)
+/// match ... {
+///     // Is this calling $e as a function, or is it the start of a new arm
+///     // with a tuple pattern?
+///     _ => $e (
+///             ^                                                          )
+///
+///     // Is this an Index operation, or new arm with a slice pattern?
+///     _ => $e [
+///             ^                                                          ]
+///
+///     // Is this a binary operator, or leading vert in a new arm? Same for
+///     // other punctuation which can either be a binary operator in
+///     // expression or unary operator in pattern, such as `&` and `-`.
+///     _ => $e |
+///             ^
+/// }
+/// ```
+///
+/// If $e is something like `{}` or `if … {}`, then terminate the current
+/// arm and parse a new arm.
+///
+/// If $e is something like `path::to` or `(…)`, continue parsing the same
+/// arm.
+///
+/// *Almost* the same classification is used as an early bail-out for parsing
+/// statements. See `expr_requires_semi_to_be_stmt`.
+pub fn expr_is_complete(e: &ast::Expr) -> bool {
+    matches!(
         e.kind,
-        ast::ExprKind::If(..)
-            | ast::ExprKind::Match(..)
-            | ast::ExprKind::Block(..)
-            | ast::ExprKind::While(..)
-            | ast::ExprKind::Loop(..)
-            | ast::ExprKind::ForLoop { .. }
-            | ast::ExprKind::TryBlock(..)
-            | ast::ExprKind::ConstBlock(..)
+        If(..)
+            | Match(..)
+            | Block(..)
+            | While(..)
+            | Loop(..)
+            | ForLoop { .. }
+            | TryBlock(..)
+            | ConstBlock(..)
     )
 }
 
+/// Does this expression require a semicolon to be treated as a statement?
+///
+/// The negation of this: "can this expression be used as a statement without a
+/// semicolon" -- is used as an early bail-out when parsing statements so that,
+/// for instance,
+///
+/// ```ignore (illustrative)
+/// if true {...} else {...}
+/// |x| 5
+/// ```
+///
+/// isn't parsed as `(if true {...} else {...} | x) | 5`.
+///
+/// Surprising special case: even though braced macro calls like `m! {}`
+/// normally do not introduce a boundary when found at the head of a match arm,
+/// they do terminate the parsing of a statement.
+///
+/// ```ignore (illustrative)
+/// match ... {
+///     _ => m! {} (),  // macro that expands to a function, which is then called
+/// }
+///
+/// let _ = { m! {} () };  // macro call followed by unit
+/// ```
+pub fn expr_requires_semi_to_be_stmt(e: &ast::Expr) -> bool {
+    match &e.kind {
+        MacCall(mac_call) => mac_call.args.delim != Delimiter::Brace,
+        _ => !expr_is_complete(e),
+    }
+}
+
 /// If an expression ends with `}`, returns the innermost expression ending in the `}`
 pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
-    use ast::ExprKind::*;
-
     loop {
         match &expr.kind {
             AddrOf(_, _, e)
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index a76935761f0..c23da8aa01e 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -1407,7 +1407,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         bounds,
                         fn_kind,
                         itctx,
-                        precise_capturing.as_deref().map(|(args, _)| args.as_slice()),
+                        precise_capturing.as_deref().map(|(args, span)| (args.as_slice(), *span)),
                     ),
                     ImplTraitContext::Universal => {
                         if let Some(&(_, span)) = precise_capturing.as_deref() {
@@ -1523,7 +1523,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         bounds: &GenericBounds,
         fn_kind: Option<FnDeclKind>,
         itctx: ImplTraitContext,
-        precise_capturing_args: Option<&[PreciseCapturingArg]>,
+        precise_capturing_args: Option<(&[PreciseCapturingArg], Span)>,
     ) -> hir::TyKind<'hir> {
         // Make sure we know that some funky desugaring has been going on here.
         // This is a first: there is code in other places like for loop
@@ -1533,7 +1533,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None);
 
         let captured_lifetimes_to_duplicate =
-            if let Some(precise_capturing) = precise_capturing_args {
+            if let Some((precise_capturing, _)) = precise_capturing_args {
                 // We'll actually validate these later on; all we need is the list of
                 // lifetimes to duplicate during this portion of lowering.
                 precise_capturing
@@ -1607,7 +1607,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         captured_lifetimes_to_duplicate: FxIndexSet<Lifetime>,
         span: Span,
         opaque_ty_span: Span,
-        precise_capturing_args: Option<&[PreciseCapturingArg]>,
+        precise_capturing_args: Option<(&[PreciseCapturingArg], Span)>,
         lower_item_bounds: impl FnOnce(&mut Self) -> &'hir [hir::GenericBound<'hir>],
     ) -> hir::TyKind<'hir> {
         let opaque_ty_def_id = self.create_def(
@@ -1698,8 +1698,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 this.with_remapping(captured_to_synthesized_mapping, |this| {
                     (
                         lower_item_bounds(this),
-                        precise_capturing_args.map(|precise_capturing| {
-                            this.lower_precise_capturing_args(precise_capturing)
+                        precise_capturing_args.map(|(precise_capturing, span)| {
+                            (
+                                this.lower_precise_capturing_args(precise_capturing),
+                                this.lower_span(span),
+                            )
                         }),
                     )
                 });
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index 2c176828c84..defb666e2b6 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -55,8 +55,8 @@ impl PpAnn for NoAnn {}
 
 pub struct Comments<'a> {
     sm: &'a SourceMap,
-    comments: Vec<Comment>,
-    current: usize,
+    // Stored in reverse order so we can consume them by popping.
+    reversed_comments: Vec<Comment>,
 }
 
 /// Returns `None` if the first `col` chars of `s` contain a non-whitespace char.
@@ -182,21 +182,25 @@ fn gather_comments(sm: &SourceMap, path: FileName, src: String) -> Vec<Comment>
 
 impl<'a> Comments<'a> {
     pub fn new(sm: &'a SourceMap, filename: FileName, input: String) -> Comments<'a> {
-        let comments = gather_comments(sm, filename, input);
-        Comments { sm, comments, current: 0 }
+        let mut comments = gather_comments(sm, filename, input);
+        comments.reverse();
+        Comments { sm, reversed_comments: comments }
     }
 
-    // FIXME: This shouldn't probably clone lmao
-    fn next(&self) -> Option<Comment> {
-        self.comments.get(self.current).cloned()
+    fn peek(&self) -> Option<&Comment> {
+        self.reversed_comments.last()
+    }
+
+    fn next(&mut self) -> Option<Comment> {
+        self.reversed_comments.pop()
     }
 
     fn trailing_comment(
-        &self,
+        &mut self,
         span: rustc_span::Span,
         next_pos: Option<BytePos>,
     ) -> Option<Comment> {
-        if let Some(cmnt) = self.next() {
+        if let Some(cmnt) = self.peek() {
             if cmnt.style != CommentStyle::Trailing {
                 return None;
             }
@@ -204,7 +208,7 @@ impl<'a> Comments<'a> {
             let comment_line = self.sm.lookup_char_pos(cmnt.pos);
             let next = next_pos.unwrap_or_else(|| cmnt.pos + BytePos(1));
             if span.hi() < cmnt.pos && cmnt.pos < next && span_line.line == comment_line.line {
-                return Some(cmnt);
+                return Some(self.next().unwrap());
             }
         }
 
@@ -400,7 +404,8 @@ impl std::ops::DerefMut for State<'_> {
 
 /// This trait is used for both AST and HIR pretty-printing.
 pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::DerefMut {
-    fn comments(&mut self) -> &mut Option<Comments<'a>>;
+    fn comments(&self) -> Option<&Comments<'a>>;
+    fn comments_mut(&mut self) -> Option<&mut Comments<'a>>;
     fn ann_post(&mut self, ident: Ident);
     fn print_generic_args(&mut self, args: &ast::GenericArgs, colons_before_params: bool);
 
@@ -442,18 +447,18 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
 
     fn maybe_print_comment(&mut self, pos: BytePos) -> bool {
         let mut has_comment = false;
-        while let Some(cmnt) = self.next_comment() {
-            if cmnt.pos < pos {
-                has_comment = true;
-                self.print_comment(&cmnt);
-            } else {
+        while let Some(cmnt) = self.peek_comment() {
+            if cmnt.pos >= pos {
                 break;
             }
+            has_comment = true;
+            let cmnt = self.next_comment().unwrap();
+            self.print_comment(cmnt);
         }
         has_comment
     }
 
-    fn print_comment(&mut self, cmnt: &Comment) {
+    fn print_comment(&mut self, cmnt: Comment) {
         match cmnt.style {
             CommentStyle::Mixed => {
                 if !self.is_beginning_of_line() {
@@ -517,19 +522,20 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
                 self.hardbreak();
             }
         }
-        if let Some(cmnts) = self.comments() {
-            cmnts.current += 1;
-        }
+    }
+
+    fn peek_comment<'b>(&'b self) -> Option<&'b Comment> where 'a: 'b {
+        self.comments().and_then(|c| c.peek())
     }
 
     fn next_comment(&mut self) -> Option<Comment> {
-        self.comments().as_mut().and_then(|c| c.next())
+        self.comments_mut().and_then(|c| c.next())
     }
 
     fn maybe_print_trailing_comment(&mut self, span: rustc_span::Span, next_pos: Option<BytePos>) {
-        if let Some(cmnts) = self.comments() {
+        if let Some(cmnts) = self.comments_mut() {
             if let Some(cmnt) = cmnts.trailing_comment(span, next_pos) {
-                self.print_comment(&cmnt);
+                self.print_comment(cmnt);
             }
         }
     }
@@ -537,11 +543,11 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
     fn print_remaining_comments(&mut self) {
         // If there aren't any remaining comments, then we need to manually
         // make sure there is a line break at the end.
-        if self.next_comment().is_none() {
+        if self.peek_comment().is_none() {
             self.hardbreak();
         }
         while let Some(cmnt) = self.next_comment() {
-            self.print_comment(&cmnt)
+            self.print_comment(cmnt)
         }
     }
 
@@ -852,8 +858,6 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
             token::NtBlock(e) => self.block_to_string(e),
             token::NtStmt(e) => self.stmt_to_string(e),
             token::NtPat(e) => self.pat_to_string(e),
-            &token::NtIdent(e, is_raw) => IdentPrinter::for_ast_ident(e, is_raw.into()).to_string(),
-            token::NtLifetime(e) => e.to_string(),
             token::NtLiteral(e) => self.expr_to_string(e),
             token::NtVis(e) => self.vis_to_string(e),
         }
@@ -915,10 +919,14 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
             token::Literal(lit) => literal_to_string(lit).into(),
 
             /* Name components */
-            token::Ident(s, is_raw) => {
-                IdentPrinter::new(s, is_raw.into(), convert_dollar_crate).to_string().into()
+            token::Ident(name, is_raw) => {
+                IdentPrinter::new(name, is_raw.into(), convert_dollar_crate).to_string().into()
+            }
+            token::NtIdent(ident, is_raw) => {
+                IdentPrinter::for_ast_ident(ident, is_raw.into()).to_string().into()
             }
-            token::Lifetime(s) => s.to_string().into(),
+            token::Lifetime(name) => name.to_string().into(),
+            token::NtLifetime(ident) => ident.name.to_string().into(),
 
             /* Other */
             token::DocComment(comment_kind, attr_style, data) => {
@@ -926,7 +934,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
             }
             token::Eof => "<eof>".into(),
 
-            token::Interpolated(ref nt) => self.nonterminal_to_string(&nt.0).into(),
+            token::Interpolated(ref nt) => self.nonterminal_to_string(&nt).into(),
         }
     }
 
@@ -994,8 +1002,12 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
 }
 
 impl<'a> PrintState<'a> for State<'a> {
-    fn comments(&mut self) -> &mut Option<Comments<'a>> {
-        &mut self.comments
+    fn comments(&self) -> Option<&Comments<'a>> {
+        self.comments.as_ref()
+    }
+
+    fn comments_mut(&mut self) -> Option<&mut Comments<'a>> {
+        self.comments.as_mut()
     }
 
     fn ann_post(&mut self, ident: Ident) {
@@ -1238,7 +1250,11 @@ impl<'a> State<'a> {
                 if let Some((init, els)) = loc.kind.init_else_opt() {
                     self.nbsp();
                     self.word_space("=");
-                    self.print_expr(init, FixupContext::default());
+                    self.print_expr_cond_paren(
+                        init,
+                        els.is_some() && classify::expr_trailing_brace(init).is_some(),
+                        FixupContext::default(),
+                    );
                     if let Some(els) = els {
                         self.cbox(INDENT_UNIT);
                         self.ibox(INDENT_UNIT);
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
index 93400c67949..1e117c46b6e 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
@@ -780,7 +780,7 @@ impl<'a> State<'a> {
                 }
                 _ => {
                     self.end(); // Close the ibox for the pattern.
-                    self.print_expr(body, FixupContext::new_stmt());
+                    self.print_expr(body, FixupContext::new_match_arm());
                     self.word(",");
                 }
             }
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/fixup.rs b/compiler/rustc_ast_pretty/src/pprust/state/fixup.rs
index d21cb82f83b..86d4796e9ce 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/fixup.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/fixup.rs
@@ -49,6 +49,38 @@ pub(crate) struct FixupContext {
     ///     No parentheses required.
     leftmost_subexpression_in_stmt: bool,
 
+    /// Print expression such that it can be parsed as a match arm.
+    ///
+    /// This is almost equivalent to `stmt`, but the grammar diverges a tiny bit
+    /// between statements and match arms when it comes to braced macro calls.
+    /// Macro calls with brace delimiter terminate a statement without a
+    /// semicolon, but do not terminate a match-arm without comma.
+    ///
+    /// ```ignore (illustrative)
+    /// m! {} - 1;  // two statements: a macro call followed by -1 literal
+    ///
+    /// match () {
+    ///     _ => m! {} - 1,  // binary subtraction operator
+    /// }
+    /// ```
+    match_arm: bool,
+
+    /// This is almost equivalent to `leftmost_subexpression_in_stmt`, other
+    /// than for braced macro calls.
+    ///
+    /// If we have `m! {} - 1` as an expression, the leftmost subexpression
+    /// `m! {}` will need to be parenthesized in the statement case but not the
+    /// match-arm case.
+    ///
+    /// ```ignore (illustrative)
+    /// (m! {}) - 1;  // subexpression needs parens
+    ///
+    /// match () {
+    ///     _ => m! {} - 1,  // no parens
+    /// }
+    /// ```
+    leftmost_subexpression_in_match_arm: bool,
+
     /// This is the difference between:
     ///
     /// ```ignore (illustrative)
@@ -68,6 +100,8 @@ impl Default for FixupContext {
         FixupContext {
             stmt: false,
             leftmost_subexpression_in_stmt: false,
+            match_arm: false,
+            leftmost_subexpression_in_match_arm: false,
             parenthesize_exterior_struct_lit: false,
         }
     }
@@ -76,13 +110,16 @@ impl Default for FixupContext {
 impl FixupContext {
     /// Create the initial fixup for printing an expression in statement
     /// position.
-    ///
-    /// This is currently also used for printing an expression as a match-arm,
-    /// but this is incorrect and leads to over-parenthesizing.
     pub fn new_stmt() -> Self {
         FixupContext { stmt: true, ..FixupContext::default() }
     }
 
+    /// Create the initial fixup for printing an expression as the right-hand
+    /// side of a match arm.
+    pub fn new_match_arm() -> Self {
+        FixupContext { match_arm: true, ..FixupContext::default() }
+    }
+
     /// Create the initial fixup for printing an expression as the "condition"
     /// of an `if` or `while`. There are a few other positions which are
     /// grammatically equivalent and also use this, such as the iterator
@@ -106,6 +143,9 @@ impl FixupContext {
         FixupContext {
             stmt: false,
             leftmost_subexpression_in_stmt: self.stmt || self.leftmost_subexpression_in_stmt,
+            match_arm: false,
+            leftmost_subexpression_in_match_arm: self.match_arm
+                || self.leftmost_subexpression_in_match_arm,
             ..self
         }
     }
@@ -119,7 +159,13 @@ impl FixupContext {
     /// example the `$b` in `$a + $b` and `-$b`, but not the one in `[$b]` or
     /// `$a.f($b)`.
     pub fn subsequent_subexpression(self) -> Self {
-        FixupContext { stmt: false, leftmost_subexpression_in_stmt: false, ..self }
+        FixupContext {
+            stmt: false,
+            leftmost_subexpression_in_stmt: false,
+            match_arm: false,
+            leftmost_subexpression_in_match_arm: false,
+            ..self
+        }
     }
 
     /// Determine whether parentheses are needed around the given expression to
@@ -128,7 +174,8 @@ impl FixupContext {
     /// The documentation on `FixupContext::leftmost_subexpression_in_stmt` has
     /// examples.
     pub fn would_cause_statement_boundary(self, expr: &Expr) -> bool {
-        self.leftmost_subexpression_in_stmt && !classify::expr_requires_semi_to_be_stmt(expr)
+        (self.leftmost_subexpression_in_stmt && !classify::expr_requires_semi_to_be_stmt(expr))
+            || (self.leftmost_subexpression_in_match_arm && classify::expr_is_complete(expr))
     }
 
     /// Determine whether parentheses are needed around the given `let`
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index 28c5c505f79..46011c1f43e 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -1010,7 +1010,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
                 clauses.iter().any(|pred| {
                     match pred.kind().skip_binder() {
                         ty::ClauseKind::Trait(data) if data.self_ty() == ty => {}
-                        ty::ClauseKind::Projection(data) if data.projection_ty.self_ty() == ty => {}
+                        ty::ClauseKind::Projection(data)
+                            if data.projection_term.self_ty() == ty => {}
                         _ => return false,
                     }
                     tcx.any_free_region_meets(pred, |r| *r == ty::ReEarlyParam(region))
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index e58723c2ec9..167ca7ba045 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -2059,10 +2059,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                     // We currently do not store the `DefId` in the `ConstraintCategory`
                     // for performances reasons. The error reporting code used by NLL only
                     // uses the span, so this doesn't cause any problems at the moment.
-                    Some(ObligationCauseCode::SpannedWhereClause(
-                        CRATE_DEF_ID.to_def_id(),
-                        predicate_span,
-                    ))
+                    Some(ObligationCauseCode::WhereClause(CRATE_DEF_ID.to_def_id(), predicate_span))
                 } else {
                     None
                 }
diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml b/compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml
index a745f2801cc..b7063f35a3e 100644
--- a/compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml
+++ b/compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml
@@ -51,6 +51,14 @@ jobs:
       if: matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
       run: rustup set default-host x86_64-pc-windows-gnu
 
+    - name: Use x86_64 compiler on macOS
+      if: matrix.os == 'macos-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-apple-darwin'
+      run: rustup set default-host x86_64-apple-darwin
+
+    - name: Select XCode version
+      if: matrix.os == 'macos-latest'
+      run: sudo xcode-select -s /Applications/Xcode_14.3.1.app
+
     - name: Prepare dependencies
       run: ./y.sh prepare
 
diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml
index 14aa850ff5c..1f5a6513f63 100644
--- a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml
+++ b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml
@@ -98,12 +98,20 @@ jobs:
       if: matrix.os == 'windows-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
       run: rustup set default-host x86_64-pc-windows-gnu
 
+    - name: Use x86_64 compiler on macOS
+      if: matrix.os == 'macos-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-apple-darwin'
+      run: rustup set default-host x86_64-apple-darwin
+
     - name: Install toolchain and emulator
       if: matrix.apt_deps != null
       run: |
         sudo apt-get update
         sudo apt-get install -y ${{ matrix.apt_deps }}
 
+    - name: Select XCode version
+      if: matrix.os == 'macos-latest'
+      run: sudo xcode-select -s /Applications/Xcode_14.3.1.app
+
     - name: Prepare dependencies
       run: ./y.sh prepare
 
@@ -230,12 +238,20 @@ jobs:
       if: matrix.os == 'windows-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
       run: rustup set default-host x86_64-pc-windows-gnu
 
+    - name: Use x86_64 compiler on macOS
+      if: matrix.os == 'macos-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-apple-darwin'
+      run: rustup set default-host x86_64-apple-darwin
+
     - name: Install MinGW toolchain
       if: matrix.os == 'ubuntu-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
       run: |
         sudo apt-get update
         sudo apt-get install -y gcc-mingw-w64-x86-64
 
+    - name: Select XCode version
+      if: matrix.os == 'macos-latest'
+      run: sudo xcode-select -s /Applications/Xcode_14.3.1.app
+
     - name: Prepare dependencies
       run: ./y.sh prepare
 
diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml b/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml
index 75ea94ee797..70c214ce8b1 100644
--- a/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml
+++ b/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml
@@ -20,7 +20,7 @@ jobs:
       uses: actions/cache@v4
       with:
         path: build/cg_clif
-        key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
+        key: ${{ runner.os }}-rustc-test-cargo-build-target-${{ hashFiles('rust-toolchain', 'Cargo.lock') }}
 
     - name: Prepare dependencies
       run: ./y.sh prepare
@@ -43,7 +43,7 @@ jobs:
       uses: actions/cache@v4
       with:
         path: build/cg_clif
-        key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
+        key: ${{ runner.os }}-rustc-test-cargo-build-target-${{ hashFiles('rust-toolchain', 'Cargo.lock') }}
 
     - name: Install ripgrep
       run: |
diff --git a/compiler/rustc_codegen_cranelift/.gitignore b/compiler/rustc_codegen_cranelift/.gitignore
index 7915fa138f8..5a38f2acb0e 100644
--- a/compiler/rustc_codegen_cranelift/.gitignore
+++ b/compiler/rustc_codegen_cranelift/.gitignore
@@ -1,8 +1,4 @@
 # Build artifacts during normal use
-/y.bin
-/y.bin.dSYM
-/y.exe
-/y.pdb
 /download
 /build
 /dist
diff --git a/compiler/rustc_codegen_cranelift/build_system/Cargo.toml b/compiler/rustc_codegen_cranelift/build_system/Cargo.toml
index f47b9bc5540..feed2b6eafe 100644
--- a/compiler/rustc_codegen_cranelift/build_system/Cargo.toml
+++ b/compiler/rustc_codegen_cranelift/build_system/Cargo.toml
@@ -11,3 +11,6 @@ path = "main.rs"
 unstable-features = [] # for rust-analyzer
 
 # Do not add any dependencies
+
+[profile.dev]
+debug = 1
diff --git a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs
index 10c3f9cfa2c..196ff8fda75 100644
--- a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs
@@ -267,12 +267,16 @@ fn build_clif_sysroot_for_triple(
             prefix.to_str().unwrap()
         ));
     }
+    rustflags.push("-Zunstable-options".to_owned());
+    for (name, values) in EXTRA_CHECK_CFGS {
+        rustflags.push(check_cfg_arg(name, *values));
+    }
     compiler.rustflags.extend(rustflags);
     let mut build_cmd = STANDARD_LIBRARY.build(&compiler, dirs);
     if channel == "release" {
         build_cmd.arg("--release");
     }
-    build_cmd.arg("--features").arg("compiler-builtins-no-asm backtrace panic-unwind");
+    build_cmd.arg("--features").arg("backtrace panic-unwind");
     build_cmd.env("CARGO_PROFILE_RELEASE_DEBUG", "true");
     build_cmd.env("__CARGO_DEFAULT_LIB_METADATA", "cg_clif");
     if compiler.triple.contains("apple") {
@@ -326,3 +330,34 @@ fn build_rtstartup(dirs: &Dirs, compiler: &Compiler) -> Option<SysrootTarget> {
 
     Some(target_libs)
 }
+
+// Copied from https://github.com/rust-lang/rust/blob/4fd98a4b1b100f5329c6efae18031791f64372d2/src/bootstrap/src/utils/helpers.rs#L569-L585
+/// Create a `--check-cfg` argument invocation for a given name
+/// and it's values.
+fn check_cfg_arg(name: &str, values: Option<&[&str]>) -> String {
+    // Creating a string of the values by concatenating each value:
+    // ',values("tvos","watchos")' or '' (nothing) when there are no values.
+    let next = match values {
+        Some(values) => {
+            let mut tmp = values.iter().flat_map(|val| [",", "\"", val, "\""]).collect::<String>();
+
+            tmp.insert_str(1, "values(");
+            tmp.push(')');
+            tmp
+        }
+        None => "".to_string(),
+    };
+    format!("--check-cfg=cfg({name}{next})")
+}
+
+const EXTRA_CHECK_CFGS: &[(&str, Option<&[&str]>)] = &[
+    ("bootstrap", None),
+    ("stdarch_intel_sde", None),
+    ("no_fp_fmt_parse", None),
+    ("no_global_oom_handling", None),
+    ("no_rc", None),
+    ("no_sync", None),
+    ("netbsd10", None),
+    ("backtrace_in_libstd", None),
+    ("target_arch", Some(&["xtensa"])),
+];
diff --git a/compiler/rustc_codegen_cranelift/build_system/main.rs b/compiler/rustc_codegen_cranelift/build_system/main.rs
index cdd2bae03f8..7dbf608f991 100644
--- a/compiler/rustc_codegen_cranelift/build_system/main.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/main.rs
@@ -147,9 +147,11 @@ fn main() {
 
     let rustup_toolchain_name = match (env::var("CARGO"), env::var("RUSTC"), env::var("RUSTDOC")) {
         (Ok(_), Ok(_), Ok(_)) => None,
-        (Err(_), Err(_), Err(_)) => Some(rustc_info::get_toolchain_name()),
-        _ => {
-            eprintln!("All of CARGO, RUSTC and RUSTDOC need to be set or none must be set");
+        (_, Err(_), Err(_)) => Some(rustc_info::get_toolchain_name()),
+        vars => {
+            eprintln!(
+                "If RUSTC or RUSTDOC is set, both need to be set and in addition CARGO needs to be set: {vars:?}"
+            );
             process::exit(1);
         }
     };
diff --git a/compiler/rustc_codegen_cranelift/build_system/tests.rs b/compiler/rustc_codegen_cranelift/build_system/tests.rs
index 76104901474..278f334796a 100644
--- a/compiler/rustc_codegen_cranelift/build_system/tests.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/tests.rs
@@ -77,7 +77,7 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
     ),
     TestCase::build_lib("build.alloc_system", "example/alloc_system.rs", "lib"),
     TestCase::build_bin_and_run("aot.alloc_example", "example/alloc_example.rs", &[]),
-    TestCase::jit_bin("jit.std_example", "example/std_example.rs", ""),
+    TestCase::jit_bin("jit.std_example", "example/std_example.rs", "arg"),
     TestCase::build_bin_and_run("aot.std_example", "example/std_example.rs", &["arg"]),
     TestCase::build_bin_and_run("aot.dst_field_align", "example/dst-field-align.rs", &[]),
     TestCase::build_bin_and_run(
diff --git a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs
index efa4be7e15a..aab20f67248 100644
--- a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs
+++ b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs
@@ -4,6 +4,7 @@
     never_type,
     linkage,
     extern_types,
+    naked_functions,
     thread_local,
     repr_simd,
     raw_ref_op
@@ -340,6 +341,7 @@ fn main() {
     ))]
     unsafe {
         global_asm_test();
+        naked_test();
     }
 
     // Both statics have a reference that points to the same anonymous allocation.
@@ -395,6 +397,14 @@ global_asm! {
     "
 }
 
+#[cfg(all(not(jit), not(no_unstable_features), target_arch = "x86_64"))]
+#[naked]
+extern "C" fn naked_test() {
+    unsafe {
+        asm!("ret", options(noreturn));
+    }
+}
+
 #[repr(C)]
 enum c_void {
     _1,
diff --git a/compiler/rustc_codegen_cranelift/example/std_example.rs b/compiler/rustc_codegen_cranelift/example/std_example.rs
index 90d4ab721da..7347b2e7789 100644
--- a/compiler/rustc_codegen_cranelift/example/std_example.rs
+++ b/compiler/rustc_codegen_cranelift/example/std_example.rs
@@ -211,6 +211,21 @@ struct I64X2(i64, i64);
 extern "C" fn foo(_a: I64X2) {}
 
 #[cfg(target_arch = "x86_64")]
+#[target_feature(enable = "sse4.2")]
+#[cfg(not(jit))]
+unsafe fn test_crc32() {
+    assert!(is_x86_feature_detected!("sse4.2"));
+
+    let a = 42u32;
+    let b = 0xdeadbeefu64;
+
+    assert_eq!(_mm_crc32_u8(a, b as u8), 4135334616);
+    assert_eq!(_mm_crc32_u16(a, b as u16), 1200687288);
+    assert_eq!(_mm_crc32_u32(a, b as u32), 2543798776);
+    assert_eq!(_mm_crc32_u64(a as u64, b as u64), 241952147);
+}
+
+#[cfg(target_arch = "x86_64")]
 #[target_feature(enable = "sse2")]
 unsafe fn test_simd() {
     assert!(is_x86_feature_detected!("sse2"));
@@ -244,10 +259,14 @@ unsafe fn test_simd() {
 
     test_mm256_shuffle_epi8();
     test_mm256_permute2x128_si256();
+    test_mm256_permutevar8x32_epi32();
 
     #[rustfmt::skip]
     let mask1 = _mm_movemask_epi8(dbg!(_mm_setr_epi8(255u8 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)));
     assert_eq!(mask1, 1);
+
+    #[cfg(not(jit))]
+    test_crc32();
 }
 
 #[cfg(target_arch = "x86_64")]
@@ -447,6 +466,16 @@ unsafe fn test_mm256_permute2x128_si256() {
     assert_eq_m256i(r, e);
 }
 
+#[cfg(target_arch = "x86_64")]
+#[target_feature(enable = "avx2")]
+unsafe fn test_mm256_permutevar8x32_epi32() {
+    let a = _mm256_setr_epi32(100, 200, 300, 400, 500, 600, 700, 800);
+    let idx = _mm256_setr_epi32(7, 6, 5, 4, 3, 2, 1, 0);
+    let r = _mm256_setr_epi32(800, 700, 600, 500, 400, 300, 200, 100);
+    let e = _mm256_permutevar8x32_epi32(a, idx);
+    assert_eq_m256i(r, e);
+}
+
 fn test_checked_mul() {
     let u: Option<u8> = u8::from_str_radix("1000", 10).ok();
     assert_eq!(u, None);
diff --git a/compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml b/compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml
index a72fa2c62a9..c8c7b45bc9a 100644
--- a/compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml
+++ b/compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml
@@ -42,9 +42,9 @@ checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
 
 [[package]]
 name = "cc"
-version = "1.0.90"
+version = "1.0.97"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5"
+checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4"
 
 [[package]]
 name = "cfg-if"
diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain
index de340cf8c35..a2ba79cbe90 100644
--- a/compiler/rustc_codegen_cranelift/rust-toolchain
+++ b/compiler/rustc_codegen_cranelift/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2024-04-23"
+channel = "nightly-2024-05-13"
 components = ["rust-src", "rustc-dev", "llvm-tools"]
diff --git a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
index 8580f4557e8..689cda21643 100755
--- a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
+++ b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
@@ -44,6 +44,7 @@ rm tests/incremental/hashes/statics.rs # same
 rm tests/ui/abi/mir/mir_codegen_calls_variadic.rs # requires float varargs
 rm tests/ui/abi/variadic-ffi.rs # requires callee side vararg support
 rm -r tests/run-make/c-link-to-rust-va-list-fn # requires callee side vararg support
+rm tests/ui/delegation/fn-header.rs
 
 # unsized locals
 rm -r tests/run-pass-valgrind/unsized-locals
@@ -87,6 +88,7 @@ rm -r tests/run-make/no-builtins-attribute # same
 rm tests/ui/abi/stack-protector.rs # requires stack protector support
 rm -r tests/run-make/emit-stack-sizes # requires support for -Z emit-stack-sizes
 rm -r tests/run-make/optimization-remarks-dir # remarks are LLVM specific
+rm -r tests/run-make/print-to-output # requires --print relocation-models
 
 # requires asm, llvm-ir and/or llvm-bc emit support
 # =============================================
@@ -151,7 +153,7 @@ index 9607ff02f96..b7d97caf9a2 100644
          let mut cmd = setup_common();
 -        let target_rpath_dir = env::var_os("TARGET_RPATH_DIR").unwrap();
 -        cmd.arg(format!("-L{}", target_rpath_dir.to_string_lossy()));
-         Self { cmd }
+         Self { cmd, stdin: None }
      }
 
 EOF
diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
index 6f346af25c6..4bcef15ad04 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
@@ -412,7 +412,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
                     Err(instance) => Some(instance),
                 }
             }
-            InstanceDef::DropGlue(_, None) => {
+            InstanceDef::DropGlue(_, None) | ty::InstanceDef::AsyncDropGlueCtorShim(_, None) => {
                 // empty drop glue - a nop.
                 let dest = target.expect("Non terminating drop_in_place_real???");
                 let ret_block = fx.get_block(dest);
@@ -597,7 +597,9 @@ pub(crate) fn codegen_drop<'tcx>(
     let ty = drop_place.layout().ty;
     let drop_instance = Instance::resolve_drop_in_place(fx.tcx, ty).polymorphize(fx.tcx);
 
-    if let ty::InstanceDef::DropGlue(_, None) = drop_instance.def {
+    if let ty::InstanceDef::DropGlue(_, None) | ty::InstanceDef::AsyncDropGlueCtorShim(_, None) =
+        drop_instance.def
+    {
         // we don't actually need to drop anything
     } else {
         match ty.kind() {
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 8874efadec9..5846689643f 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -6,6 +6,7 @@ use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
 use cranelift_module::ModuleError;
 use rustc_ast::InlineAsmOptions;
 use rustc_index::IndexVec;
+use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::ty::adjustment::PointerCoercion;
 use rustc_middle::ty::layout::FnAbiOf;
 use rustc_middle::ty::print::with_no_trimmed_paths;
@@ -14,6 +15,7 @@ use rustc_monomorphize::is_call_from_compiler_builtins_to_upstream_monomorphizat
 
 use crate::constant::ConstantCx;
 use crate::debuginfo::{FunctionDebugContext, TypeDebugContext};
+use crate::inline_asm::codegen_naked_asm;
 use crate::prelude::*;
 use crate::pretty_clif::CommentWriter;
 
@@ -32,7 +34,7 @@ pub(crate) fn codegen_fn<'tcx>(
     cached_func: Function,
     module: &mut dyn Module,
     instance: Instance<'tcx>,
-) -> CodegenedFunction {
+) -> Option<CodegenedFunction> {
     debug_assert!(!instance.args.has_infer());
 
     let symbol_name = tcx.symbol_name(instance).name.to_string();
@@ -48,6 +50,37 @@ pub(crate) fn codegen_fn<'tcx>(
         String::from_utf8_lossy(&buf).into_owned()
     });
 
+    if tcx.codegen_fn_attrs(instance.def_id()).flags.contains(CodegenFnAttrFlags::NAKED) {
+        assert_eq!(mir.basic_blocks.len(), 1);
+        assert!(mir.basic_blocks[START_BLOCK].statements.is_empty());
+
+        match &mir.basic_blocks[START_BLOCK].terminator().kind {
+            TerminatorKind::InlineAsm {
+                template,
+                operands,
+                options,
+                line_spans: _,
+                targets: _,
+                unwind: _,
+            } => {
+                codegen_naked_asm(
+                    tcx,
+                    cx,
+                    module,
+                    instance,
+                    mir.basic_blocks[START_BLOCK].terminator().source_info.span,
+                    &symbol_name,
+                    template,
+                    operands,
+                    *options,
+                );
+            }
+            _ => unreachable!(),
+        }
+
+        return None;
+    }
+
     // Declare function
     let sig = get_function_sig(tcx, module.target_config().default_call_conv, instance);
     let func_id = module.declare_function(&symbol_name, Linkage::Local, &sig).unwrap();
@@ -128,7 +161,7 @@ pub(crate) fn codegen_fn<'tcx>(
     // Verify function
     verify_func(tcx, &clif_comments, &func);
 
-    CodegenedFunction { symbol_name, func_id, func, clif_comments, func_debug_cx }
+    Some(CodegenedFunction { symbol_name, func_id, func, clif_comments, func_debug_cx })
 }
 
 pub(crate) fn compile_fn(
diff --git a/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs b/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs
index 9678969134a..a73860cf18b 100644
--- a/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs
+++ b/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs
@@ -6,7 +6,7 @@ use rustc_session::Session;
 // FIXME don't panic when a worker thread panics
 
 pub(super) struct ConcurrencyLimiter {
-    helper_thread: Option<HelperThread>,
+    helper_thread: Option<Mutex<HelperThread>>,
     state: Arc<Mutex<state::ConcurrencyLimiterState>>,
     available_token_condvar: Arc<Condvar>,
     finished: bool,
@@ -39,14 +39,14 @@ impl ConcurrencyLimiter {
             })
             .unwrap();
         ConcurrencyLimiter {
-            helper_thread: Some(helper_thread),
+            helper_thread: Some(Mutex::new(helper_thread)),
             state,
             available_token_condvar,
             finished: false,
         }
     }
 
-    pub(super) fn acquire(&mut self, dcx: &rustc_errors::DiagCtxt) -> ConcurrencyLimiterToken {
+    pub(super) fn acquire(&self, dcx: &rustc_errors::DiagCtxt) -> ConcurrencyLimiterToken {
         let mut state = self.state.lock().unwrap();
         loop {
             state.assert_invariants();
@@ -73,16 +73,11 @@ impl ConcurrencyLimiter {
                 }
             }
 
-            self.helper_thread.as_mut().unwrap().request_token();
+            self.helper_thread.as_ref().unwrap().lock().unwrap().request_token();
             state = self.available_token_condvar.wait(state).unwrap();
         }
     }
 
-    pub(super) fn job_already_done(&mut self) {
-        let mut state = self.state.lock().unwrap();
-        state.job_already_done();
-    }
-
     pub(crate) fn finished(mut self) {
         self.helper_thread.take();
 
@@ -190,14 +185,6 @@ mod state {
             self.assert_invariants();
         }
 
-        pub(super) fn job_already_done(&mut self) {
-            self.assert_invariants();
-            self.pending_jobs -= 1;
-            self.assert_invariants();
-            self.drop_excess_capacity();
-            self.assert_invariants();
-        }
-
         pub(super) fn poison(&mut self, error: String) {
             self.poisoned = true;
             self.stored_error = Some(error);
diff --git a/compiler/rustc_codegen_cranelift/src/config.rs b/compiler/rustc_codegen_cranelift/src/config.rs
index 9e92d656c76..12bce680d9e 100644
--- a/compiler/rustc_codegen_cranelift/src/config.rs
+++ b/compiler/rustc_codegen_cranelift/src/config.rs
@@ -64,8 +64,13 @@ impl Default for BackendConfig {
         BackendConfig {
             codegen_mode: CodegenMode::Aot,
             jit_args: {
-                let args = std::env::var("CG_CLIF_JIT_ARGS").unwrap_or_else(|_| String::new());
-                args.split(' ').map(|arg| arg.to_string()).collect()
+                match std::env::var("CG_CLIF_JIT_ARGS") {
+                    Ok(args) => args.split(' ').map(|arg| arg.to_string()).collect(),
+                    Err(std::env::VarError::NotPresent) => vec![],
+                    Err(std::env::VarError::NotUnicode(s)) => {
+                        panic!("CG_CLIF_JIT_ARGS not unicode: {:?}", s);
+                    }
+                }
             },
             enable_verifier: cfg!(debug_assertions) || bool_env_var("CG_CLIF_ENABLE_VERIFIER"),
             disable_incr_cache: bool_env_var("CG_CLIF_DISABLE_INCR_CACHE"),
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs
index cdf499a22f8..64e83e43d32 100644
--- a/compiler/rustc_codegen_cranelift/src/constant.rs
+++ b/compiler/rustc_codegen_cranelift/src/constant.rs
@@ -258,7 +258,7 @@ fn data_id_for_static(
 ) -> DataId {
     let attrs = tcx.codegen_fn_attrs(def_id);
 
-    let instance = Instance::mono(tcx, def_id).polymorphize(tcx);
+    let instance = Instance::mono(tcx, def_id);
     let symbol_name = tcx.symbol_name(instance).name;
 
     if let Some(import_linkage) = attrs.import_linkage {
diff --git a/compiler/rustc_codegen_cranelift/src/discriminant.rs b/compiler/rustc_codegen_cranelift/src/discriminant.rs
index 670384663e8..e7ac084558a 100644
--- a/compiler/rustc_codegen_cranelift/src/discriminant.rs
+++ b/compiler/rustc_codegen_cranelift/src/discriminant.rs
@@ -28,16 +28,20 @@ pub(crate) fn codegen_set_discriminant<'tcx>(
         } => {
             let ptr = place.place_field(fx, FieldIdx::new(tag_field));
             let to = layout.ty.discriminant_for_variant(fx.tcx, variant_index).unwrap().val;
-            let to = if ptr.layout().abi.is_signed() {
-                ty::ScalarInt::try_from_int(
-                    ptr.layout().size.sign_extend(to) as i128,
-                    ptr.layout().size,
-                )
-                .unwrap()
-            } else {
-                ty::ScalarInt::try_from_uint(to, ptr.layout().size).unwrap()
+            let to = match ptr.layout().ty.kind() {
+                ty::Uint(UintTy::U128) | ty::Int(IntTy::I128) => {
+                    let lsb = fx.bcx.ins().iconst(types::I64, to as u64 as i64);
+                    let msb = fx.bcx.ins().iconst(types::I64, (to >> 64) as u64 as i64);
+                    fx.bcx.ins().iconcat(lsb, msb)
+                }
+                ty::Uint(_) | ty::Int(_) => {
+                    let clif_ty = fx.clif_type(ptr.layout().ty).unwrap();
+                    let raw_val = ptr.layout().size.truncate(to);
+                    fx.bcx.ins().iconst(clif_ty, raw_val as i64)
+                }
+                _ => unreachable!(),
             };
-            let discr = CValue::const_val(fx, ptr.layout(), to);
+            let discr = CValue::by_val(to, ptr.layout());
             ptr.write_cvalue(fx, discr);
         }
         Variants::Multiple {
@@ -85,16 +89,21 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
                 .ty
                 .discriminant_for_variant(fx.tcx, *index)
                 .map_or(u128::from(index.as_u32()), |discr| discr.val);
-            let discr_val = if dest_layout.abi.is_signed() {
-                ty::ScalarInt::try_from_int(
-                    dest_layout.size.sign_extend(discr_val) as i128,
-                    dest_layout.size,
-                )
-                .unwrap()
-            } else {
-                ty::ScalarInt::try_from_uint(discr_val, dest_layout.size).unwrap()
+
+            let val = match dest_layout.ty.kind() {
+                ty::Uint(UintTy::U128) | ty::Int(IntTy::I128) => {
+                    let lsb = fx.bcx.ins().iconst(types::I64, discr_val as u64 as i64);
+                    let msb = fx.bcx.ins().iconst(types::I64, (discr_val >> 64) as u64 as i64);
+                    fx.bcx.ins().iconcat(lsb, msb)
+                }
+                ty::Uint(_) | ty::Int(_) => {
+                    let clif_ty = fx.clif_type(dest_layout.ty).unwrap();
+                    let raw_val = dest_layout.size.truncate(discr_val);
+                    fx.bcx.ins().iconst(clif_ty, raw_val as i64)
+                }
+                _ => unreachable!(),
             };
-            let res = CValue::const_val(fx, dest_layout, discr_val);
+            let res = CValue::by_val(val, dest_layout);
             dest.write_cvalue(fx, res);
             return;
         }
diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
index e8c96486041..fce4690f97d 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
@@ -15,6 +15,7 @@ use rustc_codegen_ssa::errors as ssa_errors;
 use rustc_codegen_ssa::{CodegenResults, CompiledModule, CrateInfo, ModuleKind};
 use rustc_data_structures::profiling::SelfProfilerRef;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::sync::{par_map, IntoDynSyncSend};
 use rustc_metadata::fs::copy_to_stdout;
 use rustc_metadata::EncodedMetadata;
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
@@ -481,15 +482,16 @@ fn module_codegen(
             for (mono_item, _) in mono_items {
                 match mono_item {
                     MonoItem::Fn(inst) => {
-                        let codegened_function = crate::base::codegen_fn(
+                        if let Some(codegened_function) = crate::base::codegen_fn(
                             tcx,
                             &mut cx,
                             &mut type_dbg,
                             Function::new(),
                             &mut module,
                             inst,
-                        );
-                        codegened_functions.push(codegened_function);
+                        ) {
+                            codegened_functions.push(codegened_function);
+                        }
                     }
                     MonoItem::Static(def_id) => {
                         let data_id = crate::constant::codegen_static(tcx, &mut module, def_id);
@@ -604,39 +606,39 @@ pub(crate) fn run_aot(
 
     let global_asm_config = Arc::new(crate::global_asm::GlobalAsmConfig::new(tcx));
 
-    let mut concurrency_limiter = ConcurrencyLimiter::new(tcx.sess, cgus.len());
+    let (todo_cgus, done_cgus) =
+        cgus.into_iter().enumerate().partition::<Vec<_>, _>(|&(i, _)| match cgu_reuse[i] {
+            _ if backend_config.disable_incr_cache => true,
+            CguReuse::No => true,
+            CguReuse::PreLto | CguReuse::PostLto => false,
+        });
+
+    let concurrency_limiter = IntoDynSyncSend(ConcurrencyLimiter::new(tcx.sess, todo_cgus.len()));
 
     let modules = tcx.sess.time("codegen mono items", || {
-        cgus.iter()
-            .enumerate()
-            .map(|(i, cgu)| {
-                let cgu_reuse =
-                    if backend_config.disable_incr_cache { CguReuse::No } else { cgu_reuse[i] };
-                match cgu_reuse {
-                    CguReuse::No => {
-                        let dep_node = cgu.codegen_dep_node(tcx);
-                        tcx.dep_graph
-                            .with_task(
-                                dep_node,
-                                tcx,
-                                (
-                                    backend_config.clone(),
-                                    global_asm_config.clone(),
-                                    cgu.name(),
-                                    concurrency_limiter.acquire(tcx.dcx()),
-                                ),
-                                module_codegen,
-                                Some(rustc_middle::dep_graph::hash_result),
-                            )
-                            .0
-                    }
-                    CguReuse::PreLto | CguReuse::PostLto => {
-                        concurrency_limiter.job_already_done();
-                        OngoingModuleCodegen::Sync(reuse_workproduct_for_cgu(tcx, cgu))
-                    }
-                }
-            })
-            .collect::<Vec<_>>()
+        let mut modules: Vec<_> = par_map(todo_cgus, |(_, cgu)| {
+            let dep_node = cgu.codegen_dep_node(tcx);
+            tcx.dep_graph
+                .with_task(
+                    dep_node,
+                    tcx,
+                    (
+                        backend_config.clone(),
+                        global_asm_config.clone(),
+                        cgu.name(),
+                        concurrency_limiter.acquire(tcx.dcx()),
+                    ),
+                    module_codegen,
+                    Some(rustc_middle::dep_graph::hash_result),
+                )
+                .0
+        });
+        modules.extend(
+            done_cgus
+                .into_iter()
+                .map(|(_, cgu)| OngoingModuleCodegen::Sync(reuse_workproduct_for_cgu(tcx, cgu))),
+        );
+        modules
     });
 
     let mut allocator_module = make_module(tcx.sess, &backend_config, "allocator_shim".to_string());
@@ -705,6 +707,6 @@ pub(crate) fn run_aot(
         metadata_module,
         metadata,
         crate_info: CrateInfo::new(tcx, target_cpu),
-        concurrency_limiter,
+        concurrency_limiter: concurrency_limiter.0,
     })
 }
diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
index 929fa92596d..4b149131b61 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
@@ -83,13 +83,6 @@ fn create_jit_module(
     );
 
     crate::allocator::codegen(tcx, &mut jit_module, &mut cx.unwind_context);
-    crate::main_shim::maybe_create_entry_wrapper(
-        tcx,
-        &mut jit_module,
-        &mut cx.unwind_context,
-        true,
-        true,
-    );
 
     (jit_module, cx)
 }
@@ -153,6 +146,14 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
         tcx.dcx().fatal("Inline asm is not supported in JIT mode");
     }
 
+    crate::main_shim::maybe_create_entry_wrapper(
+        tcx,
+        &mut jit_module,
+        &mut cx.unwind_context,
+        true,
+        true,
+    );
+
     tcx.dcx().abort_if_errors();
 
     jit_module.finalize_definitions().unwrap();
@@ -231,16 +232,16 @@ pub(crate) fn codegen_and_compile_fn<'tcx>(
             crate::PrintOnPanic(|| format!("{:?} {}", instance, tcx.symbol_name(instance).name));
 
         let cached_func = std::mem::replace(&mut cached_context.func, Function::new());
-        let codegened_func = crate::base::codegen_fn(
+        if let Some(codegened_func) = crate::base::codegen_fn(
             tcx,
             cx,
             &mut TypeDebugContext::default(),
             cached_func,
             module,
             instance,
-        );
-
-        crate::base::compile_fn(cx, cached_context, module, codegened_func);
+        ) {
+            crate::base::compile_fn(cx, cached_context, module, codegened_func);
+        }
     });
 }
 
diff --git a/compiler/rustc_codegen_cranelift/src/driver/mod.rs b/compiler/rustc_codegen_cranelift/src/driver/mod.rs
index 12e90b58410..fb0eed07c19 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/mod.rs
@@ -5,6 +5,7 @@
 //! [`codegen_static`]: crate::constant::codegen_static
 
 use rustc_data_structures::profiling::SelfProfilerRef;
+use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::mir::mono::{MonoItem, MonoItemData};
 
 use crate::prelude::*;
@@ -33,7 +34,20 @@ fn predefine_mono_items<'tcx>(
                         data.visibility,
                         is_compiler_builtins,
                     );
-                    module.declare_function(name, linkage, &sig).unwrap();
+                    let is_naked = tcx
+                        .codegen_fn_attrs(instance.def_id())
+                        .flags
+                        .contains(CodegenFnAttrFlags::NAKED);
+                    module
+                        .declare_function(
+                            name,
+                            // Naked functions are defined in a separate object
+                            // file from the codegen unit rustc expects them to
+                            // be defined in.
+                            if is_naked { Linkage::Import } else { linkage },
+                            &sig,
+                        )
+                        .unwrap();
                 }
                 MonoItem::Static(_) | MonoItem::GlobalAsm(_) => {}
             }
diff --git a/compiler/rustc_codegen_cranelift/src/global_asm.rs b/compiler/rustc_codegen_cranelift/src/global_asm.rs
index 5a0cd3990f2..0c99a5ce12f 100644
--- a/compiler/rustc_codegen_cranelift/src/global_asm.rs
+++ b/compiler/rustc_codegen_cranelift/src/global_asm.rs
@@ -81,7 +81,7 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String,
                                 );
                             }
 
-                            let instance = Instance::mono(tcx, def_id).polymorphize(tcx);
+                            let instance = Instance::mono(tcx, def_id);
                             let symbol = tcx.symbol_name(instance);
                             global_asm.push_str(symbol.name);
                         }
diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
index 28b92f730da..2de804f5e04 100644
--- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs
+++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
@@ -127,7 +127,7 @@ pub(crate) fn codegen_inline_asm_terminator<'tcx>(
             }
             InlineAsmOperand::SymStatic { def_id } => {
                 assert!(fx.tcx.is_static(def_id));
-                let instance = Instance::mono(fx.tcx, def_id).polymorphize(fx.tcx);
+                let instance = Instance::mono(fx.tcx, def_id);
                 CInlineAsmOperand::Symbol { symbol: fx.tcx.symbol_name(instance).name.to_owned() }
             }
             InlineAsmOperand::Label { .. } => {
@@ -169,6 +169,7 @@ pub(crate) fn codegen_inline_asm_inner<'tcx>(
         stack_slots_input: Vec::new(),
         stack_slots_output: Vec::new(),
         stack_slot_size: Size::from_bytes(0),
+        is_naked: false,
     };
     asm_gen.allocate_registers();
     asm_gen.allocate_stack_slots();
@@ -209,6 +210,121 @@ pub(crate) fn codegen_inline_asm_inner<'tcx>(
     call_inline_asm(fx, &asm_name, asm_gen.stack_slot_size, inputs, outputs);
 }
 
+pub(crate) fn codegen_naked_asm<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    cx: &mut crate::CodegenCx,
+    module: &mut dyn Module,
+    instance: Instance<'tcx>,
+    span: Span,
+    symbol_name: &str,
+    template: &[InlineAsmTemplatePiece],
+    operands: &[InlineAsmOperand<'tcx>],
+    options: InlineAsmOptions,
+) {
+    // FIXME add .eh_frame unwind info directives
+
+    let operands = operands
+        .iter()
+        .map(|operand| match *operand {
+            InlineAsmOperand::In { .. }
+            | InlineAsmOperand::Out { .. }
+            | InlineAsmOperand::InOut { .. } => {
+                span_bug!(span, "invalid operand type for naked asm")
+            }
+            InlineAsmOperand::Const { ref value } => {
+                let cv = instance.instantiate_mir_and_normalize_erasing_regions(
+                    tcx,
+                    ty::ParamEnv::reveal_all(),
+                    ty::EarlyBinder::bind(value.const_),
+                );
+                let const_value = cv
+                    .eval(tcx, ty::ParamEnv::reveal_all(), value.span)
+                    .expect("erroneous constant missed by mono item collection");
+
+                let value = rustc_codegen_ssa::common::asm_const_to_str(
+                    tcx,
+                    span,
+                    const_value,
+                    RevealAllLayoutCx(tcx).layout_of(cv.ty()),
+                );
+                CInlineAsmOperand::Const { value }
+            }
+            InlineAsmOperand::SymFn { ref value } => {
+                if cfg!(not(feature = "inline_asm_sym")) {
+                    tcx.dcx()
+                        .span_err(span, "asm! and global_asm! sym operands are not yet supported");
+                }
+
+                let const_ = instance.instantiate_mir_and_normalize_erasing_regions(
+                    tcx,
+                    ty::ParamEnv::reveal_all(),
+                    ty::EarlyBinder::bind(value.const_),
+                );
+                if let ty::FnDef(def_id, args) = *const_.ty().kind() {
+                    let instance = ty::Instance::resolve_for_fn_ptr(
+                        tcx,
+                        ty::ParamEnv::reveal_all(),
+                        def_id,
+                        args,
+                    )
+                    .unwrap();
+                    let symbol = tcx.symbol_name(instance);
+
+                    // Pass a wrapper rather than the function itself as the function itself may not
+                    // be exported from the main codegen unit and may thus be unreachable from the
+                    // object file created by an external assembler.
+                    let inline_asm_index = cx.inline_asm_index.get();
+                    cx.inline_asm_index.set(inline_asm_index + 1);
+                    let wrapper_name = format!(
+                        "__inline_asm_{}_wrapper_n{}",
+                        cx.cgu_name.as_str().replace('.', "__").replace('-', "_"),
+                        inline_asm_index
+                    );
+                    let sig =
+                        get_function_sig(tcx, module.target_config().default_call_conv, instance);
+                    create_wrapper_function(
+                        module,
+                        &mut cx.unwind_context,
+                        sig,
+                        &wrapper_name,
+                        symbol.name,
+                    );
+
+                    CInlineAsmOperand::Symbol { symbol: wrapper_name }
+                } else {
+                    span_bug!(span, "invalid type for asm sym (fn)");
+                }
+            }
+            InlineAsmOperand::SymStatic { def_id } => {
+                assert!(tcx.is_static(def_id));
+                let instance = Instance::mono(tcx, def_id);
+                CInlineAsmOperand::Symbol { symbol: tcx.symbol_name(instance).name.to_owned() }
+            }
+            InlineAsmOperand::Label { .. } => {
+                span_bug!(span, "asm! label operands are not yet supported");
+            }
+        })
+        .collect::<Vec<_>>();
+
+    let asm_gen = InlineAssemblyGenerator {
+        tcx,
+        arch: tcx.sess.asm_arch.unwrap(),
+        enclosing_def_id: instance.def_id(),
+        template,
+        operands: &operands,
+        options,
+        registers: Vec::new(),
+        stack_slots_clobber: Vec::new(),
+        stack_slots_input: Vec::new(),
+        stack_slots_output: Vec::new(),
+        stack_slot_size: Size::from_bytes(0),
+        is_naked: true,
+    };
+
+    let generated_asm = asm_gen.generate_asm_wrapper(symbol_name);
+    cx.global_asm.push_str(&generated_asm);
+}
+
 struct InlineAssemblyGenerator<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     arch: InlineAsmArch,
@@ -221,10 +337,13 @@ struct InlineAssemblyGenerator<'a, 'tcx> {
     stack_slots_input: Vec<Option<Size>>,
     stack_slots_output: Vec<Option<Size>>,
     stack_slot_size: Size,
+    is_naked: bool,
 }
 
 impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
     fn allocate_registers(&mut self) {
+        assert!(!self.is_naked);
+
         let sess = self.tcx.sess;
         let map = allocatable_registers(
             self.arch,
@@ -348,6 +467,8 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
     }
 
     fn allocate_stack_slots(&mut self) {
+        assert!(!self.is_naked);
+
         let mut slot_size = Size::from_bytes(0);
         let mut slots_clobber = vec![None; self.operands.len()];
         let mut slots_input = vec![None; self.operands.len()];
@@ -468,30 +589,32 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
         if is_x86 {
             generated_asm.push_str(".intel_syntax noprefix\n");
         }
-        Self::prologue(&mut generated_asm, self.arch);
+        if !self.is_naked {
+            Self::prologue(&mut generated_asm, self.arch);
+
+            // Save clobbered registers
+            if !self.options.contains(InlineAsmOptions::NORETURN) {
+                for (reg, slot) in self
+                    .registers
+                    .iter()
+                    .zip(self.stack_slots_clobber.iter().copied())
+                    .filter_map(|(r, s)| r.zip(s))
+                {
+                    Self::save_register(&mut generated_asm, self.arch, reg, slot);
+                }
+            }
 
-        // Save clobbered registers
-        if !self.options.contains(InlineAsmOptions::NORETURN) {
+            // Write input registers
             for (reg, slot) in self
                 .registers
                 .iter()
-                .zip(self.stack_slots_clobber.iter().copied())
+                .zip(self.stack_slots_input.iter().copied())
                 .filter_map(|(r, s)| r.zip(s))
             {
-                Self::save_register(&mut generated_asm, self.arch, reg, slot);
+                Self::restore_register(&mut generated_asm, self.arch, reg, slot);
             }
         }
 
-        // Write input registers
-        for (reg, slot) in self
-            .registers
-            .iter()
-            .zip(self.stack_slots_input.iter().copied())
-            .filter_map(|(r, s)| r.zip(s))
-        {
-            Self::restore_register(&mut generated_asm, self.arch, reg, slot);
-        }
-
         if is_x86 && self.options.contains(InlineAsmOptions::ATT_SYNTAX) {
             generated_asm.push_str(".att_syntax\n");
         }
@@ -553,30 +676,32 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
             generated_asm.push_str(".intel_syntax noprefix\n");
         }
 
-        if !self.options.contains(InlineAsmOptions::NORETURN) {
-            // Read output registers
-            for (reg, slot) in self
-                .registers
-                .iter()
-                .zip(self.stack_slots_output.iter().copied())
-                .filter_map(|(r, s)| r.zip(s))
-            {
-                Self::save_register(&mut generated_asm, self.arch, reg, slot);
-            }
+        if !self.is_naked {
+            if !self.options.contains(InlineAsmOptions::NORETURN) {
+                // Read output registers
+                for (reg, slot) in self
+                    .registers
+                    .iter()
+                    .zip(self.stack_slots_output.iter().copied())
+                    .filter_map(|(r, s)| r.zip(s))
+                {
+                    Self::save_register(&mut generated_asm, self.arch, reg, slot);
+                }
 
-            // Restore clobbered registers
-            for (reg, slot) in self
-                .registers
-                .iter()
-                .zip(self.stack_slots_clobber.iter().copied())
-                .filter_map(|(r, s)| r.zip(s))
-            {
-                Self::restore_register(&mut generated_asm, self.arch, reg, slot);
-            }
+                // Restore clobbered registers
+                for (reg, slot) in self
+                    .registers
+                    .iter()
+                    .zip(self.stack_slots_clobber.iter().copied())
+                    .filter_map(|(r, s)| r.zip(s))
+                {
+                    Self::restore_register(&mut generated_asm, self.arch, reg, slot);
+                }
 
-            Self::epilogue(&mut generated_asm, self.arch);
-        } else {
-            Self::epilogue_noreturn(&mut generated_asm, self.arch);
+                Self::epilogue(&mut generated_asm, self.arch);
+            } else {
+                Self::epilogue_noreturn(&mut generated_asm, self.arch);
+            }
         }
 
         if is_x86 {
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
index 8df83c706a1..27b55ecc72e 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
@@ -374,6 +374,21 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
                 }
             }
         }
+        "llvm.x86.avx2.permd" => {
+            // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_permutevar8x32_epi32
+            intrinsic_args!(fx, args => (a, idx); intrinsic);
+
+            for j in 0..=7 {
+                let index = idx.value_typed_lane(fx, fx.tcx.types.u32, j).load_scalar(fx);
+                let index = fx.bcx.ins().uextend(fx.pointer_type, index);
+                let value = a.value_lane_dyn(fx, index).load_scalar(fx);
+                ret.place_typed_lane(fx, fx.tcx.types.u32, j).to_ptr().store(
+                    fx,
+                    value,
+                    MemFlags::trusted(),
+                );
+            }
+        }
         "llvm.x86.avx2.vperm2i128"
         | "llvm.x86.avx.vperm2f128.ps.256"
         | "llvm.x86.avx.vperm2f128.pd.256" => {
@@ -832,6 +847,43 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
             }
         }
 
+        "llvm.x86.sse42.crc32.32.8"
+        | "llvm.x86.sse42.crc32.32.16"
+        | "llvm.x86.sse42.crc32.32.32"
+        | "llvm.x86.sse42.crc32.64.64" => {
+            // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#ig_expand=1419&text=_mm_crc32_u32
+            intrinsic_args!(fx, args => (crc, v); intrinsic);
+
+            let crc = crc.load_scalar(fx);
+            let v = v.load_scalar(fx);
+
+            let asm = match intrinsic {
+                "llvm.x86.sse42.crc32.32.8" => "crc32 eax, dl",
+                "llvm.x86.sse42.crc32.32.16" => "crc32 eax, dx",
+                "llvm.x86.sse42.crc32.32.32" => "crc32 eax, edx",
+                "llvm.x86.sse42.crc32.64.64" => "crc32 rax, rdx",
+                _ => unreachable!(),
+            };
+
+            codegen_inline_asm_inner(
+                fx,
+                &[InlineAsmTemplatePiece::String(asm.to_string())],
+                &[
+                    CInlineAsmOperand::InOut {
+                        reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)),
+                        _late: true,
+                        in_value: crc,
+                        out_place: Some(ret),
+                    },
+                    CInlineAsmOperand::In {
+                        reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::dx)),
+                        value: v,
+                    },
+                ],
+                InlineAsmOptions::NOSTACK | InlineAsmOptions::PURE | InlineAsmOptions::NOMEM,
+            );
+        }
+
         "llvm.x86.sse42.pcmpestri128" => {
             // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpestri&ig_expand=939
             intrinsic_args!(fx, args => (a, la, b, lb, _imm8); intrinsic);
diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs
index e72951b6f34..39bbad16b0c 100644
--- a/compiler/rustc_codegen_cranelift/src/lib.rs
+++ b/compiler/rustc_codegen_cranelift/src/lib.rs
@@ -331,9 +331,9 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Arc<dyn TargetIs
                     sess.dcx().fatal(format!("can't compile for {}: {}", target_triple, err));
                 });
             if target_triple.architecture == target_lexicon::Architecture::X86_64 {
-                // Don't use "haswell" as the default, as it implies `has_lzcnt`.
-                // macOS CI is still at Ivy Bridge EP, so `lzcnt` is interpreted as `bsr`.
-                builder.enable("nehalem").unwrap();
+                // Only set the target cpu on x86_64 as Cranelift is missing
+                // the target cpu list for most other targets.
+                builder.enable(sess.target.cpu.as_ref()).unwrap();
             }
             builder
         }
diff --git a/compiler/rustc_codegen_cranelift/src/main_shim.rs b/compiler/rustc_codegen_cranelift/src/main_shim.rs
index 1f20ec42ddb..f9a729618a5 100644
--- a/compiler/rustc_codegen_cranelift/src/main_shim.rs
+++ b/compiler/rustc_codegen_cranelift/src/main_shim.rs
@@ -29,7 +29,7 @@ pub(crate) fn maybe_create_entry_wrapper(
 
     if main_def_id.is_local() {
         let instance = Instance::mono(tcx, main_def_id).polymorphize(tcx);
-        if !is_jit && module.get_name(tcx.symbol_name(instance).name).is_none() {
+        if module.get_name(tcx.symbol_name(instance).name).is_none() {
             return;
         }
     } else if !is_primary_cgu {
diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
index a11abd0c0e9..b6d6d211e65 100644
--- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs
+++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
@@ -317,14 +317,6 @@ impl<'tcx> CValue<'tcx> {
 
         let clif_ty = fx.clif_type(layout.ty).unwrap();
 
-        if let ty::Bool = layout.ty.kind() {
-            assert!(
-                const_val == ty::ScalarInt::FALSE || const_val == ty::ScalarInt::TRUE,
-                "Invalid bool 0x{:032X}",
-                const_val
-            );
-        }
-
         let val = match layout.ty.kind() {
             ty::Uint(UintTy::U128) | ty::Int(IntTy::I128) => {
                 let const_val = const_val.assert_bits(layout.size);
diff --git a/compiler/rustc_codegen_cranelift/y.cmd b/compiler/rustc_codegen_cranelift/y.cmd
index e9b688645a4..42106849163 100644
--- a/compiler/rustc_codegen_cranelift/y.cmd
+++ b/compiler/rustc_codegen_cranelift/y.cmd
@@ -1,8 +1,6 @@
 @echo off
 echo [BUILD] build system >&2
-mkdir build 2>nul
-rustc build_system/main.rs -o build\y.exe -Cdebuginfo=1 --edition 2021 || goto :error
-build\y.exe %* || goto :error
+cargo run --manifest-path build_system/Cargo.toml -- %* || goto :error
 goto :EOF
 
 :error
diff --git a/compiler/rustc_codegen_cranelift/y.ps1 b/compiler/rustc_codegen_cranelift/y.ps1
index 02ef0fcbd50..821f0ec6e57 100644..100755
--- a/compiler/rustc_codegen_cranelift/y.ps1
+++ b/compiler/rustc_codegen_cranelift/y.ps1
@@ -1,12 +1,7 @@
 $ErrorActionPreference = "Stop"
 
 $host.ui.WriteErrorLine("[BUILD] build system")
-New-Item -ItemType Directory -Force -Path build | Out-Null
-& rustc build_system/main.rs -o build\y.exe -Cdebuginfo=1 --edition 2021
-if ($LASTEXITCODE -ne 0) {
-    exit $LASTEXITCODE
-}
-& build\y.exe $args
+& cargo run --manifest-path build_system/Cargo.toml -- $args
 if ($LASTEXITCODE -ne 0) {
     exit $LASTEXITCODE
 }
diff --git a/compiler/rustc_codegen_cranelift/y.sh b/compiler/rustc_codegen_cranelift/y.sh
index bc925a23e2a..b9152d2cc6d 100755
--- a/compiler/rustc_codegen_cranelift/y.sh
+++ b/compiler/rustc_codegen_cranelift/y.sh
@@ -2,5 +2,4 @@
 
 set -e
 echo "[BUILD] build system" 1>&2
-rustc build_system/main.rs -o y.bin -Cdebuginfo=1 --edition 2021
-exec ./y.bin "$@"
+exec cargo run --manifest-path build_system/Cargo.toml -- "$@"
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 358c24bfb82..877e5b75912 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -283,7 +283,7 @@ pub fn coerce_unsized_into<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
                 }
 
                 if src_f.layout.ty == dst_f.layout.ty {
-                    bx.typed_place_copy(dst_f, src_f);
+                    bx.typed_place_copy(dst_f.val, src_f.val, src_f.layout);
                 } else {
                     coerce_unsized_into(bx, src_f, dst_f);
                 }
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index d36972d0d86..ba6aad51316 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -1454,9 +1454,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         Some(pointee_align) => cmp::max(pointee_align, arg.layout.align.abi),
                         None => arg.layout.align.abi,
                     };
-                    let scratch = PlaceRef::alloca_aligned(bx, arg.layout, required_align);
-                    op.val.store(bx, scratch);
-                    (scratch.val.llval, scratch.val.align, true)
+                    let scratch = PlaceValue::alloca(bx, arg.layout.size, required_align);
+                    op.val.store(bx, scratch.with_type(arg.layout));
+                    (scratch.llval, scratch.align, true)
                 }
                 PassMode::Cast { .. } => {
                     let scratch = PlaceRef::alloca(bx, arg.layout);
@@ -1475,10 +1475,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         // For `foo(packed.large_field)`, and types with <4 byte alignment on x86,
                         // alignment requirements may be higher than the type's alignment, so copy
                         // to a higher-aligned alloca.
-                        let scratch = PlaceRef::alloca_aligned(bx, arg.layout, required_align);
-                        let op_place = PlaceRef { val: op_place_val, layout: op.layout };
-                        bx.typed_place_copy(scratch, op_place);
-                        (scratch.val.llval, scratch.val.align, true)
+                        let scratch = PlaceValue::alloca(bx, arg.layout.size, required_align);
+                        bx.typed_place_copy(scratch, op_place_val, op.layout);
+                        (scratch.llval, scratch.align, true)
                     } else {
                         (op_place_val.llval, op_place_val.align, true)
                     }
@@ -1567,7 +1566,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             if place_val.llextra.is_some() {
                 bug!("closure arguments must be sized");
             }
-            let tuple_ptr = PlaceRef { val: place_val, layout: tuple.layout };
+            let tuple_ptr = place_val.with_type(tuple.layout);
             for i in 0..tuple.layout.fields.count() {
                 let field_ptr = tuple_ptr.project_field(bx, i);
                 let field = bx.load_operand(field_ptr);
diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
index 2e008460798..f88deaa7abc 100644
--- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
@@ -1,4 +1,4 @@
-use super::operand::{OperandRef, OperandValue};
+use super::operand::OperandRef;
 use super::place::PlaceRef;
 use super::FunctionCx;
 use crate::errors;
@@ -93,9 +93,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 // into the (unoptimized) direct swapping implementation, so we disable it.
                 || bx.sess().target.arch == "spirv"
             {
-                let x_place = PlaceRef::new_sized(args[0].immediate(), pointee_layout);
-                let y_place = PlaceRef::new_sized(args[1].immediate(), pointee_layout);
-                bx.typed_place_swap(x_place, y_place);
+                let align = pointee_layout.align.abi;
+                let x_place = args[0].val.deref(align);
+                let y_place = args[1].val.deref(align);
+                bx.typed_place_swap(x_place, y_place, pointee_layout);
                 return Ok(());
             }
         }
@@ -113,15 +114,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             sym::va_end => bx.va_end(args[0].immediate()),
             sym::size_of_val => {
                 let tp_ty = fn_args.type_at(0);
-                let meta =
-                    if let OperandValue::Pair(_, meta) = args[0].val { Some(meta) } else { None };
+                let (_, meta) = args[0].val.pointer_parts();
                 let (llsize, _) = size_of_val::size_and_align_of_dst(bx, tp_ty, meta);
                 llsize
             }
             sym::min_align_of_val => {
                 let tp_ty = fn_args.type_at(0);
-                let meta =
-                    if let OperandValue::Pair(_, meta) = args[0].val { Some(meta) } else { None };
+                let (_, meta) = args[0].val.pointer_parts();
                 let (_, llalign) = size_of_val::size_and_align_of_dst(bx, tp_ty, meta);
                 llalign
             }
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index 0479dd11ed0..32fd9b657f9 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -61,7 +61,7 @@ pub enum OperandValue<V> {
     ZeroSized,
 }
 
-impl<V> OperandValue<V> {
+impl<V: CodegenObject> OperandValue<V> {
     /// If this is ZeroSized/Immediate/Pair, return an array of the 0/1/2 values.
     /// If this is Ref, return the place.
     #[inline]
@@ -86,6 +86,43 @@ impl<V> OperandValue<V> {
         };
         OperandValue::Pair(a, b)
     }
+
+    /// Treat this value as a pointer and return the data pointer and
+    /// optional metadata as backend values.
+    ///
+    /// If you're making a place, use [`Self::deref`] instead.
+    pub fn pointer_parts(self) -> (V, Option<V>) {
+        match self {
+            OperandValue::Immediate(llptr) => (llptr, None),
+            OperandValue::Pair(llptr, llextra) => (llptr, Some(llextra)),
+            _ => bug!("OperandValue cannot be a pointer: {self:?}"),
+        }
+    }
+
+    /// Treat this value as a pointer and return the place to which it points.
+    ///
+    /// The pointer immediate doesn't inherently know its alignment,
+    /// so you need to pass it in. If you want to get it from a type's ABI
+    /// alignment, then maybe you want [`OperandRef::deref`] instead.
+    ///
+    /// This is the inverse of [`PlaceValue::address`].
+    pub fn deref(self, align: Align) -> PlaceValue<V> {
+        let (llval, llextra) = self.pointer_parts();
+        PlaceValue { llval, llextra, align }
+    }
+
+    pub(crate) fn is_expected_variant_for_type<'tcx, Cx: LayoutTypeMethods<'tcx>>(
+        &self,
+        cx: &Cx,
+        ty: TyAndLayout<'tcx>,
+    ) -> bool {
+        match self {
+            OperandValue::ZeroSized => ty.is_zst(),
+            OperandValue::Immediate(_) => cx.is_backend_immediate(ty),
+            OperandValue::Pair(_, _) => cx.is_backend_scalar_pair(ty),
+            OperandValue::Ref(_) => cx.is_backend_ref(ty),
+        }
+    }
 }
 
 /// An `OperandRef` is an "SSA" reference to a Rust value, along with
@@ -235,6 +272,15 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
         }
     }
 
+    /// Asserts that this operand is a pointer (or reference) and returns
+    /// the place to which it points.  (This requires no code to be emitted
+    /// as we represent places using the pointer to the place.)
+    ///
+    /// This uses [`Ty::builtin_deref`] to include the type of the place and
+    /// assumes the place is aligned to the pointee's usual ABI alignment.
+    ///
+    /// If you don't need the type, see [`OperandValue::pointer_parts`]
+    /// or [`OperandValue::deref`].
     pub fn deref<Cx: LayoutTypeMethods<'tcx>>(self, cx: &Cx) -> PlaceRef<'tcx, V> {
         if self.layout.ty.is_box() {
             // Derefer should have removed all Box derefs
@@ -247,15 +293,8 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
             .builtin_deref(true)
             .unwrap_or_else(|| bug!("deref of non-pointer {:?}", self));
 
-        let (llptr, llextra) = match self.val {
-            OperandValue::Immediate(llptr) => (llptr, None),
-            OperandValue::Pair(llptr, llextra) => (llptr, Some(llextra)),
-            OperandValue::Ref(..) => bug!("Deref of by-Ref operand {:?}", self),
-            OperandValue::ZeroSized => bug!("Deref of ZST operand {:?}", self),
-        };
         let layout = cx.layout_of(projected_ty);
-        let val = PlaceValue { llval: llptr, llextra, align: layout.align.abi };
-        PlaceRef { val, layout }
+        self.val.deref(layout.align.abi).with_type(layout)
     }
 
     /// If this operand is a `Pair`, we return an aggregate with the two values.
@@ -448,8 +487,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
                 if val.llextra.is_some() {
                     bug!("cannot directly store unsized values");
                 }
-                let source_place = PlaceRef { val, layout: dest.layout };
-                bx.typed_place_copy_with_flags(dest, source_place, flags);
+                bx.typed_place_copy_with_flags(dest.val, val, dest.layout, flags);
             }
             OperandValue::Immediate(s) => {
                 let val = bx.from_immediate(s);
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index 870a105c61d..971ac2defdc 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -10,12 +10,15 @@ use rustc_middle::mir;
 use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
 use rustc_middle::ty::{self, Ty};
-use rustc_target::abi::{Align, FieldsShape, Int, Pointer, TagEncoding};
+use rustc_target::abi::{Align, FieldsShape, Int, Pointer, Size, TagEncoding};
 use rustc_target::abi::{VariantIdx, Variants};
 
 /// The location and extra runtime properties of the place.
 ///
 /// Typically found in a [`PlaceRef`] or an [`OperandValue::Ref`].
+///
+/// As a location in memory, this has no specific type. If you want to
+/// load or store it using a typed operation, use [`Self::with_type`].
 #[derive(Copy, Clone, Debug)]
 pub struct PlaceValue<V> {
     /// A pointer to the contents of the place.
@@ -35,6 +38,41 @@ impl<V: CodegenObject> PlaceValue<V> {
     pub fn new_sized(llval: V, align: Align) -> PlaceValue<V> {
         PlaceValue { llval, llextra: None, align }
     }
+
+    /// Allocates a stack slot in the function for a value
+    /// of the specified size and alignment.
+    ///
+    /// The allocation itself is untyped.
+    pub fn alloca<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx, Value = V>>(
+        bx: &mut Bx,
+        size: Size,
+        align: Align,
+    ) -> PlaceValue<V> {
+        let llval = bx.alloca(size, align);
+        PlaceValue::new_sized(llval, align)
+    }
+
+    /// Creates a `PlaceRef` to this location with the given type.
+    pub fn with_type<'tcx>(self, layout: TyAndLayout<'tcx>) -> PlaceRef<'tcx, V> {
+        debug_assert!(
+            layout.is_unsized() || layout.abi.is_uninhabited() || self.llextra.is_none(),
+            "Had pointer metadata {:?} for sized type {layout:?}",
+            self.llextra,
+        );
+        PlaceRef { val: self, layout }
+    }
+
+    /// Gets the pointer to this place as an [`OperandValue::Immediate`]
+    /// or, for those needing metadata, an [`OperandValue::Pair`].
+    ///
+    /// This is the inverse of [`OperandValue::deref`].
+    pub fn address(self) -> OperandValue<V> {
+        if let Some(llextra) = self.llextra {
+            OperandValue::Pair(self.llval, llextra)
+        } else {
+            OperandValue::Immediate(self.llval)
+        }
+    }
 }
 
 #[derive(Copy, Clone, Debug)]
@@ -52,9 +90,7 @@ pub struct PlaceRef<'tcx, V> {
 
 impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
     pub fn new_sized(llval: V, layout: TyAndLayout<'tcx>) -> PlaceRef<'tcx, V> {
-        assert!(layout.is_sized());
-        let val = PlaceValue::new_sized(llval, layout.align.abi);
-        PlaceRef { val, layout }
+        PlaceRef::new_sized_aligned(llval, layout, layout.align.abi)
     }
 
     pub fn new_sized_aligned(
@@ -63,8 +99,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
         align: Align,
     ) -> PlaceRef<'tcx, V> {
         assert!(layout.is_sized());
-        let val = PlaceValue::new_sized(llval, align);
-        PlaceRef { val, layout }
+        PlaceValue::new_sized(llval, align).with_type(layout)
     }
 
     // FIXME(eddyb) pass something else for the name so no work is done
@@ -73,17 +108,8 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
         bx: &mut Bx,
         layout: TyAndLayout<'tcx>,
     ) -> Self {
-        Self::alloca_aligned(bx, layout, layout.align.abi)
-    }
-
-    pub fn alloca_aligned<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
-        bx: &mut Bx,
-        layout: TyAndLayout<'tcx>,
-        align: Align,
-    ) -> Self {
         assert!(layout.is_sized(), "tried to statically allocate unsized place");
-        let tmp = bx.alloca(layout.size, align);
-        Self::new_sized_aligned(tmp, layout, align)
+        PlaceValue::alloca(bx, layout.size, layout.align.abi).with_type(layout)
     }
 
     /// Returns a place for an indirect reference to an unsized place.
@@ -132,18 +158,12 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
             } else {
                 bx.inbounds_ptradd(self.val.llval, bx.const_usize(offset.bytes()))
             };
-            PlaceRef {
-                val: PlaceValue {
+            let val = PlaceValue {
                     llval,
-                    llextra: if bx.cx().type_has_metadata(field.ty) {
-                        self.val.llextra
-                    } else {
-                        None
-                    },
+                llextra: if bx.cx().type_has_metadata(field.ty) { self.val.llextra } else { None },
                     align: effective_field_align,
-                },
-                layout: field,
-            }
+            };
+            val.with_type(field)
         };
 
         // Simple cases, which don't need DST adjustment:
@@ -198,7 +218,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
         let ptr = bx.inbounds_ptradd(self.val.llval, offset);
         let val =
             PlaceValue { llval: ptr, llextra: self.val.llextra, align: effective_field_align };
-        PlaceRef { val, layout: field }
+        val.with_type(field)
     }
 
     /// Obtain the actual discriminant of a value.
@@ -387,18 +407,13 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
             layout.size
         };
 
-        PlaceRef {
-            val: PlaceValue {
-                llval: bx.inbounds_gep(
+        let llval = bx.inbounds_gep(
                     bx.cx().backend_type(self.layout),
                     self.val.llval,
                     &[bx.cx().const_usize(0), llindex],
-                ),
-                llextra: None,
-                align: self.val.align.restrict_for_offset(offset),
-            },
-            layout,
-        }
+        );
+        let align = self.val.align.restrict_for_offset(offset);
+        PlaceValue::new_sized(llval, align).with_type(layout)
     }
 
     pub fn project_downcast<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index 2976ca14c92..936ed41a294 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -74,8 +74,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         if val.llextra.is_some() {
                             bug!("unsized coercion on an unsized rvalue");
                         }
-                        let source = PlaceRef { val, layout: operand.layout };
-                        base::coerce_unsized_into(bx, source, dest);
+                        base::coerce_unsized_into(bx, val.with_type(operand.layout), dest);
                     }
                     OperandValue::ZeroSized => {
                         bug!("unsized coercion on a ZST rvalue");
@@ -184,10 +183,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             OperandValue::Immediate(..) | OperandValue::Pair(..) => {
                 // When we have immediate(s), the alignment of the source is irrelevant,
                 // so we can store them using the destination's alignment.
-                src.val.store(
-                    bx,
-                    PlaceRef::new_sized_aligned(dst.val.llval, src.layout, dst.val.align),
-                );
+                src.val.store(bx, dst.val.with_type(src.layout));
             }
         }
     }
@@ -225,8 +221,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             OperandValue::Ref(source_place_val) => {
                 debug_assert_eq!(source_place_val.llextra, None);
                 debug_assert!(matches!(operand_kind, OperandValueKind::Ref));
-                let fake_place = PlaceRef { val: source_place_val, layout: cast };
-                Some(bx.load_operand(fake_place).val)
+                Some(bx.load_operand(source_place_val.with_type(cast)).val)
             }
             OperandValue::ZeroSized => {
                 let OperandValueKind::ZeroSized = operand_kind else {
@@ -452,23 +447,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     }
                     mir::CastKind::PointerCoercion(PointerCoercion::Unsize) => {
                         assert!(bx.cx().is_backend_scalar_pair(cast));
-                        let (lldata, llextra) = match operand.val {
-                            OperandValue::Pair(lldata, llextra) => {
-                                // unsize from a fat pointer -- this is a
-                                // "trait-object-to-supertrait" coercion.
-                                (lldata, Some(llextra))
-                            }
-                            OperandValue::Immediate(lldata) => {
-                                // "standard" unsize
-                                (lldata, None)
-                            }
-                            OperandValue::Ref(..) => {
-                                bug!("by-ref operand {:?} in `codegen_rvalue_operand`", operand);
-                            }
-                            OperandValue::ZeroSized => {
-                                bug!("zero-sized operand {:?} in `codegen_rvalue_operand`", operand);
-                            }
-                        };
+                        let (lldata, llextra) = operand.val.pointer_parts();
                         let (lldata, llextra) =
                             base::unsize_ptr(bx, lldata, operand.layout.ty, cast.ty, llextra);
                         OperandValue::Pair(lldata, llextra)
@@ -489,12 +468,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         }
                     }
                     mir::CastKind::DynStar => {
-                        let (lldata, llextra) = match operand.val {
-                            OperandValue::Ref(..) => todo!(),
-                            OperandValue::Immediate(v) => (v, None),
-                            OperandValue::Pair(v, l) => (v, Some(l)),
-                            OperandValue::ZeroSized => bug!("ZST -- which is not PointerLike -- in DynStar"),
-                        };
+                        let (lldata, llextra) = operand.val.pointer_parts();
                         let (lldata, llextra) =
                             base::cast_to_dyn_star(bx, lldata, operand.layout, cast.ty, llextra);
                         OperandValue::Pair(lldata, llextra)
@@ -722,24 +696,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 OperandRef { val: OperandValue::Immediate(static_), layout }
             }
             mir::Rvalue::Use(ref operand) => self.codegen_operand(bx, operand),
-            mir::Rvalue::Aggregate(box mir::AggregateKind::RawPtr(..), ref fields) => {
-                let ty = rvalue.ty(self.mir, self.cx.tcx());
-                let layout = self.cx.layout_of(self.monomorphize(ty));
-                let [data, meta] = &*fields.raw else {
-                    bug!("RawPtr fields: {fields:?}");
-                };
-                let data = self.codegen_operand(bx, data);
-                let meta = self.codegen_operand(bx, meta);
-                match (data.val, meta.val) {
-                    (p @ OperandValue::Immediate(_), OperandValue::ZeroSized) => {
-                        OperandRef { val: p, layout }
-                    }
-                    (OperandValue::Immediate(p), OperandValue::Immediate(m)) => {
-                        OperandRef { val: OperandValue::Pair(p, m), layout }
-                    }
-                    _ => bug!("RawPtr operands {data:?} {meta:?}"),
-                }
-            }
             mir::Rvalue::Repeat(..) => bug!("{rvalue:?} in codegen_rvalue_operand"),
             mir::Rvalue::Aggregate(_, ref fields) => {
                 let ty = rvalue.ty(self.mir, self.cx.tcx());
@@ -774,6 +730,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 );
 
                 let val = OperandValue::from_immediates(inputs);
+                debug_assert!(
+                    val.is_expected_variant_for_type(self.cx, layout),
+                    "Made wrong variant {val:?} for type {layout:?}",
+                );
                 OperandRef { val, layout }
             }
             mir::Rvalue::ShallowInitBox(ref operand, content_ty) => {
@@ -812,16 +772,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         mk_ptr_ty: impl FnOnce(TyCtxt<'tcx>, Ty<'tcx>) -> Ty<'tcx>,
     ) -> OperandRef<'tcx, Bx::Value> {
         let cg_place = self.codegen_place(bx, place.as_ref());
+        let val = cg_place.val.address();
 
         let ty = cg_place.layout.ty;
+        debug_assert!(
+            if bx.cx().type_has_metadata(ty) {
+                matches!(val, OperandValue::Pair(..))
+            } else {
+                matches!(val, OperandValue::Immediate(..))
+            },
+            "Address of place was unexpectedly {val:?} for pointee type {ty:?}",
+        );
 
-        // Note: places are indirect, so storing the `llval` into the
-        // destination effectively creates a reference.
-        let val = if !bx.cx().type_has_metadata(ty) {
-            OperandValue::Immediate(cg_place.val.llval)
-        } else {
-            OperandValue::Pair(cg_place.val.llval, cg_place.val.llextra.unwrap())
-        };
         OperandRef { val, layout: self.cx.layout_of(mk_ptr_ty(self.cx.tcx(), ty)) }
     }
 
diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs
index 51b22bfaf25..fdeccb90700 100644
--- a/compiler/rustc_codegen_ssa/src/traits/builder.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs
@@ -186,6 +186,15 @@ pub trait BuilderMethods<'a, 'tcx>:
         align: Align,
         flags: MemFlags,
     ) -> Self::Value;
+    fn store_to_place_with_flags(
+        &mut self,
+        val: Self::Value,
+        place: PlaceValue<Self::Value>,
+        flags: MemFlags,
+    ) -> Self::Value {
+        debug_assert_eq!(place.llextra, None);
+        self.store_with_flags(val, place.llval, place.align, flags)
+    }
     fn atomic_store(
         &mut self,
         val: Self::Value,
@@ -286,35 +295,36 @@ pub trait BuilderMethods<'a, 'tcx>:
     /// (For example, typed load-stores with alias metadata.)
     fn typed_place_copy(
         &mut self,
-        dst: PlaceRef<'tcx, Self::Value>,
-        src: PlaceRef<'tcx, Self::Value>,
+        dst: PlaceValue<Self::Value>,
+        src: PlaceValue<Self::Value>,
+        layout: TyAndLayout<'tcx>,
     ) {
-        self.typed_place_copy_with_flags(dst, src, MemFlags::empty());
+        self.typed_place_copy_with_flags(dst, src, layout, MemFlags::empty());
     }
 
     fn typed_place_copy_with_flags(
         &mut self,
-        dst: PlaceRef<'tcx, Self::Value>,
-        src: PlaceRef<'tcx, Self::Value>,
+        dst: PlaceValue<Self::Value>,
+        src: PlaceValue<Self::Value>,
+        layout: TyAndLayout<'tcx>,
         flags: MemFlags,
     ) {
-        debug_assert!(src.val.llextra.is_none(), "cannot directly copy from unsized values");
-        debug_assert!(dst.val.llextra.is_none(), "cannot directly copy into unsized values");
-        debug_assert_eq!(dst.layout.size, src.layout.size);
+        debug_assert!(layout.is_sized(), "cannot typed-copy an unsigned type");
+        debug_assert!(src.llextra.is_none(), "cannot directly copy from unsized values");
+        debug_assert!(dst.llextra.is_none(), "cannot directly copy into unsized values");
         if flags.contains(MemFlags::NONTEMPORAL) {
             // HACK(nox): This is inefficient but there is no nontemporal memcpy.
-            let ty = self.backend_type(dst.layout);
-            let val = self.load_from_place(ty, src.val);
-            self.store_with_flags(val, dst.val.llval, dst.val.align, flags);
-        } else if self.sess().opts.optimize == OptLevel::No && self.is_backend_immediate(dst.layout)
-        {
+            let ty = self.backend_type(layout);
+            let val = self.load_from_place(ty, src);
+            self.store_to_place_with_flags(val, dst, flags);
+        } else if self.sess().opts.optimize == OptLevel::No && self.is_backend_immediate(layout) {
             // If we're not optimizing, the aliasing information from `memcpy`
             // isn't useful, so just load-store the value for smaller code.
-            let temp = self.load_operand(src);
-            temp.val.store_with_flags(self, dst, flags);
-        } else if !dst.layout.is_zst() {
-            let bytes = self.const_usize(dst.layout.size.bytes());
-            self.memcpy(dst.val.llval, dst.val.align, src.val.llval, src.val.align, bytes, flags);
+            let temp = self.load_operand(src.with_type(layout));
+            temp.val.store_with_flags(self, dst.with_type(layout), flags);
+        } else if !layout.is_zst() {
+            let bytes = self.const_usize(layout.size.bytes());
+            self.memcpy(dst.llval, dst.align, src.llval, src.align, bytes, flags);
         }
     }
 
@@ -327,18 +337,19 @@ pub trait BuilderMethods<'a, 'tcx>:
     /// cases (in non-debug), preferring the fallback body instead.
     fn typed_place_swap(
         &mut self,
-        left: PlaceRef<'tcx, Self::Value>,
-        right: PlaceRef<'tcx, Self::Value>,
+        left: PlaceValue<Self::Value>,
+        right: PlaceValue<Self::Value>,
+        layout: TyAndLayout<'tcx>,
     ) {
-        let mut temp = self.load_operand(left);
+        let mut temp = self.load_operand(left.with_type(layout));
         if let OperandValue::Ref(..) = temp.val {
             // The SSA value isn't stand-alone, so we need to copy it elsewhere
-            let alloca = PlaceRef::alloca(self, left.layout);
-            self.typed_place_copy(alloca, left);
+            let alloca = PlaceRef::alloca(self, layout);
+            self.typed_place_copy(alloca.val, left, layout);
             temp = self.load_operand(alloca);
         }
-        self.typed_place_copy(left, right);
-        temp.val.store(self, right);
+        self.typed_place_copy(left, right, layout);
+        temp.val.store(self, right.with_type(layout));
     }
 
     fn select(
diff --git a/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs b/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs
index afc60d33647..94c9f056b30 100644
--- a/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs
@@ -1,9 +1,12 @@
-use crate::interpret::{self, HasStaticRootDefId, ImmTy, Immediate, InterpCx, PointerArithmetic};
+use crate::interpret::{
+    self, throw_machine_stop, HasStaticRootDefId, ImmTy, Immediate, InterpCx, PointerArithmetic,
+};
 use rustc_middle::mir::interpret::{AllocId, ConstAllocation, InterpResult};
 use rustc_middle::mir::*;
 use rustc_middle::query::TyCtxtAt;
 use rustc_middle::ty;
 use rustc_middle::ty::layout::TyAndLayout;
+use rustc_middle::{bug, span_bug};
 use rustc_span::def_id::DefId;
 
 /// Macro for machine-specific `InterpError` without allocation.
diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs
index 2c9eb393e4a..08c9609eacf 100644
--- a/compiler/rustc_const_eval/src/const_eval/error.rs
+++ b/compiler/rustc_const_eval/src/const_eval/error.rs
@@ -11,6 +11,7 @@ use rustc_span::{Span, Symbol};
 
 use super::CompileTimeInterpreter;
 use crate::errors::{self, FrameNote, ReportErrorExt};
+use crate::interpret::{err_inval, err_machine_stop};
 use crate::interpret::{ErrorHandled, Frame, InterpError, InterpErrorInfo, MachineStopType};
 
 /// The CTFE machine has some custom error kinds.
diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
index d9f329c8b0e..6a9a21bbd8e 100644
--- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -3,6 +3,7 @@ use std::sync::atomic::Ordering::Relaxed;
 use either::{Left, Right};
 
 use rustc_hir::def::DefKind;
+use rustc_middle::bug;
 use rustc_middle::mir::interpret::{AllocId, ErrorHandled, InterpErrorInfo};
 use rustc_middle::mir::{self, ConstAlloc, ConstValue};
 use rustc_middle::query::TyCtxtAt;
@@ -24,7 +25,7 @@ use crate::interpret::{
     InternKind, InterpCx, InterpError, InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking,
     StackPopCleanup,
 };
-use crate::interpret::{eval_nullary_intrinsic, InternResult};
+use crate::interpret::{eval_nullary_intrinsic, throw_exhaust, InternResult};
 use crate::CTRL_C_RECEIVED;
 
 // Returns a pointer to where the result lives
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 6e6fa70107b..836e548ae2b 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -10,6 +10,7 @@ use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::LangItem;
+use rustc_middle::bug;
 use rustc_middle::mir;
 use rustc_middle::mir::AssertMessage;
 use rustc_middle::query::TyCtxtAt;
@@ -24,8 +25,9 @@ use rustc_target::spec::abi::Abi as CallAbi;
 use crate::errors::{LongRunning, LongRunningWarn};
 use crate::fluent_generated as fluent;
 use crate::interpret::{
-    self, compile_time_machine, AllocId, AllocRange, ConstAllocation, CtfeProvenance, FnArg, FnVal,
-    Frame, ImmTy, InterpCx, InterpResult, MPlaceTy, OpTy, Pointer, PointerArithmetic, Scalar,
+    self, compile_time_machine, err_ub, throw_exhaust, throw_inval, throw_ub_custom,
+    throw_unsup_format, AllocId, AllocRange, ConstAllocation, CtfeProvenance, FnArg, FnVal, Frame,
+    ImmTy, InterpCx, InterpResult, MPlaceTy, OpTy, Pointer, PointerArithmetic, Scalar,
 };
 
 use super::error::*;
diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs
index 8efc67bcb0c..a5c8c0bb82a 100644
--- a/compiler/rustc_const_eval/src/const_eval/mod.rs
+++ b/compiler/rustc_const_eval/src/const_eval/mod.rs
@@ -1,5 +1,6 @@
 // Not in interpret to make sure we do not use private implementation details
 
+use rustc_middle::bug;
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::InterpErrorInfo;
 use rustc_middle::query::{Key, TyCtxtAt};
diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
index dcfce4e35e0..fbf2ca5ab0a 100644
--- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs
+++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
@@ -1,4 +1,5 @@
 use rustc_data_structures::stack::ensure_sufficient_stack;
+use rustc_middle::bug;
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId};
 use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout};
diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs
index 76e59ea9055..799e12f9ac9 100644
--- a/compiler/rustc_const_eval/src/interpret/cast.rs
+++ b/compiler/rustc_const_eval/src/interpret/cast.rs
@@ -7,11 +7,13 @@ use rustc_middle::mir::CastKind;
 use rustc_middle::ty::adjustment::PointerCoercion;
 use rustc_middle::ty::layout::{IntegerExt, LayoutOf, TyAndLayout};
 use rustc_middle::ty::{self, FloatTy, Ty};
+use rustc_middle::{bug, span_bug};
 use rustc_target::abi::Integer;
 use rustc_type_ir::TyKind::*;
 
 use super::{
-    util::ensure_monomorphic_enough, FnVal, ImmTy, Immediate, InterpCx, Machine, OpTy, PlaceTy,
+    err_inval, throw_ub, throw_ub_custom, util::ensure_monomorphic_enough, FnVal, ImmTy, Immediate,
+    InterpCx, Machine, OpTy, PlaceTy,
 };
 
 use crate::fluent_generated as fluent;
diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs
index caacc6f57d3..8ddc741de23 100644
--- a/compiler/rustc_const_eval/src/interpret/discriminant.rs
+++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs
@@ -1,12 +1,15 @@
 //! Functions for reading and writing discriminants of multi-variant layouts (enums and coroutines).
 
 use rustc_middle::mir;
+use rustc_middle::span_bug;
 use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt};
 use rustc_middle::ty::{self, ScalarInt, Ty};
 use rustc_target::abi::{self, TagEncoding};
 use rustc_target::abi::{VariantIdx, Variants};
 
-use super::{ImmTy, InterpCx, InterpResult, Machine, Readable, Scalar, Writeable};
+use super::{
+    err_ub, throw_ub, ImmTy, InterpCx, InterpResult, Machine, Readable, Scalar, Writeable,
+};
 
 impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     /// Writes the discriminant of the given variant.
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index 126d64329f8..344bb7cd98b 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -17,15 +17,17 @@ use rustc_middle::ty::layout::{
     TyAndLayout,
 };
 use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt, TypeFoldable, Variance};
+use rustc_middle::{bug, span_bug};
 use rustc_mir_dataflow::storage::always_storage_live_locals;
 use rustc_session::Limit;
 use rustc_span::Span;
 use rustc_target::abi::{call::FnAbi, Align, HasDataLayout, Size, TargetDataLayout};
 
 use super::{
-    GlobalId, Immediate, InterpErrorInfo, InterpResult, MPlaceTy, Machine, MemPlace, MemPlaceMeta,
-    Memory, MemoryKind, OpTy, Operand, Place, PlaceTy, Pointer, PointerArithmetic, Projectable,
-    Provenance, Scalar, StackPopJump,
+    err_inval, throw_inval, throw_ub, throw_ub_custom, throw_unsup, GlobalId, Immediate,
+    InterpErrorInfo, InterpResult, MPlaceTy, Machine, MemPlace, MemPlaceMeta, Memory, MemoryKind,
+    OpTy, Operand, Place, PlaceTy, Pointer, PointerArithmetic, Projectable, Provenance, Scalar,
+    StackPopJump,
 };
 use crate::errors;
 use crate::util;
diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs
index d4168273f29..3565b4fb516 100644
--- a/compiler/rustc_const_eval/src/interpret/intern.rs
+++ b/compiler/rustc_const_eval/src/interpret/intern.rs
@@ -24,7 +24,7 @@ use rustc_middle::ty::layout::TyAndLayout;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::sym;
 
-use super::{AllocId, Allocation, InterpCx, MPlaceTy, Machine, MemoryKind, PlaceTy};
+use super::{err_ub, AllocId, Allocation, InterpCx, MPlaceTy, Machine, MemoryKind, PlaceTy};
 use crate::const_eval;
 use crate::errors::NestedStaticInThreadLocal;
 
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index 52c31629d54..dce4d56f7e0 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -8,6 +8,7 @@ use rustc_middle::ty::layout::{LayoutOf as _, ValidityRequirement};
 use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{Ty, TyCtxt};
 use rustc_middle::{
+    bug,
     mir::{self, BinOp, ConstValue, NonDivergingIntrinsic},
     ty::layout::TyAndLayout,
 };
@@ -15,9 +16,10 @@ use rustc_span::symbol::{sym, Symbol};
 use rustc_target::abi::Size;
 
 use super::{
-    memory::MemoryKind, util::ensure_monomorphic_enough, Allocation, CheckInAllocMsg,
-    ConstAllocation, GlobalId, ImmTy, InterpCx, InterpResult, MPlaceTy, Machine, OpTy, Pointer,
-    PointerArithmetic, Scalar,
+    err_inval, err_ub_custom, err_unsup_format, memory::MemoryKind, throw_inval, throw_ub_custom,
+    throw_ub_format, util::ensure_monomorphic_enough, Allocation, CheckInAllocMsg, ConstAllocation,
+    GlobalId, ImmTy, InterpCx, InterpResult, MPlaceTy, Machine, OpTy, Pointer, PointerArithmetic,
+    Scalar,
 };
 
 use crate::fluent_generated as fluent;
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index 8405d0746df..2eaebc1924b 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -18,9 +18,9 @@ use rustc_target::abi::{Align, Size};
 use rustc_target::spec::abi::Abi as CallAbi;
 
 use super::{
-    AllocBytes, AllocId, AllocKind, AllocRange, Allocation, ConstAllocation, CtfeProvenance, FnArg,
-    Frame, ImmTy, InterpCx, InterpResult, MPlaceTy, MemoryKind, Misalignment, OpTy, PlaceTy,
-    Pointer, Provenance,
+    throw_unsup, throw_unsup_format, AllocBytes, AllocId, AllocKind, AllocRange, Allocation,
+    ConstAllocation, CtfeProvenance, FnArg, Frame, ImmTy, InterpCx, InterpResult, MPlaceTy,
+    MemoryKind, Misalignment, OpTy, PlaceTy, Pointer, Provenance,
 };
 
 /// Data returned by Machine::stack_pop,
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index 594e3b3212f..350fd480fba 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -16,6 +16,7 @@ use std::ptr;
 use rustc_ast::Mutability;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_hir::def::DefKind;
+use rustc_middle::bug;
 use rustc_middle::mir::display_allocation;
 use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TyCtxt};
 use rustc_target::abi::{Align, HasDataLayout, Size};
@@ -23,9 +24,10 @@ use rustc_target::abi::{Align, HasDataLayout, Size};
 use crate::fluent_generated as fluent;
 
 use super::{
-    alloc_range, AllocBytes, AllocId, AllocMap, AllocRange, Allocation, CheckAlignMsg,
-    CheckInAllocMsg, CtfeProvenance, GlobalAlloc, InterpCx, InterpResult, Machine, MayLeak,
-    Misalignment, Pointer, PointerArithmetic, Provenance, Scalar,
+    alloc_range, err_ub, err_ub_custom, throw_ub, throw_ub_custom, throw_unsup, throw_unsup_format,
+    AllocBytes, AllocId, AllocMap, AllocRange, Allocation, CheckAlignMsg, CheckInAllocMsg,
+    CtfeProvenance, GlobalAlloc, InterpCx, InterpResult, Machine, MayLeak, Misalignment, Pointer,
+    PointerArithmetic, Provenance, Scalar,
 };
 
 #[derive(Debug, PartialEq, Copy, Clone)]
diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs
index 718c91b2f76..bad9732f483 100644
--- a/compiler/rustc_const_eval/src/interpret/operand.rs
+++ b/compiler/rustc_const_eval/src/interpret/operand.rs
@@ -10,13 +10,14 @@ use rustc_middle::mir::interpret::ScalarSizeMismatch;
 use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
 use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter};
 use rustc_middle::ty::{ConstInt, ScalarInt, Ty, TyCtxt};
+use rustc_middle::{bug, span_bug};
 use rustc_middle::{mir, ty};
 use rustc_target::abi::{self, Abi, HasDataLayout, Size};
 
 use super::{
-    alloc_range, from_known_layout, mir_assign_valid_types, CtfeProvenance, InterpCx, InterpResult,
-    MPlaceTy, Machine, MemPlace, MemPlaceMeta, OffsetMode, PlaceTy, Pointer, Projectable,
-    Provenance, Scalar,
+    alloc_range, err_ub, from_known_layout, mir_assign_valid_types, throw_ub, CtfeProvenance,
+    InterpCx, InterpResult, MPlaceTy, Machine, MemPlace, MemPlaceMeta, OffsetMode, PlaceTy,
+    Pointer, Projectable, Provenance, Scalar,
 };
 
 /// An `Immediate` represents a single immediate self-contained Rust value.
diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs
index 2d5dbbd58b3..5f59e3d887e 100644
--- a/compiler/rustc_const_eval/src/interpret/operator.rs
+++ b/compiler/rustc_const_eval/src/interpret/operator.rs
@@ -3,10 +3,11 @@ use rustc_middle::mir;
 use rustc_middle::mir::interpret::{InterpResult, Scalar};
 use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
 use rustc_middle::ty::{self, FloatTy, ScalarInt, Ty};
+use rustc_middle::{bug, span_bug};
 use rustc_span::symbol::sym;
 use rustc_target::abi::Abi;
 
-use super::{ImmTy, Immediate, InterpCx, Machine, PlaceTy};
+use super::{err_ub, throw_ub, throw_ub_custom, ImmTy, Immediate, InterpCx, Machine, PlaceTy};
 
 use crate::fluent_generated as fluent;
 
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs
index 809aca18990..9ced825853b 100644
--- a/compiler/rustc_const_eval/src/interpret/place.rs
+++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -11,12 +11,14 @@ use rustc_middle::mir;
 use rustc_middle::ty;
 use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
 use rustc_middle::ty::Ty;
+use rustc_middle::{bug, span_bug};
 use rustc_target::abi::{Abi, Align, HasDataLayout, Size};
 
 use super::{
-    alloc_range, mir_assign_valid_types, AllocRef, AllocRefMut, CheckAlignMsg, CtfeProvenance,
-    ImmTy, Immediate, InterpCx, InterpResult, Machine, MemoryKind, Misalignment, OffsetMode, OpTy,
-    Operand, Pointer, PointerArithmetic, Projectable, Provenance, Readable, Scalar,
+    alloc_range, mir_assign_valid_types, throw_ub, AllocRef, AllocRefMut, CheckAlignMsg,
+    CtfeProvenance, ImmTy, Immediate, InterpCx, InterpResult, Machine, MemoryKind, Misalignment,
+    OffsetMode, OpTy, Operand, Pointer, PointerArithmetic, Projectable, Provenance, Readable,
+    Scalar,
 };
 
 #[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)]
diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs
index 5ff78f7b8c9..0a2fedb4840 100644
--- a/compiler/rustc_const_eval/src/interpret/projection.rs
+++ b/compiler/rustc_const_eval/src/interpret/projection.rs
@@ -14,10 +14,14 @@ use rustc_middle::mir;
 use rustc_middle::ty;
 use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
 use rustc_middle::ty::Ty;
+use rustc_middle::{bug, span_bug};
 use rustc_target::abi::Size;
 use rustc_target::abi::{self, VariantIdx};
 
-use super::{InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy, Provenance, Scalar};
+use super::{
+    throw_ub, throw_unsup_format, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy,
+    Provenance, Scalar,
+};
 
 /// Describes the constraints placed on offset-projections.
 #[derive(Copy, Clone, Debug)]
diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs
index b29034e991e..ee415c380de 100644
--- a/compiler/rustc_const_eval/src/interpret/step.rs
+++ b/compiler/rustc_const_eval/src/interpret/step.rs
@@ -7,6 +7,7 @@ use either::Either;
 use rustc_index::IndexSlice;
 use rustc_middle::mir;
 use rustc_middle::ty::layout::LayoutOf;
+use rustc_middle::{bug, span_bug};
 use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
 
 use super::{
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index b474003087b..b82c1857858 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -2,6 +2,7 @@ use std::borrow::Cow;
 
 use either::Either;
 
+use rustc_middle::span_bug;
 use rustc_middle::{
     mir,
     ty::{
@@ -19,8 +20,9 @@ use rustc_target::abi::{
 use rustc_target::spec::abi::Abi;
 
 use super::{
-    CtfeProvenance, FnVal, ImmTy, InterpCx, InterpResult, MPlaceTy, Machine, OpTy, PlaceTy,
-    Projectable, Provenance, Scalar, StackPopCleanup,
+    throw_ub, throw_ub_custom, throw_unsup_format, CtfeProvenance, FnVal, ImmTy, InterpCx,
+    InterpResult, MPlaceTy, Machine, OpTy, PlaceTy, Projectable, Provenance, Scalar,
+    StackPopCleanup,
 };
 use crate::fluent_generated as fluent;
 
diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs
index c83ef14c03f..e304d1e1cc5 100644
--- a/compiler/rustc_const_eval/src/interpret/util.rs
+++ b/compiler/rustc_const_eval/src/interpret/util.rs
@@ -1,5 +1,4 @@
 use crate::const_eval::{CompileTimeEvalContext, CompileTimeInterpreter, InterpretationResult};
-use crate::interpret::{MemPlaceMeta, MemoryKind};
 use rustc_hir::def_id::LocalDefId;
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::{Allocation, InterpResult, Pointer};
@@ -9,7 +8,7 @@ use rustc_middle::ty::{
 };
 use std::ops::ControlFlow;
 
-use super::{InterpCx, MPlaceTy};
+use super::{throw_inval, InterpCx, MPlaceTy, MemPlaceMeta, MemoryKind};
 
 /// Checks whether a type contains generic parameters which must be instantiated.
 ///
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index 14566719ccd..2bd4d9dc07a 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -13,6 +13,7 @@ use hir::def::DefKind;
 use rustc_ast::Mutability;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
+use rustc_middle::bug;
 use rustc_middle::mir::interpret::{
     ExpectedKind, InterpError, InvalidMetaKind, Misalignment, PointerKind, Provenance,
     ValidationErrorInfo, ValidationErrorKind, ValidationErrorKind::*,
@@ -27,9 +28,9 @@ use rustc_target::abi::{
 use std::hash::Hash;
 
 use super::{
-    format_interp_error, machine::AllocMap, AllocId, CheckInAllocMsg, GlobalAlloc, ImmTy,
-    Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy, Pointer, Projectable,
-    Scalar, ValueVisitor,
+    err_ub, format_interp_error, machine::AllocMap, throw_ub, AllocId, CheckInAllocMsg,
+    GlobalAlloc, ImmTy, Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy,
+    Pointer, Projectable, Scalar, ValueVisitor,
 };
 
 // for the validation errors
diff --git a/compiler/rustc_const_eval/src/interpret/visitor.rs b/compiler/rustc_const_eval/src/interpret/visitor.rs
index 84557b8e2d6..59bcc5174cb 100644
--- a/compiler/rustc_const_eval/src/interpret/visitor.rs
+++ b/compiler/rustc_const_eval/src/interpret/visitor.rs
@@ -9,7 +9,7 @@ use rustc_target::abi::{FieldsShape, VariantIdx, Variants};
 
 use std::num::NonZero;
 
-use super::{InterpCx, MPlaceTy, Machine, Projectable};
+use super::{throw_inval, InterpCx, MPlaceTy, Machine, Projectable};
 
 /// How to traverse a value and what to do when we are at the leaves.
 pub trait ValueVisitor<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>>: Sized {
diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs
index d27d42737cd..a525b838afa 100644
--- a/compiler/rustc_const_eval/src/lib.rs
+++ b/compiler/rustc_const_eval/src/lib.rs
@@ -22,8 +22,6 @@ Rust MIR: a lowered representation of Rust.
 
 #[macro_use]
 extern crate tracing;
-#[macro_use]
-extern crate rustc_middle;
 
 pub mod const_eval;
 mod errors;
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 d43dc467c0f..5edf5bb39dd 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -8,10 +8,11 @@ use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::ObligationCause;
 use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
+use rustc_middle::span_bug;
 use rustc_middle::ty::{self, adjustment::PointerCoercion, Ty, TyCtxt};
 use rustc_middle::ty::{Instance, InstanceDef, TypeVisitableExt};
 use rustc_mir_dataflow::Analysis;
-use rustc_span::{sym, Span, Symbol};
+use rustc_span::{sym, Span, Symbol, DUMMY_SP};
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
 use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt};
 use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitor};
@@ -738,7 +739,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                 let cause = ObligationCause::new(
                     terminator.source_info.span,
                     self.body.source.def_id().expect_local(),
-                    ObligationCauseCode::WhereClause(callee),
+                    ObligationCauseCode::WhereClause(callee, DUMMY_SP),
                 );
                 let normalized_predicates = ocx.normalize(&cause, param_env, predicates);
                 ocx.register_obligations(traits::predicates_for_generics(
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs
index 12e7ec15e32..308b90cd470 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs
@@ -8,6 +8,7 @@ use rustc_attr as attr;
 use rustc_errors::DiagCtxt;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_middle::bug;
 use rustc_middle::mir;
 use rustc_middle::ty::{self, PolyFnSig, TyCtxt};
 use rustc_span::Symbol;
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
index 247a2889dc5..8775685e8c7 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
@@ -8,6 +8,7 @@ use rustc_hir::def_id::DefId;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
 use rustc_middle::mir::{self, CallSource};
+use rustc_middle::span_bug;
 use rustc_middle::ty::print::{with_no_trimmed_paths, PrintTraitRefExt as _};
 use rustc_middle::ty::{
     self, suggest_constraining_type_param, Closure, FnDef, FnPtr, GenericArgKind, GenericArgsRef,
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
index 1847847d9d2..eae0e2f27db 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
@@ -5,6 +5,7 @@
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::LangItem;
 use rustc_infer::infer::TyCtxtInferExt;
+use rustc_middle::bug;
 use rustc_middle::mir;
 use rustc_middle::mir::*;
 use rustc_middle::traits::BuiltinImplSource;
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index c95166d84e9..fdc7f6a69cb 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -9,6 +9,7 @@ use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt, Variance};
+use rustc_middle::{bug, span_bug};
 use rustc_target::abi::{Size, FIRST_VARIANT};
 use rustc_target::spec::abi::Abi;
 
diff --git a/compiler/rustc_const_eval/src/util/caller_location.rs b/compiler/rustc_const_eval/src/util/caller_location.rs
index af9a4a4271d..403bc1eca13 100644
--- a/compiler/rustc_const_eval/src/util/caller_location.rs
+++ b/compiler/rustc_const_eval/src/util/caller_location.rs
@@ -1,4 +1,5 @@
 use rustc_hir::LangItem;
+use rustc_middle::bug;
 use rustc_middle::mir;
 use rustc_middle::query::TyCtxtAt;
 use rustc_middle::ty::layout::LayoutOf;
diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
index 36597507f47..68fb122a765 100644
--- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
+++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
@@ -1,3 +1,4 @@
+use rustc_middle::bug;
 use rustc_middle::ty::layout::{LayoutCx, LayoutError, LayoutOf, TyAndLayout, ValidityRequirement};
 use rustc_middle::ty::{ParamEnv, ParamEnvAnd, Ty, TyCtxt};
 use rustc_target::abi::{Abi, FieldsShape, Scalar, Variants};
diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs
index e474b952938..01e517250f7 100644
--- a/compiler/rustc_const_eval/src/util/type_name.rs
+++ b/compiler/rustc_const_eval/src/util/type_name.rs
@@ -1,6 +1,7 @@
 use rustc_data_structures::intern::Interned;
 use rustc_hir::def_id::CrateNum;
 use rustc_hir::definitions::DisambiguatedDefPathData;
+use rustc_middle::bug;
 use rustc_middle::ty::{
     self,
     print::{PrettyPrinter, Print, PrintError, Printer},
diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml
index 80b6e72e49b..2b61e17efa2 100644
--- a/compiler/rustc_data_structures/Cargo.toml
+++ b/compiler/rustc_data_structures/Cargo.toml
@@ -9,7 +9,7 @@ arrayvec = { version = "0.7", default-features = false }
 bitflags = "2.4.1"
 either = "1.0"
 elsa = "=1.7.1"
-ena = "0.14.2"
+ena = "0.14.3"
 indexmap = { version = "2.0.0" }
 jobserver_crate = { version = "0.1.28", package = "jobserver" }
 libc = "0.2"
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index b2d38a00f0b..ba6b9ef0784 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -11,6 +11,7 @@
 #![allow(internal_features)]
 #![feature(decl_macro)]
 #![feature(let_chains)]
+#![feature(panic_backtrace_config)]
 #![feature(panic_update_hook)]
 #![feature(result_flattening)]
 
@@ -1317,8 +1318,8 @@ pub fn install_ice_hook(
     // by the user. Compiler developers and other rustc users can
     // opt in to less-verbose backtraces by manually setting "RUST_BACKTRACE"
     // (e.g. `RUST_BACKTRACE=1`)
-    if std::env::var_os("RUST_BACKTRACE").is_none() {
-        std::env::set_var("RUST_BACKTRACE", "full");
+    if env::var_os("RUST_BACKTRACE").is_none() {
+        panic::set_backtrace_style(panic::BacktraceStyle::Full);
     }
 
     let using_internal_features = Arc::new(std::sync::atomic::AtomicBool::default());
diff --git a/compiler/rustc_error_codes/src/error_codes/E0457.md b/compiler/rustc_error_codes/src/error_codes/E0457.md
index e2dbf53a0f8..47bff4bc49f 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0457.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0457.md
@@ -1,4 +1,4 @@
-#### Note: this error code is no longer emitted by the compiler`
+#### Note: this error code is no longer emitted by the compiler
 
 Plugin `..` only found in rlib format, but must be available in dylib format.
 
diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs
index 40560a5ad79..2cc0167dbaa 100644
--- a/compiler/rustc_errors/src/diagnostic_impls.rs
+++ b/compiler/rustc_errors/src/diagnostic_impls.rs
@@ -100,6 +100,12 @@ impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::TraitRef<I> {
     }
 }
 
+impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::ExistentialTraitRef<I> {
+    fn into_diag_arg(self) -> DiagArgValue {
+        self.to_string().into_diag_arg()
+    }
+}
+
 into_diag_arg_for_number!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize);
 
 impl IntoDiagArg for bool {
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index 897420a11cd..67a5a9128cc 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -201,10 +201,17 @@ impl<'a> StripUnconfigured<'a> {
                     inner = self.configure_tokens(&inner);
                     Some(AttrTokenTree::Delimited(sp, spacing, delim, inner)).into_iter()
                 }
-                AttrTokenTree::Token(ref token, _)
-                    if let TokenKind::Interpolated(nt) = &token.kind =>
-                {
-                    panic!("Nonterminal should have been flattened at {:?}: {:?}", token.span, nt);
+                AttrTokenTree::Token(
+                    Token {
+                        kind:
+                            TokenKind::NtIdent(..)
+                            | TokenKind::NtLifetime(..)
+                            | TokenKind::Interpolated(..),
+                        ..
+                    },
+                    _,
+                ) => {
+                    panic!("Nonterminal should have been flattened: {:?}", tree);
                 }
                 AttrTokenTree::Token(token, spacing) => {
                     Some(AttrTokenTree::Token(token, spacing)).into_iter()
diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs
index 464361cb402..3fee39dd085 100644
--- a/compiler/rustc_expand/src/mbe/diagnostics.rs
+++ b/compiler/rustc_expand/src/mbe/diagnostics.rs
@@ -73,12 +73,6 @@ pub(super) fn failed_to_match_macro<'cx>(
         && (matches!(expected_token.kind, TokenKind::Interpolated(_))
             || matches!(token.kind, TokenKind::Interpolated(_)))
     {
-        if let TokenKind::Interpolated(node) = &expected_token.kind {
-            err.span_label(node.1, "");
-        }
-        if let TokenKind::Interpolated(node) = &token.kind {
-            err.span_label(node.1, "");
-        }
         err.note("captured metavariables except for `:tt`, `:ident` and `:lifetime` cannot be compared to other tokens");
         err.note("see <https://doc.rust-lang.org/nightly/reference/macros-by-example.html#forwarding-a-matched-fragment> for more information");
 
diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs
index ffb50f4c92e..27cf6fee702 100644
--- a/compiler/rustc_expand/src/mbe/macro_parser.rs
+++ b/compiler/rustc_expand/src/mbe/macro_parser.rs
@@ -75,10 +75,9 @@ pub(crate) use ParseResult::*;
 
 use crate::mbe::{macro_rules::Tracker, KleeneOp, TokenTree};
 
-use rustc_ast::token::{self, DocComment, Nonterminal, NonterminalKind, Token};
+use rustc_ast::token::{self, DocComment, NonterminalKind, Token};
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::sync::Lrc;
 use rustc_errors::ErrorGuaranteed;
 use rustc_lint_defs::pluralize;
 use rustc_parse::parser::{ParseNtResult, Parser};
@@ -392,7 +391,7 @@ pub(super) fn count_metavar_decls(matcher: &[TokenTree]) -> usize {
 #[derive(Debug, Clone)]
 pub(crate) enum NamedMatch {
     MatchedSeq(Vec<NamedMatch>),
-    MatchedSingle(ParseNtResult<Lrc<(Nonterminal, Span)>>),
+    MatchedSingle(ParseNtResult),
 }
 
 /// Performs a token equality check, ignoring syntax context (that is, an unhygienic comparison)
@@ -686,11 +685,7 @@ impl TtParser {
                             }
                             Ok(nt) => nt,
                         };
-                        mp.push_match(
-                            next_metavar,
-                            seq_depth,
-                            MatchedSingle(nt.map_nt(|nt| (Lrc::new((nt, span))))),
-                        );
+                        mp.push_match(next_metavar, seq_depth, MatchedSingle(nt));
                         mp.idx += 1;
                     } else {
                         unreachable!()
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index 011aa95c8a1..e35eba0f859 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -261,6 +261,16 @@ pub(super) fn transcribe<'a>(
                             // without wrapping them into groups.
                             maybe_use_metavar_location(cx, &stack, sp, tt, &mut marker)
                         }
+                        MatchedSingle(ParseNtResult::Ident(ident, is_raw)) => {
+                            marker.visit_span(&mut sp);
+                            let kind = token::NtIdent(*ident, *is_raw);
+                            TokenTree::token_alone(kind, sp)
+                        }
+                        MatchedSingle(ParseNtResult::Lifetime(ident)) => {
+                            marker.visit_span(&mut sp);
+                            let kind = token::NtLifetime(*ident);
+                            TokenTree::token_alone(kind, sp)
+                        }
                         MatchedSingle(ParseNtResult::Nt(nt)) => {
                             // Other variables are emitted into the output stream as groups with
                             // `Delimiter::Invisible` to maintain parsing priorities.
diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs
index 4b5c148cb55..530059e53c2 100644
--- a/compiler/rustc_expand/src/proc_macro.rs
+++ b/compiler/rustc_expand/src/proc_macro.rs
@@ -127,7 +127,7 @@ impl MultiItemModifier for DeriveProcMacro {
                 Annotatable::Stmt(stmt) => token::NtStmt(stmt),
                 _ => unreachable!(),
             };
-            TokenStream::token_alone(token::Interpolated(Lrc::new((nt, span))), DUMMY_SP)
+            TokenStream::token_alone(token::Interpolated(Lrc::new(nt)), DUMMY_SP)
         } else {
             item.to_tokens()
         };
diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs
index 5a66b0fbdef..1f3547c841a 100644
--- a/compiler/rustc_expand/src/proc_macro_server.rs
+++ b/compiler/rustc_expand/src/proc_macro_server.rs
@@ -220,6 +220,12 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStre
                 Ident(sym, is_raw) => {
                     trees.push(TokenTree::Ident(Ident { sym, is_raw: is_raw.into(), span }))
                 }
+                NtIdent(ident, is_raw) => trees.push(TokenTree::Ident(Ident {
+                    sym: ident.name,
+                    is_raw: is_raw.into(),
+                    span: ident.span,
+                })),
+
                 Lifetime(name) => {
                     let ident = symbol::Ident::new(name, span).without_first_quote();
                     trees.extend([
@@ -227,6 +233,15 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStre
                         TokenTree::Ident(Ident { sym: ident.name, is_raw: false, span }),
                     ]);
                 }
+                NtLifetime(ident) => {
+                    let stream = TokenStream::token_alone(token::Lifetime(ident.name), ident.span);
+                    trees.push(TokenTree::Group(Group {
+                        delimiter: pm::Delimiter::None,
+                        stream: Some(stream),
+                        span: DelimSpan::from_single(span),
+                    }))
+                }
+
                 Literal(token::Lit { kind, symbol, suffix }) => {
                     trees.push(TokenTree::Literal(self::Literal {
                         kind: FromInternal::from_internal(kind),
@@ -259,23 +274,15 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStre
                     }));
                 }
 
-                Interpolated(ref nt) if let NtIdent(ident, is_raw) = &nt.0 => {
-                    trees.push(TokenTree::Ident(Ident {
-                        sym: ident.name,
-                        is_raw: matches!(is_raw, IdentIsRaw::Yes),
-                        span: ident.span,
-                    }))
-                }
-
                 Interpolated(nt) => {
-                    let stream = TokenStream::from_nonterminal_ast(&nt.0);
+                    let stream = TokenStream::from_nonterminal_ast(&nt);
                     // A hack used to pass AST fragments to attribute and derive
                     // macros as a single nonterminal token instead of a token
                     // stream. Such token needs to be "unwrapped" and not
                     // represented as a delimited group.
                     // FIXME: It needs to be removed, but there are some
                     // compatibility issues (see #73345).
-                    if crate::base::nt_pretty_printing_compatibility_hack(&nt.0, rustc.ecx.sess) {
+                    if crate::base::nt_pretty_printing_compatibility_hack(&nt, rustc.ecx.sess) {
                         trees.extend(Self::from_internal((stream, rustc)));
                     } else {
                         trees.push(TokenTree::Group(Group {
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 7d991e21ff3..6e4cef068c5 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2631,7 +2631,7 @@ pub struct OpaqueTy<'hir> {
     /// lowered as an associated type.
     pub in_trait: bool,
     /// List of arguments captured via `impl use<'a, P, ...> Trait` syntax.
-    pub precise_capturing_args: Option<&'hir [PreciseCapturingArg<'hir>]>,
+    pub precise_capturing_args: Option<(&'hir [PreciseCapturingArg<'hir>], Span)>,
 }
 
 #[derive(Debug, Clone, Copy, HashStable_Generic)]
@@ -2641,6 +2641,15 @@ pub enum PreciseCapturingArg<'hir> {
     Param(PreciseCapturingNonLifetimeArg),
 }
 
+impl PreciseCapturingArg<'_> {
+    pub fn hir_id(self) -> HirId {
+        match self {
+            PreciseCapturingArg::Lifetime(lt) => lt.hir_id,
+            PreciseCapturingArg::Param(param) => param.hir_id,
+        }
+    }
+}
+
 /// We need to have a [`Node`] for the [`HirId`] that we attach the type/const param
 /// resolution to. Lifetimes don't have this problem, and for them, it's actually
 /// kind of detrimental to use a custom node type versus just using [`Lifetime`],
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 0b095db953b..664784cd2c6 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -533,7 +533,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::
             try_visit!(visitor.visit_id(item.hir_id()));
             try_visit!(walk_generics(visitor, generics));
             walk_list!(visitor, visit_param_bound, bounds);
-            if let Some(precise_capturing_args) = precise_capturing_args {
+            if let Some((precise_capturing_args, _)) = precise_capturing_args {
                 for arg in precise_capturing_args {
                     try_visit!(visitor.visit_precise_capturing_arg(arg));
                 }
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index fb9d97ba08b..b5c06751405 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -14,6 +14,7 @@ use rustc_infer::traits::Obligation;
 use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
 use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
 use rustc_middle::middle::stability::EvalResult;
+use rustc_middle::span_bug;
 use rustc_middle::ty::fold::BottomUpFolder;
 use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
 use rustc_middle::ty::util::{Discr, InspectCoroutineFields, IntTypeExt};
@@ -485,7 +486,7 @@ fn sanity_check_found_hidden_type<'tcx>(
 fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDefId) {
     let hir::OpaqueTy { precise_capturing_args, .. } =
         *tcx.hir_node_by_def_id(opaque_def_id).expect_item().expect_opaque_ty();
-    let Some(precise_capturing_args) = precise_capturing_args else {
+    let Some((precise_capturing_args, _)) = precise_capturing_args else {
         // No precise capturing args; nothing to validate
         return;
     };
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 b2b82670d8b..39940c8f0f3 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -19,6 +19,7 @@ use rustc_middle::ty::{
     self, GenericArgs, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
 };
 use rustc_middle::ty::{GenericParamDefKind, TyCtxt};
+use rustc_middle::{bug, span_bug};
 use rustc_span::Span;
 use rustc_trait_selection::regions::InferCtxtRegionExt;
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
@@ -819,7 +820,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx> {
                     ObligationCause::new(
                         self.span,
                         self.body_id,
-                        ObligationCauseCode::SpannedWhereClause(proj.def_id, pred_span),
+                        ObligationCauseCode::WhereClause(proj.def_id, pred_span),
                     ),
                     self.param_env,
                     pred,
@@ -2011,11 +2012,7 @@ pub(super) fn check_type_bounds<'tcx>(
         },
     );
     let mk_cause = |span: Span| {
-        let code = if span.is_dummy() {
-            ObligationCauseCode::WhereClause(trait_ty.def_id)
-        } else {
-            ObligationCauseCode::SpannedWhereClause(trait_ty.def_id, span)
-        };
+        let code = ObligationCauseCode::WhereClause(trait_ty.def_id, span);
         ObligationCause::new(impl_ty_span, impl_ty_def_id, code)
     };
 
@@ -2209,7 +2206,7 @@ fn param_env_with_gat_bounds<'tcx>(
             _ => predicates.push(
                 ty::Binder::bind_with_vars(
                     ty::ProjectionPredicate {
-                        projection_ty: ty::AliasTy::new(tcx, trait_ty.def_id, rebased_args),
+                        projection_term: ty::AliasTerm::new(tcx, trait_ty.def_id, rebased_args),
                         term: normalize_impl_ty.into(),
                     },
                     bound_vars,
@@ -2251,8 +2248,7 @@ fn try_report_async_mismatch<'tcx>(
     };
 
     for error in errors {
-        if let ObligationCauseCode::SpannedWhereClause(def_id, _) =
-            *error.root_obligation.cause.code()
+        if let ObligationCauseCode::WhereClause(def_id, _) = *error.root_obligation.cause.code()
             && def_id == async_future_def_id
             && let Some(proj) = error.root_obligation.predicate.to_opt_poly_projection_pred()
             && let Some(proj) = proj.no_bound_vars()
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
index a2a20082bb0..ca08eeea227 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
@@ -3,6 +3,7 @@ use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::{outlives::env::OutlivesEnvironment, TyCtxtInferExt};
 use rustc_lint_defs::builtin::{REFINING_IMPL_TRAIT_INTERNAL, REFINING_IMPL_TRAIT_REACHABLE};
+use rustc_middle::span_bug;
 use rustc_middle::traits::{ObligationCause, Reveal};
 use rustc_middle::ty::{
     self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperVisitable, TypeVisitable, TypeVisitor,
diff --git a/compiler/rustc_hir_analysis/src/check/entry.rs b/compiler/rustc_hir_analysis/src/check/entry.rs
index d5908cf2851..e44e8e67da3 100644
--- a/compiler/rustc_hir_analysis/src/check/entry.rs
+++ b/compiler/rustc_hir_analysis/src/check/entry.rs
@@ -1,6 +1,7 @@
 use rustc_hir as hir;
 use rustc_hir::Node;
 use rustc_infer::infer::TyCtxtInferExt;
+use rustc_middle::span_bug;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_session::config::EntryFnType;
 use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index eb1fa1baecc..00ff470a0a7 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -9,6 +9,7 @@ use crate::errors::{
 
 use rustc_errors::{codes::*, struct_span_code_err, DiagMessage};
 use rustc_hir as hir;
+use rustc_middle::bug;
 use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::def_id::LocalDefId;
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
index 45ccd0fa2e0..b09de1a4a09 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
@@ -1,6 +1,7 @@
 use rustc_ast::InlineAsmTemplatePiece;
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir as hir;
+use rustc_middle::bug;
 use rustc_middle::ty::{self, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy};
 use rustc_session::lint;
 use rustc_span::def_id::LocalDefId;
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index eb0ffc19d45..f8b0164b9a5 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -90,6 +90,7 @@ use rustc_middle::query::Providers;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::ty::{GenericArgs, GenericArgsRef};
+use rustc_middle::{bug, span_bug};
 use rustc_session::parse::feature_err;
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::{def_id::CRATE_DEF_ID, BytePos, Span, Symbol, DUMMY_SP};
@@ -343,9 +344,10 @@ fn bounds_from_generic_predicates<'tcx>(
                 let mut projections_str = vec![];
                 for projection in &projections {
                     let p = projection.skip_binder();
-                    let alias_ty = p.projection_ty;
-                    if bound == tcx.parent(alias_ty.def_id) && alias_ty.self_ty() == ty {
-                        let name = tcx.item_name(alias_ty.def_id);
+                    if bound == tcx.parent(p.projection_term.def_id)
+                        && p.projection_term.self_ty() == ty
+                    {
+                        let name = tcx.item_name(p.projection_term.def_id);
                         projections_str.push(format!("{} = {}", name, p.term));
                     }
                 }
diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs
index d2ea51f65f9..4540310937d 100644
--- a/compiler/rustc_hir_analysis/src/check/region.rs
+++ b/compiler/rustc_hir_analysis/src/check/region.rs
@@ -13,6 +13,7 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{Arm, Block, Expr, LetStmt, Pat, PatKind, Stmt};
 use rustc_index::Idx;
+use rustc_middle::bug;
 use rustc_middle::middle::region::*;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::source_map;
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 0578317f914..b918a8c32d8 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -24,6 +24,7 @@ use rustc_middle::ty::{
     TypeVisitable, TypeVisitableExt, TypeVisitor,
 };
 use rustc_middle::ty::{GenericArgKind, GenericArgs};
+use rustc_middle::{bug, span_bug};
 use rustc_session::parse::feature_err;
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::{Span, DUMMY_SP};
@@ -1550,7 +1551,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
             let cause = traits::ObligationCause::new(
                 sp,
                 wfcx.body_def_id,
-                ObligationCauseCode::WhereClause(def_id.to_def_id()),
+                ObligationCauseCode::WhereClause(def_id.to_def_id(), DUMMY_SP),
             );
             traits::Obligation::new(tcx, cause, wfcx.param_env, pred)
         });
diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
index 4a85e9983f4..e2d3ff558cf 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
@@ -10,6 +10,7 @@
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_middle::bug;
 use rustc_middle::ty::fast_reject::{simplify_type, SimplifiedType, TreatParams};
 use rustc_middle::ty::{self, CrateInherentImpls, Ty, TyCtxt};
 use rustc_span::symbol::sym;
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index 8e1b2e8e65c..bdac0d9b0b4 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -10,6 +10,7 @@ use rustc_lint_defs::builtin::UNCOVERED_PARAM_IN_PROJECTION;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::ty::{TypeFoldable, TypeFolder, TypeSuperFoldable};
 use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
+use rustc_middle::{bug, span_bug};
 use rustc_span::def_id::{DefId, LocalDefId};
 use rustc_trait_selection::traits::{self, IsFirstInputType, UncoveredTyParams};
 use rustc_trait_selection::traits::{OrphanCheckErr, OrphanCheckMode};
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 566f818f899..0b9f7fd41fb 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -30,6 +30,7 @@ use rustc_middle::hir::nested_filter;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::util::{Discr, IntTypeExt};
 use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, ToPredicate, Ty, TyCtxt};
+use rustc_middle::{bug, span_bug};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::abi::FieldIdx;
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index 02291cc603e..dd1d209389d 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -5,6 +5,7 @@ use rustc_hir as hir;
 use rustc_infer::traits::util;
 use rustc_middle::ty::GenericArgs;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable};
+use rustc_middle::{bug, span_bug};
 use rustc_span::def_id::{DefId, LocalDefId};
 use rustc_span::Span;
 
@@ -39,7 +40,7 @@ fn associated_type_bounds<'tcx>(
     let bounds_from_parent = trait_predicates.predicates.iter().copied().filter(|(pred, _)| {
         match pred.kind().skip_binder() {
             ty::ClauseKind::Trait(tr) => tr.self_ty() == item_ty,
-            ty::ClauseKind::Projection(proj) => proj.projection_ty.self_ty() == item_ty,
+            ty::ClauseKind::Projection(proj) => proj.projection_term.self_ty() == item_ty,
             ty::ClauseKind::TypeOutlives(outlives) => outlives.0 == item_ty,
             _ => false,
         }
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 7e82571d172..d348d6f789f 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -10,6 +10,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::ty::{GenericPredicates, ImplTraitInTraitData, ToPredicate};
+use rustc_middle::{bug, span_bug};
 use rustc_span::symbol::Ident;
 use rustc_span::{Span, DUMMY_SP};
 
@@ -445,7 +446,9 @@ pub(super) fn explicit_predicates_of<'tcx>(
             .copied()
             .filter(|(pred, _)| match pred.kind().skip_binder() {
                 ty::ClauseKind::Trait(tr) => !is_assoc_item_ty(tr.self_ty()),
-                ty::ClauseKind::Projection(proj) => !is_assoc_item_ty(proj.projection_ty.self_ty()),
+                ty::ClauseKind::Projection(proj) => {
+                    !is_assoc_item_ty(proj.projection_term.self_ty())
+                }
                 ty::ClauseKind::TypeOutlives(outlives) => !is_assoc_item_ty(outlives.0),
                 _ => true,
             })
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index 3ef132a3e8c..5c7733065c6 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -15,11 +15,11 @@ use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirId, HirIdMap, LifetimeName, Node};
 use rustc_macros::extension;
-use rustc_middle::bug;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::resolve_bound_vars::*;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, TyCtxt, TypeSuperVisitable, TypeVisitor};
+use rustc_middle::{bug, span_bug};
 use rustc_span::def_id::DefId;
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::Span;
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 24a5349858a..1475e53c47c 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -7,6 +7,7 @@ use rustc_middle::query::plumbing::CyclePlaceholder;
 use rustc_middle::ty::print::with_forced_trimmed_paths;
 use rustc_middle::ty::util::IntTypeExt;
 use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::{bug, span_bug};
 use rustc_span::symbol::Ident;
 use rustc_span::{Span, DUMMY_SP};
 
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
index b5765913cb8..1bec8c496ad 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
@@ -3,6 +3,7 @@ use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{self as hir, def, Expr, ImplItem, Item, Node, TraitItem};
+use rustc_middle::bug;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
 use rustc_span::{sym, ErrorGuaranteed, DUMMY_SP};
diff --git a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
index 3b8bb0731fb..620170164f5 100644
--- a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
+++ b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
@@ -1,4 +1,5 @@
 use rustc_data_structures::fx::FxHashSet;
+use rustc_middle::bug;
 use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitor};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::Span;
@@ -197,7 +198,7 @@ pub fn setup_constraining_predicates<'tcx>(
                 // Special case: watch out for some kind of sneaky attempt
                 // to project out an associated type defined by this very
                 // trait.
-                let unbound_trait_ref = projection.projection_ty.trait_ref(tcx);
+                let unbound_trait_ref = projection.projection_term.trait_ref(tcx);
                 if Some(unbound_trait_ref) == impl_trait_ref {
                     continue;
                 }
@@ -207,7 +208,7 @@ pub fn setup_constraining_predicates<'tcx>(
                 //     `<<T as Bar>::Baz as Iterator>::Output = <U as Iterator>::Output`
                 // Then the projection only applies if `T` is known, but it still
                 // does not determine `U`.
-                let inputs = parameters_for(tcx, projection.projection_ty, true);
+                let inputs = parameters_for(tcx, projection.projection_term, true);
                 let relies_only_on_inputs = inputs.iter().all(|p| input_parameters.contains(p));
                 if !relies_only_on_inputs {
                     continue;
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
index de12475678c..b0ae73fcc4b 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
@@ -5,6 +5,7 @@ use rustc_errors::{codes::*, struct_span_code_err};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_middle::bug;
 use rustc_middle::ty::print::PrintTraitRefExt as _;
 use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TyCtxt};
 use rustc_span::symbol::Ident;
@@ -326,7 +327,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             })
             .or_insert(binding.span);
 
-        let projection_ty = if let ty::AssocKind::Fn = assoc_kind {
+        let projection_term = if let ty::AssocKind::Fn = assoc_kind {
             let mut emitted_bad_param_err = None;
             // If we have an method return type bound, then we need to instantiate
             // the method's early bound params with suitable late-bound params.
@@ -380,7 +381,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             let output = if let ty::Alias(ty::Projection, alias_ty) = *output.skip_binder().kind()
                 && tcx.is_impl_trait_in_trait(alias_ty.def_id)
             {
-                alias_ty
+                alias_ty.into()
             } else {
                 return Err(tcx.dcx().emit_err(crate::errors::ReturnTypeNotationOnNonRpitit {
                     span: binding.span,
@@ -421,10 +422,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 );
                 debug!(?alias_args);
 
-                // Note that we're indeed also using `AliasTy` (alias *type*) for associated
-                // *constants* to represent *const projections*. Alias *term* would be a more
-                // appropriate name but alas.
-                ty::AliasTy::new(tcx, assoc_item.def_id, alias_args)
+                ty::AliasTerm::new(tcx, assoc_item.def_id, alias_args)
             });
 
             // Provide the resolved type of the associated constant to `type_of(AnonConst)`.
@@ -461,7 +459,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 //     for<'a> <T as Iterator>::Item = &'a str // <-- 'a is bad
                 //     for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok
                 let late_bound_in_projection_ty =
-                    tcx.collect_constrained_late_bound_regions(projection_ty);
+                    tcx.collect_constrained_late_bound_regions(projection_term);
                 let late_bound_in_term =
                     tcx.collect_referenced_late_bound_regions(trait_ref.rebind(term));
                 debug!(?late_bound_in_projection_ty);
@@ -490,8 +488,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
 
                 bounds.push_projection_bound(
                     tcx,
-                    projection_ty
-                        .map_bound(|projection_ty| ty::ProjectionPredicate { projection_ty, term }),
+                    projection_term.map_bound(|projection_term| ty::ProjectionPredicate {
+                        projection_term,
+                        term,
+                    }),
                     binding.span,
                 );
             }
@@ -501,6 +501,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 // NOTE: If `only_self_bounds` is true, do NOT expand this associated type bound into
                 // a trait predicate, since we only want to add predicates for the `Self` type.
                 if !only_self_bounds.0 {
+                    let projection_ty = projection_term
+                        .map_bound(|projection_term| projection_term.expect_ty(self.tcx()));
                     // Calling `skip_binder` is okay, because `lower_bounds` expects the `param_ty`
                     // parameter to have a skipped binder.
                     let param_ty = Ty::new_alias(tcx, ty::Projection, projection_ty.skip_binder());
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
index 38dfa8d57d3..f19492e00b4 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
@@ -16,6 +16,7 @@ use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_infer::traits::FulfillmentError;
+use rustc_middle::bug;
 use rustc_middle::query::Key;
 use rustc_middle::ty::print::PrintTraitRefExt as _;
 use rustc_middle::ty::GenericParamDefKind;
@@ -625,25 +626,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             let bound_predicate = pred.kind();
             match bound_predicate.skip_binder() {
                 ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => {
-                    let pred = bound_predicate.rebind(pred);
                     // `<Foo as Iterator>::Item = String`.
-                    let projection_ty = pred.skip_binder().projection_ty;
+                    let projection_term = pred.projection_term;
+                    let quiet_projection_term =
+                        projection_term.with_self_ty(tcx, Ty::new_var(tcx, ty::TyVid::ZERO));
 
-                    let args_with_infer_self = tcx.mk_args_from_iter(
-                        std::iter::once(Ty::new_var(tcx, ty::TyVid::ZERO).into())
-                            .chain(projection_ty.args.iter().skip(1)),
-                    );
-
-                    let quiet_projection_ty =
-                        ty::AliasTy::new(tcx, projection_ty.def_id, args_with_infer_self);
-
-                    let term = pred.skip_binder().term;
-
-                    let obligation = format!("{projection_ty} = {term}");
-                    let quiet = format!("{quiet_projection_ty} = {term}");
+                    let term = pred.term;
+                    let obligation = format!("{projection_term} = {term}");
+                    let quiet = format!("{quiet_projection_term} = {term}");
 
-                    bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
-                    Some((obligation, projection_ty.self_ty()))
+                    bound_span_label(projection_term.self_ty(), &obligation, &quiet);
+                    Some((obligation, projection_term.self_ty()))
                 }
                 ty::PredicateKind::Clause(ty::ClauseKind::Trait(poly_trait_ref)) => {
                     let p = poly_trait_ref.trait_ref;
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index 591d554d335..d16648b9e8f 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -44,6 +44,7 @@ use rustc_middle::ty::{
     self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, ParamEnv, Ty, TyCtxt,
     TypeVisitableExt,
 };
+use rustc_middle::{bug, span_bug};
 use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
 use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::symbol::{kw, Ident, Symbol};
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs
index 297cfe7027e..30b99a095f3 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs
@@ -6,8 +6,9 @@ use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_lint_defs::builtin::UNUSED_ASSOCIATED_TYPE_BOUNDS;
+use rustc_middle::span_bug;
 use rustc_middle::ty::fold::BottomUpFolder;
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
+use rustc_middle::ty::{self, ExistentialPredicateStableCmpExt as _, Ty, TyCtxt, TypeFoldable};
 use rustc_middle::ty::{DynKind, ToPredicate};
 use rustc_span::{ErrorGuaranteed, Span};
 use rustc_trait_selection::traits::error_reporting::report_object_safety_error;
@@ -280,11 +281,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
 
         let existential_projections = projection_bounds.iter().map(|(bound, _)| {
             bound.map_bound(|mut b| {
-                assert_eq!(b.projection_ty.self_ty(), dummy_self);
+                assert_eq!(b.projection_term.self_ty(), dummy_self);
 
                 // Like for trait refs, verify that `dummy_self` did not leak inside default type
                 // parameters.
-                let references_self = b.projection_ty.args.iter().skip(1).any(|arg| {
+                let references_self = b.projection_term.args.iter().skip(1).any(|arg| {
                     if arg.walk().any(|arg| arg == dummy_self.into()) {
                         return true;
                     }
@@ -294,7 +295,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                     let guar = tcx
                         .dcx()
                         .span_delayed_bug(span, "trait object projection bounds reference `Self`");
-                    b.projection_ty = replace_dummy_self_with_error(tcx, b.projection_ty, guar);
+                    b.projection_term = replace_dummy_self_with_error(tcx, b.projection_term, guar);
                 }
 
                 ty::ExistentialProjection::erase_self_ty(tcx, b)
diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
index d6ba5fa9b5b..10101aa046e 100644
--- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
@@ -4,6 +4,7 @@ use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{ForeignItem, ForeignItemKind};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::{ObligationCause, WellFormedLoc};
+use rustc_middle::bug;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::def_id::LocalDefId;
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
index de697b04ebf..6967cb4d9d0 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
@@ -212,7 +212,7 @@ fn get_impl_args(
             traits::ObligationCause::new(
                 impl1_span,
                 impl1_def_id,
-                traits::ObligationCauseCode::SpannedWhereClause(impl2_node.def_id(), span),
+                traits::ObligationCauseCode::WhereClause(impl2_node.def_id(), span),
             )
         },
     );
@@ -258,23 +258,20 @@ fn unconstrained_parent_impl_args<'tcx>(
     // unconstrained parameters.
     for (clause, _) in impl_generic_predicates.predicates.iter() {
         if let ty::ClauseKind::Projection(proj) = clause.kind().skip_binder() {
-            let projection_ty = proj.projection_ty;
-            let projected_ty = proj.term;
-
-            let unbound_trait_ref = projection_ty.trait_ref(tcx);
+            let unbound_trait_ref = proj.projection_term.trait_ref(tcx);
             if Some(unbound_trait_ref) == impl_trait_ref {
                 continue;
             }
 
-            unconstrained_parameters.extend(cgp::parameters_for(tcx, projection_ty, true));
+            unconstrained_parameters.extend(cgp::parameters_for(tcx, proj.projection_term, true));
 
-            for param in cgp::parameters_for(tcx, projected_ty, false) {
+            for param in cgp::parameters_for(tcx, proj.term, false) {
                 if !unconstrained_parameters.contains(&param) {
                     constrained_params.insert(param.0);
                 }
             }
 
-            unconstrained_parameters.extend(cgp::parameters_for(tcx, projected_ty, true));
+            unconstrained_parameters.extend(cgp::parameters_for(tcx, proj.term, true));
         }
     }
 
@@ -495,11 +492,11 @@ fn check_specialization_on<'tcx>(
                     .emit())
             }
         }
-        ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => Err(tcx
+        ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_term, term }) => Err(tcx
             .dcx()
             .struct_span_err(
                 span,
-                format!("cannot specialize on associated type `{projection_ty} == {term}`",),
+                format!("cannot specialize on associated type `{projection_term} == {term}`",),
             )
             .emit()),
         ty::ClauseKind::ConstArgHasType(..) => {
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index e75740837f8..654ef4baeb3 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -75,9 +75,6 @@ This API is completely unstable and subject to change.
 #[macro_use]
 extern crate tracing;
 
-#[macro_use]
-extern crate rustc_middle;
-
 // These are used by Clippy.
 pub mod check;
 
diff --git a/compiler/rustc_hir_analysis/src/outlives/test.rs b/compiler/rustc_hir_analysis/src/outlives/test.rs
index 60cd8c39fa0..e9b6c679bd5 100644
--- a/compiler/rustc_hir_analysis/src/outlives/test.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/test.rs
@@ -1,3 +1,4 @@
+use rustc_middle::bug;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::{symbol::sym, ErrorGuaranteed};
 
diff --git a/compiler/rustc_hir_analysis/src/outlives/utils.rs b/compiler/rustc_hir_analysis/src/outlives/utils.rs
index d3bb22d715d..95290bbecf2 100644
--- a/compiler/rustc_hir_analysis/src/outlives/utils.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/utils.rs
@@ -2,6 +2,7 @@ use rustc_data_structures::fx::FxIndexMap;
 use rustc_infer::infer::outlives::components::{push_outlives_components, Component};
 use rustc_middle::ty::{self, Region, Ty, TyCtxt};
 use rustc_middle::ty::{GenericArg, GenericArgKind};
+use rustc_middle::{bug, span_bug};
 use rustc_span::Span;
 use smallvec::smallvec;
 
diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs
index eeb8b028505..730e989edae 100644
--- a/compiler/rustc_hir_analysis/src/variance/constraints.rs
+++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs
@@ -8,6 +8,7 @@ use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::ty::{GenericArgKind, GenericArgsRef};
+use rustc_middle::{bug, span_bug};
 
 use super::terms::VarianceTerm::*;
 use super::terms::*;
diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index 27fdea01c2b..cefd8fb1ac5 100644
--- a/compiler/rustc_hir_analysis/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
@@ -8,6 +8,7 @@ use rustc_arena::DroplessArena;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::query::Providers;
+use rustc_middle::span_bug;
 use rustc_middle::ty::{self, CrateVariancesMap, GenericArgsRef, Ty, TyCtxt};
 use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable};
 
@@ -166,7 +167,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
                 }
             }
             ty::ClauseKind::Projection(ty::ProjectionPredicate {
-                projection_ty: ty::AliasTy { args, .. },
+                projection_term: ty::AliasTerm { args, .. },
                 term,
             }) => {
                 for arg in &args[1..] {
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 4f5fbd024a9..a47e6af0bf2 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -139,8 +139,12 @@ impl std::ops::DerefMut for State<'_> {
 }
 
 impl<'a> PrintState<'a> for State<'a> {
-    fn comments(&mut self) -> &mut Option<Comments<'a>> {
-        &mut self.comments
+    fn comments(&self) -> Option<&Comments<'a>> {
+        self.comments.as_ref()
+    }
+
+    fn comments_mut(&mut self) -> Option<&mut Comments<'a>> {
+        self.comments.as_mut()
     }
 
     fn ann_post(&mut self, ident: Ident) {
diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl
index 0560d0d902a..72b95a9603d 100644
--- a/compiler/rustc_hir_typeck/messages.ftl
+++ b/compiler/rustc_hir_typeck/messages.ftl
@@ -46,10 +46,6 @@ hir_typeck_ctor_is_private = tuple struct constructor `{$def}` is private
 
 hir_typeck_deref_is_empty = this expression `Deref`s to `{$deref_ty}` which implements `is_empty`
 
-hir_typeck_dereferencing_mut_binding = dereferencing `mut` binding
-    .label = `mut` dereferences the type of this binding
-    .help = this will change in edition 2024
-
 hir_typeck_expected_default_return_type = expected `()` because of default return type
 
 hir_typeck_expected_return_type = expected `{$expected}` because of return type
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index defb557867b..502a176845e 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -19,6 +19,7 @@ use rustc_middle::ty::adjustment::{
 };
 use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::{bug, span_bug};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::Span;
@@ -574,7 +575,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             self.misc(span),
                             self.param_env,
                             ty::ProjectionPredicate {
-                                projection_ty: ty::AliasTy::new(
+                                projection_term: ty::AliasTerm::new(
                                     self.tcx,
                                     fn_once_output_def_id,
                                     [arg_ty.into(), fn_sig.inputs()[0].into(), const_param],
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index 92f74281ab9..9e9a1f678ed 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -36,6 +36,7 @@ use hir::ExprKind;
 use rustc_errors::{codes::*, Applicability, Diag, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_macros::{TypeFoldable, TypeVisitable};
+use rustc_middle::bug;
 use rustc_middle::mir::Mutability;
 use rustc_middle::ty::adjustment::AllowTwoPhase;
 use rustc_middle::ty::cast::{CastKind, CastTy};
@@ -140,7 +141,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             | ty::Never
             | ty::Dynamic(_, _, ty::DynStar)
             | ty::Error(_) => {
-                self.dcx().span_bug(span, format!("`{t:?}` should be sized but is not?"));
+                let guar = self
+                    .dcx()
+                    .span_delayed_bug(span, format!("`{t:?}` should be sized but is not?"));
+                return Err(guar);
             }
         })
     }
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index f52f95db6d3..aca069d8fb5 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -10,6 +10,7 @@ use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes};
 use rustc_infer::infer::{InferOk, InferResult};
 use rustc_infer::traits::ObligationCauseCode;
 use rustc_macros::{TypeFoldable, TypeVisitable};
+use rustc_middle::span_bug;
 use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
 use rustc_middle::ty::GenericArgs;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor};
@@ -414,7 +415,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // many viable options, so pick the most restrictive.
             let trait_def_id = match bound_predicate.skip_binder() {
                 ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => {
-                    Some(data.projection_ty.trait_def_id(self.tcx))
+                    Some(data.projection_term.trait_def_id(self.tcx))
                 }
                 ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => Some(data.def_id()),
                 _ => None,
@@ -475,7 +476,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             _ => return None,
         }
 
-        let arg_param_ty = projection.skip_binder().projection_ty.args.type_at(1);
+        let arg_param_ty = projection.skip_binder().projection_term.args.type_at(1);
         let arg_param_ty = self.resolve_vars_if_possible(arg_param_ty);
         debug!(?arg_param_ty);
 
@@ -930,7 +931,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
 
         // Check that this is a projection from the `Future` trait.
-        let trait_def_id = predicate.projection_ty.trait_def_id(self.tcx);
+        let trait_def_id = predicate.projection_term.trait_def_id(self.tcx);
         let future_trait = self.tcx.require_lang_item(LangItem::Future, Some(cause_span));
         if trait_def_id != future_trait {
             debug!("deduce_future_output_from_projection: not a future");
@@ -940,11 +941,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // The `Future` trait has only one associated item, `Output`,
         // so check that this is what we see.
         let output_assoc_item = self.tcx.associated_item_def_ids(future_trait)[0];
-        if output_assoc_item != predicate.projection_ty.def_id {
+        if output_assoc_item != predicate.projection_term.def_id {
             span_bug!(
                 cause_span,
                 "projecting associated item `{:?}` from future, which is not Output `{:?}`",
-                predicate.projection_ty.def_id,
+                predicate.projection_term.def_id,
                 output_assoc_item,
             );
         }
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 88ba937e4b5..8d93f402f10 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -45,6 +45,7 @@ use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult};
 use rustc_infer::traits::{IfExpressionCause, MatchExpressionArmCause};
 use rustc_infer::traits::{Obligation, PredicateObligation};
 use rustc_middle::lint::in_external_macro;
+use rustc_middle::span_bug;
 use rustc_middle::traits::BuiltinImplSource;
 use rustc_middle::ty::adjustment::{
     Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCoercion,
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index b2112491733..706f6f875bf 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -5,6 +5,7 @@ use rustc_hir as hir;
 use rustc_hir::def::Res;
 use rustc_hir::intravisit::Visitor;
 use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
+use rustc_middle::bug;
 use rustc_middle::ty::adjustment::AllowTwoPhase;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::fold::BottomUpFolder;
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index ba8f246fd8d..f250b909596 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -651,10 +651,3 @@ pub enum SuggestBoxingForReturnImplTrait {
         ends: Vec<Span>,
     },
 }
-#[derive(LintDiagnostic)]
-#[diag(hir_typeck_dereferencing_mut_binding)]
-pub struct DereferencingMutBinding {
-    #[label]
-    #[help]
-    pub span: Span,
-}
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index cdf17f3a113..f283c013805 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -45,6 +45,7 @@ use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase};
 use rustc_middle::ty::error::{ExpectedFound, TypeError::Sorts};
 use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, AdtKind, Ty, TypeVisitableExt};
+use rustc_middle::{bug, span_bug};
 use rustc_session::errors::ExprParenthesesNeeded;
 use rustc_session::parse::feature_err;
 use rustc_span::edit_distance::find_best_match_for_name;
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index cc42e69f538..1864c7e6ef8 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -2,26 +2,34 @@
 //! normal visitor, which just walks the entire body in one shot, the
 //! `ExprUseVisitor` determines how expressions are being used.
 
+use std::cell::{Ref, RefCell};
+use std::ops::Deref;
 use std::slice::from_ref;
 
 use hir::def::DefKind;
+use hir::pat_util::EnumerateAndAdjustIterator as _;
 use hir::Expr;
+use rustc_lint::LateContext;
 // Export these here so that Clippy can use them.
 pub use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection};
 
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_hir as hir;
-use rustc_hir::def::Res;
+use rustc_hir::def::{CtorOf, Res};
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::{HirId, PatKind};
-use rustc_infer::infer::InferCtxt;
+use rustc_middle::{bug, span_bug};
 use rustc_middle::hir::place::ProjectionKind;
 use rustc_middle::mir::FakeReadCause;
-use rustc_middle::ty::{self, adjustment, AdtKind, Ty, TyCtxt};
-use rustc_target::abi::FIRST_VARIANT;
+use rustc_middle::ty::{
+    self, adjustment, AdtKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt as _,
+};
+use rustc_span::{ErrorGuaranteed, Span};
+use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
+use rustc_trait_selection::infer::InferCtxtExt;
 use ty::BorrowKind::ImmBorrow;
 
-use crate::mem_categorization as mc;
+use crate::fn_ctxt::FnCtxt;
 
 /// This trait defines the callbacks you can expect to receive when
 /// employing the ExprUseVisitor.
@@ -80,191 +88,322 @@ pub trait Delegate<'tcx> {
     );
 }
 
-#[derive(Copy, Clone, PartialEq, Debug)]
-enum ConsumeMode {
-    /// reference to x where x has a type that copies
-    Copy,
-    /// reference to x where x has a type that moves
-    Move,
+impl<'tcx, D: Delegate<'tcx>> Delegate<'tcx> for &mut D {
+    fn consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
+        (**self).consume(place_with_id, diag_expr_id)
+    }
+
+    fn borrow(
+        &mut self,
+        place_with_id: &PlaceWithHirId<'tcx>,
+        diag_expr_id: HirId,
+        bk: ty::BorrowKind,
+    ) {
+        (**self).borrow(place_with_id, diag_expr_id, bk)
+    }
+
+    fn copy(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
+        (**self).copy(place_with_id, diag_expr_id)
+    }
+
+    fn mutate(&mut self, assignee_place: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
+        (**self).mutate(assignee_place, diag_expr_id)
+    }
+
+    fn bind(&mut self, binding_place: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
+        (**self).bind(binding_place, diag_expr_id)
+    }
+
+    fn fake_read(
+        &mut self,
+        place_with_id: &PlaceWithHirId<'tcx>,
+        cause: FakeReadCause,
+        diag_expr_id: HirId,
+    ) {
+        (**self).fake_read(place_with_id, cause, diag_expr_id)
+    }
+}
+
+pub trait TypeInformationCtxt<'tcx> {
+    type TypeckResults<'a>: Deref<Target = ty::TypeckResults<'tcx>>
+    where
+        Self: 'a;
+
+    type Error;
+
+    fn typeck_results(&self) -> Self::TypeckResults<'_>;
+
+    fn resolve_vars_if_possible<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> T;
+
+    fn try_structurally_resolve_type(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx>;
+
+    fn report_error(&self, span: Span, msg: impl ToString) -> Self::Error;
+
+    fn error_reported_in_ty(&self, ty: Ty<'tcx>) -> Result<(), Self::Error>;
+
+    fn tainted_by_errors(&self) -> Result<(), Self::Error>;
+
+    fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>) -> bool;
+
+    fn body_owner_def_id(&self) -> LocalDefId;
+
+    fn tcx(&self) -> TyCtxt<'tcx>;
+}
+
+impl<'tcx> TypeInformationCtxt<'tcx> for &FnCtxt<'_, 'tcx> {
+    type TypeckResults<'a> = Ref<'a, ty::TypeckResults<'tcx>>
+    where
+        Self: 'a;
+
+    type Error = ErrorGuaranteed;
+
+    fn typeck_results(&self) -> Self::TypeckResults<'_> {
+        self.typeck_results.borrow()
+    }
+
+    fn resolve_vars_if_possible<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> T {
+        self.infcx.resolve_vars_if_possible(t)
+    }
+
+    fn try_structurally_resolve_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
+        (**self).try_structurally_resolve_type(sp, ty)
+    }
+
+    fn report_error(&self, span: Span, msg: impl ToString) -> Self::Error {
+        self.tcx.dcx().span_delayed_bug(span, msg.to_string())
+    }
+
+    fn error_reported_in_ty(&self, ty: Ty<'tcx>) -> Result<(), Self::Error> {
+        ty.error_reported()
+    }
+
+    fn tainted_by_errors(&self) -> Result<(), ErrorGuaranteed> {
+        if let Some(guar) = self.infcx.tainted_by_errors() { Err(guar) } else { Ok(()) }
+    }
+
+    fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>) -> bool {
+        self.infcx.type_is_copy_modulo_regions(self.param_env, ty)
+    }
+
+    fn body_owner_def_id(&self) -> LocalDefId {
+        self.body_id
+    }
+
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+}
+
+impl<'tcx> TypeInformationCtxt<'tcx> for (&LateContext<'tcx>, LocalDefId) {
+    type TypeckResults<'a> = &'tcx ty::TypeckResults<'tcx>
+    where
+        Self: 'a;
+
+    type Error = !;
+
+    fn typeck_results(&self) -> Self::TypeckResults<'_> {
+        self.0.maybe_typeck_results().expect("expected typeck results")
+    }
+
+    fn try_structurally_resolve_type(&self, _span: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
+        // FIXME: Maybe need to normalize here.
+        ty
+    }
+
+    fn resolve_vars_if_possible<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> T {
+        t
+    }
+
+    fn report_error(&self, span: Span, msg: impl ToString) -> ! {
+        span_bug!(span, "{}", msg.to_string())
+    }
+
+    fn error_reported_in_ty(&self, _ty: Ty<'tcx>) -> Result<(), !> {
+        Ok(())
+    }
+
+    fn tainted_by_errors(&self) -> Result<(), !> {
+        Ok(())
+    }
+
+    fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>) -> bool {
+        ty.is_copy_modulo_regions(self.0.tcx, self.0.param_env)
+    }
+
+    fn body_owner_def_id(&self) -> LocalDefId {
+        self.1
+    }
+
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        self.0.tcx
+    }
 }
 
 /// The ExprUseVisitor type
 ///
 /// This is the code that actually walks the tree.
-pub struct ExprUseVisitor<'a, 'tcx> {
-    mc: mc::MemCategorizationContext<'a, 'tcx>,
-    body_owner: LocalDefId,
-    delegate: &'a mut dyn Delegate<'tcx>,
+pub struct ExprUseVisitor<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> {
+    cx: Cx,
+    /// We use a `RefCell` here so that delegates can mutate themselves, but we can
+    /// still have calls to our own helper functions.
+    delegate: RefCell<D>,
+    upvars: Option<&'tcx FxIndexMap<HirId, hir::Upvar>>,
 }
 
-/// If the MC results in an error, it's because the type check
-/// failed (or will fail, when the error is uncovered and reported
-/// during writeback). In this case, we just ignore this part of the
-/// code.
-///
-/// Note that this macro appears similar to try!(), but, unlike try!(),
-/// it does not propagate the error.
-macro_rules! return_if_err {
-    ($inp: expr) => {
-        match $inp {
-            Ok(v) => v,
-            Err(()) => {
-                debug!("mc reported err");
-                return;
-            }
-        }
-    };
+impl<'a, 'tcx, D: Delegate<'tcx>> ExprUseVisitor<'tcx, (&'a LateContext<'tcx>, LocalDefId), D> {
+    pub fn for_clippy(cx: &'a LateContext<'tcx>, body_def_id: LocalDefId, delegate: D) -> Self {
+        Self::new((cx, body_def_id), delegate)
+    }
 }
 
-impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
+impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx, Cx, D> {
     /// Creates the ExprUseVisitor, configuring it with the various options provided:
     ///
     /// - `delegate` -- who receives the callbacks
     /// - `param_env` --- parameter environment for trait lookups (esp. pertaining to `Copy`)
     /// - `typeck_results` --- typeck results for the code being analyzed
-    pub fn new(
-        delegate: &'a mut (dyn Delegate<'tcx> + 'a),
-        infcx: &'a InferCtxt<'tcx>,
-        body_owner: LocalDefId,
-        param_env: ty::ParamEnv<'tcx>,
-        typeck_results: &'a ty::TypeckResults<'tcx>,
-    ) -> Self {
+    pub(crate) fn new(cx: Cx, delegate: D) -> Self {
         ExprUseVisitor {
-            mc: mc::MemCategorizationContext::new(infcx, param_env, body_owner, typeck_results),
-            body_owner,
-            delegate,
+            delegate: RefCell::new(delegate),
+            upvars: cx.tcx().upvars_mentioned(cx.body_owner_def_id()),
+            cx,
         }
     }
 
-    #[instrument(skip(self), level = "debug")]
-    pub fn consume_body(&mut self, body: &hir::Body<'_>) {
+    pub fn consume_body(&self, body: &hir::Body<'_>) -> Result<(), Cx::Error> {
         for param in body.params {
-            let param_ty = return_if_err!(self.mc.pat_ty_adjusted(param.pat));
+            let param_ty = self.pat_ty_adjusted(param.pat)?;
             debug!("consume_body: param_ty = {:?}", param_ty);
 
-            let param_place = self.mc.cat_rvalue(param.hir_id, param_ty);
+            let param_place = self.cat_rvalue(param.hir_id, param_ty);
 
-            self.walk_irrefutable_pat(&param_place, param.pat);
+            self.walk_irrefutable_pat(&param_place, param.pat)?;
         }
 
-        self.consume_expr(body.value);
-    }
+        self.consume_expr(body.value)?;
 
-    fn tcx(&self) -> TyCtxt<'tcx> {
-        self.mc.tcx()
+        Ok(())
     }
 
-    fn delegate_consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
-        delegate_consume(&self.mc, self.delegate, place_with_id, diag_expr_id)
+    fn consume_or_copy(&self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
+        debug!("delegate_consume(place_with_id={:?})", place_with_id);
+
+        if self.cx.type_is_copy_modulo_regions(place_with_id.place.ty()) {
+            self.delegate.borrow_mut().copy(place_with_id, diag_expr_id);
+        } else {
+            self.delegate.borrow_mut().consume(place_with_id, diag_expr_id);
+        }
     }
 
-    fn consume_exprs(&mut self, exprs: &[hir::Expr<'_>]) {
+    fn consume_exprs(&self, exprs: &[hir::Expr<'_>]) -> Result<(), Cx::Error> {
         for expr in exprs {
-            self.consume_expr(expr);
+            self.consume_expr(expr)?;
         }
+
+        Ok(())
     }
 
-    pub fn consume_expr(&mut self, expr: &hir::Expr<'_>) {
+    // FIXME: It's suspicious that this is public; clippy should probably use `walk_expr`.
+    pub fn consume_expr(&self, expr: &hir::Expr<'_>) -> Result<(), Cx::Error> {
         debug!("consume_expr(expr={:?})", expr);
 
-        let place_with_id = return_if_err!(self.mc.cat_expr(expr));
-        self.delegate_consume(&place_with_id, place_with_id.hir_id);
-        self.walk_expr(expr);
+        let place_with_id = self.cat_expr(expr)?;
+        self.consume_or_copy(&place_with_id, place_with_id.hir_id);
+        self.walk_expr(expr)?;
+        Ok(())
     }
 
-    fn mutate_expr(&mut self, expr: &hir::Expr<'_>) {
-        let place_with_id = return_if_err!(self.mc.cat_expr(expr));
-        self.delegate.mutate(&place_with_id, place_with_id.hir_id);
-        self.walk_expr(expr);
+    fn mutate_expr(&self, expr: &hir::Expr<'_>) -> Result<(), Cx::Error> {
+        let place_with_id = self.cat_expr(expr)?;
+        self.delegate.borrow_mut().mutate(&place_with_id, place_with_id.hir_id);
+        self.walk_expr(expr)?;
+        Ok(())
     }
 
-    fn borrow_expr(&mut self, expr: &hir::Expr<'_>, bk: ty::BorrowKind) {
+    fn borrow_expr(&self, expr: &hir::Expr<'_>, bk: ty::BorrowKind) -> Result<(), Cx::Error> {
         debug!("borrow_expr(expr={:?}, bk={:?})", expr, bk);
 
-        let place_with_id = return_if_err!(self.mc.cat_expr(expr));
-        self.delegate.borrow(&place_with_id, place_with_id.hir_id, bk);
-
-        self.walk_expr(expr)
-    }
-
-    fn select_from_expr(&mut self, expr: &hir::Expr<'_>) {
+        let place_with_id = self.cat_expr(expr)?;
+        self.delegate.borrow_mut().borrow(&place_with_id, place_with_id.hir_id, bk);
         self.walk_expr(expr)
     }
 
-    pub fn walk_expr(&mut self, expr: &hir::Expr<'_>) {
+    pub fn walk_expr(&self, expr: &hir::Expr<'_>) -> Result<(), Cx::Error> {
         debug!("walk_expr(expr={:?})", expr);
 
-        self.walk_adjustment(expr);
+        self.walk_adjustment(expr)?;
 
         match expr.kind {
             hir::ExprKind::Path(_) => {}
 
-            hir::ExprKind::Type(subexpr, _) => self.walk_expr(subexpr),
+            hir::ExprKind::Type(subexpr, _) => {
+                self.walk_expr(subexpr)?;
+            }
 
             hir::ExprKind::Unary(hir::UnOp::Deref, base) => {
                 // *base
-                self.select_from_expr(base);
+                self.walk_expr(base)?;
             }
 
             hir::ExprKind::Field(base, _) => {
                 // base.f
-                self.select_from_expr(base);
+                self.walk_expr(base)?;
             }
 
             hir::ExprKind::Index(lhs, rhs, _) => {
                 // lhs[rhs]
-                self.select_from_expr(lhs);
-                self.consume_expr(rhs);
+                self.walk_expr(lhs)?;
+                self.consume_expr(rhs)?;
             }
 
             hir::ExprKind::Call(callee, args) => {
                 // callee(args)
-                self.consume_expr(callee);
-                self.consume_exprs(args);
+                self.consume_expr(callee)?;
+                self.consume_exprs(args)?;
             }
 
             hir::ExprKind::MethodCall(.., receiver, args, _) => {
                 // callee.m(args)
-                self.consume_expr(receiver);
-                self.consume_exprs(args);
+                self.consume_expr(receiver)?;
+                self.consume_exprs(args)?;
             }
 
             hir::ExprKind::Struct(_, fields, ref opt_with) => {
-                self.walk_struct_expr(fields, opt_with);
+                self.walk_struct_expr(fields, opt_with)?;
             }
 
             hir::ExprKind::Tup(exprs) => {
-                self.consume_exprs(exprs);
+                self.consume_exprs(exprs)?;
             }
 
             hir::ExprKind::If(cond_expr, then_expr, ref opt_else_expr) => {
-                self.consume_expr(cond_expr);
-                self.consume_expr(then_expr);
+                self.consume_expr(cond_expr)?;
+                self.consume_expr(then_expr)?;
                 if let Some(else_expr) = *opt_else_expr {
-                    self.consume_expr(else_expr);
+                    self.consume_expr(else_expr)?;
                 }
             }
 
             hir::ExprKind::Let(hir::LetExpr { pat, init, .. }) => {
-                self.walk_local(init, pat, None, |t| t.borrow_expr(init, ty::ImmBorrow))
+                self.walk_local(init, pat, None, || self.borrow_expr(init, ty::ImmBorrow))?;
             }
 
             hir::ExprKind::Match(discr, arms, _) => {
-                let discr_place = return_if_err!(self.mc.cat_expr(discr));
-                return_if_err!(self.maybe_read_scrutinee(
+                let discr_place = self.cat_expr(discr)?;
+                self.maybe_read_scrutinee(
                     discr,
                     discr_place.clone(),
                     arms.iter().map(|arm| arm.pat),
-                ));
+                )?;
 
                 // treatment of the discriminant is handled while walking the arms.
                 for arm in arms {
-                    self.walk_arm(&discr_place, arm);
+                    self.walk_arm(&discr_place, arm)?;
                 }
             }
 
             hir::ExprKind::Array(exprs) => {
-                self.consume_exprs(exprs);
+                self.consume_exprs(exprs)?;
             }
 
             hir::ExprKind::AddrOf(_, m, base) => {
@@ -272,21 +411,23 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
                 // make sure that the thing we are pointing out stays valid
                 // for the lifetime `scope_r` of the resulting ptr:
                 let bk = ty::BorrowKind::from_mutbl(m);
-                self.borrow_expr(base, bk);
+                self.borrow_expr(base, bk)?;
             }
 
             hir::ExprKind::InlineAsm(asm) => {
                 for (op, _op_sp) in asm.operands {
                     match op {
-                        hir::InlineAsmOperand::In { expr, .. } => self.consume_expr(expr),
+                        hir::InlineAsmOperand::In { expr, .. } => {
+                            self.consume_expr(expr)?;
+                        }
                         hir::InlineAsmOperand::Out { expr: Some(expr), .. }
                         | hir::InlineAsmOperand::InOut { expr, .. } => {
-                            self.mutate_expr(expr);
+                            self.mutate_expr(expr)?;
                         }
                         hir::InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
-                            self.consume_expr(in_expr);
+                            self.consume_expr(in_expr)?;
                             if let Some(out_expr) = out_expr {
-                                self.mutate_expr(out_expr);
+                                self.mutate_expr(out_expr)?;
                             }
                         }
                         hir::InlineAsmOperand::Out { expr: None, .. }
@@ -294,7 +435,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
                         | hir::InlineAsmOperand::SymFn { .. }
                         | hir::InlineAsmOperand::SymStatic { .. } => {}
                         hir::InlineAsmOperand::Label { block } => {
-                            self.walk_block(block);
+                            self.walk_block(block)?;
                         }
                     }
                 }
@@ -307,72 +448,74 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
             | hir::ExprKind::Err(_) => {}
 
             hir::ExprKind::Loop(blk, ..) => {
-                self.walk_block(blk);
+                self.walk_block(blk)?;
             }
 
             hir::ExprKind::Unary(_, lhs) => {
-                self.consume_expr(lhs);
+                self.consume_expr(lhs)?;
             }
 
             hir::ExprKind::Binary(_, lhs, rhs) => {
-                self.consume_expr(lhs);
-                self.consume_expr(rhs);
+                self.consume_expr(lhs)?;
+                self.consume_expr(rhs)?;
             }
 
             hir::ExprKind::Block(blk, _) => {
-                self.walk_block(blk);
+                self.walk_block(blk)?;
             }
 
             hir::ExprKind::Break(_, ref opt_expr) | hir::ExprKind::Ret(ref opt_expr) => {
                 if let Some(expr) = *opt_expr {
-                    self.consume_expr(expr);
+                    self.consume_expr(expr)?;
                 }
             }
 
             hir::ExprKind::Become(call) => {
-                self.consume_expr(call);
+                self.consume_expr(call)?;
             }
 
             hir::ExprKind::Assign(lhs, rhs, _) => {
-                self.mutate_expr(lhs);
-                self.consume_expr(rhs);
+                self.mutate_expr(lhs)?;
+                self.consume_expr(rhs)?;
             }
 
             hir::ExprKind::Cast(base, _) => {
-                self.consume_expr(base);
+                self.consume_expr(base)?;
             }
 
             hir::ExprKind::DropTemps(expr) => {
-                self.consume_expr(expr);
+                self.consume_expr(expr)?;
             }
 
             hir::ExprKind::AssignOp(_, lhs, rhs) => {
-                if self.mc.typeck_results.is_method_call(expr) {
-                    self.consume_expr(lhs);
+                if self.cx.typeck_results().is_method_call(expr) {
+                    self.consume_expr(lhs)?;
                 } else {
-                    self.mutate_expr(lhs);
+                    self.mutate_expr(lhs)?;
                 }
-                self.consume_expr(rhs);
+                self.consume_expr(rhs)?;
             }
 
             hir::ExprKind::Repeat(base, _) => {
-                self.consume_expr(base);
+                self.consume_expr(base)?;
             }
 
             hir::ExprKind::Closure(closure) => {
-                self.walk_captures(closure);
+                self.walk_captures(closure)?;
             }
 
             hir::ExprKind::Yield(value, _) => {
-                self.consume_expr(value);
+                self.consume_expr(value)?;
             }
         }
+
+        Ok(())
     }
 
-    fn walk_stmt(&mut self, stmt: &hir::Stmt<'_>) {
+    fn walk_stmt(&self, stmt: &hir::Stmt<'_>) -> Result<(), Cx::Error> {
         match stmt.kind {
             hir::StmtKind::Let(hir::LetStmt { pat, init: Some(expr), els, .. }) => {
-                self.walk_local(expr, pat, *els, |_| {})
+                self.walk_local(expr, pat, *els, || Ok(()))?;
             }
 
             hir::StmtKind::Let(_) => {}
@@ -383,25 +526,26 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
             }
 
             hir::StmtKind::Expr(expr) | hir::StmtKind::Semi(expr) => {
-                self.consume_expr(expr);
+                self.consume_expr(expr)?;
             }
         }
+
+        Ok(())
     }
 
     fn maybe_read_scrutinee<'t>(
-        &mut self,
+        &self,
         discr: &Expr<'_>,
         discr_place: PlaceWithHirId<'tcx>,
         pats: impl Iterator<Item = &'t hir::Pat<'t>>,
-    ) -> Result<(), ()> {
+    ) -> Result<(), Cx::Error> {
         // Matching should not always be considered a use of the place, hence
         // discr does not necessarily need to be borrowed.
         // We only want to borrow discr if the pattern contain something other
         // than wildcards.
-        let ExprUseVisitor { ref mc, body_owner: _, delegate: _ } = *self;
         let mut needs_to_be_read = false;
         for pat in pats {
-            mc.cat_pattern(discr_place.clone(), pat, |place, pat| {
+            self.cat_pattern(discr_place.clone(), pat, &mut |place, pat| {
                 match &pat.kind {
                     PatKind::Binding(.., opt_sub_pat) => {
                         // If the opt_sub_pat is None, then the binding does not count as
@@ -419,7 +563,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
                         // A `Path` pattern is just a name like `Foo`. This is either a
                         // named constant or else it refers to an ADT variant
 
-                        let res = self.mc.typeck_results.qpath_res(qpath, pat.hir_id);
+                        let res = self.cx.typeck_results().qpath_res(qpath, pat.hir_id);
                         match res {
                             Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssocConst, _) => {
                                 // Named constants have to be equated with the value
@@ -431,7 +575,8 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
                             _ => {
                                 // Otherwise, this is a struct/enum variant, and so it's
                                 // only a read if we need to read the discriminant.
-                                needs_to_be_read |= is_multivariant_adt(place.place.ty());
+                                needs_to_be_read |=
+                                    self.is_multivariant_adt(place.place.ty(), pat.span);
                             }
                         }
                     }
@@ -443,7 +588,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
                         // perform some reads).
 
                         let place_ty = place.place.ty();
-                        needs_to_be_read |= is_multivariant_adt(place_ty);
+                        needs_to_be_read |= self.is_multivariant_adt(place_ty, pat.span);
                     }
                     PatKind::Lit(_) | PatKind::Range(..) => {
                         // If the PatKind is a Lit or a Range then we want
@@ -473,18 +618,20 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
                         // being examined
                     }
                 }
+
+                Ok(())
             })?
         }
 
         if needs_to_be_read {
-            self.borrow_expr(discr, ty::ImmBorrow);
+            self.borrow_expr(discr, ty::ImmBorrow)?;
         } else {
             let closure_def_id = match discr_place.place.base {
                 PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id),
                 _ => None,
             };
 
-            self.delegate.fake_read(
+            self.delegate.borrow_mut().fake_read(
                 &discr_place,
                 FakeReadCause::ForMatchedPlace(closure_def_id),
                 discr_place.hir_id,
@@ -492,90 +639,93 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
 
             // We always want to walk the discriminant. We want to make sure, for instance,
             // that the discriminant has been initialized.
-            self.walk_expr(discr);
+            self.walk_expr(discr)?;
         }
         Ok(())
     }
 
     fn walk_local<F>(
-        &mut self,
+        &self,
         expr: &hir::Expr<'_>,
         pat: &hir::Pat<'_>,
         els: Option<&hir::Block<'_>>,
         mut f: F,
-    ) where
-        F: FnMut(&mut Self),
+    ) -> Result<(), Cx::Error>
+    where
+        F: FnMut() -> Result<(), Cx::Error>,
     {
-        self.walk_expr(expr);
-        let expr_place = return_if_err!(self.mc.cat_expr(expr));
-        f(self);
+        self.walk_expr(expr)?;
+        let expr_place = self.cat_expr(expr)?;
+        f()?;
         if let Some(els) = els {
             // borrowing because we need to test the discriminant
-            return_if_err!(self.maybe_read_scrutinee(
-                expr,
-                expr_place.clone(),
-                from_ref(pat).iter()
-            ));
-            self.walk_block(els)
+            self.maybe_read_scrutinee(expr, expr_place.clone(), from_ref(pat).iter())?;
+            self.walk_block(els)?;
         }
-        self.walk_irrefutable_pat(&expr_place, pat);
+        self.walk_irrefutable_pat(&expr_place, pat)?;
+        Ok(())
     }
 
     /// Indicates that the value of `blk` will be consumed, meaning either copied or moved
     /// depending on its type.
-    fn walk_block(&mut self, blk: &hir::Block<'_>) {
+    fn walk_block(&self, blk: &hir::Block<'_>) -> Result<(), Cx::Error> {
         debug!("walk_block(blk.hir_id={})", blk.hir_id);
 
         for stmt in blk.stmts {
-            self.walk_stmt(stmt);
+            self.walk_stmt(stmt)?;
         }
 
         if let Some(tail_expr) = blk.expr {
-            self.consume_expr(tail_expr);
+            self.consume_expr(tail_expr)?;
         }
+
+        Ok(())
     }
 
     fn walk_struct_expr<'hir>(
-        &mut self,
+        &self,
         fields: &[hir::ExprField<'_>],
         opt_with: &Option<&'hir hir::Expr<'_>>,
-    ) {
+    ) -> Result<(), Cx::Error> {
         // Consume the expressions supplying values for each field.
         for field in fields {
-            self.consume_expr(field.expr);
+            self.consume_expr(field.expr)?;
 
             // The struct path probably didn't resolve
-            if self.mc.typeck_results.opt_field_index(field.hir_id).is_none() {
-                self.tcx().dcx().span_delayed_bug(field.span, "couldn't resolve index for field");
+            if self.cx.typeck_results().opt_field_index(field.hir_id).is_none() {
+                self.cx
+                    .tcx()
+                    .dcx()
+                    .span_delayed_bug(field.span, "couldn't resolve index for field");
             }
         }
 
         let with_expr = match *opt_with {
             Some(w) => &*w,
             None => {
-                return;
+                return Ok(());
             }
         };
 
-        let with_place = return_if_err!(self.mc.cat_expr(with_expr));
+        let with_place = self.cat_expr(with_expr)?;
 
         // Select just those fields of the `with`
         // expression that will actually be used
-        match with_place.place.ty().kind() {
+        match self.cx.try_structurally_resolve_type(with_expr.span, with_place.place.ty()).kind() {
             ty::Adt(adt, args) if adt.is_struct() => {
                 // Consume those fields of the with expression that are needed.
                 for (f_index, with_field) in adt.non_enum_variant().fields.iter_enumerated() {
-                    let is_mentioned = fields
-                        .iter()
-                        .any(|f| self.mc.typeck_results.opt_field_index(f.hir_id) == Some(f_index));
+                    let is_mentioned = fields.iter().any(|f| {
+                        self.cx.typeck_results().opt_field_index(f.hir_id) == Some(f_index)
+                    });
                     if !is_mentioned {
-                        let field_place = self.mc.cat_projection(
-                            &*with_expr,
+                        let field_place = self.cat_projection(
+                            with_expr.hir_id,
                             with_place.clone(),
-                            with_field.ty(self.tcx(), args),
+                            with_field.ty(self.cx.tcx(), args),
                             ProjectionKind::Field(f_index, FIRST_VARIANT),
                         );
-                        self.delegate_consume(&field_place, field_place.hir_id);
+                        self.consume_or_copy(&field_place, field_place.hir_id);
                     }
                 }
             }
@@ -584,7 +734,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
                 // struct; however, when EUV is run during typeck, it
                 // may not. This will generate an error earlier in typeck,
                 // so we can just ignore it.
-                if self.tcx().dcx().has_errors().is_none() {
+                if self.cx.tcx().dcx().has_errors().is_none() {
                     span_bug!(with_expr.span, "with expression doesn't evaluate to a struct");
                 }
             }
@@ -592,15 +742,18 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
 
         // walk the with expression so that complex expressions
         // are properly handled.
-        self.walk_expr(with_expr);
+        self.walk_expr(with_expr)?;
+
+        Ok(())
     }
 
     /// Invoke the appropriate delegate calls for anything that gets
     /// consumed or borrowed as part of the automatic adjustment
     /// process.
-    fn walk_adjustment(&mut self, expr: &hir::Expr<'_>) {
-        let adjustments = self.mc.typeck_results.expr_adjustments(expr);
-        let mut place_with_id = return_if_err!(self.mc.cat_expr_unadjusted(expr));
+    fn walk_adjustment(&self, expr: &hir::Expr<'_>) -> Result<(), Cx::Error> {
+        let typeck_results = self.cx.typeck_results();
+        let adjustments = typeck_results.expr_adjustments(expr);
+        let mut place_with_id = self.cat_expr_unadjusted(expr)?;
         for adjustment in adjustments {
             debug!("walk_adjustment expr={:?} adj={:?}", expr, adjustment);
             match adjustment.kind {
@@ -609,7 +762,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
                 | adjustment::Adjust::DynStar => {
                     // Creating a closure/fn-pointer or unsizing consumes
                     // the input and stores it into the resulting rvalue.
-                    self.delegate_consume(&place_with_id, place_with_id.hir_id);
+                    self.consume_or_copy(&place_with_id, place_with_id.hir_id);
                 }
 
                 adjustment::Adjust::Deref(None) => {}
@@ -621,23 +774,24 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
                 // this is an autoref of `x`.
                 adjustment::Adjust::Deref(Some(ref deref)) => {
                     let bk = ty::BorrowKind::from_mutbl(deref.mutbl);
-                    self.delegate.borrow(&place_with_id, place_with_id.hir_id, bk);
+                    self.delegate.borrow_mut().borrow(&place_with_id, place_with_id.hir_id, bk);
                 }
 
                 adjustment::Adjust::Borrow(ref autoref) => {
                     self.walk_autoref(expr, &place_with_id, autoref);
                 }
             }
-            place_with_id =
-                return_if_err!(self.mc.cat_expr_adjusted(expr, place_with_id, adjustment));
+            place_with_id = self.cat_expr_adjusted(expr, place_with_id, adjustment)?;
         }
+
+        Ok(())
     }
 
     /// Walks the autoref `autoref` applied to the autoderef'd
     /// `expr`. `base_place` is the mem-categorized form of `expr`
     /// after all relevant autoderefs have occurred.
     fn walk_autoref(
-        &mut self,
+        &self,
         expr: &hir::Expr<'_>,
         base_place: &PlaceWithHirId<'tcx>,
         autoref: &adjustment::AutoBorrow<'tcx>,
@@ -649,7 +803,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
 
         match *autoref {
             adjustment::AutoBorrow::Ref(_, m) => {
-                self.delegate.borrow(
+                self.delegate.borrow_mut().borrow(
                     base_place,
                     base_place.hir_id,
                     ty::BorrowKind::from_mutbl(m.into()),
@@ -659,80 +813,93 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
             adjustment::AutoBorrow::RawPtr(m) => {
                 debug!("walk_autoref: expr.hir_id={} base_place={:?}", expr.hir_id, base_place);
 
-                self.delegate.borrow(base_place, base_place.hir_id, ty::BorrowKind::from_mutbl(m));
+                self.delegate.borrow_mut().borrow(
+                    base_place,
+                    base_place.hir_id,
+                    ty::BorrowKind::from_mutbl(m),
+                );
             }
         }
     }
 
-    fn walk_arm(&mut self, discr_place: &PlaceWithHirId<'tcx>, arm: &hir::Arm<'_>) {
+    fn walk_arm(
+        &self,
+        discr_place: &PlaceWithHirId<'tcx>,
+        arm: &hir::Arm<'_>,
+    ) -> Result<(), Cx::Error> {
         let closure_def_id = match discr_place.place.base {
             PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id),
             _ => None,
         };
 
-        self.delegate.fake_read(
+        self.delegate.borrow_mut().fake_read(
             discr_place,
             FakeReadCause::ForMatchedPlace(closure_def_id),
             discr_place.hir_id,
         );
-        self.walk_pat(discr_place, arm.pat, arm.guard.is_some());
+        self.walk_pat(discr_place, arm.pat, arm.guard.is_some())?;
 
         if let Some(ref e) = arm.guard {
-            self.consume_expr(e)
+            self.consume_expr(e)?;
         }
 
-        self.consume_expr(arm.body);
+        self.consume_expr(arm.body)?;
+        Ok(())
     }
 
     /// Walks a pat that occurs in isolation (i.e., top-level of fn argument or
     /// let binding, and *not* a match arm or nested pat.)
-    fn walk_irrefutable_pat(&mut self, discr_place: &PlaceWithHirId<'tcx>, pat: &hir::Pat<'_>) {
+    fn walk_irrefutable_pat(
+        &self,
+        discr_place: &PlaceWithHirId<'tcx>,
+        pat: &hir::Pat<'_>,
+    ) -> Result<(), Cx::Error> {
         let closure_def_id = match discr_place.place.base {
             PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id),
             _ => None,
         };
 
-        self.delegate.fake_read(
+        self.delegate.borrow_mut().fake_read(
             discr_place,
             FakeReadCause::ForLet(closure_def_id),
             discr_place.hir_id,
         );
-        self.walk_pat(discr_place, pat, false);
+        self.walk_pat(discr_place, pat, false)?;
+        Ok(())
     }
 
     /// The core driver for walking a pattern
     fn walk_pat(
-        &mut self,
+        &self,
         discr_place: &PlaceWithHirId<'tcx>,
         pat: &hir::Pat<'_>,
         has_guard: bool,
-    ) {
+    ) -> Result<(), Cx::Error> {
         debug!("walk_pat(discr_place={:?}, pat={:?}, has_guard={:?})", discr_place, pat, has_guard);
 
-        let tcx = self.tcx();
-        let ExprUseVisitor { ref mc, body_owner: _, ref mut delegate } = *self;
-        return_if_err!(mc.cat_pattern(discr_place.clone(), pat, |place, pat| {
+        let tcx = self.cx.tcx();
+        self.cat_pattern(discr_place.clone(), pat, &mut |place, pat| {
             if let PatKind::Binding(_, canonical_id, ..) = pat.kind {
                 debug!("walk_pat: binding place={:?} pat={:?}", place, pat);
                 if let Some(bm) =
-                    mc.typeck_results.extract_binding_mode(tcx.sess, pat.hir_id, pat.span)
+                    self.cx.typeck_results().extract_binding_mode(tcx.sess, pat.hir_id, pat.span)
                 {
                     debug!("walk_pat: pat.hir_id={:?} bm={:?}", pat.hir_id, bm);
 
                     // pat_ty: the type of the binding being produced.
-                    let pat_ty = return_if_err!(mc.node_ty(pat.hir_id));
+                    let pat_ty = self.node_ty(pat.hir_id)?;
                     debug!("walk_pat: pat_ty={:?}", pat_ty);
 
                     let def = Res::Local(canonical_id);
-                    if let Ok(ref binding_place) = mc.cat_res(pat.hir_id, pat.span, pat_ty, def) {
-                        delegate.bind(binding_place, binding_place.hir_id);
+                    if let Ok(ref binding_place) = self.cat_res(pat.hir_id, pat.span, pat_ty, def) {
+                        self.delegate.borrow_mut().bind(binding_place, binding_place.hir_id);
                     }
 
                     // Subtle: MIR desugaring introduces immutable borrows for each pattern
                     // binding when lowering pattern guards to ensure that the guard does not
                     // modify the scrutinee.
                     if has_guard {
-                        delegate.borrow(place, discr_place.hir_id, ImmBorrow);
+                        self.delegate.borrow_mut().borrow(place, discr_place.hir_id, ImmBorrow);
                     }
 
                     // It is also a borrow or copy/move of the value being matched.
@@ -742,11 +909,11 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
                     match bm.0 {
                         hir::ByRef::Yes(m) => {
                             let bk = ty::BorrowKind::from_mutbl(m);
-                            delegate.borrow(place, discr_place.hir_id, bk);
+                            self.delegate.borrow_mut().borrow(place, discr_place.hir_id, bk);
                         }
                         hir::ByRef::No => {
                             debug!("walk_pat binding consuming pat");
-                            delegate_consume(mc, *delegate, place, discr_place.hir_id);
+                            self.consume_or_copy(place, discr_place.hir_id);
                         }
                     }
                 }
@@ -755,12 +922,14 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
                 // determines whether to borrow *at the level of the deref pattern* rather than
                 // borrowing the bound place (since that inner place is inside the temporary that
                 // stores the result of calling `deref()`/`deref_mut()` so can't be captured).
-                let mutable = mc.typeck_results.pat_has_ref_mut_binding(subpattern);
+                let mutable = self.cx.typeck_results().pat_has_ref_mut_binding(subpattern);
                 let mutability = if mutable { hir::Mutability::Mut } else { hir::Mutability::Not };
                 let bk = ty::BorrowKind::from_mutbl(mutability);
-                delegate.borrow(place, discr_place.hir_id, bk);
+                self.delegate.borrow_mut().borrow(place, discr_place.hir_id, bk);
             }
-        }));
+
+            Ok(())
+        })
     }
 
     /// Handle the case where the current body contains a closure.
@@ -782,7 +951,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
     ///
     /// - When reporting the Place back to the Delegate, ensure that the UpvarId uses the enclosing
     /// closure as the DefId.
-    fn walk_captures(&mut self, closure_expr: &hir::Closure<'_>) {
+    fn walk_captures(&self, closure_expr: &hir::Closure<'_>) -> Result<(), Cx::Error> {
         fn upvar_is_local_variable(
             upvars: Option<&FxIndexMap<HirId, hir::Upvar>>,
             upvar_id: HirId,
@@ -793,21 +962,21 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
 
         debug!("walk_captures({:?})", closure_expr);
 
-        let tcx = self.tcx();
+        let tcx = self.cx.tcx();
         let closure_def_id = closure_expr.def_id;
-        let upvars = tcx.upvars_mentioned(self.body_owner);
-
         // For purposes of this function, coroutine and closures are equivalent.
-        let body_owner_is_closure =
-            matches!(tcx.hir().body_owner_kind(self.body_owner), hir::BodyOwnerKind::Closure,);
+        let body_owner_is_closure = matches!(
+            tcx.hir().body_owner_kind(self.cx.body_owner_def_id()),
+            hir::BodyOwnerKind::Closure
+        );
 
         // If we have a nested closure, we want to include the fake reads present in the nested closure.
-        if let Some(fake_reads) = self.mc.typeck_results.closure_fake_reads.get(&closure_def_id) {
+        if let Some(fake_reads) = self.cx.typeck_results().closure_fake_reads.get(&closure_def_id) {
             for (fake_read, cause, hir_id) in fake_reads.iter() {
                 match fake_read.base {
                     PlaceBase::Upvar(upvar_id) => {
                         if upvar_is_local_variable(
-                            upvars,
+                            self.upvars,
                             upvar_id.var_path.hir_id,
                             body_owner_is_closure,
                         ) {
@@ -837,7 +1006,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
                         );
                     }
                 };
-                self.delegate.fake_read(
+                self.delegate.borrow_mut().fake_read(
                     &PlaceWithHirId { place: fake_read.clone(), hir_id: *hir_id },
                     *cause,
                     *hir_id,
@@ -845,10 +1014,14 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
             }
         }
 
-        if let Some(min_captures) = self.mc.typeck_results.closure_min_captures.get(&closure_def_id)
+        if let Some(min_captures) =
+            self.cx.typeck_results().closure_min_captures.get(&closure_def_id)
         {
             for (var_hir_id, min_list) in min_captures.iter() {
-                if upvars.map_or(body_owner_is_closure, |upvars| !upvars.contains_key(var_hir_id)) {
+                if self
+                    .upvars
+                    .map_or(body_owner_is_closure, |upvars| !upvars.contains_key(var_hir_id))
+                {
                     // The nested closure might be capturing the current (enclosing) closure's local variables.
                     // We check if the root variable is ever mentioned within the enclosing closure, if not
                     // then for the current body (if it's a closure) these aren't captures, we will ignore them.
@@ -860,7 +1033,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
 
                     let place_base = if body_owner_is_closure {
                         // Mark the place to be captured by the enclosing closure
-                        PlaceBase::Upvar(ty::UpvarId::new(*var_hir_id, self.body_owner))
+                        PlaceBase::Upvar(ty::UpvarId::new(*var_hir_id, self.cx.body_owner_def_id()))
                     } else {
                         // If the body owner isn't a closure then the variable must
                         // be a local variable
@@ -878,10 +1051,10 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
 
                     match capture_info.capture_kind {
                         ty::UpvarCapture::ByValue => {
-                            self.delegate_consume(&place_with_id, place_with_id.hir_id);
+                            self.consume_or_copy(&place_with_id, place_with_id.hir_id);
                         }
                         ty::UpvarCapture::ByRef(upvar_borrow) => {
-                            self.delegate.borrow(
+                            self.delegate.borrow_mut().borrow(
                                 &place_with_id,
                                 place_with_id.hir_id,
                                 upvar_borrow,
@@ -891,53 +1064,733 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
                 }
             }
         }
+
+        Ok(())
     }
 }
 
-fn copy_or_move<'a, 'tcx>(
-    mc: &mc::MemCategorizationContext<'a, 'tcx>,
-    place_with_id: &PlaceWithHirId<'tcx>,
-) -> ConsumeMode {
-    if !mc.type_is_copy_modulo_regions(place_with_id.place.ty()) {
-        ConsumeMode::Move
-    } else {
-        ConsumeMode::Copy
+/// The job of the categorization methods is to analyze an expression to
+/// determine what kind of memory is used in evaluating it (for example,
+/// where dereferences occur and what kind of pointer is dereferenced;
+/// whether the memory is mutable, etc.).
+///
+/// Categorization effectively transforms all of our expressions into
+/// expressions of the following forms (the actual enum has many more
+/// possibilities, naturally, but they are all variants of these base
+/// forms):
+/// ```ignore (not-rust)
+/// E = rvalue    // some computed rvalue
+///   | x         // address of a local variable or argument
+///   | *E        // deref of a ptr
+///   | E.comp    // access to an interior component
+/// ```
+/// Imagine a routine ToAddr(Expr) that evaluates an expression and returns an
+/// address where the result is to be found. If Expr is a place, then this
+/// is the address of the place. If `Expr` is an rvalue, this is the address of
+/// some temporary spot in memory where the result is stored.
+///
+/// Now, `cat_expr()` classifies the expression `Expr` and the address `A = ToAddr(Expr)`
+/// as follows:
+///
+/// - `cat`: what kind of expression was this? This is a subset of the
+///   full expression forms which only includes those that we care about
+///   for the purpose of the analysis.
+/// - `mutbl`: mutability of the address `A`.
+/// - `ty`: the type of data found at the address `A`.
+///
+/// The resulting categorization tree differs somewhat from the expressions
+/// themselves. For example, auto-derefs are explicit. Also, an index `a[b]` is
+/// decomposed into two operations: a dereference to reach the array data and
+/// then an index to jump forward to the relevant item.
+///
+/// ## By-reference upvars
+///
+/// One part of the codegen which may be non-obvious is that we translate
+/// closure upvars into the dereference of a borrowed pointer; this more closely
+/// resembles the runtime codegen. So, for example, if we had:
+///
+///     let mut x = 3;
+///     let y = 5;
+///     let inc = || x += y;
+///
+/// Then when we categorize `x` (*within* the closure) we would yield a
+/// result of `*x'`, effectively, where `x'` is a `Categorization::Upvar` reference
+/// tied to `x`. The type of `x'` will be a borrowed pointer.
+impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx, Cx, D> {
+    fn resolve_type_vars_or_error(
+        &self,
+        id: HirId,
+        ty: Option<Ty<'tcx>>,
+    ) -> Result<Ty<'tcx>, Cx::Error> {
+        match ty {
+            Some(ty) => {
+                let ty = self.cx.resolve_vars_if_possible(ty);
+                self.cx.error_reported_in_ty(ty)?;
+                if ty.is_ty_var() {
+                    debug!("resolve_type_vars_or_error: infer var from {:?}", ty);
+                    Err(self
+                        .cx
+                        .report_error(self.cx.tcx().hir().span(id), "encountered type variable"))
+                } else {
+                    Ok(ty)
+                }
+            }
+            None => {
+                // FIXME: We shouldn't be relying on the infcx being tainted.
+                self.cx.tainted_by_errors()?;
+                bug!(
+                    "no type for node {} in mem_categorization",
+                    self.cx.tcx().hir().node_to_string(id)
+                );
+            }
+        }
     }
-}
 
-// - If a place is used in a `ByValue` context then move it if it's not a `Copy` type.
-// - If the place that is a `Copy` type consider it an `ImmBorrow`.
-fn delegate_consume<'a, 'tcx>(
-    mc: &mc::MemCategorizationContext<'a, 'tcx>,
-    delegate: &mut (dyn Delegate<'tcx> + 'a),
-    place_with_id: &PlaceWithHirId<'tcx>,
-    diag_expr_id: HirId,
-) {
-    debug!("delegate_consume(place_with_id={:?})", place_with_id);
+    fn node_ty(&self, hir_id: HirId) -> Result<Ty<'tcx>, Cx::Error> {
+        self.resolve_type_vars_or_error(hir_id, self.cx.typeck_results().node_type_opt(hir_id))
+    }
 
-    let mode = copy_or_move(mc, place_with_id);
+    fn expr_ty(&self, expr: &hir::Expr<'_>) -> Result<Ty<'tcx>, Cx::Error> {
+        self.resolve_type_vars_or_error(expr.hir_id, self.cx.typeck_results().expr_ty_opt(expr))
+    }
 
-    match mode {
-        ConsumeMode::Move => delegate.consume(place_with_id, diag_expr_id),
-        ConsumeMode::Copy => delegate.copy(place_with_id, diag_expr_id),
+    fn expr_ty_adjusted(&self, expr: &hir::Expr<'_>) -> Result<Ty<'tcx>, Cx::Error> {
+        self.resolve_type_vars_or_error(
+            expr.hir_id,
+            self.cx.typeck_results().expr_ty_adjusted_opt(expr),
+        )
+    }
+
+    /// Returns the type of value that this pattern matches against.
+    /// Some non-obvious cases:
+    ///
+    /// - a `ref x` binding matches against a value of type `T` and gives
+    ///   `x` the type `&T`; we return `T`.
+    /// - a pattern with implicit derefs (thanks to default binding
+    ///   modes #42640) may look like `Some(x)` but in fact have
+    ///   implicit deref patterns attached (e.g., it is really
+    ///   `&Some(x)`). In that case, we return the "outermost" type
+    ///   (e.g., `&Option<T>`).
+    fn pat_ty_adjusted(&self, pat: &hir::Pat<'_>) -> Result<Ty<'tcx>, Cx::Error> {
+        // Check for implicit `&` types wrapping the pattern; note
+        // that these are never attached to binding patterns, so
+        // actually this is somewhat "disjoint" from the code below
+        // that aims to account for `ref x`.
+        if let Some(vec) = self.cx.typeck_results().pat_adjustments().get(pat.hir_id) {
+            if let Some(first_ty) = vec.first() {
+                debug!("pat_ty(pat={:?}) found adjusted ty `{:?}`", pat, first_ty);
+                return Ok(*first_ty);
+            }
+        }
+
+        self.pat_ty_unadjusted(pat)
+    }
+
+    /// Like `TypeckResults::pat_ty`, but ignores implicit `&` patterns.
+    fn pat_ty_unadjusted(&self, pat: &hir::Pat<'_>) -> Result<Ty<'tcx>, Cx::Error> {
+        let base_ty = self.node_ty(pat.hir_id)?;
+        trace!(?base_ty);
+
+        // This code detects whether we are looking at a `ref x`,
+        // and if so, figures out what the type *being borrowed* is.
+        match pat.kind {
+            PatKind::Binding(..) => {
+                let bm = *self
+                    .cx
+                    .typeck_results()
+                    .pat_binding_modes()
+                    .get(pat.hir_id)
+                    .expect("missing binding mode");
+
+                if matches!(bm.0, hir::ByRef::Yes(_)) {
+                    // a bind-by-ref means that the base_ty will be the type of the ident itself,
+                    // but what we want here is the type of the underlying value being borrowed.
+                    // So peel off one-level, turning the &T into T.
+                    match self
+                        .cx
+                        .try_structurally_resolve_type(pat.span, base_ty)
+                        .builtin_deref(false)
+                    {
+                        Some(ty) => Ok(ty),
+                        None => {
+                            debug!("By-ref binding of non-derefable type");
+                            Err(self
+                                .cx
+                                .report_error(pat.span, "by-ref binding of non-derefable type"))
+                        }
+                    }
+                } else {
+                    Ok(base_ty)
+                }
+            }
+            _ => Ok(base_ty),
+        }
+    }
+
+    fn cat_expr(&self, expr: &hir::Expr<'_>) -> Result<PlaceWithHirId<'tcx>, Cx::Error> {
+        self.cat_expr_(expr, self.cx.typeck_results().expr_adjustments(expr))
+    }
+
+    /// This recursion helper avoids going through *too many*
+    /// adjustments, since *only* non-overloaded deref recurses.
+    fn cat_expr_(
+        &self,
+        expr: &hir::Expr<'_>,
+        adjustments: &[adjustment::Adjustment<'tcx>],
+    ) -> Result<PlaceWithHirId<'tcx>, Cx::Error> {
+        match adjustments.split_last() {
+            None => self.cat_expr_unadjusted(expr),
+            Some((adjustment, previous)) => {
+                self.cat_expr_adjusted_with(expr, || self.cat_expr_(expr, previous), adjustment)
+            }
+        }
+    }
+
+    fn cat_expr_adjusted(
+        &self,
+        expr: &hir::Expr<'_>,
+        previous: PlaceWithHirId<'tcx>,
+        adjustment: &adjustment::Adjustment<'tcx>,
+    ) -> Result<PlaceWithHirId<'tcx>, Cx::Error> {
+        self.cat_expr_adjusted_with(expr, || Ok(previous), adjustment)
+    }
+
+    fn cat_expr_adjusted_with<F>(
+        &self,
+        expr: &hir::Expr<'_>,
+        previous: F,
+        adjustment: &adjustment::Adjustment<'tcx>,
+    ) -> Result<PlaceWithHirId<'tcx>, Cx::Error>
+    where
+        F: FnOnce() -> Result<PlaceWithHirId<'tcx>, Cx::Error>,
+    {
+        let target = self.cx.resolve_vars_if_possible(adjustment.target);
+        match adjustment.kind {
+            adjustment::Adjust::Deref(overloaded) => {
+                // Equivalent to *expr or something similar.
+                let base = if let Some(deref) = overloaded {
+                    let ref_ty = Ty::new_ref(self.cx.tcx(), deref.region, target, deref.mutbl);
+                    self.cat_rvalue(expr.hir_id, ref_ty)
+                } else {
+                    previous()?
+                };
+                self.cat_deref(expr.hir_id, base)
+            }
+
+            adjustment::Adjust::NeverToAny
+            | adjustment::Adjust::Pointer(_)
+            | adjustment::Adjust::Borrow(_)
+            | adjustment::Adjust::DynStar => {
+                // Result is an rvalue.
+                Ok(self.cat_rvalue(expr.hir_id, target))
+            }
+        }
     }
-}
 
-fn is_multivariant_adt(ty: Ty<'_>) -> bool {
-    if let ty::Adt(def, _) = ty.kind() {
-        // Note that if a non-exhaustive SingleVariant is defined in another crate, we need
-        // to assume that more cases will be added to the variant in the future. This mean
-        // that we should handle non-exhaustive SingleVariant the same way we would handle
-        // a MultiVariant.
-        // If the variant is not local it must be defined in another crate.
-        let is_non_exhaustive = match def.adt_kind() {
-            AdtKind::Struct | AdtKind::Union => {
-                def.non_enum_variant().is_field_list_non_exhaustive()
-            }
-            AdtKind::Enum => def.is_variant_list_non_exhaustive(),
+    fn cat_expr_unadjusted(&self, expr: &hir::Expr<'_>) -> Result<PlaceWithHirId<'tcx>, Cx::Error> {
+        let expr_ty = self.expr_ty(expr)?;
+        match expr.kind {
+            hir::ExprKind::Unary(hir::UnOp::Deref, e_base) => {
+                if self.cx.typeck_results().is_method_call(expr) {
+                    self.cat_overloaded_place(expr, e_base)
+                } else {
+                    let base = self.cat_expr(e_base)?;
+                    self.cat_deref(expr.hir_id, base)
+                }
+            }
+
+            hir::ExprKind::Field(base, _) => {
+                let base = self.cat_expr(base)?;
+                debug!(?base);
+
+                let field_idx = self
+                    .cx
+                    .typeck_results()
+                    .field_indices()
+                    .get(expr.hir_id)
+                    .cloned()
+                    .expect("Field index not found");
+
+                Ok(self.cat_projection(
+                    expr.hir_id,
+                    base,
+                    expr_ty,
+                    ProjectionKind::Field(field_idx, FIRST_VARIANT),
+                ))
+            }
+
+            hir::ExprKind::Index(base, _, _) => {
+                if self.cx.typeck_results().is_method_call(expr) {
+                    // If this is an index implemented by a method call, then it
+                    // will include an implicit deref of the result.
+                    // The call to index() returns a `&T` value, which
+                    // is an rvalue. That is what we will be
+                    // dereferencing.
+                    self.cat_overloaded_place(expr, base)
+                } else {
+                    let base = self.cat_expr(base)?;
+                    Ok(self.cat_projection(expr.hir_id, base, expr_ty, ProjectionKind::Index))
+                }
+            }
+
+            hir::ExprKind::Path(ref qpath) => {
+                let res = self.cx.typeck_results().qpath_res(qpath, expr.hir_id);
+                self.cat_res(expr.hir_id, expr.span, expr_ty, res)
+            }
+
+            hir::ExprKind::Type(e, _) => self.cat_expr(e),
+
+            hir::ExprKind::AddrOf(..)
+            | hir::ExprKind::Call(..)
+            | hir::ExprKind::Assign(..)
+            | hir::ExprKind::AssignOp(..)
+            | hir::ExprKind::Closure { .. }
+            | hir::ExprKind::Ret(..)
+            | hir::ExprKind::Become(..)
+            | hir::ExprKind::Unary(..)
+            | hir::ExprKind::Yield(..)
+            | hir::ExprKind::MethodCall(..)
+            | hir::ExprKind::Cast(..)
+            | hir::ExprKind::DropTemps(..)
+            | hir::ExprKind::Array(..)
+            | hir::ExprKind::If(..)
+            | hir::ExprKind::Tup(..)
+            | hir::ExprKind::Binary(..)
+            | hir::ExprKind::Block(..)
+            | hir::ExprKind::Let(..)
+            | hir::ExprKind::Loop(..)
+            | hir::ExprKind::Match(..)
+            | hir::ExprKind::Lit(..)
+            | hir::ExprKind::ConstBlock(..)
+            | hir::ExprKind::Break(..)
+            | hir::ExprKind::Continue(..)
+            | hir::ExprKind::Struct(..)
+            | hir::ExprKind::Repeat(..)
+            | hir::ExprKind::InlineAsm(..)
+            | hir::ExprKind::OffsetOf(..)
+            | hir::ExprKind::Err(_) => Ok(self.cat_rvalue(expr.hir_id, expr_ty)),
+        }
+    }
+
+    fn cat_res(
+        &self,
+        hir_id: HirId,
+        span: Span,
+        expr_ty: Ty<'tcx>,
+        res: Res,
+    ) -> Result<PlaceWithHirId<'tcx>, Cx::Error> {
+        match res {
+            Res::Def(
+                DefKind::Ctor(..)
+                | DefKind::Const
+                | DefKind::ConstParam
+                | DefKind::AssocConst
+                | DefKind::Fn
+                | DefKind::AssocFn,
+                _,
+            )
+            | Res::SelfCtor(..) => Ok(self.cat_rvalue(hir_id, expr_ty)),
+
+            Res::Def(DefKind::Static { .. }, _) => {
+                Ok(PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::StaticItem, Vec::new()))
+            }
+
+            Res::Local(var_id) => {
+                if self.upvars.is_some_and(|upvars| upvars.contains_key(&var_id)) {
+                    self.cat_upvar(hir_id, var_id)
+                } else {
+                    Ok(PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::Local(var_id), Vec::new()))
+                }
+            }
+
+            def => span_bug!(span, "unexpected definition in memory categorization: {:?}", def),
+        }
+    }
+
+    /// Categorize an upvar.
+    ///
+    /// Note: the actual upvar access contains invisible derefs of closure
+    /// environment and upvar reference as appropriate. Only regionck cares
+    /// about these dereferences, so we let it compute them as needed.
+    fn cat_upvar(&self, hir_id: HirId, var_id: HirId) -> Result<PlaceWithHirId<'tcx>, Cx::Error> {
+        let closure_expr_def_id = self.cx.body_owner_def_id();
+
+        let upvar_id = ty::UpvarId {
+            var_path: ty::UpvarPath { hir_id: var_id },
+            closure_expr_id: closure_expr_def_id,
         };
-        def.variants().len() > 1 || (!def.did().is_local() && is_non_exhaustive)
-    } else {
-        false
+        let var_ty = self.node_ty(var_id)?;
+
+        Ok(PlaceWithHirId::new(hir_id, var_ty, PlaceBase::Upvar(upvar_id), Vec::new()))
+    }
+
+    fn cat_rvalue(&self, hir_id: HirId, expr_ty: Ty<'tcx>) -> PlaceWithHirId<'tcx> {
+        PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::Rvalue, Vec::new())
+    }
+
+    fn cat_projection(
+        &self,
+        node: HirId,
+        base_place: PlaceWithHirId<'tcx>,
+        ty: Ty<'tcx>,
+        kind: ProjectionKind,
+    ) -> PlaceWithHirId<'tcx> {
+        let place_ty = base_place.place.ty();
+        let mut projections = base_place.place.projections;
+
+        let node_ty = self.cx.typeck_results().node_type(node);
+        // Opaque types can't have field projections, but we can instead convert
+        // the current place in-place (heh) to the hidden type, and then apply all
+        // follow up projections on that.
+        if node_ty != place_ty
+            && self
+                .cx
+                .try_structurally_resolve_type(
+                    self.cx.tcx().hir().span(base_place.hir_id),
+                    place_ty,
+                )
+                .is_impl_trait()
+        {
+            projections.push(Projection { kind: ProjectionKind::OpaqueCast, ty: node_ty });
+        }
+        projections.push(Projection { kind, ty });
+        PlaceWithHirId::new(node, base_place.place.base_ty, base_place.place.base, projections)
+    }
+
+    fn cat_overloaded_place(
+        &self,
+        expr: &hir::Expr<'_>,
+        base: &hir::Expr<'_>,
+    ) -> Result<PlaceWithHirId<'tcx>, Cx::Error> {
+        // Reconstruct the output assuming it's a reference with the
+        // same region and mutability as the receiver. This holds for
+        // `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`.
+        let place_ty = self.expr_ty(expr)?;
+        let base_ty = self.expr_ty_adjusted(base)?;
+
+        let ty::Ref(region, _, mutbl) =
+            *self.cx.try_structurally_resolve_type(base.span, base_ty).kind()
+        else {
+            span_bug!(expr.span, "cat_overloaded_place: base is not a reference");
+        };
+        let ref_ty = Ty::new_ref(self.cx.tcx(), region, place_ty, mutbl);
+
+        let base = self.cat_rvalue(expr.hir_id, ref_ty);
+        self.cat_deref(expr.hir_id, base)
+    }
+
+    fn cat_deref(
+        &self,
+        node: HirId,
+        base_place: PlaceWithHirId<'tcx>,
+    ) -> Result<PlaceWithHirId<'tcx>, Cx::Error> {
+        let base_curr_ty = base_place.place.ty();
+        let deref_ty = match self
+            .cx
+            .try_structurally_resolve_type(
+                self.cx.tcx().hir().span(base_place.hir_id),
+                base_curr_ty,
+            )
+            .builtin_deref(true)
+        {
+            Some(ty) => ty,
+            None => {
+                debug!("explicit deref of non-derefable type: {:?}", base_curr_ty);
+                return Err(self.cx.report_error(
+                    self.cx.tcx().hir().span(node),
+                    "explicit deref of non-derefable type",
+                ));
+            }
+        };
+        let mut projections = base_place.place.projections;
+        projections.push(Projection { kind: ProjectionKind::Deref, ty: deref_ty });
+
+        Ok(PlaceWithHirId::new(node, base_place.place.base_ty, base_place.place.base, projections))
+    }
+
+    /// Returns the variant index for an ADT used within a Struct or TupleStruct pattern
+    /// Here `pat_hir_id` is the HirId of the pattern itself.
+    fn variant_index_for_adt(
+        &self,
+        qpath: &hir::QPath<'_>,
+        pat_hir_id: HirId,
+        span: Span,
+    ) -> Result<VariantIdx, Cx::Error> {
+        let res = self.cx.typeck_results().qpath_res(qpath, pat_hir_id);
+        let ty = self.cx.typeck_results().node_type(pat_hir_id);
+        let ty::Adt(adt_def, _) = self.cx.try_structurally_resolve_type(span, ty).kind() else {
+            return Err(self
+                .cx
+                .report_error(span, "struct or tuple struct pattern not applied to an ADT"));
+        };
+
+        match res {
+            Res::Def(DefKind::Variant, variant_id) => Ok(adt_def.variant_index_with_id(variant_id)),
+            Res::Def(DefKind::Ctor(CtorOf::Variant, ..), variant_ctor_id) => {
+                Ok(adt_def.variant_index_with_ctor_id(variant_ctor_id))
+            }
+            Res::Def(DefKind::Ctor(CtorOf::Struct, ..), _)
+            | Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _)
+            | Res::SelfCtor(..)
+            | Res::SelfTyParam { .. }
+            | Res::SelfTyAlias { .. } => {
+                // Structs and Unions have only have one variant.
+                Ok(FIRST_VARIANT)
+            }
+            _ => bug!("expected ADT path, found={:?}", res),
+        }
+    }
+
+    /// Returns the total number of fields in an ADT variant used within a pattern.
+    /// Here `pat_hir_id` is the HirId of the pattern itself.
+    fn total_fields_in_adt_variant(
+        &self,
+        pat_hir_id: HirId,
+        variant_index: VariantIdx,
+        span: Span,
+    ) -> Result<usize, Cx::Error> {
+        let ty = self.cx.typeck_results().node_type(pat_hir_id);
+        match self.cx.try_structurally_resolve_type(span, ty).kind() {
+            ty::Adt(adt_def, _) => Ok(adt_def.variant(variant_index).fields.len()),
+            _ => {
+                self.cx
+                    .tcx()
+                    .dcx()
+                    .span_bug(span, "struct or tuple struct pattern not applied to an ADT");
+            }
+        }
+    }
+
+    /// Returns the total number of fields in a tuple used within a Tuple pattern.
+    /// Here `pat_hir_id` is the HirId of the pattern itself.
+    fn total_fields_in_tuple(&self, pat_hir_id: HirId, span: Span) -> Result<usize, Cx::Error> {
+        let ty = self.cx.typeck_results().node_type(pat_hir_id);
+        match self.cx.try_structurally_resolve_type(span, ty).kind() {
+            ty::Tuple(args) => Ok(args.len()),
+            _ => Err(self.cx.report_error(span, "tuple pattern not applied to a tuple")),
+        }
+    }
+
+    /// Here, `place` is the `PlaceWithHirId` being matched and pat is the pattern it
+    /// is being matched against.
+    ///
+    /// In general, the way that this works is that we walk down the pattern,
+    /// constructing a `PlaceWithHirId` that represents the path that will be taken
+    /// to reach the value being matched.
+    fn cat_pattern<F>(
+        &self,
+        mut place_with_id: PlaceWithHirId<'tcx>,
+        pat: &hir::Pat<'_>,
+        op: &mut F,
+    ) -> Result<(), Cx::Error>
+    where
+        F: FnMut(&PlaceWithHirId<'tcx>, &hir::Pat<'_>) -> Result<(), Cx::Error>,
+    {
+        // If (pattern) adjustments are active for this pattern, adjust the `PlaceWithHirId` correspondingly.
+        // `PlaceWithHirId`s are constructed differently from patterns. For example, in
+        //
+        // ```
+        // match foo {
+        //     &&Some(x, ) => { ... },
+        //     _ => { ... },
+        // }
+        // ```
+        //
+        // the pattern `&&Some(x,)` is represented as `Ref { Ref { TupleStruct }}`. To build the
+        // corresponding `PlaceWithHirId` we start with the `PlaceWithHirId` for `foo`, and then, by traversing the
+        // pattern, try to answer the question: given the address of `foo`, how is `x` reached?
+        //
+        // `&&Some(x,)` `place_foo`
+        //  `&Some(x,)` `deref { place_foo}`
+        //   `Some(x,)` `deref { deref { place_foo }}`
+        //       `(x,)` `field0 { deref { deref { place_foo }}}` <- resulting place
+        //
+        // The above example has no adjustments. If the code were instead the (after adjustments,
+        // equivalent) version
+        //
+        // ```
+        // match foo {
+        //     Some(x, ) => { ... },
+        //     _ => { ... },
+        // }
+        // ```
+        //
+        // Then we see that to get the same result, we must start with
+        // `deref { deref { place_foo }}` instead of `place_foo` since the pattern is now `Some(x,)`
+        // and not `&&Some(x,)`, even though its assigned type is that of `&&Some(x,)`.
+        for _ in
+            0..self.cx.typeck_results().pat_adjustments().get(pat.hir_id).map_or(0, |v| v.len())
+        {
+            debug!("applying adjustment to place_with_id={:?}", place_with_id);
+            place_with_id = self.cat_deref(pat.hir_id, place_with_id)?;
+        }
+        let place_with_id = place_with_id; // lose mutability
+        debug!("applied adjustment derefs to get place_with_id={:?}", place_with_id);
+
+        // Invoke the callback, but only now, after the `place_with_id` has adjusted.
+        //
+        // To see that this makes sense, consider `match &Some(3) { Some(x) => { ... }}`. In that
+        // case, the initial `place_with_id` will be that for `&Some(3)` and the pattern is `Some(x)`. We
+        // don't want to call `op` with these incompatible values. As written, what happens instead
+        // is that `op` is called with the adjusted place (that for `*&Some(3)`) and the pattern
+        // `Some(x)` (which matches). Recursing once more, `*&Some(3)` and the pattern `Some(x)`
+        // result in the place `Downcast<Some>(*&Some(3)).0` associated to `x` and invoke `op` with
+        // that (where the `ref` on `x` is implied).
+        op(&place_with_id, pat)?;
+
+        match pat.kind {
+            PatKind::Tuple(subpats, dots_pos) => {
+                // (p1, ..., pN)
+                let total_fields = self.total_fields_in_tuple(pat.hir_id, pat.span)?;
+
+                for (i, subpat) in subpats.iter().enumerate_and_adjust(total_fields, dots_pos) {
+                    let subpat_ty = self.pat_ty_adjusted(subpat)?;
+                    let projection_kind =
+                        ProjectionKind::Field(FieldIdx::from_usize(i), FIRST_VARIANT);
+                    let sub_place = self.cat_projection(
+                        pat.hir_id,
+                        place_with_id.clone(),
+                        subpat_ty,
+                        projection_kind,
+                    );
+                    self.cat_pattern(sub_place, subpat, op)?;
+                }
+            }
+
+            PatKind::TupleStruct(ref qpath, subpats, dots_pos) => {
+                // S(p1, ..., pN)
+                let variant_index = self.variant_index_for_adt(qpath, pat.hir_id, pat.span)?;
+                let total_fields =
+                    self.total_fields_in_adt_variant(pat.hir_id, variant_index, pat.span)?;
+
+                for (i, subpat) in subpats.iter().enumerate_and_adjust(total_fields, dots_pos) {
+                    let subpat_ty = self.pat_ty_adjusted(subpat)?;
+                    let projection_kind =
+                        ProjectionKind::Field(FieldIdx::from_usize(i), variant_index);
+                    let sub_place = self.cat_projection(
+                        pat.hir_id,
+                        place_with_id.clone(),
+                        subpat_ty,
+                        projection_kind,
+                    );
+                    self.cat_pattern(sub_place, subpat, op)?;
+                }
+            }
+
+            PatKind::Struct(ref qpath, field_pats, _) => {
+                // S { f1: p1, ..., fN: pN }
+
+                let variant_index = self.variant_index_for_adt(qpath, pat.hir_id, pat.span)?;
+
+                for fp in field_pats {
+                    let field_ty = self.pat_ty_adjusted(fp.pat)?;
+                    let field_index = self
+                        .cx
+                        .typeck_results()
+                        .field_indices()
+                        .get(fp.hir_id)
+                        .cloned()
+                        .expect("no index for a field");
+
+                    let field_place = self.cat_projection(
+                        pat.hir_id,
+                        place_with_id.clone(),
+                        field_ty,
+                        ProjectionKind::Field(field_index, variant_index),
+                    );
+                    self.cat_pattern(field_place, fp.pat, op)?;
+                }
+            }
+
+            PatKind::Or(pats) => {
+                for pat in pats {
+                    self.cat_pattern(place_with_id.clone(), pat, op)?;
+                }
+            }
+
+            PatKind::Binding(.., Some(subpat)) => {
+                self.cat_pattern(place_with_id, subpat, op)?;
+            }
+
+            PatKind::Box(subpat) | PatKind::Ref(subpat, _) => {
+                // box p1, &p1, &mut p1. we can ignore the mutability of
+                // PatKind::Ref since that information is already contained
+                // in the type.
+                let subplace = self.cat_deref(pat.hir_id, place_with_id)?;
+                self.cat_pattern(subplace, subpat, op)?;
+            }
+            PatKind::Deref(subpat) => {
+                let mutable = self.cx.typeck_results().pat_has_ref_mut_binding(subpat);
+                let mutability = if mutable { hir::Mutability::Mut } else { hir::Mutability::Not };
+                let re_erased = self.cx.tcx().lifetimes.re_erased;
+                let ty = self.pat_ty_adjusted(subpat)?;
+                let ty = Ty::new_ref(self.cx.tcx(), re_erased, ty, mutability);
+                // A deref pattern generates a temporary.
+                let place = self.cat_rvalue(pat.hir_id, ty);
+                self.cat_pattern(place, subpat, op)?;
+            }
+
+            PatKind::Slice(before, ref slice, after) => {
+                let Some(element_ty) = place_with_id.place.ty().builtin_index() else {
+                    debug!("explicit index of non-indexable type {:?}", place_with_id);
+                    return Err(self
+                        .cx
+                        .report_error(pat.span, "explicit index of non-indexable type"));
+                };
+                let elt_place = self.cat_projection(
+                    pat.hir_id,
+                    place_with_id.clone(),
+                    element_ty,
+                    ProjectionKind::Index,
+                );
+                for before_pat in before {
+                    self.cat_pattern(elt_place.clone(), before_pat, op)?;
+                }
+                if let Some(slice_pat) = *slice {
+                    let slice_pat_ty = self.pat_ty_adjusted(slice_pat)?;
+                    let slice_place = self.cat_projection(
+                        pat.hir_id,
+                        place_with_id,
+                        slice_pat_ty,
+                        ProjectionKind::Subslice,
+                    );
+                    self.cat_pattern(slice_place, slice_pat, op)?;
+                }
+                for after_pat in after {
+                    self.cat_pattern(elt_place.clone(), after_pat, op)?;
+                }
+            }
+
+            PatKind::Path(_)
+            | PatKind::Binding(.., None)
+            | PatKind::Lit(..)
+            | PatKind::Range(..)
+            | PatKind::Never
+            | PatKind::Wild
+            | PatKind::Err(_) => {
+                // always ok
+            }
+        }
+
+        Ok(())
+    }
+
+    fn is_multivariant_adt(&self, ty: Ty<'tcx>, span: Span) -> bool {
+        if let ty::Adt(def, _) = self.cx.try_structurally_resolve_type(span, ty).kind() {
+            // Note that if a non-exhaustive SingleVariant is defined in another crate, we need
+            // to assume that more cases will be added to the variant in the future. This mean
+            // that we should handle non-exhaustive SingleVariant the same way we would handle
+            // a MultiVariant.
+            // If the variant is not local it must be defined in another crate.
+            let is_non_exhaustive = match def.adt_kind() {
+                AdtKind::Struct | AdtKind::Union => {
+                    def.non_enum_variant().is_field_list_non_exhaustive()
+                }
+                AdtKind::Enum => def.is_variant_list_non_exhaustive(),
+            };
+            def.variants().len() > 1 || (!def.did().is_local() && is_non_exhaustive)
+        } else {
+            false
+        }
     }
 }
diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs
index f240a53a679..c79b6be6560 100644
--- a/compiler/rustc_hir_typeck/src/fallback.rs
+++ b/compiler/rustc_hir_typeck/src/fallback.rs
@@ -9,6 +9,7 @@ use rustc_hir as hir;
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::HirId;
 use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
+use rustc_middle::bug;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable};
 use rustc_session::lint;
 use rustc_span::DUMMY_SP;
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 881f726e1da..6e8ef044452 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -29,6 +29,7 @@ use rustc_middle::ty::{
     self, AdtKind, CanonicalUserType, GenericParamDefKind, IsIdentity, Ty, TyCtxt, UserType,
 };
 use rustc_middle::ty::{GenericArgKind, GenericArgsRef, UserArgs, UserSelfTy};
+use rustc_middle::{bug, span_bug};
 use rustc_session::lint;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::hygiene::DesugaringKind;
@@ -1409,11 +1410,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         hir_id: HirId,
     ) {
         self.add_required_obligations_with_code(span, def_id, args, |idx, span| {
-            if span.is_dummy() {
-                ObligationCauseCode::WhereClauseInExpr(def_id, hir_id, idx)
-            } else {
-                ObligationCauseCode::SpannedWhereClauseInExpr(def_id, span, hir_id, idx)
-            }
+            ObligationCauseCode::WhereClauseInExpr(def_id, span, hir_id, idx)
         })
     }
 
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
index 26996397659..4edc11d7ab1 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
@@ -14,8 +14,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         error: &mut traits::FulfillmentError<'tcx>,
     ) -> bool {
-        let (ObligationCauseCode::WhereClauseInExpr(def_id, hir_id, idx)
-        | ObligationCauseCode::SpannedWhereClauseInExpr(def_id, _, hir_id, idx)) =
+        let ObligationCauseCode::WhereClauseInExpr(def_id, _, hir_id, idx) =
             *error.obligation.cause.code().peel_derives()
         else {
             return false;
@@ -38,7 +37,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 ty::ClauseKind::Trait(pred) => {
                     (pred.trait_ref.args.to_vec(), Some(pred.self_ty().into()))
                 }
-                ty::ClauseKind::Projection(pred) => (pred.projection_ty.args.to_vec(), None),
+                ty::ClauseKind::Projection(pred) => (pred.projection_term.args.to_vec(), None),
                 ty::ClauseKind::ConstArgHasType(arg, ty) => (vec![ty.into(), arg.into()], None),
                 ty::ClauseKind::ConstEvaluatable(e) => (vec![e.into()], None),
                 _ => return false,
@@ -512,7 +511,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expr: &'tcx hir::Expr<'tcx>,
     ) -> Result<&'tcx hir::Expr<'tcx>, &'tcx hir::Expr<'tcx>> {
         match obligation_cause_code {
-            traits::ObligationCauseCode::SpannedWhereClauseInExpr(_, _, _, _) => {
+            traits::ObligationCauseCode::WhereClauseInExpr(_, _, _, _) => {
                 // This is the "root"; we assume that the `expr` is already pointing here.
                 // Therefore, we return `Ok` so that this `expr` can be refined further.
                 Ok(expr)
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 4bf82355b62..aea34407a2d 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -36,6 +36,7 @@ use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
 use rustc_middle::ty::adjustment::AllowTwoPhase;
 use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt};
+use rustc_middle::{bug, span_bug};
 use rustc_session::Session;
 use rustc_span::symbol::{kw, Ident};
 use rustc_span::{sym, BytePos, Span, DUMMY_SP};
@@ -2013,8 +2014,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         for (span, code) in errors_causecode {
             self.dcx().try_steal_modify_and_emit_err(span, StashKey::MaybeForgetReturn, |err| {
                 if let Some(fn_sig) = self.body_fn_sig()
-                    && let ObligationCauseCode::SpannedWhereClauseInExpr(_, _, binding_hir_id, ..) =
-                        code
+                    && let ObligationCauseCode::WhereClauseInExpr(_, _, binding_hir_id, ..) = code
                     && !fn_sig.output().is_unit()
                 {
                     let mut block_num = 0;
@@ -2103,7 +2103,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         //
         // This is because due to normalization, we often register duplicate
         // obligations with misc obligations that are basically impossible to
-        // line back up with a useful SpannedWhereClauseInExpr.
+        // line back up with a useful WhereClauseInExpr.
         for error in not_adjusted {
             for (span, predicate, cause) in &remap_cause {
                 if *predicate == error.obligation.predicate
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs
index 2ef254f644f..ac1e26df870 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs
@@ -38,7 +38,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.type_matches_expected_vid(expected_vid, data.self_ty())
             }
             ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => {
-                self.type_matches_expected_vid(expected_vid, data.projection_ty.self_ty())
+                self.type_matches_expected_vid(expected_vid, data.projection_term.self_ty())
             }
             ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
             | ty::PredicateKind::Subtype(..)
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index f1b719f24c7..11f288391c3 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -25,6 +25,7 @@ use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
 use rustc_infer::traits;
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::middle::stability::EvalResult;
+use rustc_middle::span_bug;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{
     self, suggest_constraining_type_params, Article, Binder, IsSuggestable, ToPredicate, Ty,
diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs
index 62711e40049..fb8863c143f 100644
--- a/compiler/rustc_hir_typeck/src/intrinsicck.rs
+++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs
@@ -2,6 +2,7 @@ use hir::HirId;
 use rustc_errors::{codes::*, struct_span_code_err};
 use rustc_hir as hir;
 use rustc_index::Idx;
+use rustc_middle::bug;
 use rustc_middle::ty::layout::{LayoutError, SizeSkeleton};
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
 use rustc_target::abi::{Pointer, VariantIdx};
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index e270e589505..6892da7a5e2 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -10,9 +10,6 @@
 #[macro_use]
 extern crate tracing;
 
-#[macro_use]
-extern crate rustc_middle;
-
 mod _match;
 mod autoderef;
 mod callee;
@@ -32,7 +29,6 @@ mod fallback;
 mod fn_ctxt;
 mod gather_locals;
 mod intrinsicck;
-mod mem_categorization;
 mod method;
 mod op;
 mod pat;
@@ -63,6 +59,7 @@ use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
 use rustc_infer::traits::{ObligationCauseCode, ObligationInspector, WellFormedLoc};
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::{bug, span_bug};
 use rustc_session::config;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::Span;
diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs
deleted file mode 100644
index ae71c484f7b..00000000000
--- a/compiler/rustc_hir_typeck/src/mem_categorization.rs
+++ /dev/null
@@ -1,774 +0,0 @@
-//! # Categorization
-//!
-//! The job of the categorization module is to analyze an expression to
-//! determine what kind of memory is used in evaluating it (for example,
-//! where dereferences occur and what kind of pointer is dereferenced;
-//! whether the memory is mutable, etc.).
-//!
-//! Categorization effectively transforms all of our expressions into
-//! expressions of the following forms (the actual enum has many more
-//! possibilities, naturally, but they are all variants of these base
-//! forms):
-//! ```ignore (not-rust)
-//! E = rvalue    // some computed rvalue
-//!   | x         // address of a local variable or argument
-//!   | *E        // deref of a ptr
-//!   | E.comp    // access to an interior component
-//! ```
-//! Imagine a routine ToAddr(Expr) that evaluates an expression and returns an
-//! address where the result is to be found. If Expr is a place, then this
-//! is the address of the place. If `Expr` is an rvalue, this is the address of
-//! some temporary spot in memory where the result is stored.
-//!
-//! Now, `cat_expr()` classifies the expression `Expr` and the address `A = ToAddr(Expr)`
-//! as follows:
-//!
-//! - `cat`: what kind of expression was this? This is a subset of the
-//!   full expression forms which only includes those that we care about
-//!   for the purpose of the analysis.
-//! - `mutbl`: mutability of the address `A`.
-//! - `ty`: the type of data found at the address `A`.
-//!
-//! The resulting categorization tree differs somewhat from the expressions
-//! themselves. For example, auto-derefs are explicit. Also, an index `a[b]` is
-//! decomposed into two operations: a dereference to reach the array data and
-//! then an index to jump forward to the relevant item.
-//!
-//! ## By-reference upvars
-//!
-//! One part of the codegen which may be non-obvious is that we translate
-//! closure upvars into the dereference of a borrowed pointer; this more closely
-//! resembles the runtime codegen. So, for example, if we had:
-//!
-//!     let mut x = 3;
-//!     let y = 5;
-//!     let inc = || x += y;
-//!
-//! Then when we categorize `x` (*within* the closure) we would yield a
-//! result of `*x'`, effectively, where `x'` is a `Categorization::Upvar` reference
-//! tied to `x`. The type of `x'` will be a borrowed pointer.
-
-use rustc_middle::hir::place::*;
-use rustc_middle::ty::adjustment;
-use rustc_middle::ty::fold::TypeFoldable;
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
-
-use rustc_data_structures::fx::FxIndexMap;
-use rustc_hir as hir;
-use rustc_hir::def::{CtorOf, DefKind, Res};
-use rustc_hir::def_id::LocalDefId;
-use rustc_hir::pat_util::EnumerateAndAdjustIterator;
-use rustc_hir::{HirId, PatKind};
-use rustc_infer::infer::InferCtxt;
-use rustc_span::Span;
-use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
-use rustc_trait_selection::infer::InferCtxtExt;
-
-pub(crate) trait HirNode {
-    fn hir_id(&self) -> HirId;
-}
-
-impl HirNode for hir::Expr<'_> {
-    fn hir_id(&self) -> HirId {
-        self.hir_id
-    }
-}
-
-impl HirNode for hir::Pat<'_> {
-    fn hir_id(&self) -> HirId {
-        self.hir_id
-    }
-}
-
-#[derive(Clone)]
-pub(crate) struct MemCategorizationContext<'a, 'tcx> {
-    pub(crate) typeck_results: &'a ty::TypeckResults<'tcx>,
-    infcx: &'a InferCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    body_owner: LocalDefId,
-    upvars: Option<&'tcx FxIndexMap<HirId, hir::Upvar>>,
-}
-
-pub(crate) type McResult<T> = Result<T, ()>;
-
-impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
-    /// Creates a `MemCategorizationContext`.
-    pub(crate) fn new(
-        infcx: &'a InferCtxt<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-        body_owner: LocalDefId,
-        typeck_results: &'a ty::TypeckResults<'tcx>,
-    ) -> MemCategorizationContext<'a, 'tcx> {
-        MemCategorizationContext {
-            typeck_results,
-            infcx,
-            param_env,
-            body_owner,
-            upvars: infcx.tcx.upvars_mentioned(body_owner),
-        }
-    }
-
-    pub(crate) fn tcx(&self) -> TyCtxt<'tcx> {
-        self.infcx.tcx
-    }
-
-    pub(crate) fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>) -> bool {
-        self.infcx.type_is_copy_modulo_regions(self.param_env, ty)
-    }
-
-    fn resolve_vars_if_possible<T>(&self, value: T) -> T
-    where
-        T: TypeFoldable<TyCtxt<'tcx>>,
-    {
-        self.infcx.resolve_vars_if_possible(value)
-    }
-
-    fn is_tainted_by_errors(&self) -> bool {
-        self.infcx.tainted_by_errors().is_some()
-    }
-
-    fn resolve_type_vars_or_error(&self, id: HirId, ty: Option<Ty<'tcx>>) -> McResult<Ty<'tcx>> {
-        match ty {
-            Some(ty) => {
-                let ty = self.resolve_vars_if_possible(ty);
-                if ty.references_error() || ty.is_ty_var() {
-                    debug!("resolve_type_vars_or_error: error from {:?}", ty);
-                    Err(())
-                } else {
-                    Ok(ty)
-                }
-            }
-            // FIXME
-            None if self.is_tainted_by_errors() => Err(()),
-            None => {
-                bug!(
-                    "no type for node {} in mem_categorization",
-                    self.tcx().hir().node_to_string(id)
-                );
-            }
-        }
-    }
-
-    pub(crate) fn node_ty(&self, hir_id: HirId) -> McResult<Ty<'tcx>> {
-        self.resolve_type_vars_or_error(hir_id, self.typeck_results.node_type_opt(hir_id))
-    }
-
-    fn expr_ty(&self, expr: &hir::Expr<'_>) -> McResult<Ty<'tcx>> {
-        self.resolve_type_vars_or_error(expr.hir_id, self.typeck_results.expr_ty_opt(expr))
-    }
-
-    pub(crate) fn expr_ty_adjusted(&self, expr: &hir::Expr<'_>) -> McResult<Ty<'tcx>> {
-        self.resolve_type_vars_or_error(expr.hir_id, self.typeck_results.expr_ty_adjusted_opt(expr))
-    }
-
-    /// Returns the type of value that this pattern matches against.
-    /// Some non-obvious cases:
-    ///
-    /// - a `ref x` binding matches against a value of type `T` and gives
-    ///   `x` the type `&T`; we return `T`.
-    /// - a pattern with implicit derefs (thanks to default binding
-    ///   modes #42640) may look like `Some(x)` but in fact have
-    ///   implicit deref patterns attached (e.g., it is really
-    ///   `&Some(x)`). In that case, we return the "outermost" type
-    ///   (e.g., `&Option<T>`).
-    pub(crate) fn pat_ty_adjusted(&self, pat: &hir::Pat<'_>) -> McResult<Ty<'tcx>> {
-        // Check for implicit `&` types wrapping the pattern; note
-        // that these are never attached to binding patterns, so
-        // actually this is somewhat "disjoint" from the code below
-        // that aims to account for `ref x`.
-        if let Some(vec) = self.typeck_results.pat_adjustments().get(pat.hir_id) {
-            if let Some(first_ty) = vec.first() {
-                debug!("pat_ty(pat={:?}) found adjusted ty `{:?}`", pat, first_ty);
-                return Ok(*first_ty);
-            }
-        }
-
-        self.pat_ty_unadjusted(pat)
-    }
-
-    /// Like `pat_ty`, but ignores implicit `&` patterns.
-    #[instrument(level = "debug", skip(self), ret)]
-    fn pat_ty_unadjusted(&self, pat: &hir::Pat<'_>) -> McResult<Ty<'tcx>> {
-        let base_ty = self.node_ty(pat.hir_id)?;
-        trace!(?base_ty);
-
-        // This code detects whether we are looking at a `ref x`,
-        // and if so, figures out what the type *being borrowed* is.
-        match pat.kind {
-            PatKind::Binding(..) => {
-                let bm = *self
-                    .typeck_results
-                    .pat_binding_modes()
-                    .get(pat.hir_id)
-                    .expect("missing binding mode");
-
-                if matches!(bm.0, hir::ByRef::Yes(_)) {
-                    // a bind-by-ref means that the base_ty will be the type of the ident itself,
-                    // but what we want here is the type of the underlying value being borrowed.
-                    // So peel off one-level, turning the &T into T.
-                    match base_ty.builtin_deref(false) {
-                        Some(ty) => Ok(ty),
-                        None => {
-                            debug!("By-ref binding of non-derefable type");
-                            Err(())
-                        }
-                    }
-                } else {
-                    Ok(base_ty)
-                }
-            }
-            _ => Ok(base_ty),
-        }
-    }
-
-    pub(crate) fn cat_expr(&self, expr: &hir::Expr<'_>) -> McResult<PlaceWithHirId<'tcx>> {
-        // This recursion helper avoids going through *too many*
-        // adjustments, since *only* non-overloaded deref recurses.
-        fn helper<'a, 'tcx>(
-            mc: &MemCategorizationContext<'a, 'tcx>,
-            expr: &hir::Expr<'_>,
-            adjustments: &[adjustment::Adjustment<'tcx>],
-        ) -> McResult<PlaceWithHirId<'tcx>> {
-            match adjustments.split_last() {
-                None => mc.cat_expr_unadjusted(expr),
-                Some((adjustment, previous)) => {
-                    mc.cat_expr_adjusted_with(expr, || helper(mc, expr, previous), adjustment)
-                }
-            }
-        }
-
-        helper(self, expr, self.typeck_results.expr_adjustments(expr))
-    }
-
-    pub(crate) fn cat_expr_adjusted(
-        &self,
-        expr: &hir::Expr<'_>,
-        previous: PlaceWithHirId<'tcx>,
-        adjustment: &adjustment::Adjustment<'tcx>,
-    ) -> McResult<PlaceWithHirId<'tcx>> {
-        self.cat_expr_adjusted_with(expr, || Ok(previous), adjustment)
-    }
-
-    #[instrument(level = "debug", skip(self, previous))]
-    fn cat_expr_adjusted_with<F>(
-        &self,
-        expr: &hir::Expr<'_>,
-        previous: F,
-        adjustment: &adjustment::Adjustment<'tcx>,
-    ) -> McResult<PlaceWithHirId<'tcx>>
-    where
-        F: FnOnce() -> McResult<PlaceWithHirId<'tcx>>,
-    {
-        let target = self.resolve_vars_if_possible(adjustment.target);
-        match adjustment.kind {
-            adjustment::Adjust::Deref(overloaded) => {
-                // Equivalent to *expr or something similar.
-                let base = if let Some(deref) = overloaded {
-                    let ref_ty = Ty::new_ref(self.tcx(), deref.region, target, deref.mutbl);
-                    self.cat_rvalue(expr.hir_id, ref_ty)
-                } else {
-                    previous()?
-                };
-                self.cat_deref(expr, base)
-            }
-
-            adjustment::Adjust::NeverToAny
-            | adjustment::Adjust::Pointer(_)
-            | adjustment::Adjust::Borrow(_)
-            | adjustment::Adjust::DynStar => {
-                // Result is an rvalue.
-                Ok(self.cat_rvalue(expr.hir_id, target))
-            }
-        }
-    }
-
-    #[instrument(level = "debug", skip(self), ret)]
-    pub(crate) fn cat_expr_unadjusted(
-        &self,
-        expr: &hir::Expr<'_>,
-    ) -> McResult<PlaceWithHirId<'tcx>> {
-        let expr_ty = self.expr_ty(expr)?;
-        match expr.kind {
-            hir::ExprKind::Unary(hir::UnOp::Deref, e_base) => {
-                if self.typeck_results.is_method_call(expr) {
-                    self.cat_overloaded_place(expr, e_base)
-                } else {
-                    let base = self.cat_expr(e_base)?;
-                    self.cat_deref(expr, base)
-                }
-            }
-
-            hir::ExprKind::Field(base, _) => {
-                let base = self.cat_expr(base)?;
-                debug!(?base);
-
-                let field_idx = self
-                    .typeck_results
-                    .field_indices()
-                    .get(expr.hir_id)
-                    .cloned()
-                    .expect("Field index not found");
-
-                Ok(self.cat_projection(
-                    expr,
-                    base,
-                    expr_ty,
-                    ProjectionKind::Field(field_idx, FIRST_VARIANT),
-                ))
-            }
-
-            hir::ExprKind::Index(base, _, _) => {
-                if self.typeck_results.is_method_call(expr) {
-                    // If this is an index implemented by a method call, then it
-                    // will include an implicit deref of the result.
-                    // The call to index() returns a `&T` value, which
-                    // is an rvalue. That is what we will be
-                    // dereferencing.
-                    self.cat_overloaded_place(expr, base)
-                } else {
-                    let base = self.cat_expr(base)?;
-                    Ok(self.cat_projection(expr, base, expr_ty, ProjectionKind::Index))
-                }
-            }
-
-            hir::ExprKind::Path(ref qpath) => {
-                let res = self.typeck_results.qpath_res(qpath, expr.hir_id);
-                self.cat_res(expr.hir_id, expr.span, expr_ty, res)
-            }
-
-            hir::ExprKind::Type(e, _) => self.cat_expr(e),
-
-            hir::ExprKind::AddrOf(..)
-            | hir::ExprKind::Call(..)
-            | hir::ExprKind::Assign(..)
-            | hir::ExprKind::AssignOp(..)
-            | hir::ExprKind::Closure { .. }
-            | hir::ExprKind::Ret(..)
-            | hir::ExprKind::Become(..)
-            | hir::ExprKind::Unary(..)
-            | hir::ExprKind::Yield(..)
-            | hir::ExprKind::MethodCall(..)
-            | hir::ExprKind::Cast(..)
-            | hir::ExprKind::DropTemps(..)
-            | hir::ExprKind::Array(..)
-            | hir::ExprKind::If(..)
-            | hir::ExprKind::Tup(..)
-            | hir::ExprKind::Binary(..)
-            | hir::ExprKind::Block(..)
-            | hir::ExprKind::Let(..)
-            | hir::ExprKind::Loop(..)
-            | hir::ExprKind::Match(..)
-            | hir::ExprKind::Lit(..)
-            | hir::ExprKind::ConstBlock(..)
-            | hir::ExprKind::Break(..)
-            | hir::ExprKind::Continue(..)
-            | hir::ExprKind::Struct(..)
-            | hir::ExprKind::Repeat(..)
-            | hir::ExprKind::InlineAsm(..)
-            | hir::ExprKind::OffsetOf(..)
-            | hir::ExprKind::Err(_) => Ok(self.cat_rvalue(expr.hir_id, expr_ty)),
-        }
-    }
-
-    #[instrument(level = "debug", skip(self, span), ret)]
-    pub(crate) fn cat_res(
-        &self,
-        hir_id: HirId,
-        span: Span,
-        expr_ty: Ty<'tcx>,
-        res: Res,
-    ) -> McResult<PlaceWithHirId<'tcx>> {
-        match res {
-            Res::Def(
-                DefKind::Ctor(..)
-                | DefKind::Const
-                | DefKind::ConstParam
-                | DefKind::AssocConst
-                | DefKind::Fn
-                | DefKind::AssocFn,
-                _,
-            )
-            | Res::SelfCtor(..) => Ok(self.cat_rvalue(hir_id, expr_ty)),
-
-            Res::Def(DefKind::Static { .. }, _) => {
-                Ok(PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::StaticItem, Vec::new()))
-            }
-
-            Res::Local(var_id) => {
-                if self.upvars.is_some_and(|upvars| upvars.contains_key(&var_id)) {
-                    self.cat_upvar(hir_id, var_id)
-                } else {
-                    Ok(PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::Local(var_id), Vec::new()))
-                }
-            }
-
-            def => span_bug!(span, "unexpected definition in memory categorization: {:?}", def),
-        }
-    }
-
-    /// Categorize an upvar.
-    ///
-    /// Note: the actual upvar access contains invisible derefs of closure
-    /// environment and upvar reference as appropriate. Only regionck cares
-    /// about these dereferences, so we let it compute them as needed.
-    #[instrument(level = "debug", skip(self), ret)]
-    fn cat_upvar(&self, hir_id: HirId, var_id: HirId) -> McResult<PlaceWithHirId<'tcx>> {
-        let closure_expr_def_id = self.body_owner;
-
-        let upvar_id = ty::UpvarId {
-            var_path: ty::UpvarPath { hir_id: var_id },
-            closure_expr_id: closure_expr_def_id,
-        };
-        let var_ty = self.node_ty(var_id)?;
-
-        Ok(PlaceWithHirId::new(hir_id, var_ty, PlaceBase::Upvar(upvar_id), Vec::new()))
-    }
-
-    #[instrument(level = "debug", skip(self), ret)]
-    pub(crate) fn cat_rvalue(&self, hir_id: HirId, expr_ty: Ty<'tcx>) -> PlaceWithHirId<'tcx> {
-        PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::Rvalue, Vec::new())
-    }
-
-    #[instrument(level = "debug", skip(self, node), ret)]
-    pub(crate) fn cat_projection<N: HirNode>(
-        &self,
-        node: &N,
-        base_place: PlaceWithHirId<'tcx>,
-        ty: Ty<'tcx>,
-        kind: ProjectionKind,
-    ) -> PlaceWithHirId<'tcx> {
-        let place_ty = base_place.place.ty();
-        let mut projections = base_place.place.projections;
-
-        let node_ty = self.typeck_results.node_type(node.hir_id());
-        // Opaque types can't have field projections, but we can instead convert
-        // the current place in-place (heh) to the hidden type, and then apply all
-        // follow up projections on that.
-        if node_ty != place_ty && matches!(place_ty.kind(), ty::Alias(ty::Opaque, ..)) {
-            projections.push(Projection { kind: ProjectionKind::OpaqueCast, ty: node_ty });
-        }
-        projections.push(Projection { kind, ty });
-        PlaceWithHirId::new(
-            node.hir_id(),
-            base_place.place.base_ty,
-            base_place.place.base,
-            projections,
-        )
-    }
-
-    #[instrument(level = "debug", skip(self))]
-    fn cat_overloaded_place(
-        &self,
-        expr: &hir::Expr<'_>,
-        base: &hir::Expr<'_>,
-    ) -> McResult<PlaceWithHirId<'tcx>> {
-        // Reconstruct the output assuming it's a reference with the
-        // same region and mutability as the receiver. This holds for
-        // `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`.
-        let place_ty = self.expr_ty(expr)?;
-        let base_ty = self.expr_ty_adjusted(base)?;
-
-        let ty::Ref(region, _, mutbl) = *base_ty.kind() else {
-            span_bug!(expr.span, "cat_overloaded_place: base is not a reference");
-        };
-        let ref_ty = Ty::new_ref(self.tcx(), region, place_ty, mutbl);
-
-        let base = self.cat_rvalue(expr.hir_id, ref_ty);
-        self.cat_deref(expr, base)
-    }
-
-    #[instrument(level = "debug", skip(self, node), ret)]
-    fn cat_deref(
-        &self,
-        node: &impl HirNode,
-        base_place: PlaceWithHirId<'tcx>,
-    ) -> McResult<PlaceWithHirId<'tcx>> {
-        let base_curr_ty = base_place.place.ty();
-        let deref_ty = match base_curr_ty.builtin_deref(true) {
-            Some(pointee_ty) => pointee_ty,
-            None => {
-                debug!("explicit deref of non-derefable type: {:?}", base_curr_ty);
-                return Err(());
-            }
-        };
-        let mut projections = base_place.place.projections;
-        projections.push(Projection { kind: ProjectionKind::Deref, ty: deref_ty });
-
-        Ok(PlaceWithHirId::new(
-            node.hir_id(),
-            base_place.place.base_ty,
-            base_place.place.base,
-            projections,
-        ))
-    }
-
-    pub(crate) fn cat_pattern<F>(
-        &self,
-        place: PlaceWithHirId<'tcx>,
-        pat: &hir::Pat<'_>,
-        mut op: F,
-    ) -> McResult<()>
-    where
-        F: FnMut(&PlaceWithHirId<'tcx>, &hir::Pat<'_>),
-    {
-        self.cat_pattern_(place, pat, &mut op)
-    }
-
-    /// Returns the variant index for an ADT used within a Struct or TupleStruct pattern
-    /// Here `pat_hir_id` is the HirId of the pattern itself.
-    fn variant_index_for_adt(
-        &self,
-        qpath: &hir::QPath<'_>,
-        pat_hir_id: HirId,
-        span: Span,
-    ) -> McResult<VariantIdx> {
-        let res = self.typeck_results.qpath_res(qpath, pat_hir_id);
-        let ty = self.typeck_results.node_type(pat_hir_id);
-        let ty::Adt(adt_def, _) = ty.kind() else {
-            self.tcx()
-                .dcx()
-                .span_delayed_bug(span, "struct or tuple struct pattern not applied to an ADT");
-            return Err(());
-        };
-
-        match res {
-            Res::Def(DefKind::Variant, variant_id) => Ok(adt_def.variant_index_with_id(variant_id)),
-            Res::Def(DefKind::Ctor(CtorOf::Variant, ..), variant_ctor_id) => {
-                Ok(adt_def.variant_index_with_ctor_id(variant_ctor_id))
-            }
-            Res::Def(DefKind::Ctor(CtorOf::Struct, ..), _)
-            | Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _)
-            | Res::SelfCtor(..)
-            | Res::SelfTyParam { .. }
-            | Res::SelfTyAlias { .. } => {
-                // Structs and Unions have only have one variant.
-                Ok(FIRST_VARIANT)
-            }
-            _ => bug!("expected ADT path, found={:?}", res),
-        }
-    }
-
-    /// Returns the total number of fields in an ADT variant used within a pattern.
-    /// Here `pat_hir_id` is the HirId of the pattern itself.
-    fn total_fields_in_adt_variant(
-        &self,
-        pat_hir_id: HirId,
-        variant_index: VariantIdx,
-        span: Span,
-    ) -> McResult<usize> {
-        let ty = self.typeck_results.node_type(pat_hir_id);
-        match ty.kind() {
-            ty::Adt(adt_def, _) => Ok(adt_def.variant(variant_index).fields.len()),
-            _ => {
-                self.tcx()
-                    .dcx()
-                    .span_bug(span, "struct or tuple struct pattern not applied to an ADT");
-            }
-        }
-    }
-
-    /// Returns the total number of fields in a tuple used within a Tuple pattern.
-    /// Here `pat_hir_id` is the HirId of the pattern itself.
-    fn total_fields_in_tuple(&self, pat_hir_id: HirId, span: Span) -> McResult<usize> {
-        let ty = self.typeck_results.node_type(pat_hir_id);
-        match ty.kind() {
-            ty::Tuple(args) => Ok(args.len()),
-            _ => {
-                self.tcx().dcx().span_delayed_bug(span, "tuple pattern not applied to a tuple");
-                Err(())
-            }
-        }
-    }
-
-    /// Here, `place` is the `PlaceWithHirId` being matched and pat is the pattern it
-    /// is being matched against.
-    ///
-    /// In general, the way that this works is that we walk down the pattern,
-    /// constructing a `PlaceWithHirId` that represents the path that will be taken
-    /// to reach the value being matched.
-    #[instrument(skip(self, op), ret, level = "debug")]
-    fn cat_pattern_<F>(
-        &self,
-        mut place_with_id: PlaceWithHirId<'tcx>,
-        pat: &hir::Pat<'_>,
-        op: &mut F,
-    ) -> McResult<()>
-    where
-        F: FnMut(&PlaceWithHirId<'tcx>, &hir::Pat<'_>),
-    {
-        // If (pattern) adjustments are active for this pattern, adjust the `PlaceWithHirId` correspondingly.
-        // `PlaceWithHirId`s are constructed differently from patterns. For example, in
-        //
-        // ```
-        // match foo {
-        //     &&Some(x, ) => { ... },
-        //     _ => { ... },
-        // }
-        // ```
-        //
-        // the pattern `&&Some(x,)` is represented as `Ref { Ref { TupleStruct }}`. To build the
-        // corresponding `PlaceWithHirId` we start with the `PlaceWithHirId` for `foo`, and then, by traversing the
-        // pattern, try to answer the question: given the address of `foo`, how is `x` reached?
-        //
-        // `&&Some(x,)` `place_foo`
-        //  `&Some(x,)` `deref { place_foo}`
-        //   `Some(x,)` `deref { deref { place_foo }}`
-        //       `(x,)` `field0 { deref { deref { place_foo }}}` <- resulting place
-        //
-        // The above example has no adjustments. If the code were instead the (after adjustments,
-        // equivalent) version
-        //
-        // ```
-        // match foo {
-        //     Some(x, ) => { ... },
-        //     _ => { ... },
-        // }
-        // ```
-        //
-        // Then we see that to get the same result, we must start with
-        // `deref { deref { place_foo }}` instead of `place_foo` since the pattern is now `Some(x,)`
-        // and not `&&Some(x,)`, even though its assigned type is that of `&&Some(x,)`.
-        for _ in 0..self.typeck_results.pat_adjustments().get(pat.hir_id).map_or(0, |v| v.len()) {
-            debug!("applying adjustment to place_with_id={:?}", place_with_id);
-            place_with_id = self.cat_deref(pat, place_with_id)?;
-        }
-        let place_with_id = place_with_id; // lose mutability
-        debug!("applied adjustment derefs to get place_with_id={:?}", place_with_id);
-
-        // Invoke the callback, but only now, after the `place_with_id` has adjusted.
-        //
-        // To see that this makes sense, consider `match &Some(3) { Some(x) => { ... }}`. In that
-        // case, the initial `place_with_id` will be that for `&Some(3)` and the pattern is `Some(x)`. We
-        // don't want to call `op` with these incompatible values. As written, what happens instead
-        // is that `op` is called with the adjusted place (that for `*&Some(3)`) and the pattern
-        // `Some(x)` (which matches). Recursing once more, `*&Some(3)` and the pattern `Some(x)`
-        // result in the place `Downcast<Some>(*&Some(3)).0` associated to `x` and invoke `op` with
-        // that (where the `ref` on `x` is implied).
-        op(&place_with_id, pat);
-
-        match pat.kind {
-            PatKind::Tuple(subpats, dots_pos) => {
-                // (p1, ..., pN)
-                let total_fields = self.total_fields_in_tuple(pat.hir_id, pat.span)?;
-
-                for (i, subpat) in subpats.iter().enumerate_and_adjust(total_fields, dots_pos) {
-                    let subpat_ty = self.pat_ty_adjusted(subpat)?;
-                    let projection_kind =
-                        ProjectionKind::Field(FieldIdx::from_usize(i), FIRST_VARIANT);
-                    let sub_place =
-                        self.cat_projection(pat, place_with_id.clone(), subpat_ty, projection_kind);
-                    self.cat_pattern_(sub_place, subpat, op)?;
-                }
-            }
-
-            PatKind::TupleStruct(ref qpath, subpats, dots_pos) => {
-                // S(p1, ..., pN)
-                let variant_index = self.variant_index_for_adt(qpath, pat.hir_id, pat.span)?;
-                let total_fields =
-                    self.total_fields_in_adt_variant(pat.hir_id, variant_index, pat.span)?;
-
-                for (i, subpat) in subpats.iter().enumerate_and_adjust(total_fields, dots_pos) {
-                    let subpat_ty = self.pat_ty_adjusted(subpat)?;
-                    let projection_kind =
-                        ProjectionKind::Field(FieldIdx::from_usize(i), variant_index);
-                    let sub_place =
-                        self.cat_projection(pat, place_with_id.clone(), subpat_ty, projection_kind);
-                    self.cat_pattern_(sub_place, subpat, op)?;
-                }
-            }
-
-            PatKind::Struct(ref qpath, field_pats, _) => {
-                // S { f1: p1, ..., fN: pN }
-
-                let variant_index = self.variant_index_for_adt(qpath, pat.hir_id, pat.span)?;
-
-                for fp in field_pats {
-                    let field_ty = self.pat_ty_adjusted(fp.pat)?;
-                    let field_index = self
-                        .typeck_results
-                        .field_indices()
-                        .get(fp.hir_id)
-                        .cloned()
-                        .expect("no index for a field");
-
-                    let field_place = self.cat_projection(
-                        pat,
-                        place_with_id.clone(),
-                        field_ty,
-                        ProjectionKind::Field(field_index, variant_index),
-                    );
-                    self.cat_pattern_(field_place, fp.pat, op)?;
-                }
-            }
-
-            PatKind::Or(pats) => {
-                for pat in pats {
-                    self.cat_pattern_(place_with_id.clone(), pat, op)?;
-                }
-            }
-
-            PatKind::Binding(.., Some(subpat)) => {
-                self.cat_pattern_(place_with_id, subpat, op)?;
-            }
-
-            PatKind::Box(subpat) | PatKind::Ref(subpat, _) => {
-                // box p1, &p1, &mut p1. we can ignore the mutability of
-                // PatKind::Ref since that information is already contained
-                // in the type.
-                let subplace = self.cat_deref(pat, place_with_id)?;
-                self.cat_pattern_(subplace, subpat, op)?;
-            }
-            PatKind::Deref(subpat) => {
-                let mutable = self.typeck_results.pat_has_ref_mut_binding(subpat);
-                let mutability = if mutable { hir::Mutability::Mut } else { hir::Mutability::Not };
-                let re_erased = self.tcx().lifetimes.re_erased;
-                let ty = self.pat_ty_adjusted(subpat)?;
-                let ty = Ty::new_ref(self.tcx(), re_erased, ty, mutability);
-                // A deref pattern generates a temporary.
-                let place = self.cat_rvalue(pat.hir_id, ty);
-                self.cat_pattern_(place, subpat, op)?;
-            }
-
-            PatKind::Slice(before, ref slice, after) => {
-                let Some(element_ty) = place_with_id.place.ty().builtin_index() else {
-                    debug!("explicit index of non-indexable type {:?}", place_with_id);
-                    return Err(());
-                };
-                let elt_place = self.cat_projection(
-                    pat,
-                    place_with_id.clone(),
-                    element_ty,
-                    ProjectionKind::Index,
-                );
-                for before_pat in before {
-                    self.cat_pattern_(elt_place.clone(), before_pat, op)?;
-                }
-                if let Some(slice_pat) = *slice {
-                    let slice_pat_ty = self.pat_ty_adjusted(slice_pat)?;
-                    let slice_place = self.cat_projection(
-                        pat,
-                        place_with_id,
-                        slice_pat_ty,
-                        ProjectionKind::Subslice,
-                    );
-                    self.cat_pattern_(slice_place, slice_pat, op)?;
-                }
-                for after_pat in after {
-                    self.cat_pattern_(elt_place.clone(), after_pat, op)?;
-                }
-            }
-
-            PatKind::Path(_)
-            | PatKind::Binding(.., None)
-            | PatKind::Lit(..)
-            | PatKind::Range(..)
-            | PatKind::Never
-            | PatKind::Wild
-            | PatKind::Err(_) => {
-                // always ok
-            }
-        }
-
-        Ok(())
-    }
-}
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index 56c296fc1c0..74254058534 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -16,6 +16,7 @@ use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::{
     self, GenericArgs, GenericArgsRef, GenericParamDefKind, Ty, TyCtxt, UserArgs, UserType,
 };
+use rustc_middle::{bug, span_bug};
 use rustc_span::{Span, DUMMY_SP};
 use rustc_trait_selection::traits;
 
@@ -564,16 +565,12 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         // `self.add_required_obligations(self.span, def_id, &all_args);`
         for obligation in traits::predicates_for_generics(
             |idx, span| {
-                let code = if span.is_dummy() {
-                    ObligationCauseCode::WhereClauseInExpr(def_id, self.call_expr.hir_id, idx)
-                } else {
-                    ObligationCauseCode::SpannedWhereClauseInExpr(
-                        def_id,
-                        span,
-                        self.call_expr.hir_id,
-                        idx,
-                    )
-                };
+                let code = ObligationCauseCode::WhereClauseInExpr(
+                    def_id,
+                    span,
+                    self.call_expr.hir_id,
+                    idx,
+                );
                 traits::ObligationCause::new(self.span, self.body_id, code)
             },
             self.param_env,
diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs
index ec613f3d14e..f82182fa058 100644
--- a/compiler/rustc_hir_typeck/src/method/mod.rs
+++ b/compiler/rustc_hir_typeck/src/method/mod.rs
@@ -20,6 +20,7 @@ use rustc_middle::query::Providers;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::{self, GenericParamDefKind, Ty, TypeVisitableExt};
 use rustc_middle::ty::{GenericArgs, GenericArgsRef};
+use rustc_middle::{bug, span_bug};
 use rustc_span::symbol::Ident;
 use rustc_span::Span;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
diff --git a/compiler/rustc_hir_typeck/src/method/prelude2021.rs b/compiler/rustc_hir_typeck/src/method/prelude2021.rs
index 305aaf3b8dd..a305461344d 100644
--- a/compiler/rustc_hir_typeck/src/method/prelude2021.rs
+++ b/compiler/rustc_hir_typeck/src/method/prelude2021.rs
@@ -7,6 +7,7 @@ use hir::HirId;
 use hir::ItemKind;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
+use rustc_middle::span_bug;
 use rustc_middle::ty::{self, Ty};
 use rustc_session::lint::builtin::RUST_2021_PRELUDE_COLLISIONS;
 use rustc_span::symbol::kw::{Empty, Underscore};
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 434bd957498..81e179c9090 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -24,6 +24,7 @@ use rustc_middle::ty::GenericParamDefKind;
 use rustc_middle::ty::ToPredicate;
 use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
 use rustc_middle::ty::{GenericArgs, GenericArgsRef};
+use rustc_middle::{bug, span_bug};
 use rustc_session::lint;
 use rustc_span::def_id::DefId;
 use rustc_span::def_id::LocalDefId;
@@ -1401,20 +1402,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                     // Convert the bounds into obligations.
                     ocx.register_obligations(traits::predicates_for_generics(
                         |idx, span| {
-                            let code = if span.is_dummy() {
-                                ObligationCauseCode::WhereClauseInExpr(
-                                    impl_def_id,
-                                    self.scope_expr_id,
-                                    idx,
-                                )
-                            } else {
-                                ObligationCauseCode::SpannedWhereClauseInExpr(
-                                    impl_def_id,
-                                    span,
-                                    self.scope_expr_id,
-                                    idx,
-                                )
-                            };
+                            let code = ObligationCauseCode::WhereClauseInExpr(
+                                impl_def_id,
+                                span,
+                                self.scope_expr_id,
+                                idx,
+                            );
                             ObligationCause::new(self.span, self.body_id, code)
                         },
                         self.param_env,
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index d1891a032e1..d50e9943384 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -23,6 +23,7 @@ use rustc_hir::PatKind::Binding;
 use rustc_hir::PathSegment;
 use rustc_hir::{ExprKind, Node, QPath};
 use rustc_infer::infer::{self, RegionVariableOrigin};
+use rustc_middle::bug;
 use rustc_middle::ty::fast_reject::DeepRejectCtxt;
 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
 use rustc_middle::ty::print::{
@@ -46,7 +47,6 @@ use std::borrow::Cow;
 use super::probe::{AutorefOrPtrAdjustment, IsSuggestion, Mode, ProbeScope};
 use super::{CandidateSource, MethodError, NoMatchData};
 use rustc_hir::intravisit::Visitor;
-use std::iter;
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
@@ -172,7 +172,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
                 }
             }
-            ty::Slice(..) | ty::Adt(..) | ty::Alias(ty::AliasKind::Opaque, _) => {
+            ty::Slice(..) | ty::Adt(..) | ty::Alias(ty::Opaque, _) => {
                 for unsatisfied in unsatisfied_predicates.iter() {
                     if is_iterator_predicate(unsatisfied.0, self.tcx) {
                         return true;
@@ -787,26 +787,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => {
                         let pred = bound_predicate.rebind(pred);
                         // `<Foo as Iterator>::Item = String`.
-                        let projection_ty = pred.skip_binder().projection_ty;
-
-                        let args_with_infer_self = tcx.mk_args_from_iter(
-                            iter::once(Ty::new_var(tcx, ty::TyVid::ZERO).into())
-                                .chain(projection_ty.args.iter().skip(1)),
-                        );
-
-                        let quiet_projection_ty =
-                            ty::AliasTy::new(tcx, projection_ty.def_id, args_with_infer_self);
+                        let projection_term = pred.skip_binder().projection_term;
+                        let quiet_projection_term =
+                            projection_term.with_self_ty(tcx, Ty::new_var(tcx, ty::TyVid::ZERO));
 
                         let term = pred.skip_binder().term;
 
-                        let obligation = format!("{projection_ty} = {term}");
+                        let obligation = format!("{projection_term} = {term}");
                         let quiet = with_forced_trimmed_paths!(format!(
                             "{} = {}",
-                            quiet_projection_ty, term
+                            quiet_projection_term, term
                         ));
 
-                        bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
-                        Some((obligation, projection_ty.self_ty()))
+                        bound_span_label(projection_term.self_ty(), &obligation, &quiet);
+                        Some((obligation, projection_term.self_ty()))
                     }
                     ty::PredicateKind::Clause(ty::ClauseKind::Trait(poly_trait_ref)) => {
                         let p = poly_trait_ref.trait_ref;
@@ -832,9 +826,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         (data.impl_or_alias_def_id, data.span)
                     }
                     Some(
-                        ObligationCauseCode::SpannedWhereClauseInExpr(def_id, span, _, _)
-                        | ObligationCauseCode::SpannedWhereClause(def_id, span),
-                    ) => (*def_id, *span),
+                        ObligationCauseCode::WhereClauseInExpr(def_id, span, _, _)
+                        | ObligationCauseCode::WhereClause(def_id, span),
+                    ) if !span.is_dummy() => (*def_id, *span),
                     _ => continue,
                 };
 
diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs
index dca1cda0694..e371775be0a 100644
--- a/compiler/rustc_hir_typeck/src/op.rs
+++ b/compiler/rustc_hir_typeck/src/op.rs
@@ -13,6 +13,7 @@ use rustc_middle::ty::adjustment::{
 };
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::{bug, span_bug};
 use rustc_session::errors::ExprParenthesesNeeded;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{sym, Ident};
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index b1a0aa689cf..b9b220d5af8 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -11,6 +11,7 @@ use rustc_hir::{self as hir, BindingMode, ByRef, HirId, Mutability, Pat, PatKind
 use rustc_infer::infer;
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::ty::{self, Ty, TypeVisitableExt};
+use rustc_middle::{bug, span_bug};
 use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
 use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::hygiene::DesugaringKind;
@@ -73,21 +74,23 @@ struct TopInfo<'tcx> {
     ///              found type `std::result::Result<_, _>`
     /// ```
     span: Option<Span>,
+    /// The [`HirId`] of the top-level pattern.
+    hir_id: HirId,
 }
 
 #[derive(Copy, Clone)]
 struct PatInfo<'tcx, 'a> {
     binding_mode: ByRef,
-    max_ref_mutbl: Mutability,
-    top_info: TopInfo<'tcx>,
-    decl_origin: Option<DeclOrigin<'a>>,
+    max_ref_mutbl: MutblCap,
+    top_info: &'a TopInfo<'tcx>,
+    decl_origin: Option<DeclOrigin<'tcx>>,
 
     /// The depth of current pattern
     current_depth: u32,
 }
 
 impl<'tcx> FnCtxt<'_, 'tcx> {
-    fn pattern_cause(&self, ti: TopInfo<'tcx>, cause_span: Span) -> ObligationCause<'tcx> {
+    fn pattern_cause(&self, ti: &TopInfo<'tcx>, cause_span: Span) -> ObligationCause<'tcx> {
         let code = ObligationCauseCode::Pattern {
             span: ti.span,
             root_ty: ti.expected,
@@ -101,7 +104,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
         cause_span: Span,
         expected: Ty<'tcx>,
         actual: Ty<'tcx>,
-        ti: TopInfo<'tcx>,
+        ti: &TopInfo<'tcx>,
     ) -> Option<Diag<'tcx>> {
         let mut diag =
             self.demand_eqtype_with_origin(&self.pattern_cause(ti, cause_span), expected, actual)?;
@@ -118,7 +121,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
         cause_span: Span,
         expected: Ty<'tcx>,
         actual: Ty<'tcx>,
-        ti: TopInfo<'tcx>,
+        ti: &TopInfo<'tcx>,
     ) {
         if let Some(err) = self.demand_eqtype_pat_diag(cause_span, expected, actual, ti) {
             err.emit();
@@ -127,22 +130,61 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
 }
 
 /// Mode for adjusting the expected type and binding mode.
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
 enum AdjustMode {
     /// Peel off all immediate reference types.
     Peel,
     /// Reset binding mode to the initial mode.
     /// Used for destructuring assignment, where we don't want any match ergonomics.
     Reset,
-    /// Produced by ref patterns.
-    /// Reset the binding mode to the initial mode,
-    /// and if the old biding mode was by-reference
-    /// with mutability matching the pattern,
-    /// mark the pattern as having consumed this reference.
-    ResetAndConsumeRef(Mutability),
     /// Pass on the input binding mode and expected type.
     Pass,
 }
 
+/// `ref mut` patterns (explicit or match-ergonomics)
+/// are not allowed behind an `&` reference.
+///
+/// This includes explicit `ref mut` behind `&` patterns
+/// that match against `&mut` references,
+/// where the code would have compiled
+/// had the pattern been written as `&mut`.
+/// However, the borrow checker will not catch
+/// this last case, so we need to throw an error ourselves.
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+enum MutblCap {
+    /// Mutability restricted to immutable.
+    Not,
+
+    /// Mutability restricted to immutable, but only because of the pattern
+    /// (not the scrutinee type).
+    ///
+    /// The contained span, if present, points to an `&` pattern
+    /// that is the reason for the restriction,
+    /// and which will be reported in a diagnostic.
+    WeaklyNot(Option<Span>),
+
+    /// No restriction on mutability
+    Mut,
+}
+
+impl MutblCap {
+    #[must_use]
+    fn cap_to_weakly_not(self, span: Option<Span>) -> Self {
+        match self {
+            MutblCap::Not => MutblCap::Not,
+            _ => MutblCap::WeaklyNot(span),
+        }
+    }
+
+    #[must_use]
+    fn as_mutbl(self) -> Mutability {
+        match self {
+            MutblCap::Not | MutblCap::WeaklyNot(_) => Mutability::Not,
+            MutblCap::Mut => Mutability::Mut,
+        }
+    }
+}
+
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Type check the given top level pattern against the `expected` type.
     ///
@@ -160,11 +202,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         origin_expr: Option<&'tcx hir::Expr<'tcx>>,
         decl_origin: Option<DeclOrigin<'tcx>>,
     ) {
-        let info = TopInfo { expected, origin_expr, span };
+        let info = TopInfo { expected, origin_expr, span, hir_id: pat.hir_id };
         let pat_info = PatInfo {
             binding_mode: ByRef::No,
-            max_ref_mutbl: Mutability::Mut,
-            top_info: info,
+            max_ref_mutbl: MutblCap::Mut,
+            top_info: &info,
             decl_origin,
             current_depth: 0,
         };
@@ -172,14 +214,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 
     /// Type check the given `pat` against the `expected` type
-    /// with the provided `def_bm` (default binding mode).
+    /// with the provided `binding_mode` (default binding mode).
     ///
     /// Outside of this module, `check_pat_top` should always be used.
     /// Conversely, inside this module, `check_pat_top` should never be used.
     #[instrument(level = "debug", skip(self, pat_info))]
     fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx, '_>) {
-        let PatInfo { binding_mode: def_bm, max_ref_mutbl, top_info: ti, current_depth, .. } =
-            pat_info;
+        let PatInfo { binding_mode, max_ref_mutbl, top_info: ti, current_depth, .. } = pat_info;
 
         let path_res = match &pat.kind {
             PatKind::Path(qpath) => Some(
@@ -188,10 +229,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             _ => None,
         };
         let adjust_mode = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res));
-        let (expected, def_bm, max_ref_mutbl, ref_pattern_already_consumed) =
-            self.calc_default_binding_mode(pat, expected, def_bm, adjust_mode, max_ref_mutbl);
+        let (expected, binding_mode, max_ref_mutbl) =
+            self.calc_default_binding_mode(pat, expected, binding_mode, adjust_mode, max_ref_mutbl);
         let pat_info = PatInfo {
-            binding_mode: def_bm,
+            binding_mode,
             max_ref_mutbl,
             top_info: ti,
             decl_origin: pat_info.decl_origin,
@@ -204,8 +245,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             PatKind::Never => expected,
             PatKind::Lit(lt) => self.check_pat_lit(pat.span, lt, expected, ti),
             PatKind::Range(lhs, rhs, _) => self.check_pat_range(pat.span, lhs, rhs, expected, ti),
-            PatKind::Binding(ba, var_id, _, sub) => {
-                self.check_pat_ident(pat, ba, var_id, sub, expected, pat_info)
+            PatKind::Binding(ba, var_id, ident, sub) => {
+                self.check_pat_ident(pat, ba, var_id, ident, sub, expected, pat_info)
             }
             PatKind::TupleStruct(ref qpath, subpats, ddpos) => {
                 self.check_pat_tuple_struct(pat, qpath, subpats, ddpos, expected, pat_info)
@@ -227,14 +268,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
             PatKind::Box(inner) => self.check_pat_box(pat.span, inner, expected, pat_info),
             PatKind::Deref(inner) => self.check_pat_deref(pat.span, inner, expected, pat_info),
-            PatKind::Ref(inner, mutbl) => self.check_pat_ref(
-                pat,
-                inner,
-                mutbl,
-                expected,
-                pat_info,
-                ref_pattern_already_consumed,
-            ),
+            PatKind::Ref(inner, mutbl) => self.check_pat_ref(pat, inner, mutbl, expected, pat_info),
             PatKind::Slice(before, slice, after) => {
                 self.check_pat_slice(pat.span, before, slice, after, expected, pat_info)
             }
@@ -287,52 +321,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     /// Compute the new expected type and default binding mode from the old ones
     /// as well as the pattern form we are currently checking.
-    ///
-    /// Last entry is only relevant for ref patterns (`&` and `&mut`);
-    /// if `true`, then the ref pattern consumed a match ergonomics inserted reference
-    /// and so does no need to match against a reference in the scrutinee type.
     fn calc_default_binding_mode(
         &self,
         pat: &'tcx Pat<'tcx>,
         expected: Ty<'tcx>,
         def_br: ByRef,
         adjust_mode: AdjustMode,
-        max_ref_mutbl: Mutability,
-    ) -> (Ty<'tcx>, ByRef, Mutability, bool) {
-        if let ByRef::Yes(mutbl) = def_br {
-            debug_assert!(mutbl <= max_ref_mutbl);
+        max_ref_mutbl: MutblCap,
+    ) -> (Ty<'tcx>, ByRef, MutblCap) {
+        if let ByRef::Yes(Mutability::Mut) = def_br {
+            debug_assert!(max_ref_mutbl == MutblCap::Mut);
         }
         match adjust_mode {
-            AdjustMode::Pass => (expected, def_br, max_ref_mutbl, false),
-            AdjustMode::Reset => (expected, ByRef::No, Mutability::Mut, false),
-            AdjustMode::ResetAndConsumeRef(ref_pat_mutbl) => {
-                let mutbls_match = def_br == ByRef::Yes(ref_pat_mutbl);
-                if pat.span.at_least_rust_2024() && self.tcx.features().ref_pat_eat_one_layer_2024 {
-                    if mutbls_match {
-                        debug!("consuming inherited reference");
-                        (expected, ByRef::No, cmp::min(max_ref_mutbl, ref_pat_mutbl), true)
-                    } else {
-                        let (new_ty, new_bm, max_ref_mutbl) = if ref_pat_mutbl == Mutability::Mut {
-                            self.peel_off_references(
-                                pat,
-                                expected,
-                                def_br,
-                                Mutability::Not,
-                                max_ref_mutbl,
-                            )
-                        } else {
-                            (expected, def_br.cap_ref_mutability(Mutability::Not), Mutability::Not)
-                        };
-                        (new_ty, new_bm, max_ref_mutbl, false)
-                    }
-                } else {
-                    (expected, ByRef::No, max_ref_mutbl, mutbls_match)
-                }
-            }
+            AdjustMode::Pass => (expected, def_br, max_ref_mutbl),
+            AdjustMode::Reset => (expected, ByRef::No, MutblCap::Mut),
             AdjustMode::Peel => {
-                let peeled =
-                    self.peel_off_references(pat, expected, def_br, Mutability::Mut, max_ref_mutbl);
-                (peeled.0, peeled.1, peeled.2, false)
+                self.peel_off_references(pat, expected, def_br, Mutability::Mut, max_ref_mutbl)
             }
         }
     }
@@ -378,17 +382,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // a reference type wherefore peeling doesn't give up any expressiveness.
                 _ => AdjustMode::Peel,
             },
-            // When encountering a `& mut? pat` pattern, reset to "by value".
-            // This is so that `x` and `y` here are by value, as they appear to be:
-            //
-            // ```
-            // match &(&22, &44) {
-            //   (&x, &y) => ...
-            // }
-            // ```
-            //
-            // See issue #46688.
-            PatKind::Ref(_, mutbl) => AdjustMode::ResetAndConsumeRef(*mutbl),
+            // Ref patterns are complicated, we handle them in `check_pat_ref`.
+            PatKind::Ref(..) => AdjustMode::Pass,
             // A `_` pattern works with any expected type, so there's no need to do anything.
             PatKind::Wild
             // A malformed pattern doesn't have an expected type, so let's just accept any type.
@@ -414,8 +409,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expected: Ty<'tcx>,
         mut def_br: ByRef,
         max_peelable_mutability: Mutability,
-        mut max_ref_mutability: Mutability,
-    ) -> (Ty<'tcx>, ByRef, Mutability) {
+        mut max_ref_mutability: MutblCap,
+    ) -> (Ty<'tcx>, ByRef, MutblCap) {
         let mut expected = self.try_structurally_resolve_type(pat.span, expected);
         // Peel off as many `&` or `&mut` from the scrutinee type as possible. For example,
         // for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches
@@ -449,9 +444,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         if pat.span.at_least_rust_2024() && self.tcx.features().ref_pat_eat_one_layer_2024 {
-            def_br = def_br.cap_ref_mutability(max_ref_mutability);
+            def_br = def_br.cap_ref_mutability(max_ref_mutability.as_mutbl());
             if def_br == ByRef::Yes(Mutability::Not) {
-                max_ref_mutability = Mutability::Not;
+                max_ref_mutability = MutblCap::Not;
             }
         }
 
@@ -471,7 +466,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         span: Span,
         lt: &hir::Expr<'tcx>,
         expected: Ty<'tcx>,
-        ti: TopInfo<'tcx>,
+        ti: &TopInfo<'tcx>,
     ) -> Ty<'tcx> {
         // We've already computed the type above (when checking for a non-ref pat),
         // so avoid computing it again.
@@ -541,7 +536,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         lhs: Option<&'tcx hir::Expr<'tcx>>,
         rhs: Option<&'tcx hir::Expr<'tcx>>,
         expected: Ty<'tcx>,
-        ti: TopInfo<'tcx>,
+        ti: &TopInfo<'tcx>,
     ) -> Ty<'tcx> {
         let calc_side = |opt_expr: Option<&'tcx hir::Expr<'tcx>>| match opt_expr {
             None => None,
@@ -668,8 +663,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn check_pat_ident(
         &self,
         pat: &'tcx Pat<'tcx>,
-        ba: BindingMode,
+        user_bind_annot: BindingMode,
         var_id: HirId,
+        ident: Ident,
         sub: Option<&'tcx Pat<'tcx>>,
         expected: Ty<'tcx>,
         pat_info: PatInfo<'tcx, '_>,
@@ -677,24 +673,44 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let PatInfo { binding_mode: def_br, top_info: ti, .. } = pat_info;
 
         // Determine the binding mode...
-        let bm = match ba {
+        let bm = match user_bind_annot {
+            // `mut` resets binding mode on edition <= 2021
             BindingMode(ByRef::No, Mutability::Mut)
                 if !(pat.span.at_least_rust_2024()
                     && self.tcx.features().mut_preserve_binding_mode_2024)
                     && matches!(def_br, ByRef::Yes(_)) =>
             {
-                // `mut x` resets the binding mode in edition <= 2021.
-                self.tcx.emit_node_span_lint(
-                    rustc_lint::builtin::DEREFERENCING_MUT_BINDING,
-                    pat.hir_id,
-                    pat.span,
-                    errors::DereferencingMutBinding { span: pat.span },
-                );
+                self.typeck_results
+                    .borrow_mut()
+                    .rust_2024_migration_desugared_pats_mut()
+                    .insert(pat_info.top_info.hir_id);
                 BindingMode(ByRef::No, Mutability::Mut)
             }
             BindingMode(ByRef::No, mutbl) => BindingMode(def_br, mutbl),
-            BindingMode(ByRef::Yes(_), _) => ba,
+            BindingMode(ByRef::Yes(_), _) => user_bind_annot,
         };
+
+        if bm.0 == ByRef::Yes(Mutability::Mut)
+            && let MutblCap::WeaklyNot(and_pat_span) = pat_info.max_ref_mutbl
+        {
+            let mut err = struct_span_code_err!(
+                self.tcx.dcx(),
+                ident.span,
+                E0596,
+                "cannot borrow as mutable inside an `&` pattern"
+            );
+
+            if let Some(span) = and_pat_span {
+                err.span_suggestion(
+                    span,
+                    "replace this `&` with `&mut`",
+                    "&mut ",
+                    Applicability::MachineApplicable,
+                );
+            }
+            err.emit();
+        }
+
         // ...and store it in a side table:
         self.typeck_results.borrow_mut().pat_binding_modes_mut().insert(pat.hir_id, bm);
 
@@ -720,7 +736,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // If there are multiple arms, make sure they all agree on
         // what the type of the binding `x` ought to be.
         if var_id != pat.hir_id {
-            self.check_binding_alt_eq_ty(ba, pat.span, var_id, local_ty, ti);
+            self.check_binding_alt_eq_ty(user_bind_annot, pat.span, var_id, local_ty, ti);
         }
 
         if let Some(p) = sub {
@@ -739,7 +755,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         span: Span,
         var_id: HirId,
         ty: Ty<'tcx>,
-        ti: TopInfo<'tcx>,
+        ti: &TopInfo<'tcx>,
     ) {
         let var_ty = self.local_ty(span, var_id);
         if let Some(mut err) = self.demand_eqtype_pat_diag(span, var_ty, ty, ti) {
@@ -981,7 +997,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         qpath: &hir::QPath<'_>,
         path_resolution: (Res, Option<LoweredTy<'tcx>>, &'tcx [hir::PathSegment<'tcx>]),
         expected: Ty<'tcx>,
-        ti: TopInfo<'tcx>,
+        ti: &TopInfo<'tcx>,
     ) -> Ty<'tcx> {
         let tcx = self.tcx;
 
@@ -2105,72 +2121,145 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         pat: &'tcx Pat<'tcx>,
         inner: &'tcx Pat<'tcx>,
-        mutbl: Mutability,
-        expected: Ty<'tcx>,
-        pat_info: PatInfo<'tcx, '_>,
-        consumed_inherited_ref: bool,
+        pat_mutbl: Mutability,
+        mut expected: Ty<'tcx>,
+        mut pat_info: PatInfo<'tcx, '_>,
     ) -> Ty<'tcx> {
-        if consumed_inherited_ref
-            && pat.span.at_least_rust_2024()
-            && self.tcx.features().ref_pat_eat_one_layer_2024
-        {
-            self.typeck_results.borrow_mut().skipped_ref_pats_mut().insert(pat.hir_id);
-            self.check_pat(inner, expected, pat_info);
-            expected
+        // FIXME: repace with `bool` once final decision on 1 vs 2 layers is made
+        #[derive(Clone, Copy, Debug, PartialEq, Eq)]
+        enum MatchErgonomicsMode {
+            EatOneLayer,
+            EatTwoLayers,
+            Legacy,
+        }
+
+        let match_ergonomics_mode =
+            if pat.span.at_least_rust_2024() && self.tcx.features().ref_pat_eat_one_layer_2024 {
+                MatchErgonomicsMode::EatOneLayer
+            } else if self.tcx.features().ref_pat_everywhere {
+                MatchErgonomicsMode::EatTwoLayers
+            } else {
+                MatchErgonomicsMode::Legacy
+            };
+
+        let mut inherited_ref_mutbl_match = false;
+        if match_ergonomics_mode != MatchErgonomicsMode::Legacy {
+            if pat_mutbl == Mutability::Not {
+                // Prevent the inner pattern from binding with `ref mut`.
+                pat_info.max_ref_mutbl = pat_info.max_ref_mutbl.cap_to_weakly_not(
+                    inner.span.find_ancestor_inside(pat.span).map(|end| pat.span.until(end)),
+                );
+            }
+
+            if let ByRef::Yes(inh_mut) = pat_info.binding_mode {
+                inherited_ref_mutbl_match = pat_mutbl <= inh_mut;
+            }
+
+            if inherited_ref_mutbl_match {
+                pat_info.binding_mode = ByRef::No;
+                if match_ergonomics_mode == MatchErgonomicsMode::EatOneLayer {
+                    self.typeck_results.borrow_mut().skipped_ref_pats_mut().insert(pat.hir_id);
+                    self.check_pat(inner, expected, pat_info);
+                    return expected;
+                }
+            } else if match_ergonomics_mode == MatchErgonomicsMode::EatOneLayer
+                && pat_mutbl == Mutability::Mut
+            {
+                // `&mut` patterns pell off `&` references
+                let (new_expected, new_bm, max_ref_mutbl) = self.peel_off_references(
+                    pat,
+                    expected,
+                    pat_info.binding_mode,
+                    Mutability::Not,
+                    pat_info.max_ref_mutbl,
+                );
+                expected = new_expected;
+                pat_info.binding_mode = new_bm;
+                pat_info.max_ref_mutbl = max_ref_mutbl;
+            }
         } else {
-            let tcx = self.tcx;
-            let expected = self.shallow_resolve(expected);
-            let (ref_ty, inner_ty) = match self.check_dereferenceable(pat.span, expected, inner) {
-                Ok(()) => {
-                    // `demand::subtype` would be good enough, but using `eqtype` turns
-                    // out to be equally general. See (note_1) for details.
-
-                    // Take region, inner-type from expected type if we can,
-                    // to avoid creating needless variables. This also helps with
-                    // the bad interactions of the given hack detailed in (note_1).
-                    debug!("check_pat_ref: expected={:?}", expected);
-                    match *expected.kind() {
-                        ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => (expected, r_ty),
-                        _ => {
-                            if consumed_inherited_ref && self.tcx.features().ref_pat_everywhere {
-                                // We already matched against a match-ergonmics inserted reference,
-                                // so we don't need to match against a reference from the original type.
-                                // Save this infor for use in lowering later
-                                self.typeck_results
-                                    .borrow_mut()
-                                    .skipped_ref_pats_mut()
-                                    .insert(pat.hir_id);
-                                (expected, expected)
-                            } else {
-                                let inner_ty = self.next_ty_var(inner.span);
-                                let ref_ty = self.new_ref_ty(pat.span, mutbl, inner_ty);
-                                debug!("check_pat_ref: demanding {:?} = {:?}", expected, ref_ty);
-                                let err = self.demand_eqtype_pat_diag(
-                                    pat.span,
-                                    expected,
-                                    ref_ty,
-                                    pat_info.top_info,
-                                );
+            // Reset binding mode on old editions
 
-                                // Look for a case like `fn foo(&foo: u32)` and suggest
-                                // `fn foo(foo: &u32)`
-                                if let Some(mut err) = err {
-                                    self.borrow_pat_suggestion(&mut err, pat);
-                                    err.emit();
-                                }
-                                (ref_ty, inner_ty)
-                            }
+            if pat_info.binding_mode != ByRef::No {
+                pat_info.binding_mode = ByRef::No;
+
+                self.typeck_results
+                    .borrow_mut()
+                    .rust_2024_migration_desugared_pats_mut()
+                    .insert(pat_info.top_info.hir_id);
+            }
+
+            pat_info.max_ref_mutbl = MutblCap::Mut;
+        }
+
+        let tcx = self.tcx;
+        expected = self.try_structurally_resolve_type(pat.span, expected);
+        let (ref_ty, inner_ty) = match self.check_dereferenceable(pat.span, expected, inner) {
+            Ok(()) => {
+                // `demand::subtype` would be good enough, but using `eqtype` turns
+                // out to be equally general. See (note_1) for details.
+
+                // Take region, inner-type from expected type if we can,
+                // to avoid creating needless variables. This also helps with
+                // the bad interactions of the given hack detailed in (note_1).
+                debug!("check_pat_ref: expected={:?}", expected);
+                match *expected.kind() {
+                    ty::Ref(_, r_ty, r_mutbl) if r_mutbl == pat_mutbl => {
+                        if r_mutbl == Mutability::Not
+                            && match_ergonomics_mode != MatchErgonomicsMode::Legacy
+                        {
+                            pat_info.max_ref_mutbl = MutblCap::Not;
                         }
+
+                        (expected, r_ty)
+                    }
+
+                    // `&` pattern eats `&mut` reference
+                    ty::Ref(_, r_ty, Mutability::Mut)
+                        if pat_mutbl == Mutability::Not
+                            && match_ergonomics_mode != MatchErgonomicsMode::Legacy =>
+                    {
+                        (expected, r_ty)
+                    }
+
+                    _ if inherited_ref_mutbl_match
+                        && match_ergonomics_mode == MatchErgonomicsMode::EatTwoLayers =>
+                    {
+                        // We already matched against a match-ergonmics inserted reference,
+                        // so we don't need to match against a reference from the original type.
+                        // Save this info for use in lowering later
+                        self.typeck_results.borrow_mut().skipped_ref_pats_mut().insert(pat.hir_id);
+                        (expected, expected)
+                    }
+
+                    _ => {
+                        let inner_ty = self.next_ty_var(inner.span);
+                        let ref_ty = self.new_ref_ty(pat.span, pat_mutbl, inner_ty);
+                        debug!("check_pat_ref: demanding {:?} = {:?}", expected, ref_ty);
+                        let err = self.demand_eqtype_pat_diag(
+                            pat.span,
+                            expected,
+                            ref_ty,
+                            pat_info.top_info,
+                        );
+
+                        // Look for a case like `fn foo(&foo: u32)` and suggest
+                        // `fn foo(foo: &u32)`
+                        if let Some(mut err) = err {
+                            self.borrow_pat_suggestion(&mut err, pat);
+                            err.emit();
+                        }
+                        (ref_ty, inner_ty)
                     }
                 }
-                Err(guar) => {
-                    let err = Ty::new_error(tcx, guar);
-                    (err, err)
-                }
-            };
-            self.check_pat(inner, inner_ty, pat_info);
-            ref_ty
-        }
+            }
+            Err(guar) => {
+                let err = Ty::new_error(tcx, guar);
+                (err, err)
+            }
+        };
+        self.check_pat(inner, inner_ty, pat_info);
+        ref_ty
     }
 
     /// Create a reference type with a fresh region variable.
diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs
index 374279722ba..515e1b5ed0e 100644
--- a/compiler/rustc_hir_typeck/src/place_op.rs
+++ b/compiler/rustc_hir_typeck/src/place_op.rs
@@ -5,6 +5,7 @@ use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir_analysis::autoderef::Autoderef;
 use rustc_infer::infer::InferOk;
+use rustc_middle::span_bug;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref, PointerCoercion};
 use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
 use rustc_middle::ty::{self, Ty};
diff --git a/compiler/rustc_hir_typeck/src/rvalue_scopes.rs b/compiler/rustc_hir_typeck/src/rvalue_scopes.rs
index 34ce0ab1f8b..805f36d9b97 100644
--- a/compiler/rustc_hir_typeck/src/rvalue_scopes.rs
+++ b/compiler/rustc_hir_typeck/src/rvalue_scopes.rs
@@ -2,6 +2,7 @@ use super::FnCtxt;
 use hir::def_id::DefId;
 use hir::Node;
 use rustc_hir as hir;
+use rustc_middle::bug;
 use rustc_middle::middle::region::{RvalueCandidateType, Scope, ScopeTree};
 use rustc_middle::ty::RvalueScopes;
 
diff --git a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs
index 31ce271a5fc..19d6481cc1b 100644
--- a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs
+++ b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs
@@ -5,6 +5,7 @@ use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::{HirId, HirIdMap};
 use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
+use rustc_middle::span_bug;
 use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::def_id::LocalDefIdMap;
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index 2bf4f51a803..d313c0eafe1 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -47,6 +47,7 @@ use rustc_middle::ty::{
     self, ClosureSizeProfileData, Ty, TyCtxt, TypeVisitableExt as _, TypeckResults, UpvarArgs,
     UpvarCapture,
 };
+use rustc_middle::{bug, span_bug};
 use rustc_session::lint;
 use rustc_span::sym;
 use rustc_span::{BytePos, Pos, Span, Symbol};
@@ -252,12 +253,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
         }
 
-        euv::ExprUseVisitor::new(
+        let _ = euv::ExprUseVisitor::new(
+            &FnCtxt::new(self, self.tcx.param_env(closure_def_id), closure_def_id),
             &mut delegate,
-            &self.infcx,
-            closure_def_id,
-            self.param_env,
-            &self.typeck_results.borrow(),
         )
         .consume_body(body);
 
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index 0a40ffb0d5a..f798deea207 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -9,6 +9,7 @@ use rustc_hir as hir;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::HirId;
 use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
+use rustc_middle::span_bug;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
@@ -346,6 +347,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
             _ => {}
         };
 
+        self.visit_rust_2024_migration_desugared_pats(p.hir_id);
         self.visit_skipped_ref_pats(p.hir_id);
         self.visit_pat_adjustments(p.span, p.hir_id);
 
@@ -655,6 +657,22 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         }
     }
 
+    #[instrument(skip(self), level = "debug")]
+    fn visit_rust_2024_migration_desugared_pats(&mut self, hir_id: hir::HirId) {
+        if self
+            .fcx
+            .typeck_results
+            .borrow_mut()
+            .rust_2024_migration_desugared_pats_mut()
+            .remove(hir_id)
+        {
+            debug!(
+                "node is a pat whose match ergonomics are desugared by the Rust 2024 migration lint"
+            );
+            self.typeck_results.rust_2024_migration_desugared_pats_mut().insert(hir_id);
+        }
+    }
+
     #[instrument(skip(self, span), level = "debug")]
     fn visit_pat_adjustments(&mut self, span: Span, hir_id: HirId) {
         let adjustment = self.fcx.typeck_results.borrow_mut().pat_adjustments_mut().remove(hir_id);
diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs
index c7f07ebed97..f0b336ca046 100644
--- a/compiler/rustc_infer/src/errors/note_and_explain.rs
+++ b/compiler/rustc_infer/src/errors/note_and_explain.rs
@@ -1,6 +1,7 @@
 use crate::fluent_generated as fluent;
 use crate::infer::error_reporting::nice_region_error::find_anon_type;
 use rustc_errors::{Diag, EmissionGuarantee, IntoDiagArg, SubdiagMessageOp, Subdiagnostic};
+use rustc_middle::bug;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::{symbol::kw, Span};
 
diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs
index 0f21d3966c4..eaef715fe5d 100644
--- a/compiler/rustc_infer/src/infer/at.rs
+++ b/compiler/rustc_infer/src/infer/at.rs
@@ -27,6 +27,7 @@
 
 use super::*;
 
+use rustc_middle::bug;
 use rustc_middle::ty::relate::{Relate, TypeRelation};
 use rustc_middle::ty::{Const, ImplSubject};
 
@@ -436,6 +437,20 @@ impl<'tcx> ToTrace<'tcx> for ty::AliasTy<'tcx> {
         a: Self,
         b: Self,
     ) -> TypeTrace<'tcx> {
+        TypeTrace {
+            cause: cause.clone(),
+            values: Aliases(ExpectedFound::new(a_is_expected, a.into(), b.into())),
+        }
+    }
+}
+
+impl<'tcx> ToTrace<'tcx> for ty::AliasTerm<'tcx> {
+    fn to_trace(
+        cause: &ObligationCause<'tcx>,
+        a_is_expected: bool,
+        a: Self,
+        b: Self,
+    ) -> TypeTrace<'tcx> {
         TypeTrace { cause: cause.clone(), values: Aliases(ExpectedFound::new(a_is_expected, a, b)) }
     }
 }
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index 4d712e9ffd3..27b06c4b73e 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -9,6 +9,7 @@ use crate::infer::canonical::{
     Canonical, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind, OriginalQueryValues,
 };
 use crate::infer::InferCtxt;
+use rustc_middle::bug;
 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
 use rustc_middle::ty::GenericArg;
 use rustc_middle::ty::{self, BoundVar, InferConst, List, Ty, TyCtxt, TypeFlags, TypeVisitableExt};
diff --git a/compiler/rustc_infer/src/infer/canonical/instantiate.rs b/compiler/rustc_infer/src/infer/canonical/instantiate.rs
index f95cc13623c..de0e15ef3de 100644
--- a/compiler/rustc_infer/src/infer/canonical/instantiate.rs
+++ b/compiler/rustc_infer/src/infer/canonical/instantiate.rs
@@ -8,6 +8,7 @@
 
 use crate::infer::canonical::{Canonical, CanonicalVarValues};
 use rustc_macros::extension;
+use rustc_middle::bug;
 use rustc_middle::ty::fold::{FnMutDelegate, TypeFoldable};
 use rustc_middle::ty::GenericArgKind;
 use rustc_middle::ty::{self, TyCtxt};
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index b948067e750..1732913e191 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -25,6 +25,7 @@ use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::{self, BoundVar, Ty, TyCtxt};
 use rustc_middle::ty::{GenericArg, GenericArgKind};
+use rustc_middle::{bug, span_bug};
 use std::fmt::Debug;
 use std::iter;
 
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 46310941113..d0687dfc6fd 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -69,6 +69,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::lang_items::LangItem;
 use rustc_macros::extension;
+use rustc_middle::bug;
 use rustc_middle::dep_graph::DepContext;
 use rustc_middle::ty::print::{with_forced_trimmed_paths, PrintError, PrintTraitRefExt as _};
 use rustc_middle::ty::relate::{self, RelateResult, TypeRelation};
@@ -410,7 +411,7 @@ impl<'tcx> InferCtxt<'tcx> {
                     .kind()
                     .map_bound(|kind| match kind {
                         ty::ClauseKind::Projection(projection_predicate)
-                            if projection_predicate.projection_ty.def_id == item_def_id =>
+                            if projection_predicate.projection_term.def_id == item_def_id =>
                         {
                             projection_predicate.term.ty()
                         }
@@ -883,9 +884,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 err.help("...or use `match` instead of `let...else`");
             }
             _ => {
-                if let ObligationCauseCode::SpannedWhereClause(_, span)
-                | ObligationCauseCode::SpannedWhereClauseInExpr(_, span, ..) =
+                if let ObligationCauseCode::WhereClause(_, span)
+                | ObligationCauseCode::WhereClauseInExpr(_, span, ..) =
                     cause.code().peel_derives()
+                    && !span.is_dummy()
                     && let TypeError::RegionsPlaceholderMismatch = terr
                 {
                     err.span_note(*span, "the lifetime requirement is introduced here");
diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
index 415f0eee8c5..b4decbf14a2 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
@@ -11,6 +11,7 @@ use rustc_hir::def::{CtorOf, DefKind, Namespace};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{Body, Closure, Expr, ExprKind, FnRetTy, HirId, LetStmt, LocalSource};
+use rustc_middle::bug;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::infer::unify_key::ConstVariableValue;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs
index b6c38739e9a..45dce0a0e33 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs
@@ -13,6 +13,7 @@ use rustc_data_structures::fx::FxIndexSet;
 use rustc_errors::{ErrorGuaranteed, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::intravisit::Visitor;
+use rustc_middle::bug;
 use rustc_middle::ty::TypeVisitor;
 
 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
@@ -38,11 +39,14 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         let ObligationCauseCode::MatchImpl(parent, impl_def_id) = code else {
             return None;
         };
-        let (ObligationCauseCode::SpannedWhereClause(_, binding_span)
-        | ObligationCauseCode::SpannedWhereClauseInExpr(_, binding_span, ..)) = *parent.code()
+        let (ObligationCauseCode::WhereClause(_, binding_span)
+        | ObligationCauseCode::WhereClauseInExpr(_, binding_span, ..)) = *parent.code()
         else {
             return None;
         };
+        if binding_span.is_dummy() {
+            return None;
+        }
 
         // FIXME: we should point at the lifetime
         let multi_span: MultiSpan = vec![binding_span].into();
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 dbd165c093a..8859772848f 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
@@ -10,7 +10,8 @@ use crate::traits::{ObligationCause, ObligationCauseCode};
 use rustc_data_structures::intern::Interned;
 use rustc_errors::{Diag, IntoDiagArg};
 use rustc_hir::def::Namespace;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
+use rustc_middle::bug;
 use rustc_middle::ty::error::ExpectedFound;
 use rustc_middle::ty::print::{FmtPrinter, Print, PrintTraitRefExt as _, RegionHighlightMode};
 use rustc_middle::ty::GenericArgsRef;
@@ -240,8 +241,9 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
         let span = cause.span();
 
         let (leading_ellipsis, satisfy_span, where_span, dup_span, def_id) =
-            if let ObligationCauseCode::WhereClause(def_id)
-            | ObligationCauseCode::WhereClauseInExpr(def_id, ..) = *cause.code()
+            if let ObligationCauseCode::WhereClause(def_id, span)
+            | ObligationCauseCode::WhereClauseInExpr(def_id, span, ..) = *cause.code()
+                && def_id != CRATE_DEF_ID.to_def_id()
             {
                 (
                     true,
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
index e5950a7c935..8a1e3a7ac71 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -214,7 +214,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                 _ => cause.code(),
             }
             && let (
-                &ObligationCauseCode::WhereClause(item_def_id)
+                &ObligationCauseCode::WhereClause(item_def_id, _)
                 | &ObligationCauseCode::WhereClauseInExpr(item_def_id, ..),
                 None,
             ) = (code, override_error_code)
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs
index ecbe65fe926..00dd20a2cc2 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs
@@ -357,21 +357,22 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             infer::Subtype(box ref trace)
                 if matches!(
                     &trace.cause.code().peel_derives(),
-                    ObligationCauseCode::SpannedWhereClause(..)
-                        | ObligationCauseCode::SpannedWhereClauseInExpr(..)
+                    ObligationCauseCode::WhereClause(..)
+                        | ObligationCauseCode::WhereClauseInExpr(..)
                 ) =>
             {
                 // Hack to get around the borrow checker because trace.cause has an `Rc`.
-                if let ObligationCauseCode::SpannedWhereClause(_, span)
-                | ObligationCauseCode::SpannedWhereClauseInExpr(_, span, ..) =
+                if let ObligationCauseCode::WhereClause(_, span)
+                | ObligationCauseCode::WhereClauseInExpr(_, span, ..) =
                     &trace.cause.code().peel_derives()
+                    && !span.is_dummy()
                 {
                     let span = *span;
                     self.report_concrete_failure(placeholder_origin, sub, sup)
                         .with_span_note(span, "the lifetime requirement is introduced here")
                 } else {
                     unreachable!(
-                        "control flow ensures we have a `BindingObligation` or `SpannedWhereClauseInExpr` here..."
+                        "control flow ensures we have a `BindingObligation` or `WhereClauseInExpr` here..."
                     )
                 }
             }
diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs
index ef9c407acef..b2d89523ea8 100644
--- a/compiler/rustc_infer/src/infer/freshen.rs
+++ b/compiler/rustc_infer/src/infer/freshen.rs
@@ -32,6 +32,7 @@
 //! inferencer knows "so far".
 use super::InferCtxt;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_middle::bug;
 use rustc_middle::infer::unify_key::ToType;
 use rustc_middle::ty::fold::TypeFolder;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitableExt};
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 5ae7f8bf504..72944c9c7de 100644
--- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
+++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
@@ -20,6 +20,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::ty::{ReBound, RePlaceholder, ReVar};
 use rustc_middle::ty::{ReEarlyParam, ReErased, ReError, ReLateParam, ReStatic};
 use rustc_middle::ty::{Region, RegionVid};
+use rustc_middle::{bug, span_bug};
 use rustc_span::Span;
 use std::fmt;
 
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index ce82296a8aa..723f4c81ca5 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -44,6 +44,7 @@ use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{self, GenericParamDefKind, InferConst, InferTy, Ty, TyCtxt};
 use rustc_middle::ty::{ConstVid, EffectVid, FloatVid, IntVid, TyVid};
 use rustc_middle::ty::{GenericArg, GenericArgKind, GenericArgs, GenericArgsRef};
+use rustc_middle::{bug, span_bug};
 use rustc_span::symbol::Symbol;
 use rustc_span::Span;
 use snapshot::undo_log::InferCtxtUndoLogs;
@@ -403,7 +404,7 @@ impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> {
 pub enum ValuePairs<'tcx> {
     Regions(ExpectedFound<ty::Region<'tcx>>),
     Terms(ExpectedFound<ty::Term<'tcx>>),
-    Aliases(ExpectedFound<ty::AliasTy<'tcx>>),
+    Aliases(ExpectedFound<ty::AliasTerm<'tcx>>),
     TraitRefs(ExpectedFound<ty::TraitRef<'tcx>>),
     PolySigs(ExpectedFound<ty::PolyFnSig<'tcx>>),
     ExistentialTraitRef(ExpectedFound<ty::PolyExistentialTraitRef<'tcx>>),
diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs
index 703bd5ae90b..8eb3185673b 100644
--- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs
@@ -588,7 +588,7 @@ impl<'tcx> InferCtxt<'tcx> {
                             && !tcx.is_impl_trait_in_trait(projection_ty.def_id)
                             && !self.next_trait_solver() =>
                     {
-                        self.infer_projection(
+                        self.projection_ty_to_infer(
                             param_env,
                             projection_ty,
                             cause.clone(),
diff --git a/compiler/rustc_infer/src/infer/opaque_types/table.rs b/compiler/rustc_infer/src/infer/opaque_types/table.rs
index a7ddf475436..e07d181e4e0 100644
--- a/compiler/rustc_infer/src/infer/opaque_types/table.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types/table.rs
@@ -1,4 +1,5 @@
 use rustc_data_structures::undo_log::UndoLogs;
+use rustc_middle::bug;
 use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty};
 
 use crate::infer::snapshot::undo_log::{InferCtxtUndoLogs, UndoLog};
diff --git a/compiler/rustc_infer/src/infer/outlives/env.rs b/compiler/rustc_infer/src/infer/outlives/env.rs
index f8dbfdde30c..c44a5082f68 100644
--- a/compiler/rustc_infer/src/infer/outlives/env.rs
+++ b/compiler/rustc_infer/src/infer/outlives/env.rs
@@ -3,6 +3,7 @@ use crate::infer::GenericKind;
 use crate::traits::query::OutlivesBound;
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_data_structures::transitive_relation::TransitiveRelationBuilder;
+use rustc_middle::bug;
 use rustc_middle::ty::{self, Region};
 
 use super::explicit_outlives_bounds;
diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs
index 94f8a2664f9..32c790523b6 100644
--- a/compiler/rustc_infer/src/infer/outlives/obligations.rs
+++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs
@@ -67,6 +67,7 @@ use crate::infer::snapshot::undo_log::UndoLog;
 use crate::infer::{self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, VerifyBound};
 use crate::traits::{ObligationCause, ObligationCauseCode};
 use rustc_data_structures::undo_log::UndoLogs;
+use rustc_middle::bug;
 use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::traits::query::NoSolution;
 use rustc_middle::ty::{
@@ -103,8 +104,12 @@ impl<'tcx> InferCtxt<'tcx> {
                 cause.span,
                 sup_type,
                 match cause.code().peel_derives() {
-                    ObligationCauseCode::SpannedWhereClause(_, span)
-                    | ObligationCauseCode::SpannedWhereClauseInExpr(_, span, ..) => Some(*span),
+                    ObligationCauseCode::WhereClause(_, span)
+                    | ObligationCauseCode::WhereClauseInExpr(_, span, ..)
+                        if !span.is_dummy() =>
+                    {
+                        Some(*span)
+                    }
                     _ => None,
                 },
             )
diff --git a/compiler/rustc_infer/src/infer/projection.rs b/compiler/rustc_infer/src/infer/projection.rs
index 041838ffc16..16786347980 100644
--- a/compiler/rustc_infer/src/infer/projection.rs
+++ b/compiler/rustc_infer/src/infer/projection.rs
@@ -12,7 +12,7 @@ impl<'tcx> InferCtxt<'tcx> {
     /// of the given projection. This allows us to proceed with projections
     /// while they cannot be resolved yet due to missing information or
     /// simply due to the lack of access to the trait resolution machinery.
-    pub fn infer_projection(
+    pub fn projection_ty_to_infer(
         &self,
         param_env: ty::ParamEnv<'tcx>,
         projection_ty: ty::AliasTy<'tcx>,
@@ -24,7 +24,7 @@ impl<'tcx> InferCtxt<'tcx> {
         let def_id = projection_ty.def_id;
         let ty_var = self.next_ty_var(self.tcx.def_span(def_id));
         let projection = ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::Projection(
-            ty::ProjectionPredicate { projection_ty, term: ty_var.into() },
+            ty::ProjectionPredicate { projection_term: projection_ty.into(), term: ty_var.into() },
         )));
         let obligation =
             Obligation::with_depth(self.tcx, cause, recursion_depth, param_env, projection);
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 6e8efa3e7c1..255ca52d3e9 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
@@ -3,6 +3,7 @@ use crate::infer::snapshot::CombinedSnapshot;
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::graph::{scc::Sccs, vec_graph::VecGraph};
 use rustc_index::Idx;
+use rustc_middle::span_bug;
 use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::relate::RelateResult;
 
diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
index 223e6e3d344..6f755e07ff1 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
@@ -17,6 +17,7 @@ use rustc_middle::ty::ReStatic;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::ty::{ReBound, ReVar};
 use rustc_middle::ty::{Region, RegionVid};
+use rustc_middle::{bug, span_bug};
 use rustc_span::Span;
 
 use std::ops::Range;
diff --git a/compiler/rustc_infer/src/infer/relate/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs
index 8a3125f9ded..c1baadfa8df 100644
--- a/compiler/rustc_infer/src/infer/relate/combine.rs
+++ b/compiler/rustc_infer/src/infer/relate/combine.rs
@@ -24,6 +24,7 @@ use super::type_relating::TypeRelating;
 use super::StructurallyRelateAliases;
 use crate::infer::{DefineOpaqueTypes, InferCtxt, TypeTrace};
 use crate::traits::{Obligation, PredicateObligations};
+use rustc_middle::bug;
 use rustc_middle::infer::canonical::OriginalQueryValues;
 use rustc_middle::infer::unify_key::EffectVarValue;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs
index 5880ca788bc..d4c7d752c95 100644
--- a/compiler/rustc_infer/src/infer/relate/generalize.rs
+++ b/compiler/rustc_infer/src/infer/relate/generalize.rs
@@ -6,6 +6,7 @@ use crate::infer::{InferCtxt, ObligationEmittingRelation, RegionVariableOrigin};
 use rustc_data_structures::sso::SsoHashMap;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir::def_id::DefId;
+use rustc_middle::bug;
 use rustc_middle::infer::unify_key::ConstVariableValue;
 use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
@@ -101,7 +102,7 @@ impl<'tcx> InferCtxt<'tcx> {
                         // instead create a new inference variable `?normalized_source`, emitting
                         // `Projection(normalized_source, ?ty_normalized)` and `?normalized_source <: generalized_ty`.
                         relation.register_predicates([ty::ProjectionPredicate {
-                            projection_ty: data,
+                            projection_term: data.into(),
                             term: generalized_ty.into(),
                         }]);
                     }
diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs
index 758aac004dc..61b13dd9a54 100644
--- a/compiler/rustc_infer/src/infer/resolve.rs
+++ b/compiler/rustc_infer/src/infer/resolve.rs
@@ -1,4 +1,5 @@
 use super::{FixupError, FixupResult, InferCtxt};
+use rustc_middle::bug;
 use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFolder, TypeSuperFoldable};
 use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{self, Const, InferConst, Ty, TyCtxt, TypeFoldable};
diff --git a/compiler/rustc_infer/src/infer/type_variable.rs b/compiler/rustc_infer/src/infer/type_variable.rs
index 96afa257ebb..b56b39e61f0 100644
--- a/compiler/rustc_infer/src/infer/type_variable.rs
+++ b/compiler/rustc_infer/src/infer/type_variable.rs
@@ -1,6 +1,7 @@
 use rustc_data_structures::undo_log::Rollback;
 use rustc_hir::def_id::DefId;
 use rustc_index::IndexVec;
+use rustc_middle::bug;
 use rustc_middle::ty::{self, Ty, TyVid};
 use rustc_span::Span;
 
diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs
index 0299af61d45..28d908abf83 100644
--- a/compiler/rustc_infer/src/lib.rs
+++ b/compiler/rustc_infer/src/lib.rs
@@ -31,8 +31,6 @@
 
 #[macro_use]
 extern crate tracing;
-#[macro_use]
-extern crate rustc_middle;
 
 mod errors;
 pub mod infer;
diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs
index 85510cf2dcc..f77a92bf9bc 100644
--- a/compiler/rustc_infer/src/traits/mod.rs
+++ b/compiler/rustc_infer/src/traits/mod.rs
@@ -27,7 +27,7 @@ pub use self::engine::{TraitEngine, TraitEngineExt};
 pub use self::project::MismatchedProjectionTypes;
 pub(crate) use self::project::UndoLog;
 pub use self::project::{
-    Normalized, NormalizedTy, ProjectionCache, ProjectionCacheEntry, ProjectionCacheKey,
+    Normalized, NormalizedTerm, ProjectionCache, ProjectionCacheEntry, ProjectionCacheKey,
     ProjectionCacheStorage, Reveal,
 };
 pub use rustc_middle::traits::*;
diff --git a/compiler/rustc_infer/src/traits/project.rs b/compiler/rustc_infer/src/traits/project.rs
index c6ffba59638..b696264aab0 100644
--- a/compiler/rustc_infer/src/traits/project.rs
+++ b/compiler/rustc_infer/src/traits/project.rs
@@ -8,7 +8,7 @@ use rustc_data_structures::{
     snapshot_map::{self, SnapshotMapRef, SnapshotMapStorage},
     undo_log::Rollback,
 };
-use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty;
 
 pub use rustc_middle::traits::{EvaluationResult, Reveal};
 
@@ -26,7 +26,7 @@ pub struct Normalized<'tcx, T> {
     pub obligations: Vec<PredicateObligation<'tcx>>,
 }
 
-pub type NormalizedTy<'tcx> = Normalized<'tcx, Ty<'tcx>>;
+pub type NormalizedTerm<'tcx> = Normalized<'tcx, ty::Term<'tcx>>;
 
 impl<'tcx, T> Normalized<'tcx, T> {
     pub fn with<U>(self, value: U) -> Normalized<'tcx, U> {
@@ -77,13 +77,13 @@ pub struct ProjectionCacheStorage<'tcx> {
 
 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
 pub struct ProjectionCacheKey<'tcx> {
-    ty: ty::AliasTy<'tcx>,
+    term: ty::AliasTerm<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
 }
 
 impl<'tcx> ProjectionCacheKey<'tcx> {
-    pub fn new(ty: ty::AliasTy<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self {
-        Self { ty, param_env }
+    pub fn new(term: ty::AliasTerm<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self {
+        Self { term, param_env }
     }
 }
 
@@ -93,8 +93,8 @@ pub enum ProjectionCacheEntry<'tcx> {
     Ambiguous,
     Recur,
     Error,
-    NormalizedTy {
-        ty: Normalized<'tcx, ty::Term<'tcx>>,
+    NormalizedTerm {
+        ty: NormalizedTerm<'tcx>,
         /// If we were able to successfully evaluate the
         /// corresponding cache entry key during predicate
         /// evaluation, then this field stores the final
@@ -175,11 +175,7 @@ impl<'tcx> ProjectionCache<'_, 'tcx> {
     }
 
     /// Indicates that `key` was normalized to `value`.
-    pub fn insert_term(
-        &mut self,
-        key: ProjectionCacheKey<'tcx>,
-        value: Normalized<'tcx, ty::Term<'tcx>>,
-    ) {
+    pub fn insert_term(&mut self, key: ProjectionCacheKey<'tcx>, value: NormalizedTerm<'tcx>) {
         debug!(
             "ProjectionCacheEntry::insert_ty: adding cache entry: key={:?}, value={:?}",
             key, value
@@ -190,7 +186,7 @@ impl<'tcx> ProjectionCache<'_, 'tcx> {
             return;
         }
         let fresh_key =
-            map.insert(key, ProjectionCacheEntry::NormalizedTy { ty: value, complete: None });
+            map.insert(key, ProjectionCacheEntry::NormalizedTerm { ty: value, complete: None });
         assert!(!fresh_key, "never started projecting `{key:?}`");
     }
 
@@ -201,13 +197,16 @@ impl<'tcx> ProjectionCache<'_, 'tcx> {
     pub fn complete(&mut self, key: ProjectionCacheKey<'tcx>, result: EvaluationResult) {
         let mut map = self.map();
         match map.get(&key) {
-            Some(ProjectionCacheEntry::NormalizedTy { ty, complete: _ }) => {
+            Some(ProjectionCacheEntry::NormalizedTerm { ty, complete: _ }) => {
                 info!("ProjectionCacheEntry::complete({:?}) - completing {:?}", key, ty);
                 let mut ty = ty.clone();
                 if result.must_apply_considering_regions() {
                     ty.obligations = vec![];
                 }
-                map.insert(key, ProjectionCacheEntry::NormalizedTy { ty, complete: Some(result) });
+                map.insert(
+                    key,
+                    ProjectionCacheEntry::NormalizedTerm { ty, complete: Some(result) },
+                );
             }
             ref value => {
                 // Type inference could "strand behind" old cache entries. Leave
@@ -219,7 +218,7 @@ impl<'tcx> ProjectionCache<'_, 'tcx> {
 
     pub fn is_complete(&mut self, key: ProjectionCacheKey<'tcx>) -> Option<EvaluationResult> {
         self.map().get(&key).and_then(|res| match res {
-            ProjectionCacheEntry::NormalizedTy { ty: _, complete } => *complete,
+            ProjectionCacheEntry::NormalizedTerm { ty: _, complete } => *complete,
             _ => None,
         })
     }
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 676a7c21841..5180fce2eb3 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -269,6 +269,17 @@ lint_identifier_uncommon_codepoints = identifier contains {$codepoints_len ->
 
 lint_ignored_unless_crate_specified = {$level}({$name}) is ignored unless specified at crate level
 
+lint_impl_trait_overcaptures = `{$self_ty}` will capture more lifetimes than possibly intended in edition 2024
+    .note = specifically, {$num_captured ->
+        [one] this lifetime is
+        *[other] these lifetimes are
+     } in scope but not mentioned in the type's bounds
+    .note2 = all lifetimes in scope will be captured by `impl Trait`s in edition 2024
+    .suggestion = use the precise capturing `use<...>` syntax to make the captures explicit
+
+lint_impl_trait_redundant_captures = all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
+    .suggestion = remove the `use<...>` syntax
+
 lint_improper_ctypes = `extern` {$desc} uses type `{$ty}`, which is not FFI-safe
     .label = not FFI-safe
     .note = the type is defined here
diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs
new file mode 100644
index 00000000000..30bf80b915b
--- /dev/null
+++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs
@@ -0,0 +1,425 @@
+use rustc_data_structures::fx::FxIndexSet;
+use rustc_data_structures::unord::UnordSet;
+use rustc_errors::{Applicability, LintDiagnostic};
+use rustc_hir as hir;
+use rustc_hir::def::DefKind;
+use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_macros::LintDiagnostic;
+use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
+use rustc_middle::ty::{
+    self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
+};
+use rustc_middle::{bug, span_bug};
+use rustc_session::{declare_lint, declare_lint_pass};
+use rustc_span::{sym, BytePos, Span};
+
+use crate::fluent_generated as fluent;
+use crate::{LateContext, LateLintPass};
+
+declare_lint! {
+    /// The `impl_trait_overcaptures` lint warns against cases where lifetime
+    /// capture behavior will differ in edition 2024.
+    ///
+    /// In the 2024 edition, `impl Trait`s will capture all lifetimes in scope,
+    /// rather than just the lifetimes that are mentioned in the bounds of the type.
+    /// Often these sets are equal, but if not, it means that the `impl Trait` may
+    /// cause erroneous borrow-checker errors.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,compile_fail
+    /// # #![feature(precise_capturing)]
+    /// # #![allow(incomplete_features)]
+    /// # #![deny(impl_trait_overcaptures)]
+    /// # use std::fmt::Display;
+    /// let mut x = vec![];
+    /// x.push(1);
+    ///
+    /// fn test(x: &Vec<i32>) -> impl Display {
+    ///     x[0]
+    /// }
+    ///
+    /// let element = test(&x);
+    /// x.push(2);
+    /// println!("{element}");
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// In edition < 2024, the returned `impl Display` doesn't capture the
+    /// lifetime from the `&Vec<i32>`, so the vector can be mutably borrowed
+    /// while the `impl Display` is live.
+    ///
+    /// To fix this, we can explicitly state that the `impl Display` doesn't
+    /// capture any lifetimes, using `impl use<> Display`.
+    pub IMPL_TRAIT_OVERCAPTURES,
+    Allow,
+    "`impl Trait` will capture more lifetimes than possibly intended in edition 2024",
+    @feature_gate = sym::precise_capturing;
+    //@future_incompatible = FutureIncompatibleInfo {
+    //    reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2024),
+    //    reference: "<FIXME>",
+    //};
+}
+
+declare_lint! {
+    /// The `impl_trait_redundant_captures` lint warns against cases where use of the
+    /// precise capturing `use<...>` syntax is not needed.
+    ///
+    /// In the 2024 edition, `impl Trait`s will capture all lifetimes in scope.
+    /// If precise-capturing `use<...>` syntax is used, and the set of parameters
+    /// that are captures are *equal* to the set of parameters in scope, then
+    /// the syntax is redundant, and can be removed.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,compile_fail
+    /// # #![feature(precise_capturing, lifetime_capture_rules_2024)]
+    /// # #![allow(incomplete_features)]
+    /// # #![deny(impl_trait_redundant_captures)]
+    /// fn test<'a>(x: &'a i32) -> impl use<'a> Sized { x }
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// To fix this, remove the `use<'a>`, since the lifetime is already captured
+    /// since it is in scope.
+    pub IMPL_TRAIT_REDUNDANT_CAPTURES,
+    Warn,
+    "redundant precise-capturing `use<...>` syntax on an `impl Trait`",
+    @feature_gate = sym::precise_capturing;
+}
+
+declare_lint_pass!(
+    /// Lint for opaque types that will begin capturing in-scope but unmentioned lifetimes
+    /// in edition 2024.
+    ImplTraitOvercaptures => [IMPL_TRAIT_OVERCAPTURES, IMPL_TRAIT_REDUNDANT_CAPTURES]
+);
+
+impl<'tcx> LateLintPass<'tcx> for ImplTraitOvercaptures {
+    fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::Item<'tcx>) {
+        match &it.kind {
+            hir::ItemKind::Fn(..) => check_fn(cx.tcx, it.owner_id.def_id),
+            _ => {}
+        }
+    }
+
+    fn check_impl_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::ImplItem<'tcx>) {
+        match &it.kind {
+            hir::ImplItemKind::Fn(_, _) => check_fn(cx.tcx, it.owner_id.def_id),
+            _ => {}
+        }
+    }
+
+    fn check_trait_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::TraitItem<'tcx>) {
+        match &it.kind {
+            hir::TraitItemKind::Fn(_, _) => check_fn(cx.tcx, it.owner_id.def_id),
+            _ => {}
+        }
+    }
+}
+
+fn check_fn(tcx: TyCtxt<'_>, parent_def_id: LocalDefId) {
+    let sig = tcx.fn_sig(parent_def_id).instantiate_identity();
+
+    let mut in_scope_parameters = FxIndexSet::default();
+    // Populate the in_scope_parameters list first with all of the generics in scope
+    let mut current_def_id = Some(parent_def_id.to_def_id());
+    while let Some(def_id) = current_def_id {
+        let generics = tcx.generics_of(def_id);
+        for param in &generics.own_params {
+            in_scope_parameters.insert(param.def_id);
+        }
+        current_def_id = generics.parent;
+    }
+
+    // Then visit the signature to walk through all the binders (incl. the late-bound
+    // vars on the function itself, which we need to count too).
+    sig.visit_with(&mut VisitOpaqueTypes {
+        tcx,
+        parent_def_id,
+        in_scope_parameters,
+        seen: Default::default(),
+    });
+}
+
+struct VisitOpaqueTypes<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    parent_def_id: LocalDefId,
+    in_scope_parameters: FxIndexSet<DefId>,
+    seen: FxIndexSet<LocalDefId>,
+}
+
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for VisitOpaqueTypes<'tcx> {
+    fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
+        &mut self,
+        t: &ty::Binder<'tcx, T>,
+    ) -> Self::Result {
+        // When we get into a binder, we need to add its own bound vars to the scope.
+        let mut added = vec![];
+        for arg in t.bound_vars() {
+            let arg: ty::BoundVariableKind = arg;
+            match arg {
+                ty::BoundVariableKind::Region(ty::BoundRegionKind::BrNamed(def_id, ..))
+                | ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(def_id, _)) => {
+                    added.push(def_id);
+                    let unique = self.in_scope_parameters.insert(def_id);
+                    assert!(unique);
+                }
+                _ => {
+                    self.tcx.dcx().span_delayed_bug(
+                        self.tcx.def_span(self.parent_def_id),
+                        format!("unsupported bound variable kind: {arg:?}"),
+                    );
+                }
+            }
+        }
+
+        t.super_visit_with(self);
+
+        // And remove them. The `shift_remove` should be `O(1)` since we're popping
+        // them off from the end.
+        for arg in added.into_iter().rev() {
+            self.in_scope_parameters.shift_remove(&arg);
+        }
+    }
+
+    fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
+        if !t.has_aliases() {
+            return;
+        }
+
+        if let ty::Alias(ty::Projection, opaque_ty) = *t.kind()
+            && self.tcx.is_impl_trait_in_trait(opaque_ty.def_id)
+        {
+            // visit the opaque of the RPITIT
+            self.tcx
+                .type_of(opaque_ty.def_id)
+                .instantiate(self.tcx, opaque_ty.args)
+                .visit_with(self)
+        } else if let ty::Alias(ty::Opaque, opaque_ty) = *t.kind()
+            && let Some(opaque_def_id) = opaque_ty.def_id.as_local()
+            // Don't recurse infinitely on an opaque
+            && self.seen.insert(opaque_def_id)
+            // If it's owned by this function
+            && let opaque =
+                self.tcx.hir_node_by_def_id(opaque_def_id).expect_item().expect_opaque_ty()
+            && let hir::OpaqueTyOrigin::FnReturn(parent_def_id) = opaque.origin
+            && parent_def_id == self.parent_def_id
+        {
+            // Compute the set of args that are captured by the opaque...
+            let mut captured = FxIndexSet::default();
+            let variances = self.tcx.variances_of(opaque_def_id);
+            let mut current_def_id = Some(opaque_def_id.to_def_id());
+            while let Some(def_id) = current_def_id {
+                let generics = self.tcx.generics_of(def_id);
+                for param in &generics.own_params {
+                    // A param is captured if it's invariant.
+                    if variances[param.index as usize] != ty::Invariant {
+                        continue;
+                    }
+                    // We need to turn all `ty::Param`/`ConstKind::Param` and
+                    // `ReEarlyParam`/`ReBound` into def ids.
+                    captured.insert(extract_def_id_from_arg(
+                        self.tcx,
+                        generics,
+                        opaque_ty.args[param.index as usize],
+                    ));
+                }
+                current_def_id = generics.parent;
+            }
+
+            // Compute the set of in scope params that are not captured. Get their spans,
+            // since that's all we really care about them for emitting the diagnostic.
+            let uncaptured_spans: Vec<_> = self
+                .in_scope_parameters
+                .iter()
+                .filter(|def_id| !captured.contains(*def_id))
+                .map(|def_id| self.tcx.def_span(def_id))
+                .collect();
+
+            let opaque_span = self.tcx.def_span(opaque_def_id);
+            let new_capture_rules =
+                opaque_span.at_least_rust_2024() || self.tcx.features().lifetime_capture_rules_2024;
+
+            // If we have uncaptured args, and if the opaque doesn't already have
+            // `use<>` syntax on it, and we're < edition 2024, then warn the user.
+            if !new_capture_rules
+                && opaque.precise_capturing_args.is_none()
+                && !uncaptured_spans.is_empty()
+            {
+                let suggestion = if let Ok(snippet) =
+                    self.tcx.sess.source_map().span_to_snippet(opaque_span)
+                    && snippet.starts_with("impl ")
+                {
+                    let (lifetimes, others): (Vec<_>, Vec<_>) = captured
+                        .into_iter()
+                        .partition(|def_id| self.tcx.def_kind(*def_id) == DefKind::LifetimeParam);
+                    // Take all lifetime params first, then all others (ty/ct).
+                    let generics: Vec<_> = lifetimes
+                        .into_iter()
+                        .chain(others)
+                        .map(|def_id| self.tcx.item_name(def_id).to_string())
+                        .collect();
+                    // Make sure that we're not trying to name any APITs
+                    if generics.iter().all(|name| !name.starts_with("impl ")) {
+                        Some((
+                            format!(" use<{}>", generics.join(", ")),
+                            opaque_span.with_lo(opaque_span.lo() + BytePos(4)).shrink_to_lo(),
+                        ))
+                    } else {
+                        None
+                    }
+                } else {
+                    None
+                };
+
+                self.tcx.emit_node_span_lint(
+                    IMPL_TRAIT_OVERCAPTURES,
+                    self.tcx.local_def_id_to_hir_id(opaque_def_id),
+                    opaque_span,
+                    ImplTraitOvercapturesLint {
+                        self_ty: t,
+                        num_captured: uncaptured_spans.len(),
+                        uncaptured_spans,
+                        suggestion,
+                    },
+                );
+            }
+            // Otherwise, if we are edition 2024, have `use<>` syntax, and
+            // have no uncaptured args, then we should warn to the user that
+            // it's redundant to capture all args explicitly.
+            else if new_capture_rules
+                && let Some((captured_args, capturing_span)) = opaque.precise_capturing_args
+            {
+                let mut explicitly_captured = UnordSet::default();
+                for arg in captured_args {
+                    match self.tcx.named_bound_var(arg.hir_id()) {
+                        Some(
+                            ResolvedArg::EarlyBound(def_id) | ResolvedArg::LateBound(_, _, def_id),
+                        ) => {
+                            if self.tcx.def_kind(self.tcx.parent(def_id)) == DefKind::OpaqueTy {
+                                let (ty::ReEarlyParam(ty::EarlyParamRegion { def_id, .. })
+                                | ty::ReLateParam(ty::LateParamRegion {
+                                    bound_region: ty::BoundRegionKind::BrNamed(def_id, _),
+                                    ..
+                                })) = self
+                                    .tcx
+                                    .map_opaque_lifetime_to_parent_lifetime(def_id.expect_local())
+                                    .kind()
+                                else {
+                                    span_bug!(
+                                        self.tcx.def_span(def_id),
+                                        "variable should have been duplicated from a parent"
+                                    );
+                                };
+                                explicitly_captured.insert(def_id);
+                            } else {
+                                explicitly_captured.insert(def_id);
+                            }
+                        }
+                        _ => {
+                            self.tcx.dcx().span_delayed_bug(
+                                self.tcx.hir().span(arg.hir_id()),
+                                "no valid for captured arg",
+                            );
+                        }
+                    }
+                }
+
+                if self
+                    .in_scope_parameters
+                    .iter()
+                    .all(|def_id| explicitly_captured.contains(def_id))
+                {
+                    self.tcx.emit_node_span_lint(
+                        IMPL_TRAIT_REDUNDANT_CAPTURES,
+                        self.tcx.local_def_id_to_hir_id(opaque_def_id),
+                        opaque_span,
+                        ImplTraitRedundantCapturesLint { capturing_span },
+                    );
+                }
+            }
+
+            // Walk into the bounds of the opaque, too, since we want to get nested opaques
+            // in this lint as well. Interestingly, one place that I expect this lint to fire
+            // is for `impl for<'a> Bound<Out = impl Other>`, since `impl Other` will begin
+            // to capture `'a` in e2024 (even though late-bound vars in opaques are not allowed).
+            for clause in
+                self.tcx.item_bounds(opaque_ty.def_id).iter_instantiated(self.tcx, opaque_ty.args)
+            {
+                clause.visit_with(self)
+            }
+        }
+
+        t.super_visit_with(self);
+    }
+}
+
+struct ImplTraitOvercapturesLint<'tcx> {
+    uncaptured_spans: Vec<Span>,
+    self_ty: Ty<'tcx>,
+    num_captured: usize,
+    suggestion: Option<(String, Span)>,
+}
+
+impl<'a> LintDiagnostic<'a, ()> for ImplTraitOvercapturesLint<'_> {
+    fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::Diag<'a, ()>) {
+        diag.arg("self_ty", self.self_ty.to_string())
+            .arg("num_captured", self.num_captured)
+            .span_note(self.uncaptured_spans, fluent::lint_note)
+            .note(fluent::lint_note2);
+        if let Some((suggestion, span)) = self.suggestion {
+            diag.span_suggestion(
+                span,
+                fluent::lint_suggestion,
+                suggestion,
+                Applicability::MachineApplicable,
+            );
+        }
+    }
+
+    fn msg(&self) -> rustc_errors::DiagMessage {
+        fluent::lint_impl_trait_overcaptures
+    }
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_impl_trait_redundant_captures)]
+struct ImplTraitRedundantCapturesLint {
+    #[suggestion(lint_suggestion, code = "", applicability = "machine-applicable")]
+    capturing_span: Span,
+}
+
+fn extract_def_id_from_arg<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    generics: &'tcx ty::Generics,
+    arg: ty::GenericArg<'tcx>,
+) -> DefId {
+    match arg.unpack() {
+        ty::GenericArgKind::Lifetime(re) => match *re {
+            ty::ReEarlyParam(ebr) => generics.region_param(ebr, tcx).def_id,
+            ty::ReBound(
+                _,
+                ty::BoundRegion { kind: ty::BoundRegionKind::BrNamed(def_id, ..), .. },
+            ) => def_id,
+            _ => unreachable!(),
+        },
+        ty::GenericArgKind::Type(ty) => {
+            let ty::Param(param_ty) = *ty.kind() else {
+                bug!();
+            };
+            generics.type_param(param_ty, tcx).def_id
+        }
+        ty::GenericArgKind::Const(ct) => {
+            let ty::ConstKind::Param(param_ct) = ct.kind() else {
+                bug!();
+            };
+            generics.const_param(param_ct, tcx).def_id
+        }
+    }
+}
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index a78b410f500..d93edadcfbc 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -55,6 +55,7 @@ mod expect;
 mod for_loops_over_fallibles;
 mod foreign_modules;
 pub mod hidden_unicode_codepoints;
+mod impl_trait_overcaptures;
 mod internal;
 mod invalid_from_utf8;
 mod late;
@@ -94,6 +95,7 @@ use drop_forget_useless::*;
 use enum_intrinsics_non_enums::EnumIntrinsicsNonEnums;
 use for_loops_over_fallibles::*;
 use hidden_unicode_codepoints::*;
+use impl_trait_overcaptures::ImplTraitOvercaptures;
 use internal::*;
 use invalid_from_utf8::*;
 use let_underscore::*;
@@ -228,6 +230,7 @@ late_lint_methods!(
             MissingDoc: MissingDoc,
             AsyncFnInTrait: AsyncFnInTrait,
             NonLocalDefinitions: NonLocalDefinitions::default(),
+            ImplTraitOvercaptures: ImplTraitOvercaptures,
         ]
     ]
 );
diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
index 1ea1f496e50..eda40e4a011 100644
--- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
+++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
@@ -1,9 +1,8 @@
 use rustc_hir as hir;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_macros::{LintDiagnostic, Subdiagnostic};
-use rustc_middle::ty::{
-    self, fold::BottomUpFolder, print::TraitPredPrintModifiersAndPath, Ty, TypeFoldable,
-};
+use rustc_middle::ty::print::{PrintTraitPredicateExt as _, TraitPredPrintModifiersAndPath};
+use rustc_middle::ty::{self, fold::BottomUpFolder, Ty, TypeFoldable};
 use rustc_session::{declare_lint, declare_lint_pass};
 use rustc_span::{symbol::kw, Span};
 use rustc_trait_selection::traits;
@@ -108,8 +107,11 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
                     return;
                 }
 
-                let proj_ty =
-                    Ty::new_projection(cx.tcx, proj.projection_ty.def_id, proj.projection_ty.args);
+                let proj_ty = Ty::new_projection(
+                    cx.tcx,
+                    proj.projection_term.def_id,
+                    proj.projection_term.args,
+                );
                 // For every instance of the projection type in the bounds,
                 // replace them with the term we're assigning to the associated
                 // type in our opaque type.
@@ -124,8 +126,8 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
                 // with `impl Send: OtherTrait`.
                 for (assoc_pred, assoc_pred_span) in cx
                     .tcx
-                    .explicit_item_bounds(proj.projection_ty.def_id)
-                    .iter_instantiated_copied(cx.tcx, proj.projection_ty.args)
+                    .explicit_item_bounds(proj.projection_term.def_id)
+                    .iter_instantiated_copied(cx.tcx, proj.projection_term.args)
                 {
                     let assoc_pred = assoc_pred.fold_with(proj_replacer);
                     let Ok(assoc_pred) = traits::fully_normalize(
diff --git a/compiler/rustc_lint/src/reference_casting.rs b/compiler/rustc_lint/src/reference_casting.rs
index b80e90c25a3..34153e3a220 100644
--- a/compiler/rustc_lint/src/reference_casting.rs
+++ b/compiler/rustc_lint/src/reference_casting.rs
@@ -202,8 +202,10 @@ fn is_cast_to_bigger_memory_layout<'tcx>(
 
     // if the current expr looks like this `&mut expr[index]` then just looking
     // at `expr[index]` won't give us the underlying allocation, so we just skip it
-    // the same logic applies field access like `&mut expr.field`
-    if let ExprKind::Index(..) | ExprKind::Field(..) = e_alloc.kind {
+    // the same logic applies field access `&mut expr.field` and reborrows `&mut *expr`.
+    if let ExprKind::Index(..) | ExprKind::Field(..) | ExprKind::Unary(UnOp::Deref, ..) =
+        e_alloc.kind
+    {
         return None;
     }
 
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 2b147e052ae..8866b2be078 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -677,6 +677,33 @@ trait UnusedDelimLint {
         }
 
         // Check if LHS needs parens to prevent false-positives in cases like `fn x() -> u8 { ({ 0 } + 1) }`.
+        //
+        // FIXME: https://github.com/rust-lang/rust/issues/119426
+        // The syntax tree in this code is from after macro expansion, so the
+        // current implementation has both false negatives and false positives
+        // related to expressions containing macros.
+        //
+        //     macro_rules! m1 {
+        //         () => {
+        //             1
+        //         };
+        //     }
+        //
+        //     fn f1() -> u8 {
+        //         // Lint says parens are not needed, but they are.
+        //         (m1! {} + 1)
+        //     }
+        //
+        //     macro_rules! m2 {
+        //         () => {
+        //             loop { break 1; }
+        //         };
+        //     }
+        //
+        //     fn f2() -> u8 {
+        //         // Lint says parens are needed, but they are not.
+        //         (m2!() + 1)
+        //     }
         {
             let mut innermost = inner;
             loop {
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index eea3ca44c48..53694545772 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -38,7 +38,6 @@ declare_lint_pass! {
         DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
         DEPRECATED_IN_FUTURE,
         DEPRECATED_WHERE_CLAUSE_LOCATION,
-        DEREFERENCING_MUT_BINDING,
         DUPLICATE_MACRO_ATTRIBUTES,
         ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT,
         ELIDED_LIFETIMES_IN_PATHS,
@@ -90,6 +89,7 @@ declare_lint_pass! {
         RUST_2021_INCOMPATIBLE_OR_PATTERNS,
         RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX,
         RUST_2021_PRELUDE_COLLISIONS,
+        RUST_2024_INCOMPATIBLE_PAT,
         SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
         SINGLE_USE_LIFETIMES,
         SOFT_UNSTABLE,
@@ -1630,34 +1630,34 @@ declare_lint! {
 }
 
 declare_lint! {
-    /// The `dereferencing_mut_binding` lint detects a `mut x` pattern that resets the binding mode,
-    /// as this behavior will change in rust 2024.
+    /// The `rust_2024_incompatible_pat` lint
+    /// detects patterns whose meaning will change in the Rust 2024 edition.
     ///
     /// ### Example
     ///
-    /// ```rust
-    /// # #![warn(dereferencing_mut_binding)]
-    /// let x = Some(123u32);
-    /// let _y = match &x {
-    ///     Some(mut x) => {
-    ///         x += 1;
-    ///         x
-    ///     }
-    ///     None => 0,
-    /// };
+    /// ```rust,edition2021
+    /// #![feature(ref_pat_eat_one_layer_2024)]
+    /// #![warn(rust_2024_incompatible_pat)]
+    ///
+    /// if let Some(&a) = &Some(&0u8) {
+    ///     let _: u8 = a;
+    /// }
+    /// if let Some(mut _a) = &mut Some(0u8) {
+    ///     _a = 7u8;
+    /// }
     /// ```
     ///
     /// {{produces}}
     ///
     /// ### Explanation
     ///
-    /// Without the `mut`, `x` would have type `&u32`. Pre-2024, adding `mut` makes `x` have type
-    /// `u32`, which was deemed surprising. After edition 2024, adding `mut` will not change the
-    /// type of `x`. This lint warns users of editions before 2024 to update their code.
-    pub DEREFERENCING_MUT_BINDING,
+    /// In Rust 2024 and above, the `mut` keyword does not reset the pattern binding mode,
+    /// and nor do `&` or `&mut` patterns. The lint will suggest code that
+    /// has the same meaning in all editions.
+    pub RUST_2024_INCOMPATIBLE_PAT,
     Allow,
-    "detects `mut x` bindings that change the type of `x`",
-    @feature_gate = sym::mut_preserve_binding_mode_2024;
+    "detects patterns whose meaning will change in Rust 2024",
+    @feature_gate = sym::ref_pat_eat_one_layer_2024;
     // FIXME uncomment below upon stabilization
     /*@future_incompatible = FutureIncompatibleInfo {
         reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2024),
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index 888c2427d8f..e3205fc1d30 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -16,6 +16,7 @@ use rustc_fs_util::try_canonicalize;
 use rustc_hir::def_id::{CrateNum, LocalDefId, StableCrateId, LOCAL_CRATE};
 use rustc_hir::definitions::Definitions;
 use rustc_index::IndexVec;
+use rustc_middle::bug;
 use rustc_middle::ty::{TyCtxt, TyCtxtFeed};
 use rustc_session::config::{self, CrateType, ExternLocation};
 use rustc_session::cstore::{CrateDepKind, CrateSource, ExternCrate, ExternCrateSource};
diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs
index 4d1bd455412..99181f9c860 100644
--- a/compiler/rustc_metadata/src/dependency_format.rs
+++ b/compiler/rustc_metadata/src/dependency_format.rs
@@ -59,6 +59,7 @@ use crate::errors::{
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def_id::CrateNum;
+use rustc_middle::bug;
 use rustc_middle::middle::dependency_format::{Dependencies, DependencyList, Linkage};
 use rustc_middle::ty::TyCtxt;
 use rustc_session::config::CrateType;
diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs
index c8162a1f0ee..99584845e49 100644
--- a/compiler/rustc_metadata/src/lib.rs
+++ b/compiler/rustc_metadata/src/lib.rs
@@ -20,9 +20,6 @@
 extern crate proc_macro;
 
 #[macro_use]
-extern crate rustc_middle;
-
-#[macro_use]
 extern crate tracing;
 
 pub use rmeta::provide;
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 2a33088513b..bb68c6eaf09 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -21,6 +21,7 @@ use rustc_middle::middle::lib_features::LibFeatures;
 use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
 use rustc_middle::ty::codec::TyDecoder;
 use rustc_middle::ty::Visibility;
+use rustc_middle::{bug, implement_ty_decoder};
 use rustc_serialize::opaque::MemDecoder;
 use rustc_serialize::{Decodable, Decoder};
 use rustc_session::cstore::{CrateSource, ExternCrate};
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 531b2e05411..c783149a695 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -11,6 +11,7 @@ use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE};
 use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
 use rustc_middle::arena::ArenaAllocatable;
+use rustc_middle::bug;
 use rustc_middle::metadata::ModChild;
 use rustc_middle::middle::exported_symbols::ExportedSymbol;
 use rustc_middle::middle::stability::DeprecationEntry;
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 7c96a6fa9a9..db0dc6d9064 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -20,6 +20,7 @@ use rustc_middle::ty::codec::TyEncoder;
 use rustc_middle::ty::fast_reject::{self, TreatParams};
 use rustc_middle::ty::{AssocItemContainer, SymbolName};
 use rustc_middle::util::common::to_readable_str;
+use rustc_middle::{bug, span_bug};
 use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder};
 use rustc_session::config::{CrateType, OptLevel};
 use rustc_span::hygiene::HygieneEncodeContext;
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index c9cb2f5a240..79e4ff81093 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -24,6 +24,7 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
 use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
 use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault;
 use rustc_middle::mir;
+use rustc_middle::trivially_parameterized_over_tcx;
 use rustc_middle::ty::fast_reject::SimplifiedType;
 use rustc_middle::ty::{self, ReprOptions, Ty, UnusedGenericParams};
 use rustc_middle::ty::{DeducedParamAttrs, ParameterizedOverTcx, TyCtxt};
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index 383241465c3..6e152cbcb65 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -188,8 +188,9 @@ impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
 }
 
 /// Error information for when the program we executed turned out not to actually be a valid
-/// program. This cannot happen in stand-alone Miri, but it can happen during CTFE/ConstProp
-/// where we work on generic code or execution does not have all information available.
+/// program. This cannot happen in stand-alone Miri (except for layout errors that are only detect
+/// during monomorphization), but it can happen during CTFE/ConstProp where we work on generic code
+/// or execution does not have all information available.
 #[derive(Debug)]
 pub enum InvalidProgramInfo<'tcx> {
     /// Resolution can fail if we are in a too generic context.
@@ -507,7 +508,7 @@ pub enum ValidationErrorKind<'tcx> {
 /// Miri engine, e.g., CTFE does not support dereferencing pointers at integral addresses.
 #[derive(Debug)]
 pub enum UnsupportedOpInfo {
-    /// Free-form case. Only for errors that are never caught!
+    /// Free-form case. Only for errors that are never caught! Used by Miri.
     // FIXME still use translatable diagnostics
     Unsupported(String),
     /// Unsized local variables.
@@ -592,3 +593,117 @@ impl InterpError<'_> {
         )
     }
 }
+
+// Macros for constructing / throwing `InterpError`
+#[macro_export]
+macro_rules! err_unsup {
+    ($($tt:tt)*) => {
+        $crate::mir::interpret::InterpError::Unsupported(
+            $crate::mir::interpret::UnsupportedOpInfo::$($tt)*
+        )
+    };
+}
+
+#[macro_export]
+macro_rules! err_unsup_format {
+    ($($tt:tt)*) => { $crate::err_unsup!(Unsupported(format!($($tt)*))) };
+}
+
+#[macro_export]
+macro_rules! err_inval {
+    ($($tt:tt)*) => {
+        $crate::mir::interpret::InterpError::InvalidProgram(
+            $crate::mir::interpret::InvalidProgramInfo::$($tt)*
+        )
+    };
+}
+
+#[macro_export]
+macro_rules! err_ub {
+    ($($tt:tt)*) => {
+        $crate::mir::interpret::InterpError::UndefinedBehavior(
+            $crate::mir::interpret::UndefinedBehaviorInfo::$($tt)*
+        )
+    };
+}
+
+#[macro_export]
+macro_rules! err_ub_format {
+    ($($tt:tt)*) => { $crate::err_ub!(Ub(format!($($tt)*))) };
+}
+
+#[macro_export]
+macro_rules! err_ub_custom {
+    ($msg:expr $(, $($name:ident = $value:expr),* $(,)?)?) => {{
+        $(
+            let ($($name,)*) = ($($value,)*);
+        )?
+        $crate::err_ub!(Custom(
+            $crate::error::CustomSubdiagnostic {
+                msg: || $msg,
+                add_args: Box::new(move |mut set_arg| {
+                    $($(
+                        set_arg(stringify!($name).into(), rustc_errors::IntoDiagArg::into_diag_arg($name));
+                    )*)?
+                })
+            }
+        ))
+    }};
+}
+
+#[macro_export]
+macro_rules! err_exhaust {
+    ($($tt:tt)*) => {
+        $crate::mir::interpret::InterpError::ResourceExhaustion(
+            $crate::mir::interpret::ResourceExhaustionInfo::$($tt)*
+        )
+    };
+}
+
+#[macro_export]
+macro_rules! err_machine_stop {
+    ($($tt:tt)*) => {
+        $crate::mir::interpret::InterpError::MachineStop(Box::new($($tt)*))
+    };
+}
+
+// In the `throw_*` macros, avoid `return` to make them work with `try {}`.
+#[macro_export]
+macro_rules! throw_unsup {
+    ($($tt:tt)*) => { do yeet $crate::err_unsup!($($tt)*) };
+}
+
+#[macro_export]
+macro_rules! throw_unsup_format {
+    ($($tt:tt)*) => { do yeet $crate::err_unsup_format!($($tt)*) };
+}
+
+#[macro_export]
+macro_rules! throw_inval {
+    ($($tt:tt)*) => { do yeet $crate::err_inval!($($tt)*) };
+}
+
+#[macro_export]
+macro_rules! throw_ub {
+    ($($tt:tt)*) => { do yeet $crate::err_ub!($($tt)*) };
+}
+
+#[macro_export]
+macro_rules! throw_ub_format {
+    ($($tt:tt)*) => { do yeet $crate::err_ub_format!($($tt)*) };
+}
+
+#[macro_export]
+macro_rules! throw_ub_custom {
+    ($($tt:tt)*) => { do yeet $crate::err_ub_custom!($($tt)*) };
+}
+
+#[macro_export]
+macro_rules! throw_exhaust {
+    ($($tt:tt)*) => { do yeet $crate::err_exhaust!($($tt)*) };
+}
+
+#[macro_export]
+macro_rules! throw_machine_stop {
+    ($($tt:tt)*) => { do yeet $crate::err_machine_stop!($($tt)*) };
+}
diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs
index 38cb1d5f9a0..739b1410e6d 100644
--- a/compiler/rustc_middle/src/mir/interpret/mod.rs
+++ b/compiler/rustc_middle/src/mir/interpret/mod.rs
@@ -1,120 +1,9 @@
 //! An interpreter for MIR used in CTFE and by miri.
 
-#[macro_export]
-macro_rules! err_unsup {
-    ($($tt:tt)*) => {
-        $crate::mir::interpret::InterpError::Unsupported(
-            $crate::mir::interpret::UnsupportedOpInfo::$($tt)*
-        )
-    };
-}
-
-#[macro_export]
-macro_rules! err_unsup_format {
-    ($($tt:tt)*) => { err_unsup!(Unsupported(format!($($tt)*))) };
-}
-
-#[macro_export]
-macro_rules! err_inval {
-    ($($tt:tt)*) => {
-        $crate::mir::interpret::InterpError::InvalidProgram(
-            $crate::mir::interpret::InvalidProgramInfo::$($tt)*
-        )
-    };
-}
-
-#[macro_export]
-macro_rules! err_ub {
-    ($($tt:tt)*) => {
-        $crate::mir::interpret::InterpError::UndefinedBehavior(
-            $crate::mir::interpret::UndefinedBehaviorInfo::$($tt)*
-        )
-    };
-}
-
-#[macro_export]
-macro_rules! err_ub_format {
-    ($($tt:tt)*) => { err_ub!(Ub(format!($($tt)*))) };
-}
-
-#[macro_export]
-macro_rules! err_exhaust {
-    ($($tt:tt)*) => {
-        $crate::mir::interpret::InterpError::ResourceExhaustion(
-            $crate::mir::interpret::ResourceExhaustionInfo::$($tt)*
-        )
-    };
-}
-
-#[macro_export]
-macro_rules! err_machine_stop {
-    ($($tt:tt)*) => {
-        $crate::mir::interpret::InterpError::MachineStop(Box::new($($tt)*))
-    };
-}
-
-// In the `throw_*` macros, avoid `return` to make them work with `try {}`.
-#[macro_export]
-macro_rules! throw_unsup {
-    ($($tt:tt)*) => { do yeet err_unsup!($($tt)*) };
-}
-
-#[macro_export]
-macro_rules! throw_unsup_format {
-    ($($tt:tt)*) => { throw_unsup!(Unsupported(format!($($tt)*))) };
-}
-
-#[macro_export]
-macro_rules! throw_inval {
-    ($($tt:tt)*) => { do yeet err_inval!($($tt)*) };
-}
-
-#[macro_export]
-macro_rules! throw_ub {
-    ($($tt:tt)*) => { do yeet err_ub!($($tt)*) };
-}
-
-#[macro_export]
-macro_rules! throw_ub_format {
-    ($($tt:tt)*) => { throw_ub!(Ub(format!($($tt)*))) };
-}
-
-#[macro_export]
-macro_rules! throw_exhaust {
-    ($($tt:tt)*) => { do yeet err_exhaust!($($tt)*) };
-}
-
-#[macro_export]
-macro_rules! throw_machine_stop {
-    ($($tt:tt)*) => { do yeet err_machine_stop!($($tt)*) };
-}
-
-#[macro_export]
-macro_rules! err_ub_custom {
-    ($msg:expr $(, $($name:ident = $value:expr),* $(,)?)?) => {{
-        $(
-            let ($($name,)*) = ($($value,)*);
-        )?
-        err_ub!(Custom(
-            rustc_middle::error::CustomSubdiagnostic {
-                msg: || $msg,
-                add_args: Box::new(move |mut set_arg| {
-                    $($(
-                        set_arg(stringify!($name).into(), rustc_errors::IntoDiagArg::into_diag_arg($name));
-                    )*)?
-                })
-            }
-        ))
-    }};
-}
-
-#[macro_export]
-macro_rules! throw_ub_custom {
-    ($($tt:tt)*) => { do yeet err_ub_custom!($($tt)*) };
-}
+#[macro_use]
+mod error;
 
 mod allocation;
-mod error;
 mod pointer;
 mod queries;
 mod value;
@@ -150,6 +39,12 @@ pub use self::error::{
     ScalarSizeMismatch, UndefinedBehaviorInfo, UnsupportedOpInfo, ValidationErrorInfo,
     ValidationErrorKind,
 };
+// Also make the error macros available from this module.
+pub use {
+    err_exhaust, err_inval, err_machine_stop, err_ub, err_ub_custom, err_ub_format, err_unsup,
+    err_unsup_format, throw_exhaust, throw_inval, throw_machine_stop, throw_ub, throw_ub_custom,
+    throw_ub_format, throw_unsup, throw_unsup_format,
+};
 
 pub use self::value::Scalar;
 
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 6c33a29ea81..fb796bf87a1 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -247,22 +247,15 @@ pub enum ObligationCauseCode<'tcx> {
     /// A tuple is WF only if its middle elements are `Sized`.
     TupleElem,
 
-    /// Must satisfy all of the where-clause predicates of the
-    /// given item.
-    WhereClause(DefId),
-
-    /// Like `WhereClause`, but carries the span of the
-    /// predicate when it can be identified.
-    SpannedWhereClause(DefId, Span),
-
-    /// Like `WhereClause`, but carries the `HirId` of the
-    /// expression that caused the obligation, and the `usize`
-    /// indicates exactly which predicate it is in the list of
-    /// instantiated predicates.
-    WhereClauseInExpr(DefId, HirId, usize),
-
-    /// Combines `SpannedWhereClause` and `WhereClauseInExpr`.
-    SpannedWhereClauseInExpr(DefId, Span, HirId, usize),
+    /// Represents a clause that comes from a specific item.
+    /// The span corresponds to the clause.
+    WhereClause(DefId, Span),
+
+    /// Like `WhereClause`, but also identifies the expression
+    /// which requires the `where` clause to be proven, and also
+    /// identifies the index of the predicate in the `predicates_of`
+    /// list of the item.
+    WhereClauseInExpr(DefId, Span, HirId, usize),
 
     /// A type like `&'a T` is WF only if `T: 'a`.
     ReferenceOutlivesReferent(Ty<'tcx>),
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 0464be2df06..e831db1a41b 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -26,6 +26,7 @@ use crate::traits::solve;
 use crate::traits::solve::{
     ExternalConstraints, ExternalConstraintsData, PredefinedOpaques, PredefinedOpaquesData,
 };
+use crate::ty::predicate::ExistentialPredicateStableCmpExt as _;
 use crate::ty::{
     self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Clauses, Const, ConstData,
     GenericParamDefKind, ImplPolarity, List, ListWithCachedTypeInfo, ParamConst, ParamTy, Pattern,
@@ -99,17 +100,17 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
     type CanonicalVars = CanonicalVarInfos<'tcx>;
 
     type Ty = Ty<'tcx>;
-    type Pat = Pattern<'tcx>;
     type Tys = &'tcx List<Ty<'tcx>>;
     type AliasTy = ty::AliasTy<'tcx>;
     type ParamTy = ParamTy;
     type BoundTy = ty::BoundTy;
     type PlaceholderTy = ty::PlaceholderType;
-
     type ErrorGuaranteed = ErrorGuaranteed;
+
     type BoundExistentialPredicates = &'tcx List<PolyExistentialPredicate<'tcx>>;
     type PolyFnSig = PolyFnSig<'tcx>;
     type AllocId = crate::mir::interpret::AllocId;
+    type Pat = Pattern<'tcx>;
 
     type Const = ty::Const<'tcx>;
     type AliasConst = ty::UnevaluatedConst<'tcx>;
@@ -121,8 +122,8 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
 
     type Region = Region<'tcx>;
     type EarlyParamRegion = ty::EarlyParamRegion;
-    type BoundRegion = ty::BoundRegion;
     type LateParamRegion = ty::LateParamRegion;
+    type BoundRegion = ty::BoundRegion;
     type InferRegion = ty::RegionVid;
     type PlaceholderRegion = ty::PlaceholderRegion;
 
@@ -131,6 +132,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
     type RegionOutlivesPredicate = ty::RegionOutlivesPredicate<'tcx>;
     type TypeOutlivesPredicate = ty::TypeOutlivesPredicate<'tcx>;
     type ProjectionPredicate = ty::ProjectionPredicate<'tcx>;
+    type AliasTerm = ty::AliasTerm<'tcx>;
     type NormalizesTo = ty::NormalizesTo<'tcx>;
     type SubtypePredicate = ty::SubtypePredicate<'tcx>;
     type CoercePredicate = ty::CoercePredicate<'tcx>;
@@ -146,6 +148,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
         self.generics_of(def_id)
     }
 
+    fn mk_args(self, args: &[Self::GenericArg]) -> Self::GenericArgs {
+        self.mk_args(args)
+    }
+
     fn check_and_mk_args(
         self,
         def_id: DefId,
@@ -153,6 +159,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
     ) -> ty::GenericArgsRef<'tcx> {
         self.check_and_mk_args(def_id, args)
     }
+
+    fn parent(self, def_id: Self::DefId) -> Self::DefId {
+        self.parent(def_id)
+    }
 }
 
 type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>;
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index 0dc835671d5..4de7d532c96 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -294,10 +294,10 @@ impl FlagComputation {
                 self.add_ty(b);
             }
             ty::PredicateKind::Clause(ty::ClauseKind::Projection(ty::ProjectionPredicate {
-                projection_ty,
+                projection_term,
                 term,
             })) => {
-                self.add_alias_ty(projection_ty);
+                self.add_alias_term(projection_term);
                 self.add_term(term);
             }
             ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
@@ -313,7 +313,7 @@ impl FlagComputation {
             }
             ty::PredicateKind::Ambiguous => {}
             ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term }) => {
-                self.add_alias_ty(alias);
+                self.add_alias_term(alias);
                 self.add_term(term);
             }
             ty::PredicateKind::AliasRelate(t1, t2, _) => {
@@ -410,6 +410,10 @@ impl FlagComputation {
         self.add_args(alias_ty.args);
     }
 
+    fn add_alias_term(&mut self, alias_term: ty::AliasTerm<'_>) {
+        self.add_args(alias_term.args);
+    }
+
     fn add_args(&mut self, args: &[GenericArg<'_>]) {
         for kind in args {
             match kind.unpack() {
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 12cefc23233..dc5e881843a 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -96,13 +96,13 @@ pub use self::list::{List, ListWithCachedTypeInfo};
 pub use self::parameterized::ParameterizedOverTcx;
 pub use self::pattern::{Pattern, PatternKind};
 pub use self::predicate::{
-    Clause, ClauseKind, CoercePredicate, ExistentialPredicate, ExistentialProjection,
-    ExistentialTraitRef, NormalizesTo, OutlivesPredicate, PolyCoercePredicate,
-    PolyExistentialPredicate, PolyExistentialProjection, PolyExistentialTraitRef,
-    PolyProjectionPredicate, PolyRegionOutlivesPredicate, PolySubtypePredicate, PolyTraitPredicate,
-    PolyTraitRef, PolyTypeOutlivesPredicate, Predicate, PredicateKind, ProjectionPredicate,
-    RegionOutlivesPredicate, SubtypePredicate, ToPolyTraitRef, ToPredicate, TraitPredicate,
-    TraitRef, TypeOutlivesPredicate,
+    Clause, ClauseKind, CoercePredicate, ExistentialPredicate, ExistentialPredicateStableCmpExt,
+    ExistentialProjection, ExistentialTraitRef, NormalizesTo, OutlivesPredicate,
+    PolyCoercePredicate, PolyExistentialPredicate, PolyExistentialProjection,
+    PolyExistentialTraitRef, PolyProjectionPredicate, PolyRegionOutlivesPredicate,
+    PolySubtypePredicate, PolyTraitPredicate, PolyTraitRef, PolyTypeOutlivesPredicate, Predicate,
+    PredicateKind, ProjectionPredicate, RegionOutlivesPredicate, SubtypePredicate, ToPolyTraitRef,
+    ToPredicate, TraitPredicate, TraitRef, TypeOutlivesPredicate,
 };
 pub use self::region::{
     BoundRegion, BoundRegionKind, BoundRegionKind::*, EarlyParamRegion, LateParamRegion, Region,
@@ -110,11 +110,11 @@ pub use self::region::{
 };
 pub use self::rvalue_scopes::RvalueScopes;
 pub use self::sty::{
-    AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig,
-    ClosureArgs, ClosureArgsParts, CoroutineArgs, CoroutineArgsParts, CoroutineClosureArgs,
-    CoroutineClosureArgsParts, CoroutineClosureSignature, FnSig, GenSig, InlineConstArgs,
-    InlineConstArgsParts, ParamConst, ParamTy, PolyFnSig, TyKind, TypeAndMut, UpvarArgs,
-    VarianceDiagInfo,
+    AliasTerm, AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind,
+    CanonicalPolyFnSig, ClosureArgs, ClosureArgsParts, CoroutineArgs, CoroutineArgsParts,
+    CoroutineClosureArgs, CoroutineClosureArgsParts, CoroutineClosureSignature, FnSig, GenSig,
+    InlineConstArgs, InlineConstArgsParts, ParamConst, ParamTy, PolyFnSig, TyKind, TypeAndMut,
+    UpvarArgs, VarianceDiagInfo,
 };
 pub use self::trait_def::TraitDef;
 pub use self::typeck_results::{
@@ -277,61 +277,6 @@ pub enum ImplSubject<'tcx> {
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)]
 #[derive(TypeFoldable, TypeVisitable)]
-pub enum ImplPolarity {
-    /// `impl Trait for Type`
-    Positive,
-    /// `impl !Trait for Type`
-    Negative,
-    /// `#[rustc_reservation_impl] impl Trait for Type`
-    ///
-    /// This is a "stability hack", not a real Rust feature.
-    /// See #64631 for details.
-    Reservation,
-}
-
-impl fmt::Display for ImplPolarity {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            Self::Positive => f.write_str("positive"),
-            Self::Negative => f.write_str("negative"),
-            Self::Reservation => f.write_str("reservation"),
-        }
-    }
-}
-
-/// Polarity for a trait predicate. May either be negative or positive.
-/// Distinguished from [`ImplPolarity`] since we never compute goals with
-/// "reservation" level.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)]
-#[derive(TypeFoldable, TypeVisitable)]
-pub enum PredicatePolarity {
-    /// `Type: Trait`
-    Positive,
-    /// `Type: !Trait`
-    Negative,
-}
-
-impl PredicatePolarity {
-    /// Flips polarity by turning `Positive` into `Negative` and `Negative` into `Positive`.
-    pub fn flip(&self) -> PredicatePolarity {
-        match self {
-            PredicatePolarity::Positive => PredicatePolarity::Negative,
-            PredicatePolarity::Negative => PredicatePolarity::Positive,
-        }
-    }
-}
-
-impl fmt::Display for PredicatePolarity {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            Self::Positive => f.write_str("positive"),
-            Self::Negative => f.write_str("negative"),
-        }
-    }
-}
-
-#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)]
-#[derive(TypeFoldable, TypeVisitable)]
 pub enum Asyncness {
     Yes,
     No,
@@ -684,15 +629,14 @@ impl<'tcx> Term<'tcx> {
         }
     }
 
-    /// This function returns the inner `AliasTy` for a `ty::Alias` or `ConstKind::Unevaluated`.
-    pub fn to_alias_ty(&self, tcx: TyCtxt<'tcx>) -> Option<AliasTy<'tcx>> {
+    pub fn to_alias_term(self) -> Option<AliasTerm<'tcx>> {
         match self.unpack() {
             TermKind::Ty(ty) => match *ty.kind() {
-                ty::Alias(_kind, alias_ty) => Some(alias_ty),
+                ty::Alias(_kind, alias_ty) => Some(alias_ty.into()),
                 _ => None,
             },
             TermKind::Const(ct) => match ct.kind() {
-                ConstKind::Unevaluated(uv) => Some(AliasTy::new(tcx, uv.def, uv.args)),
+                ConstKind::Unevaluated(uv) => Some(uv.into()),
                 _ => None,
             },
         }
diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs
index 5387036d409..e78856517b2 100644
--- a/compiler/rustc_middle/src/ty/predicate.rs
+++ b/compiler/rustc_middle/src/ty/predicate.rs
@@ -1,22 +1,28 @@
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::intern::Interned;
-use rustc_errors::{DiagArgValue, IntoDiagArg};
 use rustc_hir::def_id::DefId;
-use rustc_macros::{HashStable, Lift, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
-use rustc_type_ir::ClauseKind as IrClauseKind;
-use rustc_type_ir::PredicateKind as IrPredicateKind;
-use rustc_type_ir::TraitRef as IrTraitRef;
+use rustc_macros::{
+    extension, HashStable, Lift, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable,
+};
+use rustc_type_ir as ir;
 use std::cmp::Ordering;
 
-use crate::ty::visit::TypeVisitableExt;
 use crate::ty::{
-    self, AliasTy, Binder, DebruijnIndex, DebugWithInfcx, EarlyBinder, GenericArgsRef,
-    PredicatePolarity, Term, Ty, TyCtxt, TypeFlags, WithCachedTypeInfo,
+    self, Binder, DebruijnIndex, EarlyBinder, PredicatePolarity, Term, Ty, TyCtxt, TypeFlags,
+    WithCachedTypeInfo,
 };
 
-pub type TraitRef<'tcx> = IrTraitRef<TyCtxt<'tcx>>;
-pub type ClauseKind<'tcx> = IrClauseKind<TyCtxt<'tcx>>;
-pub type PredicateKind<'tcx> = IrPredicateKind<TyCtxt<'tcx>>;
+pub type TraitRef<'tcx> = ir::TraitRef<TyCtxt<'tcx>>;
+pub type ProjectionPredicate<'tcx> = ir::ProjectionPredicate<TyCtxt<'tcx>>;
+pub type ExistentialPredicate<'tcx> = ir::ExistentialPredicate<TyCtxt<'tcx>>;
+pub type ExistentialTraitRef<'tcx> = ir::ExistentialTraitRef<TyCtxt<'tcx>>;
+pub type ExistentialProjection<'tcx> = ir::ExistentialProjection<TyCtxt<'tcx>>;
+pub type TraitPredicate<'tcx> = ir::TraitPredicate<TyCtxt<'tcx>>;
+pub type ClauseKind<'tcx> = ir::ClauseKind<TyCtxt<'tcx>>;
+pub type PredicateKind<'tcx> = ir::PredicateKind<TyCtxt<'tcx>>;
+pub type NormalizesTo<'tcx> = ir::NormalizesTo<TyCtxt<'tcx>>;
+pub type CoercePredicate<'tcx> = ir::CoercePredicate<TyCtxt<'tcx>>;
+pub type SubtypePredicate<'tcx> = ir::SubtypePredicate<TyCtxt<'tcx>>;
 
 /// A statement that can be proven by a trait solver. This includes things that may
 /// show up in where clauses, such as trait predicates and projection predicates,
@@ -195,43 +201,25 @@ impl<'tcx> Clause<'tcx> {
     }
 }
 
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub enum ExistentialPredicate<'tcx> {
-    /// E.g., `Iterator`.
-    Trait(ExistentialTraitRef<'tcx>),
-    /// E.g., `Iterator::Item = T`.
-    Projection(ExistentialProjection<'tcx>),
-    /// E.g., `Send`.
-    AutoTrait(DefId),
-}
-
-impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ExistentialPredicate<'tcx> {
-    fn fmt<Infcx: rustc_type_ir::InferCtxtLike<Interner = TyCtxt<'tcx>>>(
-        this: rustc_type_ir::WithInfcx<'_, Infcx, &Self>,
-        f: &mut std::fmt::Formatter<'_>,
-    ) -> std::fmt::Result {
-        std::fmt::Debug::fmt(&this.data, f)
-    }
-}
-
+#[extension(pub trait ExistentialPredicateStableCmpExt<'tcx>)]
 impl<'tcx> ExistentialPredicate<'tcx> {
     /// Compares via an ordering that will not change if modules are reordered or other changes are
     /// made to the tree. In particular, this ordering is preserved across incremental compilations.
-    pub fn stable_cmp(&self, tcx: TyCtxt<'tcx>, other: &Self) -> Ordering {
-        use self::ExistentialPredicate::*;
+    fn stable_cmp(&self, tcx: TyCtxt<'tcx>, other: &Self) -> Ordering {
         match (*self, *other) {
-            (Trait(_), Trait(_)) => Ordering::Equal,
-            (Projection(ref a), Projection(ref b)) => {
+            (ExistentialPredicate::Trait(_), ExistentialPredicate::Trait(_)) => Ordering::Equal,
+            (ExistentialPredicate::Projection(ref a), ExistentialPredicate::Projection(ref b)) => {
                 tcx.def_path_hash(a.def_id).cmp(&tcx.def_path_hash(b.def_id))
             }
-            (AutoTrait(ref a), AutoTrait(ref b)) => {
+            (ExistentialPredicate::AutoTrait(ref a), ExistentialPredicate::AutoTrait(ref b)) => {
                 tcx.def_path_hash(*a).cmp(&tcx.def_path_hash(*b))
             }
-            (Trait(_), _) => Ordering::Less,
-            (Projection(_), Trait(_)) => Ordering::Greater,
-            (Projection(_), _) => Ordering::Less,
-            (AutoTrait(_), _) => Ordering::Greater,
+            (ExistentialPredicate::Trait(_), _) => Ordering::Less,
+            (ExistentialPredicate::Projection(_), ExistentialPredicate::Trait(_)) => {
+                Ordering::Greater
+            }
+            (ExistentialPredicate::Projection(_), _) => Ordering::Less,
+            (ExistentialPredicate::AutoTrait(_), _) => Ordering::Greater,
         }
     }
 }
@@ -340,52 +328,6 @@ impl<'tcx> PolyTraitRef<'tcx> {
     }
 }
 
-/// An existential reference to a trait, where `Self` is erased.
-/// For example, the trait object `Trait<'a, 'b, X, Y>` is:
-/// ```ignore (illustrative)
-/// exists T. T: Trait<'a, 'b, X, Y>
-/// ```
-/// The generic parameters don't include the erased `Self`, only trait
-/// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above).
-#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct ExistentialTraitRef<'tcx> {
-    pub def_id: DefId,
-    pub args: GenericArgsRef<'tcx>,
-}
-
-impl<'tcx> ExistentialTraitRef<'tcx> {
-    pub fn erase_self_ty(
-        tcx: TyCtxt<'tcx>,
-        trait_ref: ty::TraitRef<'tcx>,
-    ) -> ty::ExistentialTraitRef<'tcx> {
-        // Assert there is a Self.
-        trait_ref.args.type_at(0);
-
-        ty::ExistentialTraitRef {
-            def_id: trait_ref.def_id,
-            args: tcx.mk_args(&trait_ref.args[1..]),
-        }
-    }
-
-    /// Object types don't have a self type specified. Therefore, when
-    /// we convert the principal trait-ref into a normal trait-ref,
-    /// you must give *some* self type. A common choice is `mk_err()`
-    /// or some placeholder type.
-    pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::TraitRef<'tcx> {
-        // otherwise the escaping vars would be captured by the binder
-        // debug_assert!(!self_ty.has_escaping_bound_vars());
-
-        ty::TraitRef::new(tcx, self.def_id, [self_ty.into()].into_iter().chain(self.args.iter()))
-    }
-}
-
-impl<'tcx> IntoDiagArg for ExistentialTraitRef<'tcx> {
-    fn into_diag_arg(self) -> DiagArgValue {
-        self.to_string().into_diag_arg()
-    }
-}
-
 pub type PolyExistentialTraitRef<'tcx> = ty::Binder<'tcx, ExistentialTraitRef<'tcx>>;
 
 impl<'tcx> PolyExistentialTraitRef<'tcx> {
@@ -402,62 +344,8 @@ impl<'tcx> PolyExistentialTraitRef<'tcx> {
     }
 }
 
-/// A `ProjectionPredicate` for an `ExistentialTraitRef`.
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct ExistentialProjection<'tcx> {
-    pub def_id: DefId,
-    pub args: GenericArgsRef<'tcx>,
-    pub term: Term<'tcx>,
-}
-
 pub type PolyExistentialProjection<'tcx> = ty::Binder<'tcx, ExistentialProjection<'tcx>>;
 
-impl<'tcx> ExistentialProjection<'tcx> {
-    /// Extracts the underlying existential trait reference from this projection.
-    /// For example, if this is a projection of `exists T. <T as Iterator>::Item == X`,
-    /// then this function would return an `exists T. T: Iterator` existential trait
-    /// reference.
-    pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::ExistentialTraitRef<'tcx> {
-        let def_id = tcx.parent(self.def_id);
-        let args_count = tcx.generics_of(def_id).count() - 1;
-        let args = tcx.mk_args(&self.args[..args_count]);
-        ty::ExistentialTraitRef { def_id, args }
-    }
-
-    pub fn with_self_ty(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        self_ty: Ty<'tcx>,
-    ) -> ty::ProjectionPredicate<'tcx> {
-        // otherwise the escaping regions would be captured by the binders
-        debug_assert!(!self_ty.has_escaping_bound_vars());
-
-        ty::ProjectionPredicate {
-            projection_ty: AliasTy::new(
-                tcx,
-                self.def_id,
-                [self_ty.into()].into_iter().chain(self.args),
-            ),
-            term: self.term,
-        }
-    }
-
-    pub fn erase_self_ty(
-        tcx: TyCtxt<'tcx>,
-        projection_predicate: ty::ProjectionPredicate<'tcx>,
-    ) -> Self {
-        // Assert there is a Self.
-        projection_predicate.projection_ty.args.type_at(0);
-
-        Self {
-            def_id: projection_predicate.projection_ty.def_id,
-            args: tcx.mk_args(&projection_predicate.projection_ty.args[1..]),
-            term: projection_predicate.term,
-        }
-    }
-}
-
 impl<'tcx> PolyExistentialProjection<'tcx> {
     pub fn with_self_ty(
         &self,
@@ -578,37 +466,8 @@ impl<'tcx> Clause<'tcx> {
     }
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct TraitPredicate<'tcx> {
-    pub trait_ref: TraitRef<'tcx>,
-
-    /// If polarity is Positive: we are proving that the trait is implemented.
-    ///
-    /// If polarity is Negative: we are proving that a negative impl of this trait
-    /// exists. (Note that coherence also checks whether negative impls of supertraits
-    /// exist via a series of predicates.)
-    ///
-    /// If polarity is Reserved: that's a bug.
-    pub polarity: PredicatePolarity,
-}
-
 pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>;
 
-impl<'tcx> TraitPredicate<'tcx> {
-    pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
-        Self { trait_ref: self.trait_ref.with_self_ty(tcx, self_ty), ..self }
-    }
-
-    pub fn def_id(self) -> DefId {
-        self.trait_ref.def_id
-    }
-
-    pub fn self_ty(self) -> Ty<'tcx> {
-        self.trait_ref.self_ty()
-    }
-}
-
 impl<'tcx> PolyTraitPredicate<'tcx> {
     pub fn def_id(self) -> DefId {
         // Ok to skip binder since trait `DefId` does not care about regions.
@@ -634,71 +493,17 @@ pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate<Ty<'tcx>, ty::Region<'t
 pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder<'tcx, RegionOutlivesPredicate<'tcx>>;
 pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder<'tcx, TypeOutlivesPredicate<'tcx>>;
 
-/// Encodes that `a` must be a subtype of `b`. The `a_is_expected` flag indicates
-/// whether the `a` type is the type that we should label as "expected" when
-/// presenting user diagnostics.
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct SubtypePredicate<'tcx> {
-    pub a_is_expected: bool,
-    pub a: Ty<'tcx>,
-    pub b: Ty<'tcx>,
-}
 pub type PolySubtypePredicate<'tcx> = ty::Binder<'tcx, SubtypePredicate<'tcx>>;
 
-/// Encodes that we have to coerce *from* the `a` type to the `b` type.
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct CoercePredicate<'tcx> {
-    pub a: Ty<'tcx>,
-    pub b: Ty<'tcx>,
-}
 pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>;
 
-/// This kind of predicate has no *direct* correspondent in the
-/// syntax, but it roughly corresponds to the syntactic forms:
-///
-/// 1. `T: TraitRef<..., Item = Type>`
-/// 2. `<T as TraitRef<...>>::Item == Type` (NYI)
-///
-/// In particular, form #1 is "desugared" to the combination of a
-/// normal trait predicate (`T: TraitRef<...>`) and one of these
-/// predicates. Form #2 is a broader form in that it also permits
-/// equality between arbitrary types. Processing an instance of
-/// Form #2 eventually yields one of these `ProjectionPredicate`
-/// instances to normalize the LHS.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct ProjectionPredicate<'tcx> {
-    pub projection_ty: AliasTy<'tcx>,
-    pub term: Term<'tcx>,
-}
-
-impl<'tcx> ProjectionPredicate<'tcx> {
-    pub fn self_ty(self) -> Ty<'tcx> {
-        self.projection_ty.self_ty()
-    }
-
-    pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ProjectionPredicate<'tcx> {
-        Self { projection_ty: self.projection_ty.with_self_ty(tcx, self_ty), ..self }
-    }
-
-    pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId {
-        self.projection_ty.trait_def_id(tcx)
-    }
-
-    pub fn def_id(self) -> DefId {
-        self.projection_ty.def_id
-    }
-}
-
 pub type PolyProjectionPredicate<'tcx> = Binder<'tcx, ProjectionPredicate<'tcx>>;
 
 impl<'tcx> PolyProjectionPredicate<'tcx> {
     /// Returns the `DefId` of the trait of the associated item being projected.
     #[inline]
     pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId {
-        self.skip_binder().projection_ty.trait_def_id(tcx)
+        self.skip_binder().projection_term.trait_def_id(tcx)
     }
 
     /// Get the [PolyTraitRef] required for this projection to be well formed.
@@ -711,7 +516,7 @@ impl<'tcx> PolyProjectionPredicate<'tcx> {
         // This is because here `self` has a `Binder` and so does our
         // return value, so we are preserving the number of binding
         // levels.
-        self.map_bound(|predicate| predicate.projection_ty.trait_ref(tcx))
+        self.map_bound(|predicate| predicate.projection_term.trait_ref(tcx))
     }
 
     pub fn term(&self) -> Binder<'tcx, Term<'tcx>> {
@@ -724,34 +529,7 @@ impl<'tcx> PolyProjectionPredicate<'tcx> {
     /// associated type, which is in `tcx.associated_item(projection_def_id()).container`.
     pub fn projection_def_id(&self) -> DefId {
         // Ok to skip binder since trait `DefId` does not care about regions.
-        self.skip_binder().projection_ty.def_id
-    }
-}
-
-/// Used by the new solver. Unlike a `ProjectionPredicate` this can only be
-/// proven by actually normalizing `alias`.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct NormalizesTo<'tcx> {
-    pub alias: AliasTy<'tcx>,
-    pub term: Term<'tcx>,
-}
-
-impl<'tcx> NormalizesTo<'tcx> {
-    pub fn self_ty(self) -> Ty<'tcx> {
-        self.alias.self_ty()
-    }
-
-    pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> NormalizesTo<'tcx> {
-        Self { alias: self.alias.with_self_ty(tcx, self_ty), ..self }
-    }
-
-    pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId {
-        self.alias.trait_def_id(tcx)
-    }
-
-    pub fn def_id(self) -> DefId {
-        self.alias.def_id
+        self.skip_binder().projection_term.def_id
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 14a628ab064..8d8ed70a757 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1277,7 +1277,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
 
     fn pretty_print_inherent_projection(
         &mut self,
-        alias_ty: ty::AliasTy<'tcx>,
+        alias_ty: ty::AliasTerm<'tcx>,
     ) -> Result<(), PrintError> {
         let def_key = self.tcx().def_key(alias_ty.def_id);
         self.path_generic_args(
@@ -2953,8 +2953,9 @@ impl<'tcx> fmt::Debug for TraitPredPrintModifiersAndPath<'tcx> {
     }
 }
 
+#[extension(pub trait PrintTraitPredicateExt<'tcx>)]
 impl<'tcx> ty::TraitPredicate<'tcx> {
-    pub fn print_modifiers_and_trait_path(self) -> TraitPredPrintModifiersAndPath<'tcx> {
+    fn print_modifiers_and_trait_path(self) -> TraitPredPrintModifiersAndPath<'tcx> {
         TraitPredPrintModifiersAndPath(self)
     }
 }
@@ -3037,6 +3038,15 @@ define_print! {
         p!(write("<{} as {}>", self.self_ty(), self.print_only_trait_path()))
     }
 
+    ty::TraitPredicate<'tcx> {
+        p!(print(self.trait_ref.self_ty()), ": ");
+        p!(pretty_print_bound_constness(self.trait_ref));
+        if let ty::PredicatePolarity::Negative = self.polarity {
+            p!("!");
+        }
+        p!(print(self.trait_ref.print_trait_sugared()))
+    }
+
     ty::TypeAndMut<'tcx> {
         p!(write("{}", self.mutbl.prefix_str()), print(self.ty))
     }
@@ -3077,13 +3087,15 @@ define_print! {
             ty::PredicateKind::AliasRelate(t1, t2, dir) => p!(print(t1), write(" {} ", dir), print(t2)),
         }
     }
-}
-
-define_print_and_forward_display! {
-    (self, cx):
 
-    &'tcx ty::List<Ty<'tcx>> {
-        p!("{{", comma_sep(self.iter()), "}}")
+    ty::ExistentialPredicate<'tcx> {
+        match *self {
+            ty::ExistentialPredicate::Trait(x) => p!(print(x)),
+            ty::ExistentialPredicate::Projection(x) => p!(print(x)),
+            ty::ExistentialPredicate::AutoTrait(def_id) => {
+                p!(print_def_path(def_id, &[]));
+            }
+        }
     }
 
     ty::ExistentialTraitRef<'tcx> {
@@ -3098,14 +3110,36 @@ define_print_and_forward_display! {
         p!(write("{} = ", name), print(self.term))
     }
 
-    ty::ExistentialPredicate<'tcx> {
-        match *self {
-            ty::ExistentialPredicate::Trait(x) => p!(print(x)),
-            ty::ExistentialPredicate::Projection(x) => p!(print(x)),
-            ty::ExistentialPredicate::AutoTrait(def_id) => {
-                p!(print_def_path(def_id, &[]));
-            }
-        }
+    ty::ProjectionPredicate<'tcx> {
+        p!(print(self.projection_term), " == ");
+        cx.reset_type_limit();
+        p!(print(self.term))
+    }
+
+    ty::SubtypePredicate<'tcx> {
+        p!(print(self.a), " <: ");
+        cx.reset_type_limit();
+        p!(print(self.b))
+    }
+
+    ty::CoercePredicate<'tcx> {
+        p!(print(self.a), " -> ");
+        cx.reset_type_limit();
+        p!(print(self.b))
+    }
+
+    ty::NormalizesTo<'tcx> {
+        p!(print(self.alias), " normalizes-to ");
+        cx.reset_type_limit();
+        p!(print(self.term))
+    }
+}
+
+define_print_and_forward_display! {
+    (self, cx):
+
+    &'tcx ty::List<Ty<'tcx>> {
+        p!("{{", comma_sep(self.iter()), "}}")
     }
 
     ty::FnSig<'tcx> {
@@ -3164,39 +3198,6 @@ define_print_and_forward_display! {
         p!(write("{}", self.name))
     }
 
-    ty::SubtypePredicate<'tcx> {
-        p!(print(self.a), " <: ");
-        cx.reset_type_limit();
-        p!(print(self.b))
-    }
-
-    ty::CoercePredicate<'tcx> {
-        p!(print(self.a), " -> ");
-        cx.reset_type_limit();
-        p!(print(self.b))
-    }
-
-    ty::TraitPredicate<'tcx> {
-        p!(print(self.trait_ref.self_ty()), ": ");
-        p!(pretty_print_bound_constness(self.trait_ref));
-        if let ty::PredicatePolarity::Negative = self.polarity {
-            p!("!");
-        }
-        p!(print(self.trait_ref.print_trait_sugared()))
-    }
-
-    ty::ProjectionPredicate<'tcx> {
-        p!(print(self.projection_ty), " == ");
-        cx.reset_type_limit();
-        p!(print(self.term))
-    }
-
-    ty::NormalizesTo<'tcx> {
-        p!(print(self.alias), " normalizes-to ");
-        cx.reset_type_limit();
-        p!(print(self.term))
-    }
-
     ty::Term<'tcx> {
       match self.unpack() {
         ty::TermKind::Ty(ty) => p!(print(ty)),
@@ -3205,20 +3206,29 @@ define_print_and_forward_display! {
     }
 
     ty::AliasTy<'tcx> {
-        if let DefKind::Impl { of_trait: false } = cx.tcx().def_kind(cx.tcx().parent(self.def_id)) {
-            p!(pretty_print_inherent_projection(*self))
-        } else {
-            // If we're printing verbosely, or don't want to invoke queries
-            // (`is_impl_trait_in_trait`), then fall back to printing the def path.
-            // This is likely what you want if you're debugging the compiler anyways.
-            if !(cx.should_print_verbose() || with_reduced_queries())
-                && cx.tcx().is_impl_trait_in_trait(self.def_id)
-            {
-                return cx.pretty_print_opaque_impl_type(self.def_id, self.args);
-            } else {
-                p!(print_def_path(self.def_id, self.args));
+        let alias_term: ty::AliasTerm<'tcx> = (*self).into();
+        p!(print(alias_term))
+    }
+
+    ty::AliasTerm<'tcx> {
+        match self.kind(cx.tcx()) {
+            ty::AliasTermKind::InherentTy => p!(pretty_print_inherent_projection(*self)),
+            ty::AliasTermKind::ProjectionTy
+            | ty::AliasTermKind::WeakTy
+            | ty::AliasTermKind::OpaqueTy
+            | ty::AliasTermKind::UnevaluatedConst
+            | ty::AliasTermKind::ProjectionConst => {
+                // If we're printing verbosely, or don't want to invoke queries
+                // (`is_impl_trait_in_trait`), then fall back to printing the def path.
+                // This is likely what you want if you're debugging the compiler anyways.
+                if !(cx.should_print_verbose() || with_reduced_queries())
+                    && cx.tcx().is_impl_trait_in_trait(self.def_id)
+                {
+                    return cx.pretty_print_opaque_impl_type(self.def_id, self.args);
+                } else {
+                    p!(print_def_path(self.def_id, self.args));
+                }
             }
-
         }
     }
 
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index 7063ef07201..eaf5fdf5710 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -5,10 +5,11 @@
 //! subtyping, type equality, etc.
 
 use crate::ty::error::{ExpectedFound, TypeError};
-use crate::ty::{self, Expr, ImplSubject, Term, TermKind, Ty, TyCtxt, TypeFoldable};
-use crate::ty::{GenericArg, GenericArgKind, GenericArgsRef};
+use crate::ty::{
+    self, ExistentialPredicate, ExistentialPredicateStableCmpExt as _, Expr, GenericArg,
+    GenericArgKind, GenericArgsRef, ImplSubject, Term, TermKind, Ty, TyCtxt, TypeFoldable,
+};
 use rustc_hir as hir;
-use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_macros::TypeVisitable;
 use rustc_target::spec::abi;
@@ -225,8 +226,8 @@ impl<'tcx> Relate<'tcx> for ty::AliasTy<'tcx> {
         if a.def_id != b.def_id {
             Err(TypeError::ProjectionMismatched(expected_found(a.def_id, b.def_id)))
         } else {
-            let args = match relation.tcx().def_kind(a.def_id) {
-                DefKind::OpaqueTy => relate_args_with_variances(
+            let args = match a.kind(relation.tcx()) {
+                ty::Opaque => relate_args_with_variances(
                     relation,
                     a.def_id,
                     relation.tcx().variances_of(a.def_id),
@@ -234,16 +235,46 @@ impl<'tcx> Relate<'tcx> for ty::AliasTy<'tcx> {
                     b.args,
                     false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
                 )?,
-                DefKind::AssocTy | DefKind::AssocConst | DefKind::TyAlias => {
+                ty::Projection | ty::Weak | ty::Inherent => {
                     relate_args_invariantly(relation, a.args, b.args)?
                 }
-                def => bug!("unknown alias DefKind: {def:?}"),
             };
             Ok(ty::AliasTy::new(relation.tcx(), a.def_id, args))
         }
     }
 }
 
+impl<'tcx> Relate<'tcx> for ty::AliasTerm<'tcx> {
+    fn relate<R: TypeRelation<'tcx>>(
+        relation: &mut R,
+        a: ty::AliasTerm<'tcx>,
+        b: ty::AliasTerm<'tcx>,
+    ) -> RelateResult<'tcx, ty::AliasTerm<'tcx>> {
+        if a.def_id != b.def_id {
+            Err(TypeError::ProjectionMismatched(expected_found(a.def_id, b.def_id)))
+        } else {
+            let args = match a.kind(relation.tcx()) {
+                ty::AliasTermKind::OpaqueTy => relate_args_with_variances(
+                    relation,
+                    a.def_id,
+                    relation.tcx().variances_of(a.def_id),
+                    a.args,
+                    b.args,
+                    false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
+                )?,
+                ty::AliasTermKind::ProjectionTy
+                | ty::AliasTermKind::WeakTy
+                | ty::AliasTermKind::InherentTy
+                | ty::AliasTermKind::UnevaluatedConst
+                | ty::AliasTermKind::ProjectionConst => {
+                    relate_args_invariantly(relation, a.args, b.args)?
+                }
+            };
+            Ok(ty::AliasTerm::new(relation.tcx(), a.def_id, args))
+        }
+    }
+}
+
 impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
@@ -702,14 +733,21 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> {
         }
 
         let v = iter::zip(a_v, b_v).map(|(ep_a, ep_b)| {
-            use crate::ty::ExistentialPredicate::*;
             match (ep_a.skip_binder(), ep_b.skip_binder()) {
-                (Trait(a), Trait(b)) => Ok(ep_a
-                    .rebind(Trait(relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder()))),
-                (Projection(a), Projection(b)) => Ok(ep_a.rebind(Projection(
-                    relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(),
-                ))),
-                (AutoTrait(a), AutoTrait(b)) if a == b => Ok(ep_a.rebind(AutoTrait(a))),
+                (ExistentialPredicate::Trait(a), ExistentialPredicate::Trait(b)) => Ok(ep_a
+                    .rebind(ExistentialPredicate::Trait(
+                        relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(),
+                    ))),
+                (ExistentialPredicate::Projection(a), ExistentialPredicate::Projection(b)) => {
+                    Ok(ep_a.rebind(ExistentialPredicate::Projection(
+                        relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(),
+                    )))
+                }
+                (ExistentialPredicate::AutoTrait(a), ExistentialPredicate::AutoTrait(b))
+                    if a == b =>
+                {
+                    Ok(ep_a.rebind(ExistentialPredicate::AutoTrait(a)))
+                }
                 _ => Err(TypeError::ExistentialMismatch(expected_found(a, b))),
             }
         });
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index a7770f71926..6abd685343b 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -55,12 +55,6 @@ impl fmt::Debug for ty::UpvarId {
     }
 }
 
-impl<'tcx> fmt::Debug for ty::ExistentialTraitRef<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        with_no_trimmed_paths!(fmt::Display::fmt(self, f))
-    }
-}
-
 impl<'tcx> fmt::Debug for ty::adjustment::Adjustment<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "{:?} -> {}", self.kind, self.target)
@@ -158,25 +152,6 @@ impl fmt::Debug for ty::ParamConst {
     }
 }
 
-impl<'tcx> fmt::Debug for ty::TraitPredicate<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        // FIXME(effects) printing?
-        write!(f, "TraitPredicate({:?}, polarity:{:?})", self.trait_ref, self.polarity)
-    }
-}
-
-impl<'tcx> fmt::Debug for ty::ProjectionPredicate<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "ProjectionPredicate({:?}, {:?})", self.projection_ty, self.term)
-    }
-}
-
-impl<'tcx> fmt::Debug for ty::NormalizesTo<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "NormalizesTo({:?}, {:?})", self.alias, self.term)
-    }
-}
-
 impl<'tcx> fmt::Debug for ty::Predicate<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "{:?}", self.kind())
@@ -435,7 +410,7 @@ TrivialTypeTraversalImpls! {
     crate::ty::BoundRegionKind,
     crate::ty::AssocItem,
     crate::ty::AssocKind,
-    crate::ty::AliasKind,
+    crate::ty::AliasTyKind,
     crate::ty::Placeholder<crate::ty::BoundRegion>,
     crate::ty::Placeholder<crate::ty::BoundTy>,
     crate::ty::Placeholder<ty::BoundVar>,
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index a97244dda9a..16301633247 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1105,14 +1105,14 @@ where
     }
 }
 
-/// Represents the projection of an associated type.
+/// Represents the unprojected term of a projection goal.
 ///
 /// * For a projection, this would be `<Ty as Trait<...>>::N<...>`.
 /// * For an inherent projection, this would be `Ty::N<...>`.
 /// * For an opaque type, there is no explicit syntax.
 #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct AliasTy<'tcx> {
+pub struct AliasTerm<'tcx> {
     /// The parameters of the associated or opaque item.
     ///
     /// For a projection, these are the generic parameters for the trait and the
@@ -1137,7 +1137,232 @@ pub struct AliasTy<'tcx> {
     /// aka. `tcx.parent(def_id)`.
     pub def_id: DefId,
 
-    /// This field exists to prevent the creation of `AliasTy` without using
+    /// This field exists to prevent the creation of `AliasTerm` without using
+    /// [AliasTerm::new].
+    _use_alias_term_new_instead: (),
+}
+
+// FIXME: Remove these when we uplift `AliasTerm`
+use crate::ty::{DebugWithInfcx, InferCtxtLike, WithInfcx};
+impl<'tcx> std::fmt::Debug for AliasTerm<'tcx> {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        WithInfcx::with_no_infcx(self).fmt(f)
+    }
+}
+impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for AliasTerm<'tcx> {
+    fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>(
+        this: WithInfcx<'_, Infcx, &Self>,
+        f: &mut std::fmt::Formatter<'_>,
+    ) -> std::fmt::Result {
+        f.debug_struct("AliasTerm")
+            .field("args", &this.map(|data| data.args))
+            .field("def_id", &this.data.def_id)
+            .finish()
+    }
+}
+
+impl<'tcx> rustc_type_ir::inherent::AliasTerm<TyCtxt<'tcx>> for AliasTerm<'tcx> {
+    fn new(
+        interner: TyCtxt<'tcx>,
+        trait_def_id: DefId,
+        args: impl IntoIterator<Item: Into<ty::GenericArg<'tcx>>>,
+    ) -> Self {
+        AliasTerm::new(interner, trait_def_id, args)
+    }
+
+    fn def_id(self) -> DefId {
+        self.def_id
+    }
+
+    fn args(self) -> ty::GenericArgsRef<'tcx> {
+        self.args
+    }
+
+    fn trait_def_id(self, interner: TyCtxt<'tcx>) -> DefId {
+        self.trait_def_id(interner)
+    }
+
+    fn self_ty(self) -> Ty<'tcx> {
+        self.self_ty()
+    }
+
+    fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
+        self.with_self_ty(tcx, self_ty)
+    }
+}
+
+impl<'tcx> AliasTerm<'tcx> {
+    pub fn new(
+        tcx: TyCtxt<'tcx>,
+        def_id: DefId,
+        args: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
+    ) -> AliasTerm<'tcx> {
+        let args = tcx.check_and_mk_args(def_id, args);
+        AliasTerm { def_id, args, _use_alias_term_new_instead: () }
+    }
+
+    pub fn expect_ty(self, tcx: TyCtxt<'tcx>) -> AliasTy<'tcx> {
+        match self.kind(tcx) {
+            ty::AliasTermKind::ProjectionTy
+            | ty::AliasTermKind::InherentTy
+            | ty::AliasTermKind::OpaqueTy
+            | ty::AliasTermKind::WeakTy => {}
+            ty::AliasTermKind::UnevaluatedConst | ty::AliasTermKind::ProjectionConst => {
+                bug!("Cannot turn `UnevaluatedConst` into `AliasTy`")
+            }
+        }
+        ty::AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () }
+    }
+
+    pub fn kind(self, tcx: TyCtxt<'tcx>) -> ty::AliasTermKind {
+        match tcx.def_kind(self.def_id) {
+            DefKind::AssocTy => {
+                if let DefKind::Impl { of_trait: false } = tcx.def_kind(tcx.parent(self.def_id)) {
+                    ty::AliasTermKind::InherentTy
+                } else {
+                    ty::AliasTermKind::ProjectionTy
+                }
+            }
+            DefKind::OpaqueTy => ty::AliasTermKind::OpaqueTy,
+            DefKind::TyAlias => ty::AliasTermKind::WeakTy,
+            DefKind::AnonConst => ty::AliasTermKind::UnevaluatedConst,
+            DefKind::AssocConst => ty::AliasTermKind::ProjectionConst,
+            kind => bug!("unexpected DefKind in AliasTy: {kind:?}"),
+        }
+    }
+}
+
+/// The following methods work only with (trait) associated item projections.
+impl<'tcx> AliasTerm<'tcx> {
+    pub fn self_ty(self) -> Ty<'tcx> {
+        self.args.type_at(0)
+    }
+
+    pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
+        AliasTerm::new(
+            tcx,
+            self.def_id,
+            [self_ty.into()].into_iter().chain(self.args.iter().skip(1)),
+        )
+    }
+
+    pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId {
+        match tcx.def_kind(self.def_id) {
+            DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.def_id),
+            kind => bug!("expected a projection AliasTy; found {kind:?}"),
+        }
+    }
+
+    /// Extracts the underlying trait reference from this projection.
+    /// For example, if this is a projection of `<T as Iterator>::Item`,
+    /// then this function would return a `T: Iterator` trait reference.
+    ///
+    /// NOTE: This will drop the args for generic associated types
+    /// consider calling [Self::trait_ref_and_own_args] to get those
+    /// as well.
+    pub fn trait_ref(self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> {
+        let def_id = self.trait_def_id(tcx);
+        ty::TraitRef::new(tcx, def_id, self.args.truncate_to(tcx, tcx.generics_of(def_id)))
+    }
+
+    /// Extracts the underlying trait reference and own args from this projection.
+    /// For example, if this is a projection of `<T as StreamingIterator>::Item<'a>`,
+    /// then this function would return a `T: StreamingIterator` trait reference and `['a]` as the own args
+    pub fn trait_ref_and_own_args(
+        self,
+        tcx: TyCtxt<'tcx>,
+    ) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) {
+        let trait_def_id = self.trait_def_id(tcx);
+        let trait_generics = tcx.generics_of(trait_def_id);
+        (
+            ty::TraitRef::new(tcx, trait_def_id, self.args.truncate_to(tcx, trait_generics)),
+            &self.args[trait_generics.count()..],
+        )
+    }
+
+    pub fn to_term(self, tcx: TyCtxt<'tcx>) -> ty::Term<'tcx> {
+        match self.kind(tcx) {
+            ty::AliasTermKind::ProjectionTy => Ty::new_alias(
+                tcx,
+                ty::Projection,
+                AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
+            )
+            .into(),
+            ty::AliasTermKind::InherentTy => Ty::new_alias(
+                tcx,
+                ty::Inherent,
+                AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
+            )
+            .into(),
+            ty::AliasTermKind::OpaqueTy => Ty::new_alias(
+                tcx,
+                ty::Opaque,
+                AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
+            )
+            .into(),
+            ty::AliasTermKind::WeakTy => Ty::new_alias(
+                tcx,
+                ty::Weak,
+                AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
+            )
+            .into(),
+            ty::AliasTermKind::UnevaluatedConst | ty::AliasTermKind::ProjectionConst => {
+                ty::Const::new_unevaluated(
+                    tcx,
+                    ty::UnevaluatedConst::new(self.def_id, self.args),
+                    tcx.type_of(self.def_id).instantiate(tcx, self.args),
+                )
+                .into()
+            }
+        }
+    }
+}
+
+impl<'tcx> From<AliasTy<'tcx>> for AliasTerm<'tcx> {
+    fn from(ty: AliasTy<'tcx>) -> Self {
+        AliasTerm { args: ty.args, def_id: ty.def_id, _use_alias_term_new_instead: () }
+    }
+}
+
+impl<'tcx> From<ty::UnevaluatedConst<'tcx>> for AliasTerm<'tcx> {
+    fn from(ct: ty::UnevaluatedConst<'tcx>) -> Self {
+        AliasTerm { args: ct.args, def_id: ct.def, _use_alias_term_new_instead: () }
+    }
+}
+
+/// Represents the projection of an associated, opaque, or lazy-type-alias type.
+///
+/// * For a projection, this would be `<Ty as Trait<...>>::N<...>`.
+/// * For an inherent projection, this would be `Ty::N<...>`.
+/// * For an opaque type, there is no explicit syntax.
+#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
+#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
+pub struct AliasTy<'tcx> {
+    /// The parameters of the associated or opaque type.
+    ///
+    /// For a projection, these are the generic parameters for the trait and the
+    /// GAT parameters, if there are any.
+    ///
+    /// For an inherent projection, they consist of the self type and the GAT parameters,
+    /// if there are any.
+    ///
+    /// For RPIT the generic parameters are for the generics of the function,
+    /// while for TAIT it is used for the generic parameters of the alias.
+    pub args: GenericArgsRef<'tcx>,
+
+    /// The `DefId` of the `TraitItem` or `ImplItem` for the associated type `N` depending on whether
+    /// this is a projection or an inherent projection or the `DefId` of the `OpaqueType` item if
+    /// this is an opaque.
+    ///
+    /// During codegen, `tcx.type_of(def_id)` can be used to get the type of the
+    /// underlying type if the type is an opaque.
+    ///
+    /// Note that if this is an associated type, this is not the `DefId` of the
+    /// `TraitRef` containing this associated type, which is in `tcx.associated_item(def_id).container`,
+    /// aka. `tcx.parent(def_id)`.
+    pub def_id: DefId,
+
+    /// This field exists to prevent the creation of `AliasT` without using
     /// [AliasTy::new].
     _use_alias_ty_new_instead: (),
 }
@@ -1152,7 +1377,7 @@ impl<'tcx> AliasTy<'tcx> {
         ty::AliasTy { def_id, args, _use_alias_ty_new_instead: () }
     }
 
-    pub fn kind(self, tcx: TyCtxt<'tcx>) -> ty::AliasKind {
+    pub fn kind(self, tcx: TyCtxt<'tcx>) -> ty::AliasTyKind {
         match tcx.def_kind(self.def_id) {
             DefKind::AssocTy
                 if let DefKind::Impl { of_trait: false } =
@@ -1169,24 +1394,7 @@ impl<'tcx> AliasTy<'tcx> {
 
     /// Whether this alias type is an opaque.
     pub fn is_opaque(self, tcx: TyCtxt<'tcx>) -> bool {
-        matches!(self.opt_kind(tcx), Some(ty::Opaque))
-    }
-
-    /// FIXME: rename `AliasTy` to `AliasTerm` and always handle
-    /// constants. This function can then be removed.
-    pub fn opt_kind(self, tcx: TyCtxt<'tcx>) -> Option<ty::AliasKind> {
-        match tcx.def_kind(self.def_id) {
-            DefKind::AssocTy
-                if let DefKind::Impl { of_trait: false } =
-                    tcx.def_kind(tcx.parent(self.def_id)) =>
-            {
-                Some(ty::Inherent)
-            }
-            DefKind::AssocTy => Some(ty::Projection),
-            DefKind::OpaqueTy => Some(ty::Opaque),
-            DefKind::TyAlias => Some(ty::Weak),
-            _ => None,
-        }
+        matches!(self.kind(tcx), ty::Opaque)
     }
 
     pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
@@ -1194,7 +1402,7 @@ impl<'tcx> AliasTy<'tcx> {
     }
 }
 
-/// The following methods work only with associated type projections.
+/// The following methods work only with (trait) associated type projections.
 impl<'tcx> AliasTy<'tcx> {
     pub fn self_ty(self) -> Ty<'tcx> {
         self.args.type_at(0)
@@ -1203,10 +1411,7 @@ impl<'tcx> AliasTy<'tcx> {
     pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
         AliasTy::new(tcx, self.def_id, [self_ty.into()].into_iter().chain(self.args.iter().skip(1)))
     }
-}
 
-/// The following methods work only with trait associated type projections.
-impl<'tcx> AliasTy<'tcx> {
     pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId {
         match tcx.def_kind(self.def_id) {
             DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.def_id),
@@ -1221,7 +1426,6 @@ impl<'tcx> AliasTy<'tcx> {
         self,
         tcx: TyCtxt<'tcx>,
     ) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) {
-        debug_assert!(matches!(tcx.def_kind(self.def_id), DefKind::AssocTy | DefKind::AssocConst));
         let trait_def_id = self.trait_def_id(tcx);
         let trait_generics = tcx.generics_of(trait_def_id);
         (
@@ -1511,7 +1715,7 @@ impl<'tcx> Ty<'tcx> {
     #[inline]
     pub fn new_alias(
         tcx: TyCtxt<'tcx>,
-        kind: ty::AliasKind,
+        kind: ty::AliasTyKind,
         alias_ty: ty::AliasTy<'tcx>,
     ) -> Ty<'tcx> {
         debug_assert_matches!(
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index 41f417dfd4b..24e3e623ff2 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -79,6 +79,10 @@ pub struct TypeckResults<'tcx> {
     /// Stores the actual binding mode for all instances of [`BindingMode`].
     pat_binding_modes: ItemLocalMap<BindingMode>,
 
+    /// Top-level patterns whose match ergonomics need to be desugared
+    /// by the Rust 2021 -> 2024 migration lint.
+    rust_2024_migration_desugared_pats: ItemLocalSet,
+
     /// Stores the types which were implicitly dereferenced in pattern binding modes
     /// for later usage in THIR lowering. For example,
     ///
@@ -229,6 +233,7 @@ impl<'tcx> TypeckResults<'tcx> {
             adjustments: Default::default(),
             pat_binding_modes: Default::default(),
             pat_adjustments: Default::default(),
+            rust_2024_migration_desugared_pats: Default::default(),
             skipped_ref_pats: Default::default(),
             closure_kind_origins: Default::default(),
             liberated_fn_sigs: Default::default(),
@@ -432,6 +437,20 @@ impl<'tcx> TypeckResults<'tcx> {
         LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments }
     }
 
+    pub fn rust_2024_migration_desugared_pats(&self) -> LocalSetInContext<'_> {
+        LocalSetInContext {
+            hir_owner: self.hir_owner,
+            data: &self.rust_2024_migration_desugared_pats,
+        }
+    }
+
+    pub fn rust_2024_migration_desugared_pats_mut(&mut self) -> LocalSetInContextMut<'_> {
+        LocalSetInContextMut {
+            hir_owner: self.hir_owner,
+            data: &mut self.rust_2024_migration_desugared_pats,
+        }
+    }
+
     pub fn skipped_ref_pats(&self) -> LocalSetInContext<'_> {
         LocalSetInContext { hir_owner: self.hir_owner, data: &self.skipped_ref_pats }
     }
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 6ad4f492f74..04ce3de8874 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -1086,7 +1086,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for OpaqueTypeExpander<'tcx> {
         {
             p.kind()
                 .rebind(ty::ProjectionPredicate {
-                    projection_ty: projection_pred.projection_ty.fold_with(self),
+                    projection_term: projection_pred.projection_term.fold_with(self),
                     // Don't fold the term on the RHS of the projection predicate.
                     // This is because for default trait methods with RPITITs, we
                     // install a `NormalizesTo(Projection(RPITIT) -> Opaque(RPITIT))`
diff --git a/compiler/rustc_mir_build/Cargo.toml b/compiler/rustc_mir_build/Cargo.toml
index 6618e4f5a00..77f27236437 100644
--- a/compiler/rustc_mir_build/Cargo.toml
+++ b/compiler/rustc_mir_build/Cargo.toml
@@ -16,6 +16,7 @@ rustc_fluent_macro = { path = "../rustc_fluent_macro" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
 rustc_infer = { path = "../rustc_infer" }
+rustc_lint = { path = "../rustc_lint" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_middle = { path = "../rustc_middle" }
 rustc_pattern_analysis = { path = "../rustc_pattern_analysis" }
diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl
index 34440c60cf3..0bb44dbb870 100644
--- a/compiler/rustc_mir_build/messages.ftl
+++ b/compiler/rustc_mir_build/messages.ftl
@@ -267,6 +267,8 @@ mir_build_pointer_pattern = function pointers and raw pointers not derived from
 
 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_rust_2024_incompatible_pat = the semantics of this pattern will change in edition 2024
+
 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
diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs
index 00e99f330f7..6ae98e15946 100644
--- a/compiler/rustc_mir_build/src/build/block.rs
+++ b/compiler/rustc_mir_build/src/build/block.rs
@@ -1,6 +1,7 @@
 use crate::build::ForGuard::OutsideGuard;
 use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
 use rustc_middle::middle::region::Scope;
+use rustc_middle::span_bug;
 use rustc_middle::thir::*;
 use rustc_middle::{mir::*, ty};
 use rustc_span::Span;
diff --git a/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs b/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs
index 566dba460d4..9cfb25e663d 100644
--- a/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs
+++ b/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs
@@ -1,5 +1,6 @@
 use std::collections::VecDeque;
 
+use rustc_middle::bug;
 use rustc_middle::mir::coverage::{
     BlockMarkerId, ConditionId, ConditionInfo, MCDCBranchSpan, MCDCDecisionSpan,
 };
diff --git a/compiler/rustc_mir_build/src/build/custom/mod.rs b/compiler/rustc_mir_build/src/build/custom/mod.rs
index 30877e38318..a0a512a2eff 100644
--- a/compiler/rustc_mir_build/src/build/custom/mod.rs
+++ b/compiler/rustc_mir_build/src/build/custom/mod.rs
@@ -24,6 +24,7 @@ use rustc_hir::HirId;
 use rustc_index::{IndexSlice, IndexVec};
 use rustc_middle::{
     mir::*,
+    span_bug,
     thir::*,
     ty::{ParamEnv, Ty, TyCtxt},
 };
diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
index a557f61b016..817f5f787b1 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
@@ -9,6 +9,7 @@ use rustc_middle::thir::*;
 use rustc_middle::ty::{
     self, CanonicalUserType, CanonicalUserTypeAnnotation, TyCtxt, UserTypeAnnotationIndex,
 };
+use rustc_middle::{bug, span_bug};
 use rustc_target::abi::Size;
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs
index 060b328ef48..9963629fc52 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_place.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs
@@ -4,6 +4,7 @@ use crate::build::expr::category::Category;
 use crate::build::ForGuard::{OutsideGuard, RefWithinGuard};
 use crate::build::{BlockAnd, BlockAndExtension, Builder, Capture, CaptureMap};
 use rustc_hir::def_id::LocalDefId;
+use rustc_middle::bug;
 use rustc_middle::hir::place::Projection as HirProjection;
 use rustc_middle::hir::place::ProjectionKind as HirProjectionKind;
 use rustc_middle::middle::region;
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 260ab058e60..0b2248d049a 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -9,6 +9,7 @@ use crate::build::expr::as_place::PlaceBase;
 use crate::build::expr::category::{Category, RvalueFunc};
 use crate::build::{BlockAnd, BlockAndExtension, Builder, NeedsTemporary};
 use rustc_hir::lang_items::LangItem;
+use rustc_middle::bug;
 use rustc_middle::middle::region;
 use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::mir::*;
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index c8360b6a5fd..f8c91073045 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -7,6 +7,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir as hir;
 use rustc_middle::mir::*;
+use rustc_middle::span_bug;
 use rustc_middle::thir::*;
 use rustc_middle::ty::CanonicalUserTypeAnnotation;
 use rustc_span::source_map::Spanned;
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index 7cf4fac731b..3fc719394bf 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -12,6 +12,7 @@ use crate::build::{BlockAnd, BlockAndExtension, Builder};
 use crate::build::{GuardFrame, GuardFrameLocal, LocalsForNode};
 use rustc_data_structures::{fx::FxIndexMap, stack::ensure_sufficient_stack};
 use rustc_hir::{BindingMode, ByRef};
+use rustc_middle::bug;
 use rustc_middle::middle::region;
 use rustc_middle::mir::{self, *};
 use rustc_middle::thir::{self, *};
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index 7f65697fa4b..f3faeb4158e 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -13,6 +13,7 @@ use rustc_middle::mir::*;
 use rustc_middle::ty::util::IntTypeExt;
 use rustc_middle::ty::GenericArg;
 use rustc_middle::ty::{self, adjustment::PointerCoercion, Ty, TyCtxt};
+use rustc_middle::{bug, span_bug};
 use rustc_span::def_id::DefId;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{sym, Symbol};
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index 794e7ebb7b4..92cd7f75d62 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -20,6 +20,7 @@ use rustc_middle::mir::*;
 use rustc_middle::query::TyCtxtAt;
 use rustc_middle::thir::{self, ExprId, LintLevel, LocalVarId, Param, ParamId, PatKind, Thir};
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::{bug, span_bug};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 use rustc_span::Symbol;
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index 2d31e84aba7..be32363fec5 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -90,6 +90,7 @@ use rustc_index::{IndexSlice, IndexVec};
 use rustc_middle::middle::region;
 use rustc_middle::mir::*;
 use rustc_middle::thir::{ExprId, LintLevel};
+use rustc_middle::{bug, span_bug};
 use rustc_session::lint::Level;
 use rustc_span::source_map::Spanned;
 use rustc_span::{Span, DUMMY_SP};
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index 227d19c3e43..b9990d65ec7 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -4,6 +4,7 @@ use crate::errors::*;
 use rustc_errors::DiagArgValue;
 use rustc_hir::{self as hir, BindingMode, ByRef, HirId, Mutability};
 use rustc_middle::mir::BorrowKind;
+use rustc_middle::span_bug;
 use rustc_middle::thir::visit::Visitor;
 use rustc_middle::thir::*;
 use rustc_middle::ty::print::with_no_trimmed_paths;
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index f67113afd6d..e2a28467b84 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -950,3 +950,30 @@ pub enum RustcBoxAttrReason {
     #[note(mir_build_missing_box)]
     MissingBox,
 }
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_rust_2024_incompatible_pat)]
+pub struct Rust2024IncompatiblePat {
+    #[subdiagnostic]
+    pub sugg: Rust2024IncompatiblePatSugg,
+}
+
+pub struct Rust2024IncompatiblePatSugg {
+    pub suggestion: Vec<(Span, String)>,
+}
+
+impl Subdiagnostic for Rust2024IncompatiblePatSugg {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+        self,
+        diag: &mut Diag<'_, G>,
+        _f: &F,
+    ) {
+        let applicability =
+            if self.suggestion.iter().all(|(span, _)| span.can_be_used_for_suggestions()) {
+                Applicability::MachineApplicable
+            } else {
+                Applicability::MaybeIncorrect
+            };
+        diag.multipart_suggestion("desugar the match ergonomics", self.suggestion, applicability);
+    }
+}
diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs
index e79e3b887fb..2e1cb0e1b5e 100644
--- a/compiler/rustc_mir_build/src/lib.rs
+++ b/compiler/rustc_mir_build/src/lib.rs
@@ -12,8 +12,6 @@
 
 #[macro_use]
 extern crate tracing;
-#[macro_use]
-extern crate rustc_middle;
 
 mod build;
 mod check_unsafety;
diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs
index 65cc13286af..03c7c1fd6ec 100644
--- a/compiler/rustc_mir_build/src/thir/constant.rs
+++ b/compiler/rustc_mir_build/src/thir/constant.rs
@@ -1,4 +1,5 @@
 use rustc_ast as ast;
+use rustc_middle::bug;
 use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
 use rustc_middle::ty::{self, ParamEnv, ScalarInt, TyCtxt};
 
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index c697e16217b..b7766666960 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -21,6 +21,7 @@ use rustc_middle::ty::GenericArgs;
 use rustc_middle::ty::{
     self, AdtKind, InlineConstArgs, InlineConstArgsParts, ScalarInt, Ty, UpvarArgs, UserType,
 };
+use rustc_middle::{bug, span_bug};
 use rustc_span::source_map::Spanned;
 use rustc_span::{sym, Span, DUMMY_SP};
 use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index 79738b54035..d1d21f88aef 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -13,6 +13,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::HirId;
 use rustc_hir::Node;
+use rustc_middle::bug;
 use rustc_middle::middle::region;
 use rustc_middle::thir::*;
 use rustc_middle::ty::{self, RvalueScopes, TyCtxt};
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 25ab9046706..592f0dcf4ef 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -1,9 +1,3 @@
-use rustc_pattern_analysis::errors::Uncovered;
-use rustc_pattern_analysis::rustc::{
-    Constructor, DeconstructedPat, MatchArm, RustcPatCtxt as PatCtxt, Usefulness, UsefulnessReport,
-    WitnessPat,
-};
-
 use crate::errors::*;
 
 use rustc_arena::{DroplessArena, TypedArena};
@@ -14,11 +8,17 @@ use rustc_errors::{codes::*, struct_span_code_err, Applicability, ErrorGuarantee
 use rustc_hir::def::*;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::{self as hir, BindingMode, ByRef, HirId};
+use rustc_middle::bug;
 use rustc_middle::middle::limits::get_limit_size;
 use rustc_middle::thir::visit::Visitor;
 use rustc_middle::thir::*;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
+use rustc_pattern_analysis::errors::Uncovered;
+use rustc_pattern_analysis::rustc::{
+    Constructor, DeconstructedPat, MatchArm, RustcPatCtxt as PatCtxt, Usefulness, UsefulnessReport,
+    WitnessPat,
+};
 use rustc_session::lint::builtin::{
     BINDINGS_WITH_VARIANT_NAME, IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS,
 };
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index 65c53be8ddd..c6f81c3cb99 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -4,6 +4,7 @@ use rustc_index::Idx;
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_infer::traits::Obligation;
 use rustc_middle::mir;
+use rustc_middle::span_bug;
 use rustc_middle::thir::{FieldPat, Pat, PatKind};
 use rustc_middle::ty::{self, Ty, TyCtxt, ValTree};
 use rustc_session::lint;
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 5c016682d8d..dc845b3d4ac 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -11,8 +11,9 @@ use crate::thir::util::UserAnnotatedTyHelpers;
 use rustc_errors::codes::*;
 use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::pat_util::EnumerateAndAdjustIterator;
-use rustc_hir::{self as hir, RangeEnd};
+use rustc_hir::{self as hir, ByRef, Mutability, RangeEnd};
 use rustc_index::Idx;
+use rustc_lint as lint;
 use rustc_middle::mir::interpret::{ErrorHandled, GlobalId, LitToConstError, LitToConstInput};
 use rustc_middle::mir::{self, Const};
 use rustc_middle::thir::{
@@ -20,6 +21,7 @@ use rustc_middle::thir::{
 };
 use rustc_middle::ty::layout::IntegerExt;
 use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::{bug, span_bug};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::{ErrorGuaranteed, Span};
 use rustc_target::abi::{FieldIdx, Integer};
@@ -30,6 +32,9 @@ struct PatCtxt<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     typeck_results: &'a ty::TypeckResults<'tcx>,
+
+    /// Used by the Rust 2024 migration lint.
+    rust_2024_migration_suggestion: Option<Rust2024IncompatiblePatSugg>,
 }
 
 pub(super) fn pat_from_hir<'a, 'tcx>(
@@ -38,9 +43,25 @@ pub(super) fn pat_from_hir<'a, 'tcx>(
     typeck_results: &'a ty::TypeckResults<'tcx>,
     pat: &'tcx hir::Pat<'tcx>,
 ) -> Box<Pat<'tcx>> {
-    let mut pcx = PatCtxt { tcx, param_env, typeck_results };
+    let mut pcx = PatCtxt {
+        tcx,
+        param_env,
+        typeck_results,
+        rust_2024_migration_suggestion: typeck_results
+            .rust_2024_migration_desugared_pats()
+            .contains(pat.hir_id)
+            .then_some(Rust2024IncompatiblePatSugg { suggestion: Vec::new() }),
+    };
     let result = pcx.lower_pattern(pat);
     debug!("pat_from_hir({:?}) = {:?}", pat, result);
+    if let Some(sugg) = pcx.rust_2024_migration_suggestion {
+        tcx.emit_node_span_lint(
+            lint::builtin::RUST_2024_INCOMPATIBLE_PAT,
+            pat.hir_id,
+            pat.span,
+            Rust2024IncompatiblePat { sugg },
+        );
+    }
     result
 }
 
@@ -73,17 +94,38 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
             }
             _ => self.lower_pattern_unadjusted(pat),
         };
-        self.typeck_results.pat_adjustments().get(pat.hir_id).unwrap_or(&vec![]).iter().rev().fold(
-            unadjusted_pat,
-            |pat: Box<_>, ref_ty| {
-                debug!("{:?}: wrapping pattern with type {:?}", pat, ref_ty);
-                Box::new(Pat {
-                    span: pat.span,
-                    ty: *ref_ty,
-                    kind: PatKind::Deref { subpattern: pat },
+
+        let adjustments: &[Ty<'tcx>] =
+            self.typeck_results.pat_adjustments().get(pat.hir_id).map_or(&[], |v| &**v);
+        let adjusted_pat = adjustments.iter().rev().fold(unadjusted_pat, |thir_pat, ref_ty| {
+            debug!("{:?}: wrapping pattern with type {:?}", thir_pat, ref_ty);
+            Box::new(Pat {
+                span: thir_pat.span,
+                ty: *ref_ty,
+                kind: PatKind::Deref { subpattern: thir_pat },
+            })
+        });
+
+        if let Some(s) = &mut self.rust_2024_migration_suggestion
+            && !adjustments.is_empty()
+        {
+            let suggestion_str: String = adjustments
+                .iter()
+                .map(|ref_ty| {
+                    let &ty::Ref(_, _, mutbl) = ref_ty.kind() else {
+                        span_bug!(pat.span, "pattern implicitly dereferences a non-ref type");
+                    };
+
+                    match mutbl {
+                        ty::Mutability::Not => "&",
+                        ty::Mutability::Mut => "&mut ",
+                    }
                 })
-            },
-        )
+                .collect();
+            s.suggestion.push((pat.span.shrink_to_lo(), suggestion_str));
+        };
+
+        adjusted_pat
     }
 
     fn lower_pattern_range_endpoint(
@@ -272,7 +314,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
                 PatKind::Deref { subpattern: self.lower_pattern(subpattern) }
             }
 
-            hir::PatKind::Slice(prefix, ref slice, suffix) => {
+            hir::PatKind::Slice(prefix, slice, suffix) => {
                 self.slice_or_array_pattern(pat.span, ty, prefix, slice, suffix)
             }
 
@@ -284,7 +326,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
                 PatKind::Leaf { subpatterns }
             }
 
-            hir::PatKind::Binding(_, id, ident, ref sub) => {
+            hir::PatKind::Binding(explicit_ba, id, ident, sub) => {
                 if let Some(ident_span) = ident.span.find_ancestor_inside(span) {
                     span = span.with_hi(ident_span.hi());
                 }
@@ -295,6 +337,20 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
                     .get(pat.hir_id)
                     .expect("missing binding mode");
 
+                if let Some(s) = &mut self.rust_2024_migration_suggestion
+                    && explicit_ba.0 == ByRef::No
+                    && let ByRef::Yes(mutbl) = mode.0
+                {
+                    let sugg_str = match mutbl {
+                        Mutability::Not => "ref ",
+                        Mutability::Mut => "ref mut ",
+                    };
+                    s.suggestion.push((
+                        pat.span.with_lo(ident.span.lo()).shrink_to_lo(),
+                        sugg_str.to_owned(),
+                    ))
+                }
+
                 // A ref x pattern is the same node used for x, and as such it has
                 // x's type, which is &T, where we want T (the type being matched).
                 let var_ty = ty;
@@ -366,10 +422,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         pats.iter().map(|p| self.lower_pattern(p)).collect()
     }
 
-    fn lower_opt_pattern(
-        &mut self,
-        pat: &'tcx Option<&'tcx hir::Pat<'tcx>>,
-    ) -> Option<Box<Pat<'tcx>>> {
+    fn lower_opt_pattern(&mut self, pat: Option<&'tcx hir::Pat<'tcx>>) -> Option<Box<Pat<'tcx>>> {
         pat.map(|p| self.lower_pattern(p))
     }
 
@@ -378,7 +431,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         span: Span,
         ty: Ty<'tcx>,
         prefix: &'tcx [hir::Pat<'tcx>],
-        slice: &'tcx Option<&'tcx hir::Pat<'tcx>>,
+        slice: Option<&'tcx hir::Pat<'tcx>>,
         suffix: &'tcx [hir::Pat<'tcx>],
     ) -> PatKind<'tcx> {
         let prefix = self.lower_patterns(prefix);
diff --git a/compiler/rustc_mir_build/src/thir/util.rs b/compiler/rustc_mir_build/src/thir/util.rs
index 52c9cf14ac8..340eb3c2eea 100644
--- a/compiler/rustc_mir_build/src/thir/util.rs
+++ b/compiler/rustc_mir_build/src/thir/util.rs
@@ -1,4 +1,5 @@
 use rustc_hir as hir;
+use rustc_middle::bug;
 use rustc_middle::ty::{self, CanonicalUserType, TyCtxt, UserType};
 
 pub(crate) trait UserAnnotatedTyHelpers<'tcx> {
diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
index ba70a4453d6..d43fca3dc7e 100644
--- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
+++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
@@ -1,5 +1,6 @@
 use rustc_ast::InlineAsmOptions;
 use rustc_middle::mir::*;
+use rustc_middle::span_bug;
 use rustc_middle::ty::layout;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_target::spec::abi::Abi;
diff --git a/compiler/rustc_mir_transform/src/check_packed_ref.rs b/compiler/rustc_mir_transform/src/check_packed_ref.rs
index a405ed6088d..5f67bd75c48 100644
--- a/compiler/rustc_mir_transform/src/check_packed_ref.rs
+++ b/compiler/rustc_mir_transform/src/check_packed_ref.rs
@@ -1,5 +1,6 @@
 use rustc_middle::mir::visit::{PlaceContext, Visitor};
 use rustc_middle::mir::*;
+use rustc_middle::span_bug;
 use rustc_middle::ty::{self, TyCtxt};
 
 use crate::MirLint;
diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs
index 3008016863e..a3e6e5a5a91 100644
--- a/compiler/rustc_mir_transform/src/coroutine.rs
+++ b/compiler/rustc_mir_transform/src/coroutine.rs
@@ -70,6 +70,7 @@ use rustc_middle::mir::*;
 use rustc_middle::ty::CoroutineArgs;
 use rustc_middle::ty::InstanceDef;
 use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::{bug, span_bug};
 use rustc_mir_dataflow::impls::{
     MaybeBorrowedLocals, MaybeLiveLocals, MaybeRequiresStorage, MaybeStorageLive,
 };
diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
index 3d6c1a95204..10c0567eb4b 100644
--- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
+++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
@@ -71,6 +71,7 @@
 
 use rustc_data_structures::unord::UnordMap;
 use rustc_hir as hir;
+use rustc_middle::bug;
 use rustc_middle::hir::place::{Projection, ProjectionKind};
 use rustc_middle::mir::visit::MutVisitor;
 use rustc_middle::mir::{self, dump_mir, MirPass};
diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs
index 6e73a476421..b98554ec00f 100644
--- a/compiler/rustc_mir_transform/src/coverage/counters.rs
+++ b/compiler/rustc_mir_transform/src/coverage/counters.rs
@@ -4,6 +4,7 @@ use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::graph::DirectedGraph;
 use rustc_index::IndexVec;
+use rustc_middle::bug;
 use rustc_middle::mir::coverage::{CounterId, CovTerm, Expression, ExpressionId, Op};
 
 use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph, TraverseCoverageGraphWithLoops};
diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs
index 1895735ab35..fd74a2a97e2 100644
--- a/compiler/rustc_mir_transform/src/coverage/graph.rs
+++ b/compiler/rustc_mir_transform/src/coverage/graph.rs
@@ -4,6 +4,7 @@ use rustc_data_structures::graph::dominators::{self, Dominators};
 use rustc_data_structures::graph::{self, DirectedGraph, StartNode};
 use rustc_index::bit_set::BitSet;
 use rustc_index::IndexVec;
+use rustc_middle::bug;
 use rustc_middle::mir::{self, BasicBlock, Terminator, TerminatorKind};
 
 use std::cmp::Ordering;
diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs
index a0570c45f96..f2f76ac70c2 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans.rs
@@ -1,3 +1,4 @@
+use rustc_middle::bug;
 use rustc_middle::mir;
 use rustc_span::{BytePos, Span};
 
diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs
index 4ce37b5defc..d1727a94a35 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs
@@ -1,5 +1,6 @@
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashSet;
+use rustc_middle::bug;
 use rustc_middle::mir::coverage::CoverageKind;
 use rustc_middle::mir::{
     self, AggregateKind, FakeReadCause, Rvalue, Statement, StatementKind, Terminator,
diff --git a/compiler/rustc_mir_transform/src/coverage/tests.rs b/compiler/rustc_mir_transform/src/coverage/tests.rs
index cf1a2b399f9..ca64688e6b8 100644
--- a/compiler/rustc_mir_transform/src/coverage/tests.rs
+++ b/compiler/rustc_mir_transform/src/coverage/tests.rs
@@ -30,6 +30,7 @@ use super::graph::{self, BasicCoverageBlock};
 use itertools::Itertools;
 use rustc_data_structures::graph::{DirectedGraph, Successors};
 use rustc_index::{Idx, IndexVec};
+use rustc_middle::bug;
 use rustc_middle::mir::*;
 use rustc_middle::ty;
 use rustc_span::{BytePos, Pos, Span, DUMMY_SP};
diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
index 3019b275fb2..a42d64f86be 100644
--- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
+++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
@@ -6,6 +6,7 @@ use rustc_const_eval::const_eval::{throw_machine_stop_str, DummyMachine};
 use rustc_const_eval::interpret::{ImmTy, Immediate, InterpCx, OpTy, PlaceTy, Projectable};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def::DefKind;
+use rustc_middle::bug;
 use rustc_middle::mir::interpret::{InterpResult, Scalar};
 use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
 use rustc_middle::mir::*;
diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs
index e6317e5469c..08dba1de500 100644
--- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs
+++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs
@@ -13,6 +13,7 @@
 //!
 
 use crate::util::is_within_packed;
+use rustc_middle::bug;
 use rustc_middle::mir::visit::Visitor;
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs
index 10fea09531a..1bc383fccc7 100644
--- a/compiler/rustc_mir_transform/src/dest_prop.rs
+++ b/compiler/rustc_mir_transform/src/dest_prop.rs
@@ -135,6 +135,7 @@ use crate::MirPass;
 use rustc_data_structures::fx::{FxIndexMap, IndexEntry, IndexOccupiedEntry};
 use rustc_index::bit_set::BitSet;
 use rustc_index::interval::SparseIntervalMatrix;
+use rustc_middle::bug;
 use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
 use rustc_middle::mir::HasLocalDecls;
 use rustc_middle::mir::{dump_mir, PassWhere};
diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
index 318674f24e7..d955b96d06a 100644
--- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
@@ -6,6 +6,7 @@ use rustc_hir::def_id::DefId;
 use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::visit::MutVisitor;
 use rustc_middle::mir::*;
+use rustc_middle::span_bug;
 use rustc_middle::ty::{Ty, TyCtxt};
 use rustc_target::abi::FieldIdx;
 
diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
index 0970c4de19f..5e3cd853675 100644
--- a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
+++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
@@ -4,6 +4,7 @@ use rustc_middle::query::LocalCrate;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::layout;
 use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::{bug, span_bug};
 use rustc_session::lint::builtin::FFI_UNWIND_CALLS;
 use rustc_target::spec::abi::Abi;
 use rustc_target::spec::PanicStrategy;
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index 342d1a1cd5b..123166a764d 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -91,6 +91,7 @@ use rustc_hir::def::DefKind;
 use rustc_index::bit_set::BitSet;
 use rustc_index::newtype_index;
 use rustc_index::IndexVec;
+use rustc_middle::bug;
 use rustc_middle::mir::interpret::GlobalAlloc;
 use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 7a3b08f82f6..401056cd496 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -6,6 +6,7 @@ use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_index::bit_set::BitSet;
 use rustc_index::Idx;
+use rustc_middle::bug;
 use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs
index fd768cc96ae..f1adeab3f88 100644
--- a/compiler/rustc_mir_transform/src/instsimplify.rs
+++ b/compiler/rustc_mir_transform/src/instsimplify.rs
@@ -2,6 +2,7 @@
 
 use crate::simplify::simplify_duplicate_switch_targets;
 use rustc_ast::attr;
+use rustc_middle::bug;
 use rustc_middle::mir::*;
 use rustc_middle::ty::layout;
 use rustc_middle::ty::layout::ValidityRequirement;
diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs
index a458297210d..ae807655b68 100644
--- a/compiler/rustc_mir_transform/src/jump_threading.rs
+++ b/compiler/rustc_mir_transform/src/jump_threading.rs
@@ -41,6 +41,7 @@ use rustc_const_eval::interpret::{ImmTy, Immediate, InterpCx, OpTy, Projectable}
 use rustc_data_structures::fx::FxHashSet;
 use rustc_index::bit_set::BitSet;
 use rustc_index::IndexVec;
+use rustc_middle::bug;
 use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::mir::visit::Visitor;
 use rustc_middle::mir::*;
diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs
index 90c1c7ba63b..d0a5a6cada8 100644
--- a/compiler/rustc_mir_transform/src/known_panics_lint.rs
+++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs
@@ -14,6 +14,7 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def::DefKind;
 use rustc_hir::HirId;
 use rustc_index::{bit_set::BitSet, IndexVec};
+use rustc_middle::bug;
 use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
 use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index e69c5da757e..9af48f0bad2 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -16,8 +16,6 @@
 
 #[macro_use]
 extern crate tracing;
-#[macro_use]
-extern crate rustc_middle;
 
 use hir::ConstContext;
 use required_consts::RequiredConstsVisitor;
@@ -38,6 +36,7 @@ use rustc_middle::mir::{
 use rustc_middle::query;
 use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
 use rustc_middle::util::Providers;
+use rustc_middle::{bug, span_bug};
 use rustc_span::{source_map::Spanned, sym, DUMMY_SP};
 use rustc_trait_selection::traits;
 
diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
index da63fcf23d9..43d8c45bb2d 100644
--- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs
+++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
@@ -2,6 +2,7 @@
 
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::{bug, span_bug};
 use rustc_span::symbol::sym;
 
 pub struct LowerIntrinsics;
diff --git a/compiler/rustc_mir_transform/src/nrvo.rs b/compiler/rustc_mir_transform/src/nrvo.rs
index 232c290e0fb..885dbd5f339 100644
--- a/compiler/rustc_mir_transform/src/nrvo.rs
+++ b/compiler/rustc_mir_transform/src/nrvo.rs
@@ -2,6 +2,7 @@
 
 use rustc_hir::Mutability;
 use rustc_index::bit_set::BitSet;
+use rustc_middle::bug;
 use rustc_middle::mir::visit::{MutVisitor, NonUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::{self, BasicBlock, Local, Location};
 use rustc_middle::ty::TyCtxt;
diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs
index 689a547689a..b3116c002d3 100644
--- a/compiler/rustc_mir_transform/src/promote_consts.rs
+++ b/compiler/rustc_mir_transform/src/promote_consts.rs
@@ -20,6 +20,7 @@ use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Vis
 use rustc_middle::mir::*;
 use rustc_middle::ty::GenericArgs;
 use rustc_middle::ty::{self, List, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::{bug, span_bug};
 use rustc_span::Span;
 
 use rustc_index::{Idx, IndexSlice, IndexVec};
diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs
index 044ae32c1d4..801ef14c9cd 100644
--- a/compiler/rustc_mir_transform/src/ref_prop.rs
+++ b/compiler/rustc_mir_transform/src/ref_prop.rs
@@ -1,6 +1,7 @@
 use rustc_data_structures::fx::FxHashSet;
 use rustc_index::bit_set::BitSet;
 use rustc_index::IndexVec;
+use rustc_middle::bug;
 use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index 1c85a604053..cd8a43d6e6c 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -5,6 +5,7 @@ use rustc_middle::mir::*;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::GenericArgs;
 use rustc_middle::ty::{self, CoroutineArgs, EarlyBinder, Ty, TyCtxt};
+use rustc_middle::{bug, span_bug};
 use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
 
 use rustc_index::{Idx, IndexVec};
diff --git a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs
index 80eadb9abdc..f4481c22fc1 100644
--- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs
+++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs
@@ -14,6 +14,7 @@ use rustc_middle::mir::{
 use rustc_middle::ty::adjustment::PointerCoercion;
 use rustc_middle::ty::util::Discr;
 use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::{bug, span_bug};
 use rustc_span::source_map::respan;
 use rustc_span::{Span, Symbol};
 use rustc_target::abi::{FieldIdx, VariantIdx};
@@ -534,8 +535,7 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> {
             }
 
             // If projection of Discriminant then compare with `Ty::discriminant_ty`
-            if let ty::Alias(ty::AliasKind::Projection, ty::AliasTy { args, def_id, .. }) =
-                expected_ty.kind()
+            if let ty::Alias(ty::Projection, ty::AliasTy { args, def_id, .. }) = expected_ty.kind()
                 && Some(*def_id) == self.tcx.lang_items().discriminant_type()
                 && args.first().unwrap().as_type().unwrap().discriminant_ty(self.tcx) == operand_ty
             {
diff --git a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
index 1a8cfc41178..03907babf2b 100644
--- a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
+++ b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
@@ -2,6 +2,7 @@ use std::iter;
 
 use super::MirPass;
 use rustc_middle::{
+    bug,
     mir::{
         interpret::Scalar, BasicBlock, BinOp, Body, Operand, Place, Rvalue, Statement,
         StatementKind, SwitchTargets, TerminatorKind,
diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs
index 06d5e17fdd6..cdf3305b560 100644
--- a/compiler/rustc_mir_transform/src/sroa.rs
+++ b/compiler/rustc_mir_transform/src/sroa.rs
@@ -1,6 +1,7 @@
 use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
 use rustc_index::bit_set::{BitSet, GrowableBitSet};
 use rustc_index::IndexVec;
+use rustc_middle::bug;
 use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs
index 55fed7d9da2..fb870425f6e 100644
--- a/compiler/rustc_mir_transform/src/ssa.rs
+++ b/compiler/rustc_mir_transform/src/ssa.rs
@@ -9,6 +9,7 @@
 use rustc_data_structures::graph::dominators::Dominators;
 use rustc_index::bit_set::BitSet;
 use rustc_index::{IndexSlice, IndexVec};
+use rustc_middle::bug;
 use rustc_middle::middle::resolve_bound_vars::Set1;
 use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
diff --git a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
index 66b6235eb93..1404a45f4d2 100644
--- a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
+++ b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
@@ -2,6 +2,7 @@
 
 use crate::MirPass;
 use rustc_data_structures::fx::FxHashSet;
+use rustc_middle::bug;
 use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::{
     BasicBlock, BasicBlockData, BasicBlocks, Body, Local, Operand, Rvalue, StatementKind,
diff --git a/compiler/rustc_mir_transform/src/unreachable_prop.rs b/compiler/rustc_mir_transform/src/unreachable_prop.rs
index 8ad7bc394c5..a6c3c3b189e 100644
--- a/compiler/rustc_mir_transform/src/unreachable_prop.rs
+++ b/compiler/rustc_mir_transform/src/unreachable_prop.rs
@@ -3,6 +3,7 @@
 //! post-order traversal of the blocks.
 
 use rustc_data_structures::fx::FxHashSet;
+use rustc_middle::bug;
 use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::*;
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 2f68a299f26..3f08a830b0c 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -83,7 +83,7 @@ pub(crate) struct IncorrectSemicolon<'a> {
     #[suggestion(style = "short", code = "", applicability = "machine-applicable")]
     pub span: Span,
     #[help]
-    pub opt_help: Option<()>,
+    pub show_help: bool,
     pub name: &'a str,
 }
 
diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs
index b5a5a2a90ee..eabe0226b2f 100644
--- a/compiler/rustc_parse/src/lexer/tokentrees.rs
+++ b/compiler/rustc_parse/src/lexer/tokentrees.rs
@@ -241,7 +241,7 @@ impl<'psess, 'src> TokenTreesReader<'psess, 'src> {
         // we have no way of tracking this in the lexer itself, so we piggyback on the parser
         let mut in_cond = false;
         while parser.token != token::Eof {
-            if let Err(diff_err) = parser.err_diff_marker() {
+            if let Err(diff_err) = parser.err_vcs_conflict_marker() {
                 diff_errs.push(diff_err);
             } else if parser.is_keyword_ahead(0, &[kw::If, kw::While]) {
                 in_cond = true;
diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs
index d5d8060d909..a57eb70c705 100644
--- a/compiler/rustc_parse/src/parser/attr.rs
+++ b/compiler/rustc_parse/src/parser/attr.rs
@@ -363,7 +363,7 @@ impl<'a> Parser<'a> {
         // We can't use `maybe_whole` here because it would bump in the `None`
         // case, which we don't want.
         if let token::Interpolated(nt) = &self.token.kind
-            && let token::NtMeta(attr_item) = &nt.0
+            && let token::NtMeta(attr_item) = &**nt
         {
             match attr_item.meta(attr_item.path.span) {
                 Some(meta) => {
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 50698dbf9c1..ac12787f2ef 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -1817,34 +1817,31 @@ impl<'a> Parser<'a> {
         Ok(P(T::recovered(Some(P(QSelf { ty, path_span, position: 0 })), path)))
     }
 
-    pub fn maybe_consume_incorrect_semicolon(&mut self, items: &[P<Item>]) -> bool {
-        if self.token.kind == TokenKind::Semi {
-            self.bump();
-
-            let mut err =
-                IncorrectSemicolon { span: self.prev_token.span, opt_help: None, name: "" };
+    /// This function gets called in places where a semicolon is NOT expected and if there's a
+    /// semicolon it emits the appropriate error and returns true.
+    pub fn maybe_consume_incorrect_semicolon(&mut self, previous_item: Option<&Item>) -> bool {
+        if self.token.kind != TokenKind::Semi {
+            return false;
+        }
 
-            if !items.is_empty() {
-                let previous_item = &items[items.len() - 1];
-                let previous_item_kind_name = match previous_item.kind {
+        // Check previous item to add it to the diagnostic, for example to say
+        // `enum declarations are not followed by a semicolon`
+        let err = match previous_item {
+            Some(previous_item) => {
+                let name = match previous_item.kind {
                     // Say "braced struct" because tuple-structs and
                     // braceless-empty-struct declarations do take a semicolon.
-                    ItemKind::Struct(..) => Some("braced struct"),
-                    ItemKind::Enum(..) => Some("enum"),
-                    ItemKind::Trait(..) => Some("trait"),
-                    ItemKind::Union(..) => Some("union"),
-                    _ => None,
+                    ItemKind::Struct(..) => "braced struct",
+                    _ => previous_item.kind.descr(),
                 };
-                if let Some(name) = previous_item_kind_name {
-                    err.opt_help = Some(());
-                    err.name = name;
-                }
+                IncorrectSemicolon { span: self.token.span, name, show_help: true }
             }
-            self.dcx().emit_err(err);
-            true
-        } else {
-            false
-        }
+            None => IncorrectSemicolon { span: self.token.span, name: "", show_help: false },
+        };
+        self.dcx().emit_err(err);
+
+        self.bump();
+        true
     }
 
     /// Creates a `Diag` for an unexpected token `t` and tries to recover if it is a
@@ -2372,9 +2369,9 @@ impl<'a> Parser<'a> {
         // in a subsequent macro invocation (#71039).
         let mut tok = self.token.clone();
         let mut labels = vec![];
-        while let TokenKind::Interpolated(node) = &tok.kind {
-            let tokens = node.0.tokens();
-            labels.push(node.clone());
+        while let TokenKind::Interpolated(nt) = &tok.kind {
+            let tokens = nt.tokens();
+            labels.push(nt.clone());
             if let Some(tokens) = tokens
                 && let tokens = tokens.to_attr_token_stream()
                 && let tokens = tokens.0.deref()
@@ -2387,27 +2384,20 @@ impl<'a> Parser<'a> {
         }
         let mut iter = labels.into_iter().peekable();
         let mut show_link = false;
-        while let Some(node) = iter.next() {
-            let descr = node.0.descr();
+        while let Some(nt) = iter.next() {
+            let descr = nt.descr();
             if let Some(next) = iter.peek() {
-                let next_descr = next.0.descr();
+                let next_descr = next.descr();
                 if next_descr != descr {
-                    err.span_label(next.1, format!("this macro fragment matcher is {next_descr}"));
-                    err.span_label(node.1, format!("this macro fragment matcher is {descr}"));
-                    err.span_label(
-                        next.0.use_span(),
-                        format!("this is expected to be {next_descr}"),
-                    );
+                    err.span_label(next.use_span(), format!("this is expected to be {next_descr}"));
                     err.span_label(
-                        node.0.use_span(),
+                        nt.use_span(),
                         format!(
                             "this is interpreted as {}, but it is expected to be {}",
                             next_descr, descr,
                         ),
                     );
                     show_link = true;
-                } else {
-                    err.span_label(node.1, "");
                 }
             }
         }
@@ -2964,13 +2954,23 @@ impl<'a> Parser<'a> {
         err
     }
 
-    pub fn is_diff_marker(&mut self, long_kind: &TokenKind, short_kind: &TokenKind) -> bool {
+    /// This checks if this is a conflict marker, depending of the parameter passed.
+    ///
+    /// * `>>>>>`
+    /// * `=====`
+    /// * `<<<<<`
+    ///
+    pub fn is_vcs_conflict_marker(
+        &mut self,
+        long_kind: &TokenKind,
+        short_kind: &TokenKind,
+    ) -> bool {
         (0..3).all(|i| self.look_ahead(i, |tok| tok == long_kind))
             && self.look_ahead(3, |tok| tok == short_kind)
     }
 
-    fn diff_marker(&mut self, long_kind: &TokenKind, short_kind: &TokenKind) -> Option<Span> {
-        if self.is_diff_marker(long_kind, short_kind) {
+    fn conflict_marker(&mut self, long_kind: &TokenKind, short_kind: &TokenKind) -> Option<Span> {
+        if self.is_vcs_conflict_marker(long_kind, short_kind) {
             let lo = self.token.span;
             for _ in 0..4 {
                 self.bump();
@@ -2980,15 +2980,16 @@ impl<'a> Parser<'a> {
         None
     }
 
-    pub fn recover_diff_marker(&mut self) {
-        if let Err(err) = self.err_diff_marker() {
+    pub fn recover_vcs_conflict_marker(&mut self) {
+        if let Err(err) = self.err_vcs_conflict_marker() {
             err.emit();
             FatalError.raise();
         }
     }
 
-    pub fn err_diff_marker(&mut self) -> PResult<'a, ()> {
-        let Some(start) = self.diff_marker(&TokenKind::BinOp(token::Shl), &TokenKind::Lt) else {
+    pub fn err_vcs_conflict_marker(&mut self) -> PResult<'a, ()> {
+        let Some(start) = self.conflict_marker(&TokenKind::BinOp(token::Shl), &TokenKind::Lt)
+        else {
             return Ok(());
         };
         let mut spans = Vec::with_capacity(3);
@@ -3000,13 +3001,15 @@ impl<'a> Parser<'a> {
             if self.token.kind == TokenKind::Eof {
                 break;
             }
-            if let Some(span) = self.diff_marker(&TokenKind::OrOr, &TokenKind::BinOp(token::Or)) {
+            if let Some(span) = self.conflict_marker(&TokenKind::OrOr, &TokenKind::BinOp(token::Or))
+            {
                 middlediff3 = Some(span);
             }
-            if let Some(span) = self.diff_marker(&TokenKind::EqEq, &TokenKind::Eq) {
+            if let Some(span) = self.conflict_marker(&TokenKind::EqEq, &TokenKind::Eq) {
                 middle = Some(span);
             }
-            if let Some(span) = self.diff_marker(&TokenKind::BinOp(token::Shr), &TokenKind::Gt) {
+            if let Some(span) = self.conflict_marker(&TokenKind::BinOp(token::Shr), &TokenKind::Gt)
+            {
                 spans.push(span);
                 end = Some(span);
                 break;
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 577003e94fb..d2d21624150 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -45,7 +45,7 @@ use thin_vec::{thin_vec, ThinVec};
 macro_rules! maybe_whole_expr {
     ($p:expr) => {
         if let token::Interpolated(nt) = &$p.token.kind {
-            match &nt.0 {
+            match &**nt {
                 token::NtExpr(e) | token::NtLiteral(e) => {
                     let e = e.clone();
                     $p.bump();
@@ -497,8 +497,7 @@ impl<'a> Parser<'a> {
 
     /// Checks if this expression is a successfully parsed statement.
     fn expr_is_complete(&self, e: &Expr) -> bool {
-        self.restrictions.contains(Restrictions::STMT_EXPR)
-            && !classify::expr_requires_semi_to_be_stmt(e)
+        self.restrictions.contains(Restrictions::STMT_EXPR) && classify::expr_is_complete(e)
     }
 
     /// Parses `x..y`, `x..=y`, and `x..`/`x..=`.
@@ -725,7 +724,9 @@ impl<'a> Parser<'a> {
     /// Returns the span of expr if it was not interpolated, or the span of the interpolated token.
     fn interpolated_or_expr_span(&self, expr: &Expr) -> Span {
         match self.prev_token.kind {
-            TokenKind::Interpolated(..) => self.prev_token.span,
+            TokenKind::NtIdent(..) | TokenKind::NtLifetime(..) | TokenKind::Interpolated(..) => {
+                self.prev_token.span
+            }
             _ => expr.span,
         }
     }
@@ -2691,8 +2692,33 @@ impl<'a> Parser<'a> {
             let first_tok_span = self.token.span;
             match self.parse_expr() {
                 Ok(cond)
-                // If it's not a free-standing expression, and is followed by a block,
-                // then it's very likely the condition to an `else if`.
+                // Try to guess the difference between a "condition-like" vs
+                // "statement-like" expression.
+                //
+                // We are seeing the following code, in which $cond is neither
+                // ExprKind::Block nor ExprKind::If (the 2 cases wherein this
+                // would be valid syntax).
+                //
+                //     if ... {
+                //     } else $cond
+                //
+                // If $cond is "condition-like" such as ExprKind::Binary, we
+                // want to suggest inserting `if`.
+                //
+                //     if ... {
+                //     } else if a == b {
+                //            ^^
+                //     }
+                //
+                // If $cond is "statement-like" such as ExprKind::While then we
+                // want to suggest wrapping in braces.
+                //
+                //     if ... {
+                //     } else {
+                //            ^
+                //         while true {}
+                //     }
+                //     ^
                     if self.check(&TokenKind::OpenDelim(Delimiter::Brace))
                         && classify::expr_requires_semi_to_be_stmt(&cond) =>
                 {
@@ -3136,7 +3162,7 @@ impl<'a> Parser<'a> {
                         err
                     })?;
 
-                let require_comma = classify::expr_requires_semi_to_be_stmt(&expr)
+                let require_comma = !classify::expr_is_complete(&expr)
                     && this.token != token::CloseDelim(Delimiter::Brace);
 
                 if !require_comma {
@@ -3708,7 +3734,7 @@ impl<'a> Parser<'a> {
     /// Parses `ident (COLON expr)?`.
     fn parse_expr_field(&mut self) -> PResult<'a, ExprField> {
         let attrs = self.parse_outer_attributes()?;
-        self.recover_diff_marker();
+        self.recover_vcs_conflict_marker();
         self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
             let lo = this.token.span;
 
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index df6996dbc45..34cdf8a9b5f 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -49,6 +49,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses the contents of a module (inner attributes followed by module items).
+    /// We exit once we hit `term`
     pub fn parse_mod(
         &mut self,
         term: &TokenKind,
@@ -59,13 +60,13 @@ impl<'a> Parser<'a> {
         let post_attr_lo = self.token.span;
         let mut items = ThinVec::new();
         while let Some(item) = self.parse_item(ForceCollect::No)? {
+            self.maybe_consume_incorrect_semicolon(Some(&item));
             items.push(item);
-            self.maybe_consume_incorrect_semicolon(&items);
         }
 
         if !self.eat(term) {
             let token_str = super::token_descr(&self.token);
-            if !self.maybe_consume_incorrect_semicolon(&items) {
+            if !self.maybe_consume_incorrect_semicolon(items.last().map(|x| &**x)) {
                 let msg = format!("expected item, found {token_str}");
                 let mut err = self.dcx().struct_span_err(self.token.span, msg);
                 let span = self.token.span;
@@ -101,9 +102,9 @@ impl<'a> Parser<'a> {
         fn_parse_mode: FnParseMode,
         force_collect: ForceCollect,
     ) -> PResult<'a, Option<Item>> {
-        self.recover_diff_marker();
+        self.recover_vcs_conflict_marker();
         let attrs = self.parse_outer_attributes()?;
-        self.recover_diff_marker();
+        self.recover_vcs_conflict_marker();
         self.parse_item_common(attrs, true, false, fn_parse_mode, force_collect)
     }
 
@@ -194,12 +195,12 @@ impl<'a> Parser<'a> {
         fn_parse_mode: FnParseMode,
         case: Case,
     ) -> PResult<'a, Option<ItemInfo>> {
-        let def_final = def == &Defaultness::Final;
+        let check_pub = def == &Defaultness::Final;
         let mut def_ = || mem::replace(def, Defaultness::Final);
 
         let info = if self.eat_keyword_case(kw::Use, case) {
             self.parse_use_item()?
-        } else if self.check_fn_front_matter(def_final, case) {
+        } else if self.check_fn_front_matter(check_pub, case) {
             // FUNCTION ITEM
             let (ident, sig, generics, body) =
                 self.parse_fn(attrs, fn_parse_mode, lo, vis, case)?;
@@ -310,7 +311,7 @@ impl<'a> Parser<'a> {
         Ok(Some(info))
     }
 
-    fn recover_import_as_use(&mut self) -> PResult<'a, Option<(Ident, ItemKind)>> {
+    fn recover_import_as_use(&mut self) -> PResult<'a, Option<ItemInfo>> {
         let span = self.token.span;
         let token_name = super::token_descr(&self.token);
         let snapshot = self.create_snapshot_for_diagnostic();
@@ -328,7 +329,7 @@ impl<'a> Parser<'a> {
         }
     }
 
-    fn parse_use_item(&mut self) -> PResult<'a, (Ident, ItemKind)> {
+    fn parse_use_item(&mut self) -> PResult<'a, ItemInfo> {
         let tree = self.parse_use_tree()?;
         if let Err(mut e) = self.expect_semi() {
             match tree.kind {
@@ -723,7 +724,7 @@ impl<'a> Parser<'a> {
             if self.recover_doc_comment_before_brace() {
                 continue;
             }
-            self.recover_diff_marker();
+            self.recover_vcs_conflict_marker();
             match parse_item(self) {
                 Ok(None) => {
                     let mut is_unnecessary_semicolon = !items.is_empty()
@@ -1070,7 +1071,7 @@ impl<'a> Parser<'a> {
     /// ```
     fn parse_use_tree_list(&mut self) -> PResult<'a, ThinVec<(UseTree, ast::NodeId)>> {
         self.parse_delim_comma_seq(Delimiter::Brace, |p| {
-            p.recover_diff_marker();
+            p.recover_vcs_conflict_marker();
             Ok((p.parse_use_tree()?, DUMMY_NODE_ID))
         })
         .map(|(r, _)| r)
@@ -1497,9 +1498,9 @@ impl<'a> Parser<'a> {
     }
 
     fn parse_enum_variant(&mut self, span: Span) -> PResult<'a, Option<Variant>> {
-        self.recover_diff_marker();
+        self.recover_vcs_conflict_marker();
         let variant_attrs = self.parse_outer_attributes()?;
-        self.recover_diff_marker();
+        self.recover_vcs_conflict_marker();
         let help = "enum variants can be `Variant`, `Variant = <integer>`, \
                     `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`";
         self.collect_tokens_trailing_token(
@@ -1688,6 +1689,10 @@ impl<'a> Parser<'a> {
         Ok((class_name, ItemKind::Union(vdata, generics)))
     }
 
+    /// This function parses the fields of record structs:
+    ///
+    ///   - `struct S { ... }`
+    ///   - `enum E { Variant { ... } }`
     pub(crate) fn parse_record_struct_body(
         &mut self,
         adt_ty: &str,
@@ -1714,19 +1719,10 @@ impl<'a> Parser<'a> {
             self.eat(&token::CloseDelim(Delimiter::Brace));
         } else {
             let token_str = super::token_descr(&self.token);
-            let msg = format!(
-                "expected {}`{{` after struct name, found {}",
-                if parsed_where { "" } else { "`where`, or " },
-                token_str
-            );
+            let where_str = if parsed_where { "" } else { "`where`, or " };
+            let msg = format!("expected {where_str}`{{` after struct name, found {token_str}");
             let mut err = self.dcx().struct_span_err(self.token.span, msg);
-            err.span_label(
-                self.token.span,
-                format!(
-                    "expected {}`{{` after struct name",
-                    if parsed_where { "" } else { "`where`, or " }
-                ),
-            );
+            err.span_label(self.token.span, format!("expected {where_str}`{{` after struct name",));
             return Err(err);
         }
 
@@ -1740,7 +1736,7 @@ impl<'a> Parser<'a> {
             let attrs = p.parse_outer_attributes()?;
             p.collect_tokens_trailing_token(attrs, ForceCollect::No, |p, attrs| {
                 let mut snapshot = None;
-                if p.is_diff_marker(&TokenKind::BinOp(token::Shl), &TokenKind::Lt) {
+                if p.is_vcs_conflict_marker(&TokenKind::BinOp(token::Shl), &TokenKind::Lt) {
                     // Account for `<<<<<<<` diff markers. We can't proactively error here because
                     // that can be a valid type start, so we snapshot and reparse only we've
                     // encountered another parse error.
@@ -1751,7 +1747,7 @@ impl<'a> Parser<'a> {
                     Ok(vis) => vis,
                     Err(err) => {
                         if let Some(ref mut snapshot) = snapshot {
-                            snapshot.recover_diff_marker();
+                            snapshot.recover_vcs_conflict_marker();
                         }
                         return Err(err);
                     }
@@ -1760,7 +1756,7 @@ impl<'a> Parser<'a> {
                     Ok(ty) => ty,
                     Err(err) => {
                         if let Some(ref mut snapshot) = snapshot {
-                            snapshot.recover_diff_marker();
+                            snapshot.recover_vcs_conflict_marker();
                         }
                         return Err(err);
                     }
@@ -1785,9 +1781,9 @@ impl<'a> Parser<'a> {
 
     /// Parses an element of a struct declaration.
     fn parse_field_def(&mut self, adt_ty: &str) -> PResult<'a, FieldDef> {
-        self.recover_diff_marker();
+        self.recover_vcs_conflict_marker();
         let attrs = self.parse_outer_attributes()?;
-        self.recover_diff_marker();
+        self.recover_vcs_conflict_marker();
         self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
             let lo = this.token.span;
             let vis = this.parse_visibility(FollowedByType::No)?;
@@ -2647,7 +2643,7 @@ impl<'a> Parser<'a> {
         }
 
         let (mut params, _) = self.parse_paren_comma_seq(|p| {
-            p.recover_diff_marker();
+            p.recover_vcs_conflict_marker();
             let snapshot = p.create_snapshot_for_diagnostic();
             let param = p.parse_param_general(req_name, first_param).or_else(|e| {
                 let guar = e.emit();
@@ -2841,7 +2837,7 @@ impl<'a> Parser<'a> {
 
     fn is_named_param(&self) -> bool {
         let offset = match &self.token.kind {
-            token::Interpolated(nt) => match &nt.0 {
+            token::Interpolated(nt) => match &**nt {
                 token::NtPat(..) => return self.look_ahead(1, |t| t == &token::Colon),
                 _ => 0,
             },
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index bfb6c4a3885..3e0a98a55ae 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -11,7 +11,6 @@ mod stmt;
 mod ty;
 
 use crate::lexer::UnmatchedDelim;
-use ast::token::IdentIsRaw;
 pub use attr_wrapper::AttrWrapper;
 pub use diagnostics::AttemptLocalParseRecovery;
 pub(crate) use expr::ForbiddenLetReason;
@@ -21,7 +20,7 @@ pub use path::PathStyle;
 
 use core::fmt;
 use rustc_ast::ptr::P;
-use rustc_ast::token::{self, Delimiter, Token, TokenKind};
+use rustc_ast::token::{self, Delimiter, IdentIsRaw, Nonterminal, Token, TokenKind};
 use rustc_ast::tokenstream::{AttributesData, DelimSpacing, DelimSpan, Spacing};
 use rustc_ast::tokenstream::{TokenStream, TokenTree, TokenTreeCursor};
 use rustc_ast::util::case::Case;
@@ -32,6 +31,7 @@ use rustc_ast::{
 };
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::sync::Lrc;
 use rustc_errors::{Applicability, Diag, FatalError, MultiSpan, PResult};
 use rustc_session::parse::ParseSess;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -107,7 +107,7 @@ pub enum TrailingToken {
 macro_rules! maybe_whole {
     ($p:expr, $constructor:ident, |$x:ident| $e:expr) => {
         if let token::Interpolated(nt) = &$p.token.kind
-            && let token::$constructor(x) = &nt.0
+            && let token::$constructor(x) = &**nt
         {
             #[allow(unused_mut)]
             let mut $x = x.clone();
@@ -125,7 +125,7 @@ macro_rules! maybe_recover_from_interpolated_ty_qpath {
             && $self.may_recover()
             && $self.look_ahead(1, |t| t == &token::PathSep)
             && let token::Interpolated(nt) = &$self.token.kind
-            && let token::NtTy(ty) = &nt.0
+            && let token::NtTy(ty) = &**nt
         {
             let ty = ty.clone();
             $self.bump();
@@ -407,7 +407,9 @@ pub(super) fn token_descr(token: &Token) -> String {
         (Some(TokenDescription::Keyword), _) => Some("keyword"),
         (Some(TokenDescription::ReservedKeyword), _) => Some("reserved keyword"),
         (Some(TokenDescription::DocComment), _) => Some("doc comment"),
-        (None, TokenKind::Interpolated(node)) => Some(node.0.descr()),
+        (None, TokenKind::NtIdent(..)) => Some("identifier"),
+        (None, TokenKind::NtLifetime(..)) => Some("lifetime"),
+        (None, TokenKind::Interpolated(node)) => Some(node.descr()),
         (None, _) => None,
     };
 
@@ -708,7 +710,7 @@ impl<'a> Parser<'a> {
     fn check_inline_const(&self, dist: usize) -> bool {
         self.is_keyword_ahead(dist, &[kw::Const])
             && self.look_ahead(dist + 1, |t| match &t.kind {
-                token::Interpolated(nt) => matches!(&nt.0, token::NtBlock(..)),
+                token::Interpolated(nt) => matches!(&**nt, token::NtBlock(..)),
                 token::OpenDelim(Delimiter::Brace) => true,
                 _ => false,
             })
@@ -1631,19 +1633,11 @@ pub enum FlatToken {
 
 // Metavar captures of various kinds.
 #[derive(Clone, Debug)]
-pub enum ParseNtResult<NtType> {
+pub enum ParseNtResult {
     Tt(TokenTree),
-    Nt(NtType),
-}
+    Ident(Ident, IdentIsRaw),
+    Lifetime(Ident),
 
-impl<T> ParseNtResult<T> {
-    pub fn map_nt<F, U>(self, mut f: F) -> ParseNtResult<U>
-    where
-        F: FnMut(T) -> U,
-    {
-        match self {
-            ParseNtResult::Tt(tt) => ParseNtResult::Tt(tt),
-            ParseNtResult::Nt(nt) => ParseNtResult::Nt(f(nt)),
-        }
-    }
+    /// This case will eventually be removed, along with `Token::Interpolate`.
+    Nt(Lrc<Nonterminal>),
 }
diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs
index 73b17353ac9..a6f0ab78b5c 100644
--- a/compiler/rustc_parse/src/parser/nonterminal.rs
+++ b/compiler/rustc_parse/src/parser/nonterminal.rs
@@ -1,7 +1,8 @@
 use rustc_ast::ptr::P;
-use rustc_ast::token::{self, Delimiter, Nonterminal, Nonterminal::*, NonterminalKind, Token};
+use rustc_ast::token::{self, Delimiter, Nonterminal::*, NonterminalKind, Token};
 use rustc_ast::HasTokens;
 use rustc_ast_pretty::pprust;
+use rustc_data_structures::sync::Lrc;
 use rustc_errors::PResult;
 use rustc_span::symbol::{kw, Ident};
 
@@ -24,15 +25,13 @@ impl<'a> Parser<'a> {
                 | NtPat(_)
                 | NtExpr(_)
                 | NtTy(_)
-                | NtIdent(..)
                 | NtLiteral(_) // `true`, `false`
                 | NtMeta(_)
                 | NtPath(_) => true,
 
                 NtItem(_)
                 | NtBlock(_)
-                | NtVis(_)
-                | NtLifetime(_) => false,
+                | NtVis(_) => false,
             }
         }
 
@@ -49,25 +48,30 @@ impl<'a> Parser<'a> {
             NonterminalKind::Literal => token.can_begin_literal_maybe_minus(),
             NonterminalKind::Vis => match token.kind {
                 // The follow-set of :vis + "priv" keyword + interpolated
-                token::Comma | token::Ident(..) | token::Interpolated(_) => true,
+                token::Comma
+                | token::Ident(..)
+                | token::NtIdent(..)
+                | token::NtLifetime(..)
+                | token::Interpolated(_) => true,
                 _ => token.can_begin_type(),
             },
             NonterminalKind::Block => match &token.kind {
                 token::OpenDelim(Delimiter::Brace) => true,
-                token::Interpolated(nt) => match &nt.0 {
-                    NtBlock(_) | NtLifetime(_) | NtStmt(_) | NtExpr(_) | NtLiteral(_) => true,
-                    NtItem(_) | NtPat(_) | NtTy(_) | NtIdent(..) | NtMeta(_) | NtPath(_)
-                    | NtVis(_) => false,
+                token::NtLifetime(..) => true,
+                token::Interpolated(nt) => match &**nt {
+                    NtBlock(_) | NtStmt(_) | NtExpr(_) | NtLiteral(_) => true,
+                    NtItem(_) | NtPat(_) | NtTy(_) | NtMeta(_) | NtPath(_) | NtVis(_) => false,
                 },
                 _ => false,
             },
             NonterminalKind::Path | NonterminalKind::Meta => match &token.kind {
-                token::PathSep | token::Ident(..) => true,
-                token::Interpolated(nt) => may_be_ident(&nt.0),
+                token::PathSep | token::Ident(..) | token::NtIdent(..) => true,
+                token::Interpolated(nt) => may_be_ident(nt),
                 _ => false,
             },
             NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr => match &token.kind {
-                token::Ident(..) |                          // box, ref, mut, and other identifiers (can stricten)
+                // box, ref, mut, and other identifiers (can stricten)
+                token::Ident(..) | token::NtIdent(..) |
                 token::OpenDelim(Delimiter::Parenthesis) |  // tuple pattern
                 token::OpenDelim(Delimiter::Bracket) |      // slice pattern
                 token::BinOp(token::And) |                  // reference
@@ -81,14 +85,11 @@ impl<'a> Parser<'a> {
                 token::BinOp(token::Shl) => true,           // path (double UFCS)
                 // leading vert `|` or-pattern
                 token::BinOp(token::Or) => matches!(kind, NonterminalKind::PatWithOr),
-                token::Interpolated(nt) => may_be_ident(&nt.0),
+                token::Interpolated(nt) => may_be_ident(nt),
                 _ => false,
             },
             NonterminalKind::Lifetime => match &token.kind {
-                token::Lifetime(_) => true,
-                token::Interpolated(nt) => {
-                    matches!(&nt.0, NtLifetime(_))
-                }
+                token::Lifetime(_) | token::NtLifetime(..) => true,
                 _ => false,
             },
             NonterminalKind::TT | NonterminalKind::Item | NonterminalKind::Stmt => {
@@ -100,10 +101,7 @@ impl<'a> Parser<'a> {
     /// Parse a non-terminal (e.g. MBE `:pat` or `:ident`). Inlined because there is only one call
     /// site.
     #[inline]
-    pub fn parse_nonterminal(
-        &mut self,
-        kind: NonterminalKind,
-    ) -> PResult<'a, ParseNtResult<Nonterminal>> {
+    pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, ParseNtResult> {
         // A `macro_rules!` invocation may pass a captured item/expr to a proc-macro,
         // which requires having captured tokens available. Since we cannot determine
         // in advance whether or not a proc-macro will be (transitively) invoked,
@@ -156,15 +154,16 @@ impl<'a> Parser<'a> {
             }
 
             // this could be handled like a token, since it is one
-            NonterminalKind::Ident if let Some((ident, is_raw)) = get_macro_ident(&self.token) => {
-                self.bump();
-                NtIdent(ident, is_raw)
-            }
             NonterminalKind::Ident => {
-                return Err(self.dcx().create_err(UnexpectedNonterminal::Ident {
-                    span: self.token.span,
-                    token: self.token.clone(),
-                }));
+                return if let Some((ident, is_raw)) = get_macro_ident(&self.token) {
+                    self.bump();
+                    Ok(ParseNtResult::Ident(ident, is_raw))
+                } else {
+                    Err(self.dcx().create_err(UnexpectedNonterminal::Ident {
+                        span: self.token.span,
+                        token: self.token.clone(),
+                    }))
+                };
             }
             NonterminalKind::Path => {
                 NtPath(P(self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?))
@@ -175,14 +174,14 @@ impl<'a> Parser<'a> {
                     .collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?))
             }
             NonterminalKind::Lifetime => {
-                if self.check_lifetime() {
-                    NtLifetime(self.expect_lifetime().ident)
+                return if self.check_lifetime() {
+                    Ok(ParseNtResult::Lifetime(self.expect_lifetime().ident))
                 } else {
-                    return Err(self.dcx().create_err(UnexpectedNonterminal::Lifetime {
+                    Err(self.dcx().create_err(UnexpectedNonterminal::Lifetime {
                         span: self.token.span,
                         token: self.token.clone(),
-                    }));
-                }
+                    }))
+                };
             }
         };
 
@@ -196,7 +195,7 @@ impl<'a> Parser<'a> {
             );
         }
 
-        Ok(ParseNtResult::Nt(nt))
+        Ok(ParseNtResult::Nt(Lrc::new(nt)))
     }
 }
 
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index 78d3d019bf4..8af415f7c9d 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -757,7 +757,7 @@ impl<'a> Parser<'a> {
 
         // Make sure we don't allow e.g. `let mut $p;` where `$p:pat`.
         if let token::Interpolated(nt) = &self.token.kind {
-            if let token::NtPat(..) = &nt.0 {
+            if let token::NtPat(..) = &**nt {
                 self.expected_ident_found_err().emit();
             }
         }
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index 3636a357978..c37d3f0441d 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -193,7 +193,7 @@ impl<'a> Parser<'a> {
         maybe_whole!(self, NtPath, |path| reject_generics_if_mod_style(self, path.into_inner()));
 
         if let token::Interpolated(nt) = &self.token.kind {
-            if let token::NtTy(ty) = &nt.0 {
+            if let token::NtTy(ty) = &**nt {
                 if let ast::TyKind::Path(None, path) = &ty.kind {
                     let path = path.clone();
                     self.bump();
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index d70afebf1b2..7424fbea9b0 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -567,7 +567,7 @@ impl<'a> Parser<'a> {
             if self.token == token::Eof {
                 break;
             }
-            if self.is_diff_marker(&TokenKind::BinOp(token::Shl), &TokenKind::Lt) {
+            if self.is_vcs_conflict_marker(&TokenKind::BinOp(token::Shl), &TokenKind::Lt) {
                 // Account for `<<<<<<<` diff markers. We can't proactively error here because
                 // that can be a valid path start, so we snapshot and reparse only we've
                 // encountered another parse error.
@@ -576,7 +576,7 @@ impl<'a> Parser<'a> {
             let stmt = match self.parse_full_stmt(recover) {
                 Err(mut err) if recover.yes() => {
                     if let Some(ref mut snapshot) = snapshot {
-                        snapshot.recover_diff_marker();
+                        snapshot.recover_vcs_conflict_marker();
                     }
                     if self.token == token::Colon {
                         // if a previous and next token of the current one is
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 7096b201f84..2f08a48c7bc 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -675,8 +675,8 @@ impl<'a> Parser<'a> {
         let precise_capturing = if self.eat_keyword(kw::Use) {
             let use_span = self.prev_token.span;
             self.psess.gated_spans.gate(sym::precise_capturing, use_span);
-            let args = self.parse_precise_capturing_args()?;
-            Some(P((args, use_span)))
+            let (args, args_span) = self.parse_precise_capturing_args()?;
+            Some(P((args, use_span.to(args_span))))
         } else {
             None
         };
@@ -689,32 +689,34 @@ impl<'a> Parser<'a> {
         Ok(TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds, precise_capturing))
     }
 
-    fn parse_precise_capturing_args(&mut self) -> PResult<'a, ThinVec<PreciseCapturingArg>> {
-        Ok(self
-            .parse_unspanned_seq(
-                &TokenKind::Lt,
-                &TokenKind::Gt,
-                SeqSep::trailing_allowed(token::Comma),
-                |self_| {
-                    if self_.check_keyword(kw::SelfUpper) {
-                        self_.bump();
-                        Ok(PreciseCapturingArg::Arg(
-                            ast::Path::from_ident(self_.prev_token.ident().unwrap().0),
-                            DUMMY_NODE_ID,
-                        ))
-                    } else if self_.check_ident() {
-                        Ok(PreciseCapturingArg::Arg(
-                            ast::Path::from_ident(self_.parse_ident()?),
-                            DUMMY_NODE_ID,
-                        ))
-                    } else if self_.check_lifetime() {
-                        Ok(PreciseCapturingArg::Lifetime(self_.expect_lifetime()))
-                    } else {
-                        self_.unexpected_any()
-                    }
-                },
-            )?
-            .0)
+    fn parse_precise_capturing_args(
+        &mut self,
+    ) -> PResult<'a, (ThinVec<PreciseCapturingArg>, Span)> {
+        let lo = self.token.span;
+        let (args, _) = self.parse_unspanned_seq(
+            &TokenKind::Lt,
+            &TokenKind::Gt,
+            SeqSep::trailing_allowed(token::Comma),
+            |self_| {
+                if self_.check_keyword(kw::SelfUpper) {
+                    self_.bump();
+                    Ok(PreciseCapturingArg::Arg(
+                        ast::Path::from_ident(self_.prev_token.ident().unwrap().0),
+                        DUMMY_NODE_ID,
+                    ))
+                } else if self_.check_ident() {
+                    Ok(PreciseCapturingArg::Arg(
+                        ast::Path::from_ident(self_.parse_ident()?),
+                        DUMMY_NODE_ID,
+                    ))
+                } else if self_.check_lifetime() {
+                    Ok(PreciseCapturingArg::Lifetime(self_.expect_lifetime()))
+                } else {
+                    self_.unexpected_any()
+                }
+            },
+        )?;
+        Ok((args, lo.to(self.prev_token.span)))
     }
 
     /// Is a `dyn B0 + ... + Bn` type allowed here?
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index c8143015583..f631ae76de5 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -117,7 +117,7 @@ where
         if V::SHALLOW { V::Result::output() } else { args.visit_with(self) }
     }
 
-    fn visit_projection_ty(&mut self, projection: ty::AliasTy<'tcx>) -> V::Result {
+    fn visit_projection_term(&mut self, projection: ty::AliasTerm<'tcx>) -> V::Result {
         let tcx = self.def_id_visitor.tcx();
         let (trait_ref, assoc_args) = projection.trait_ref_and_own_args(tcx);
         try_visit!(self.visit_trait(trait_ref));
@@ -135,9 +135,12 @@ where
             ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => {
                 self.visit_trait(trait_ref)
             }
-            ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => {
+            ty::ClauseKind::Projection(ty::ProjectionPredicate {
+                projection_term: projection_ty,
+                term,
+            }) => {
                 try_visit!(term.visit_with(self));
-                self.visit_projection_ty(projection_ty)
+                self.visit_projection_term(projection_ty)
             }
             ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, _region)) => ty.visit_with(self),
             ty::ClauseKind::RegionOutlives(..) => V::Result::output(),
@@ -226,7 +229,7 @@ where
                 return if V::SHALLOW {
                     V::Result::output()
                 } else if kind == ty::Projection {
-                    self.visit_projection_ty(data)
+                    self.visit_projection_term(data.into())
                 } else {
                     V::Result::from_branch(
                         data.args.iter().try_for_each(|arg| arg.visit_with(self).branch()),
diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs
index 914481d712e..85f55553af3 100644
--- a/compiler/rustc_query_impl/src/lib.rs
+++ b/compiler/rustc_query_impl/src/lib.rs
@@ -8,9 +8,6 @@
 #![allow(rustc::potential_query_instability, unused_parens)]
 #![allow(internal_features)]
 
-#[macro_use]
-extern crate rustc_middle;
-
 use crate::plumbing::{__rust_begin_short_backtrace, encode_all_query_results, try_mark_green};
 use crate::profiling_support::QueryKeyStringCache;
 use field_offset::offset_of;
@@ -222,4 +219,4 @@ pub fn query_system<'tcx>(
     }
 }
 
-rustc_query_append! { define_queries! }
+rustc_middle::rustc_query_append! { define_queries! }
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index a7696b1fbaf..86531bd9590 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -7,8 +7,8 @@ use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
 use rustc_data_structures::sync::Lock;
 use rustc_data_structures::unord::UnordMap;
 use rustc_errors::DiagInner;
-
 use rustc_index::Idx;
+use rustc_middle::bug;
 use rustc_middle::dep_graph::dep_kinds;
 use rustc_middle::dep_graph::{
     self, DepContext, DepKind, DepKindStruct, DepNode, DepNodeIndex, SerializedDepNodeIndex,
@@ -781,6 +781,7 @@ macro_rules! define_queries {
         #[allow(nonstandard_style)]
         mod query_callbacks {
             use super::*;
+            use rustc_middle::bug;
             use rustc_query_system::dep_graph::FingerprintStyle;
 
             // We use this for most things when incr. comp. is turned off.
@@ -849,7 +850,7 @@ macro_rules! define_queries {
         }
 
         pub fn query_callbacks<'tcx>(arena: &'tcx Arena<'tcx>) -> &'tcx [DepKindStruct<'tcx>] {
-            arena.alloc_from_iter(make_dep_kind_array!(query_callbacks))
+            arena.alloc_from_iter(rustc_middle::make_dep_kind_array!(query_callbacks))
         }
     }
 }
diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
index 7141c6c9bb0..21433cfdb61 100644
--- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
+++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
@@ -8,7 +8,8 @@ use rustc_hir::LangItem;
 use rustc_middle::bug;
 use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
 use rustc_middle::ty::{
-    self, Instance, IntTy, List, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, UintTy,
+    self, ExistentialPredicateStableCmpExt as _, Instance, IntTy, List, Ty, TyCtxt, TypeFoldable,
+    TypeVisitableExt, UintTy,
 };
 use rustc_span::sym;
 use rustc_trait_selection::traits;
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
index c442d33cf86..44737e6ce40 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
@@ -9,7 +9,7 @@ use stable_mir::ty::{
 
 use crate::rustc_smir::{alloc, Stable, Tables};
 
-impl<'tcx> Stable<'tcx> for ty::AliasKind {
+impl<'tcx> Stable<'tcx> for ty::AliasTyKind {
     type T = stable_mir::ty::AliasKind;
     fn stable(&self, _: &mut Tables<'_>) -> Self::T {
         match self {
@@ -29,6 +29,14 @@ impl<'tcx> Stable<'tcx> for ty::AliasTy<'tcx> {
     }
 }
 
+impl<'tcx> Stable<'tcx> for ty::AliasTerm<'tcx> {
+    type T = stable_mir::ty::AliasTerm;
+    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+        let ty::AliasTerm { args, def_id, .. } = self;
+        stable_mir::ty::AliasTerm { def_id: tables.alias_def(*def_id), args: args.stable(tables) }
+    }
+}
+
 impl<'tcx> Stable<'tcx> for ty::DynKind {
     type T = stable_mir::ty::DynKind;
 
@@ -715,9 +723,9 @@ impl<'tcx> Stable<'tcx> for ty::ProjectionPredicate<'tcx> {
     type T = stable_mir::ty::ProjectionPredicate;
 
     fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
-        let ty::ProjectionPredicate { projection_ty, term } = self;
+        let ty::ProjectionPredicate { projection_term, term } = self;
         stable_mir::ty::ProjectionPredicate {
-            projection_ty: projection_ty.stable(tables),
+            projection_term: projection_term.stable(tables),
             term: term.unpack().stable(tables),
         }
     }
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 1de2ecbb700..9fb217d2f84 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -319,11 +319,10 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
             ty::Uint(UintTy::U64) => "y",
             ty::Uint(UintTy::U128) => "o",
             ty::Uint(UintTy::Usize) => "j",
-            // FIXME(f16_f128): update these once `rustc-demangle` supports the new types
-            ty::Float(FloatTy::F16) => unimplemented!("f16_f128"),
+            ty::Float(FloatTy::F16) => "C3f16",
             ty::Float(FloatTy::F32) => "f",
             ty::Float(FloatTy::F64) => "d",
-            ty::Float(FloatTy::F128) => unimplemented!("f16_f128"),
+            ty::Float(FloatTy::F128) => "C4f128",
             ty::Never => "z",
 
             // Placeholders (should be demangled as `_`).
diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs
index d667bad44e3..c5b2065080b 100644
--- a/compiler/rustc_target/src/spec/base/apple/mod.rs
+++ b/compiler/rustc_target/src/spec/base/apple/mod.rs
@@ -17,14 +17,9 @@ pub enum Arch {
     Arm64e,
     Arm64_32,
     I386,
-    I386_sim,
     I686,
     X86_64,
     X86_64h,
-    X86_64_sim,
-    X86_64_macabi,
-    Arm64_macabi,
-    Arm64_sim,
 }
 
 impl Arch {
@@ -32,12 +27,12 @@ impl Arch {
         match self {
             Armv7k => "armv7k",
             Armv7s => "armv7s",
-            Arm64 | Arm64_macabi | Arm64_sim => "arm64",
+            Arm64 => "arm64",
             Arm64e => "arm64e",
             Arm64_32 => "arm64_32",
-            I386 | I386_sim => "i386",
+            I386 => "i386",
             I686 => "i686",
-            X86_64 | X86_64_sim | X86_64_macabi => "x86_64",
+            X86_64 => "x86_64",
             X86_64h => "x86_64h",
         }
     }
@@ -45,61 +40,70 @@ impl Arch {
     pub fn target_arch(self) -> Cow<'static, str> {
         Cow::Borrowed(match self {
             Armv7k | Armv7s => "arm",
-            Arm64 | Arm64e | Arm64_32 | Arm64_macabi | Arm64_sim => "aarch64",
-            I386 | I386_sim | I686 => "x86",
-            X86_64 | X86_64_sim | X86_64_macabi | X86_64h => "x86_64",
+            Arm64 | Arm64e | Arm64_32 => "aarch64",
+            I386 | I686 => "x86",
+            X86_64 | X86_64h => "x86_64",
         })
     }
 
-    fn target_abi(self) -> &'static str {
-        match self {
-            Armv7k | Armv7s | Arm64 | Arm64e | Arm64_32 | I386 | I686 | X86_64 | X86_64h => "",
-            X86_64_macabi | Arm64_macabi => "macabi",
-            I386_sim | Arm64_sim | X86_64_sim => "sim",
-        }
-    }
-
-    fn target_cpu(self) -> &'static str {
+    fn target_cpu(self, abi: TargetAbi) -> &'static str {
         match self {
             Armv7k => "cortex-a8",
             Armv7s => "swift", // iOS 10 is only supported on iPhone 5 or higher.
-            Arm64 => "apple-a7",
+            Arm64 => match abi {
+                TargetAbi::Normal => "apple-a7",
+                TargetAbi::Simulator => "apple-a12",
+                TargetAbi::MacCatalyst => "apple-a12",
+            },
             Arm64e => "apple-a12",
             Arm64_32 => "apple-s4",
             // Only macOS 10.12+ is supported, which means
             // all x86_64/x86 CPUs must be running at least penryn
             // https://github.com/llvm/llvm-project/blob/01f924d0e37a5deae51df0d77e10a15b63aa0c0f/clang/lib/Driver/ToolChains/Arch/X86.cpp#L79-L82
-            I386 | I386_sim | I686 => "penryn",
-            X86_64 | X86_64_sim => "penryn",
-            X86_64_macabi => "penryn",
+            I386 | I686 => "penryn",
+            X86_64 => "penryn",
             // Note: `core-avx2` is slightly more advanced than `x86_64h`, see
             // comments (and disabled features) in `x86_64h_apple_darwin` for
             // details. It is a higher baseline then `penryn` however.
             X86_64h => "core-avx2",
-            Arm64_macabi => "apple-a12",
-            Arm64_sim => "apple-a12",
         }
     }
 
     fn stack_probes(self) -> StackProbeType {
         match self {
             Armv7k | Armv7s => StackProbeType::None,
-            Arm64 | Arm64e | Arm64_32 | I386 | I386_sim | I686 | X86_64 | X86_64h | X86_64_sim
-            | X86_64_macabi | Arm64_macabi | Arm64_sim => StackProbeType::Inline,
+            Arm64 | Arm64e | Arm64_32 | I386 | I686 | X86_64 | X86_64h => StackProbeType::Inline,
         }
     }
 }
 
-fn pre_link_args(os: &'static str, arch: Arch, abi: &'static str) -> LinkArgs {
+#[derive(Copy, Clone, PartialEq)]
+pub enum TargetAbi {
+    Normal,
+    Simulator,
+    MacCatalyst,
+}
+
+impl TargetAbi {
+    fn target_abi(self) -> &'static str {
+        match self {
+            Self::Normal => "",
+            Self::MacCatalyst => "macabi",
+            Self::Simulator => "sim",
+        }
+    }
+}
+
+fn pre_link_args(os: &'static str, arch: Arch, abi: TargetAbi) -> LinkArgs {
     let platform_name: StaticCow<str> = match abi {
-        "sim" => format!("{os}-simulator").into(),
-        "macabi" => "mac-catalyst".into(),
-        _ => os.into(),
+        TargetAbi::Normal => os.into(),
+        TargetAbi::Simulator => format!("{os}-simulator").into(),
+        TargetAbi::MacCatalyst => "mac-catalyst".into(),
     };
 
     let min_version: StaticCow<str> = {
         let (major, minor) = match os {
-            "ios" => ios_deployment_target(arch, abi),
+            "ios" => ios_deployment_target(arch, abi.target_abi()),
             "tvos" => tvos_deployment_target(),
             "watchos" => watchos_deployment_target(),
             "visionos" => visionos_deployment_target(),
@@ -119,7 +123,7 @@ fn pre_link_args(os: &'static str, arch: Arch, abi: &'static str) -> LinkArgs {
         LinkerFlavor::Darwin(Cc::No, Lld::No),
         [platform_name, min_version, sdk_version].into_iter(),
     );
-    if abi != "macabi" {
+    if abi != TargetAbi::MacCatalyst {
         add_link_args(
             &mut args,
             LinkerFlavor::Darwin(Cc::Yes, Lld::No),
@@ -136,13 +140,11 @@ fn pre_link_args(os: &'static str, arch: Arch, abi: &'static str) -> LinkArgs {
     args
 }
 
-pub fn opts(os: &'static str, arch: Arch) -> TargetOptions {
-    let abi = arch.target_abi();
-
+pub fn opts(os: &'static str, arch: Arch, abi: TargetAbi) -> TargetOptions {
     TargetOptions {
-        abi: abi.into(),
+        abi: abi.target_abi().into(),
         os: os.into(),
-        cpu: arch.target_cpu().into(),
+        cpu: arch.target_cpu(abi).into(),
         link_env_remove: link_env_remove(os),
         vendor: "apple".into(),
         linker_flavor: LinkerFlavor::Darwin(Cc::Yes, Lld::No),
@@ -263,8 +265,7 @@ fn from_set_deployment_target(var_name: &str) -> Option<(u32, u32)> {
 
 fn macos_default_deployment_target(arch: Arch) -> (u32, u32) {
     match arch {
-        // Note: Arm64_sim is not included since macOS has no simulator.
-        Arm64 | Arm64e | Arm64_macabi => (11, 0),
+        Arm64 | Arm64e => (11, 0),
         _ => (10, 12),
     }
 }
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 8307803676e..8ba945e193c 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -1774,6 +1774,9 @@ supported_targets! {
     ("aarch64-unknown-linux-ohos", aarch64_unknown_linux_ohos),
     ("armv7-unknown-linux-ohos", armv7_unknown_linux_ohos),
     ("x86_64-unknown-linux-ohos", x86_64_unknown_linux_ohos),
+
+    ("x86_64-unknown-linux-none", x86_64_unknown_linux_none),
+
 }
 
 /// Cow-Vec-Str: Cow<'static, [Cow<'static, str>]>
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
index c59c0ee8f7a..4e2964174f9 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
@@ -1,9 +1,9 @@
-use crate::spec::base::apple::{macos_llvm_target, opts, Arch};
+use crate::spec::base::apple::{macos_llvm_target, opts, Arch, TargetAbi};
 use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
 
 pub fn target() -> Target {
     let arch = Arch::Arm64;
-    let mut base = opts("macos", arch);
+    let mut base = opts("macos", arch, TargetAbi::Normal);
     base.cpu = "apple-m1".into();
     base.max_atomic_width = Some(128);
 
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs
index 4bbd9627738..20655689772 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs
@@ -1,9 +1,9 @@
-use crate::spec::base::apple::{ios_llvm_target, opts, Arch};
+use crate::spec::base::apple::{ios_llvm_target, opts, Arch, TargetAbi};
 use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
 
 pub fn target() -> Target {
     let arch = Arch::Arm64;
-    let mut base = opts("ios", arch);
+    let mut base = opts("ios", arch, TargetAbi::Normal);
     base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD;
 
     Target {
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs
index af413e892ce..4c008f7985e 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs
@@ -1,9 +1,9 @@
-use crate::spec::base::apple::{mac_catalyst_llvm_target, opts, Arch};
+use crate::spec::base::apple::{mac_catalyst_llvm_target, opts, Arch, TargetAbi};
 use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
 
 pub fn target() -> Target {
-    let arch = Arch::Arm64_macabi;
-    let mut base = opts("ios", arch);
+    let arch = Arch::Arm64;
+    let mut base = opts("ios", arch, TargetAbi::MacCatalyst);
     base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD;
 
     Target {
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs
index 2c1dd415150..4a63abdf541 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs
@@ -1,9 +1,9 @@
-use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch};
+use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch, TargetAbi};
 use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
 
 pub fn target() -> Target {
-    let arch = Arch::Arm64_sim;
-    let mut base = opts("ios", arch);
+    let arch = Arch::Arm64;
+    let mut base = opts("ios", arch, TargetAbi::Simulator);
     base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD;
 
     Target {
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs
index b5623c89835..3310e6c9e8a 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs
@@ -1,4 +1,4 @@
-use crate::spec::base::apple::{opts, tvos_llvm_target, Arch};
+use crate::spec::base::apple::{opts, tvos_llvm_target, Arch, TargetAbi};
 use crate::spec::{FramePointer, Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -18,7 +18,7 @@ pub fn target() -> Target {
             features: "+neon,+fp-armv8,+apple-a7".into(),
             max_atomic_width: Some(128),
             frame_pointer: FramePointer::NonLeaf,
-            ..opts("tvos", arch)
+            ..opts("tvos", arch, TargetAbi::Normal)
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs
index cf4bbb1082c..b901c663afa 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{opts, tvos_sim_llvm_target, Arch};
+use crate::spec::base::apple::{opts, tvos_sim_llvm_target, Arch, TargetAbi};
 use crate::spec::{FramePointer, Target, TargetOptions};
 
 pub fn target() -> Target {
-    let arch = Arch::Arm64_sim;
+    let arch = Arch::Arm64;
     Target {
         llvm_target: tvos_sim_llvm_target(arch).into(),
         metadata: crate::spec::TargetMetadata {
@@ -18,7 +18,7 @@ pub fn target() -> Target {
             features: "+neon,+fp-armv8,+apple-a7".into(),
             max_atomic_width: Some(128),
             frame_pointer: FramePointer::NonLeaf,
-            ..opts("tvos", arch)
+            ..opts("tvos", arch, TargetAbi::Simulator)
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs
index bacc4671f33..b0798e5e4f5 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs
@@ -1,9 +1,9 @@
-use crate::spec::base::apple::{opts, visionos_llvm_target, Arch};
+use crate::spec::base::apple::{opts, visionos_llvm_target, Arch, TargetAbi};
 use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
 
 pub fn target() -> Target {
     let arch = Arch::Arm64;
-    let mut base = opts("visionos", arch);
+    let mut base = opts("visionos", arch, TargetAbi::Normal);
     base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD;
 
     Target {
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs
index 99df73cb9df..7b2d2b6a8e4 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs
@@ -1,9 +1,9 @@
-use crate::spec::base::apple::{opts, visionos_sim_llvm_target, Arch};
+use crate::spec::base::apple::{opts, visionos_sim_llvm_target, Arch, TargetAbi};
 use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
 
 pub fn target() -> Target {
-    let arch = Arch::Arm64_sim;
-    let mut base = opts("visionos", arch);
+    let arch = Arch::Arm64;
+    let mut base = opts("visionos", arch, TargetAbi::Simulator);
     base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD;
 
     Target {
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs
index 3fbb7803f8c..a00a97a133f 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{opts, Arch};
+use crate::spec::base::apple::{opts, Arch, TargetAbi};
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
-    let base = opts("watchos", Arch::Arm64);
+    let base = opts("watchos", Arch::Arm64, TargetAbi::Normal);
     Target {
         llvm_target: "aarch64-apple-watchos".into(),
         metadata: crate::spec::TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs
index c13615b8b2a..e2f80b7b7a8 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{opts, watchos_sim_llvm_target, Arch};
+use crate::spec::base::apple::{opts, watchos_sim_llvm_target, Arch, TargetAbi};
 use crate::spec::{FramePointer, Target, TargetOptions};
 
 pub fn target() -> Target {
-    let arch = Arch::Arm64_sim;
+    let arch = Arch::Arm64;
     Target {
         // Clang automatically chooses a more specific target based on
         // WATCHOS_DEPLOYMENT_TARGET.
@@ -22,7 +22,7 @@ pub fn target() -> Target {
             features: "+neon,+fp-armv8,+apple-a7".into(),
             max_atomic_width: Some(128),
             frame_pointer: FramePointer::NonLeaf,
-            ..opts("watchos", arch)
+            ..opts("watchos", arch, TargetAbi::Simulator)
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs
index 38166a88ff3..3ca8c9969c2 100644
--- a/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs
@@ -1,9 +1,9 @@
-use crate::spec::base::apple::{opts, watchos_llvm_target, Arch};
+use crate::spec::base::apple::{opts, watchos_llvm_target, Arch, TargetAbi};
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
     let arch = Arch::Arm64_32;
-    let base = opts("watchos", arch);
+    let base = opts("watchos", arch, TargetAbi::Normal);
     Target {
         llvm_target: watchos_llvm_target(arch).into(),
         metadata: crate::spec::TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs
index cf69309e1c0..90be518638e 100644
--- a/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs
@@ -1,9 +1,9 @@
-use crate::spec::base::apple::{macos_llvm_target, opts, Arch};
+use crate::spec::base::apple::{macos_llvm_target, opts, Arch, TargetAbi};
 use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
 
 pub fn target() -> Target {
     let arch = Arch::Arm64e;
-    let mut base = opts("macos", arch);
+    let mut base = opts("macos", arch, TargetAbi::Normal);
     base.cpu = "apple-m1".into();
     base.max_atomic_width = Some(128);
 
diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs
index bff40745545..56470d29eae 100644
--- a/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs
@@ -1,9 +1,9 @@
-use crate::spec::base::apple::{ios_llvm_target, opts, Arch};
+use crate::spec::base::apple::{ios_llvm_target, opts, Arch, TargetAbi};
 use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
 
 pub fn target() -> Target {
     let arch = Arch::Arm64e;
-    let mut base = opts("ios", arch);
+    let mut base = opts("ios", arch, TargetAbi::Normal);
     base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD;
 
     Target {
diff --git a/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs
index 42ad9e0a35e..5c675c22ef5 100644
--- a/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs
@@ -1,4 +1,4 @@
-use crate::spec::base::apple::{opts, Arch};
+use crate::spec::base::apple::{opts, Arch, TargetAbi};
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -19,7 +19,7 @@ pub fn target() -> Target {
             max_atomic_width: Some(64),
             dynamic_linking: false,
             position_independent_executables: true,
-            ..opts("watchos", arch)
+            ..opts("watchos", arch, TargetAbi::Normal)
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs b/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs
index 40e5fc3f20d..4dd475e3a82 100644
--- a/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs
@@ -1,4 +1,4 @@
-use crate::spec::base::apple::{ios_llvm_target, opts, Arch};
+use crate::spec::base::apple::{ios_llvm_target, opts, Arch, TargetAbi};
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -17,7 +17,7 @@ pub fn target() -> Target {
         options: TargetOptions {
             features: "+v7,+vfp4,+neon".into(),
             max_atomic_width: Some(64),
-            ..opts("ios", arch)
+            ..opts("ios", arch, TargetAbi::Normal)
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs
index afa92ba99c6..c03a0974bc1 100644
--- a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs
@@ -1,10 +1,11 @@
-use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch};
+use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch, TargetAbi};
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
+    let arch = Arch::I386;
     // i386-apple-ios is a simulator target, even though it isn't declared
     // that way in the target name like the other ones...
-    let arch = Arch::I386_sim;
+    let abi = TargetAbi::Simulator;
     Target {
         // Clang automatically chooses a more specific target based on
         // IPHONEOS_DEPLOYMENT_TARGET.
@@ -22,6 +23,6 @@ pub fn target() -> Target {
             i128:128-f64:32:64-f80:128-n8:16:32-S128"
             .into(),
         arch: arch.target_arch(),
-        options: TargetOptions { max_atomic_width: Some(64), ..opts("ios", arch) },
+        options: TargetOptions { max_atomic_width: Some(64), ..opts("ios", arch, abi) },
     }
 }
diff --git a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
index 34a447a97ef..aea6a1ac4ec 100644
--- a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
@@ -1,10 +1,10 @@
-use crate::spec::base::apple::{macos_llvm_target, opts, Arch};
+use crate::spec::base::apple::{macos_llvm_target, opts, Arch, TargetAbi};
 use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, TargetOptions};
 
 pub fn target() -> Target {
     // ld64 only understands i386 and not i686
     let arch = Arch::I386;
-    let mut base = opts("macos", arch);
+    let mut base = opts("macos", arch, TargetAbi::Normal);
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m32"]);
     base.frame_pointer = FramePointer::Always;
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
index 1716c590aa5..21acd750df2 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
@@ -1,10 +1,10 @@
-use crate::spec::base::apple::{macos_llvm_target, opts, Arch};
+use crate::spec::base::apple::{macos_llvm_target, opts, Arch, TargetAbi};
 use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet};
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
     let arch = Arch::X86_64;
-    let mut base = opts("macos", arch);
+    let mut base = opts("macos", arch, TargetAbi::Normal);
     base.max_atomic_width = Some(128); // penryn+ supports cmpxchg16b
     base.frame_pointer = FramePointer::Always;
     base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]);
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs
index fa22c2907d2..ec61b796764 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs
@@ -1,11 +1,11 @@
-use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch};
+use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch, TargetAbi};
 use crate::spec::{SanitizerSet, Target, TargetOptions};
 
 pub fn target() -> Target {
+    let arch = Arch::X86_64;
     // x86_64-apple-ios is a simulator target, even though it isn't declared
     // that way in the target name like the other ones...
-    let arch = Arch::X86_64_sim;
-    let mut base = opts("ios", arch);
+    let mut base = opts("ios", arch, TargetAbi::Simulator);
     base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD;
 
     Target {
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs
index 9b479de8165..bd967ee972b 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs
@@ -1,9 +1,9 @@
-use crate::spec::base::apple::{mac_catalyst_llvm_target, opts, Arch};
+use crate::spec::base::apple::{mac_catalyst_llvm_target, opts, Arch, TargetAbi};
 use crate::spec::{SanitizerSet, Target, TargetOptions};
 
 pub fn target() -> Target {
-    let arch = Arch::X86_64_macabi;
-    let mut base = opts("ios", arch);
+    let arch = Arch::X86_64;
+    let mut base = opts("ios", arch, TargetAbi::MacCatalyst);
     base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD;
 
     Target {
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs
index f62d31c5166..55b2e1afcd3 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs
@@ -1,10 +1,11 @@
-use crate::spec::base::apple::{opts, tvos_sim_llvm_target, Arch};
+use crate::spec::base::apple::{opts, tvos_sim_llvm_target, Arch, TargetAbi};
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
+    let arch = Arch::X86_64;
     // x86_64-apple-tvos is a simulator target, even though it isn't declared
     // that way in the target name like the other ones...
-    let arch = Arch::X86_64_sim;
+    let abi = TargetAbi::Simulator;
     Target {
         llvm_target: tvos_sim_llvm_target(arch).into(),
         metadata: crate::spec::TargetMetadata {
@@ -17,6 +18,6 @@ pub fn target() -> Target {
         data_layout:
             "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
         arch: arch.target_arch(),
-        options: TargetOptions { max_atomic_width: Some(128), ..opts("tvos", arch) },
+        options: TargetOptions { max_atomic_width: Some(128), ..opts("tvos", arch, abi) },
     }
 }
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs
index 371aab8b508..a783eff15b2 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{opts, watchos_sim_llvm_target, Arch};
+use crate::spec::base::apple::{opts, watchos_sim_llvm_target, Arch, TargetAbi};
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
-    let arch = Arch::X86_64_sim;
+    let arch = Arch::X86_64;
     Target {
         llvm_target: watchos_sim_llvm_target(arch).into(),
         metadata: crate::spec::TargetMetadata {
@@ -15,6 +15,9 @@ pub fn target() -> Target {
         data_layout:
             "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
         arch: arch.target_arch(),
-        options: TargetOptions { max_atomic_width: Some(128), ..opts("watchos", arch) },
+        options: TargetOptions {
+            max_atomic_width: Some(128),
+            ..opts("watchos", arch, TargetAbi::Simulator)
+        },
     }
 }
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_none.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_none.rs
new file mode 100644
index 00000000000..b6e331bd854
--- /dev/null
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_none.rs
@@ -0,0 +1,25 @@
+use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target};
+
+pub fn target() -> Target {
+    let mut base = base::linux::opts();
+    base.cpu = "x86-64".into();
+    base.max_atomic_width = Some(64);
+    base.stack_probes = StackProbeType::Inline;
+    base.linker_flavor = LinkerFlavor::Gnu(Cc::No, Lld::Yes);
+    base.linker = Some("rust-lld".into());
+
+    Target {
+        llvm_target: "x86_64-unknown-linux-none".into(),
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
+        pointer_width: 64,
+        data_layout:
+            "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
+        arch: "x86_64".into(),
+        options: base,
+    }
+}
diff --git a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
index b17e21e5d12..fe6cbca32c7 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
@@ -1,10 +1,10 @@
-use crate::spec::base::apple::{macos_llvm_target, opts, Arch};
+use crate::spec::base::apple::{macos_llvm_target, opts, Arch, TargetAbi};
 use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet};
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
     let arch = Arch::X86_64h;
-    let mut base = opts("macos", arch);
+    let mut base = opts("macos", arch, TargetAbi::Normal);
     base.max_atomic_width = Some(128);
     base.frame_pointer = FramePointer::Always;
     base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]);
diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs
index f1f03b810a9..521e4ef0c9e 100644
--- a/compiler/rustc_trait_selection/src/lib.rs
+++ b/compiler/rustc_trait_selection/src/lib.rs
@@ -30,8 +30,6 @@
 
 #[macro_use]
 extern crate tracing;
-#[macro_use]
-extern crate rustc_middle;
 
 pub mod errors;
 pub mod infer;
diff --git a/compiler/rustc_trait_selection/src/solve/alias_relate.rs b/compiler/rustc_trait_selection/src/solve/alias_relate.rs
index f2c441dcbed..65cc0a45857 100644
--- a/compiler/rustc_trait_selection/src/solve/alias_relate.rs
+++ b/compiler/rustc_trait_selection/src/solve/alias_relate.rs
@@ -20,7 +20,7 @@ use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
 use rustc_middle::ty;
 
 impl<'tcx> EvalCtxt<'_, 'tcx> {
-    #[instrument(level = "debug", skip(self), ret)]
+    #[instrument(level = "trace", skip(self), ret)]
     pub(super) fn compute_alias_relate_goal(
         &mut self,
         goal: Goal<'tcx, (ty::Term<'tcx>, ty::Term<'tcx>, ty::AliasRelationDirection)>,
@@ -29,7 +29,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         let Goal { param_env, predicate: (lhs, rhs, direction) } = goal;
 
         // Structurally normalize the lhs.
-        let lhs = if let Some(alias) = lhs.to_alias_ty(self.tcx()) {
+        let lhs = if let Some(alias) = lhs.to_alias_term() {
             let term = self.next_term_infer_of_kind(lhs);
             self.add_normalizes_to_goal(goal.with(tcx, ty::NormalizesTo { alias, term }));
             term
@@ -38,7 +38,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         };
 
         // Structurally normalize the rhs.
-        let rhs = if let Some(alias) = rhs.to_alias_ty(self.tcx()) {
+        let rhs = if let Some(alias) = rhs.to_alias_term() {
             let term = self.next_term_infer_of_kind(rhs);
             self.add_normalizes_to_goal(goal.with(tcx, ty::NormalizesTo { alias, term }));
             term
@@ -50,13 +50,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         self.try_evaluate_added_goals()?;
         let lhs = self.resolve_vars_if_possible(lhs);
         let rhs = self.resolve_vars_if_possible(rhs);
-        debug!(?lhs, ?rhs);
+        trace!(?lhs, ?rhs);
 
         let variance = match direction {
             ty::AliasRelationDirection::Equate => ty::Variance::Invariant,
             ty::AliasRelationDirection::Subtype => ty::Variance::Covariant,
         };
-        match (lhs.to_alias_ty(tcx), rhs.to_alias_ty(tcx)) {
+        match (lhs.to_alias_term(), rhs.to_alias_term()) {
             (None, None) => {
                 self.relate(param_env, lhs, variance, rhs)?;
                 self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
index f2ca42a0be9..9a027d7f937 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
@@ -4,6 +4,7 @@ use crate::solve::GoalSource;
 use crate::solve::{inspect, EvalCtxt, SolverMode};
 use rustc_hir::def_id::DefId;
 use rustc_infer::traits::query::NoSolution;
+use rustc_middle::bug;
 use rustc_middle::traits::solve::inspect::ProbeKind;
 use rustc_middle::traits::solve::{
     CandidateSource, CanonicalResponse, Certainty, Goal, MaybeCause, QueryResult,
@@ -331,7 +332,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             .enter(|this| this.evaluate_added_goals_and_make_canonical_response(certainty))
     }
 
-    #[instrument(level = "debug", skip_all)]
+    #[instrument(level = "trace", skip_all)]
     fn assemble_non_blanket_impl_candidates<G: GoalKind<'tcx>>(
         &mut self,
         goal: Goal<'tcx, G>,
@@ -447,7 +448,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         }
     }
 
-    #[instrument(level = "debug", skip_all)]
+    #[instrument(level = "trace", skip_all)]
     fn assemble_blanket_impl_candidates<G: GoalKind<'tcx>>(
         &mut self,
         goal: Goal<'tcx, G>,
@@ -470,7 +471,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         }
     }
 
-    #[instrument(level = "debug", skip_all)]
+    #[instrument(level = "trace", skip_all)]
     fn assemble_builtin_impl_candidates<G: GoalKind<'tcx>>(
         &mut self,
         goal: Goal<'tcx, G>,
@@ -544,7 +545,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         }
     }
 
-    #[instrument(level = "debug", skip_all)]
+    #[instrument(level = "trace", skip_all)]
     fn assemble_param_env_candidates<G: GoalKind<'tcx>>(
         &mut self,
         goal: Goal<'tcx, G>,
@@ -561,7 +562,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         }
     }
 
-    #[instrument(level = "debug", skip_all)]
+    #[instrument(level = "trace", skip_all)]
     fn assemble_alias_bound_candidates<G: GoalKind<'tcx>>(
         &mut self,
         goal: Goal<'tcx, G>,
@@ -665,7 +666,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         }
     }
 
-    #[instrument(level = "debug", skip_all)]
+    #[instrument(level = "trace", skip_all)]
     fn assemble_object_bound_candidates<G: GoalKind<'tcx>>(
         &mut self,
         goal: Goal<'tcx, G>,
@@ -756,7 +757,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
     ///
     /// To do so we add an ambiguous candidate in case such an unknown impl could
     /// apply to the current goal.
-    #[instrument(level = "debug", skip_all)]
+    #[instrument(level = "trace", skip_all)]
     fn assemble_coherence_unknowable_candidates<G: GoalKind<'tcx>>(
         &mut self,
         goal: Goal<'tcx, G>,
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 a8b1a182d3c..9e844d78702 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
@@ -5,6 +5,7 @@ use rustc_hir::LangItem;
 use rustc_hir::{def_id::DefId, Movability, Mutability};
 use rustc_infer::traits::query::NoSolution;
 use rustc_macros::{TypeFoldable, TypeVisitable};
+use rustc_middle::bug;
 use rustc_middle::traits::solve::Goal;
 use rustc_middle::ty::{
     self, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
@@ -17,7 +18,7 @@ use crate::solve::EvalCtxt;
 //
 // For types with an "existential" binder, i.e. coroutine witnesses, we also
 // instantiate the binder with placeholders eagerly.
-#[instrument(level = "debug", skip(ecx), ret)]
+#[instrument(level = "trace", skip(ecx), ret)]
 pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
     ecx: &EvalCtxt<'_, 'tcx>,
     ty: Ty<'tcx>,
@@ -96,7 +97,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
     }
 }
 
-#[instrument(level = "debug", skip(ecx), ret)]
+#[instrument(level = "trace", skip(ecx), ret)]
 pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>(
     ecx: &EvalCtxt<'_, 'tcx>,
     ty: Ty<'tcx>,
@@ -160,7 +161,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>(
     }
 }
 
-#[instrument(level = "debug", skip(ecx), ret)]
+#[instrument(level = "trace", skip(ecx), ret)]
 pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
     ecx: &EvalCtxt<'_, 'tcx>,
     ty: Ty<'tcx>,
@@ -698,7 +699,7 @@ pub(in crate::solve) fn predicates_for_object_candidate<'tcx>(
                 old_ty,
                 None,
                 "{} has two generic parameters: {} and {}",
-                proj.projection_ty,
+                proj.projection_term,
                 proj.term,
                 old_ty.unwrap()
             );
@@ -739,7 +740,11 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceProjectionWith<'_, 'tcx> {
             // FIXME: Technically this equate could be fallible...
             self.nested.extend(
                 self.ecx
-                    .eq_and_get_goals(self.param_env, alias_ty, proj.projection_ty)
+                    .eq_and_get_goals(
+                        self.param_env,
+                        alias_ty,
+                        proj.projection_term.expect_ty(self.ecx.tcx()),
+                    )
                     .expect("expected to be able to unify goal projection with dyn's projection"),
             );
             proj.term.ty().unwrap()
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 d6010242e4c..2058650f288 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
@@ -22,6 +22,7 @@ use rustc_infer::infer::resolve::EagerResolver;
 use rustc_infer::infer::RegionVariableOrigin;
 use rustc_infer::infer::{InferCtxt, InferOk};
 use rustc_infer::traits::solve::NestedNormalizationGoals;
+use rustc_middle::bug;
 use rustc_middle::infer::canonical::Canonical;
 use rustc_middle::traits::query::NoSolution;
 use rustc_middle::traits::solve::{
@@ -83,7 +84,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
     ///   the values inferred while solving the instantiated goal.
     /// - `external_constraints`: additional constraints which aren't expressible
     ///   using simple unification of inference variables.
-    #[instrument(level = "debug", skip(self), ret)]
+    #[instrument(level = "trace", skip(self), ret)]
     pub(in crate::solve) fn evaluate_added_goals_and_make_canonical_response(
         &mut self,
         certainty: Certainty,
@@ -166,7 +167,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
     /// external constraints do not need to record that opaque, since if it is
     /// further constrained by inference, that will be passed back in the var
     /// values.
-    #[instrument(level = "debug", skip(self), ret)]
+    #[instrument(level = "trace", skip(self), ret)]
     fn compute_external_query_constraints(
         &self,
         normalization_nested_goals: NestedNormalizationGoals<'tcx>,
@@ -174,7 +175,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         // 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");
+            trace!(?e, "failed the leak check");
             NoSolution
         })?;
 
@@ -334,7 +335,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
     /// whether an alias is rigid by using the trait solver. When instantiating a response
     /// from the solver we assume that the solver correctly handled aliases and therefore
     /// always relate them structurally here.
-    #[instrument(level = "debug", skip(infcx))]
+    #[instrument(level = "trace", skip(infcx))]
     fn unify_query_var_values(
         infcx: &InferCtxt<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
@@ -407,7 +408,7 @@ pub(in crate::solve) fn make_canonical_state<'tcx, T: TypeFoldable<TyCtxt<'tcx>>
 /// This currently assumes that unifying the var values trivially succeeds.
 /// Adding any inference constraints which weren't present when originally
 /// computing the canonical query can result in bugs.
-#[instrument(level = "debug", skip(infcx, span, param_env))]
+#[instrument(level = "trace", skip(infcx, span, param_env))]
 pub(in crate::solve) fn instantiate_canonical_state<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
     infcx: &InferCtxt<'tcx>,
     span: Span,
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
index 9cd1841051d..e5d26e530ee 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
@@ -9,6 +9,7 @@ use rustc_infer::traits::query::NoSolution;
 use rustc_infer::traits::solve::{MaybeCause, NestedNormalizationGoals};
 use rustc_infer::traits::ObligationCause;
 use rustc_macros::{extension, HashStable};
+use rustc_middle::bug;
 use rustc_middle::infer::canonical::CanonicalVarInfos;
 use rustc_middle::traits::solve::inspect;
 use rustc_middle::traits::solve::{
@@ -458,7 +459,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
         }
     }
 
-    #[instrument(level = "debug", skip(self))]
+    #[instrument(level = "trace", skip(self))]
     pub(super) fn add_normalizes_to_goal(&mut self, goal: Goal<'tcx, ty::NormalizesTo<'tcx>>) {
         self.inspect.add_normalizes_to_goal(self.infcx, self.max_input_universe, goal);
         self.nested_goals.normalizes_to_goals.push(goal);
@@ -472,7 +473,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
 
     // Recursively evaluates all the goals added to this `EvalCtxt` to completion, returning
     // the certainty of all the goals.
-    #[instrument(level = "debug", skip(self))]
+    #[instrument(level = "trace", skip(self))]
     pub(super) fn try_evaluate_added_goals(&mut self) -> Result<Certainty, NoSolution> {
         self.inspect.start_evaluate_added_goals();
         let mut response = Ok(Certainty::overflow(false));
@@ -526,7 +527,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
                 unconstrained_goal,
             )?;
             // Add the nested goals from normalization to our own nested goals.
-            debug!(?nested_goals);
+            trace!(?nested_goals);
             goals.goals.extend(nested_goals);
 
             // Finally, equate the goal's RHS with the unconstrained var.
@@ -622,7 +623,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
     ///
     /// This is the case if the `term` does not occur in any other part of the predicate
     /// and is able to name all other placeholder and inference variables.
-    #[instrument(level = "debug", skip(self), ret)]
+    #[instrument(level = "trace", skip(self), ret)]
     pub(super) fn term_is_fully_unconstrained(
         &self,
         goal: Goal<'tcx, ty::NormalizesTo<'tcx>>,
@@ -718,7 +719,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             && goal.param_env.visit_with(&mut visitor).is_continue()
     }
 
-    #[instrument(level = "debug", skip(self, param_env), ret)]
+    #[instrument(level = "trace", skip(self, param_env), ret)]
     pub(super) fn eq<T: ToTrace<'tcx>>(
         &mut self,
         param_env: ty::ParamEnv<'tcx>,
@@ -733,7 +734,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
                 self.add_goals(GoalSource::Misc, obligations.into_iter().map(|o| o.into()));
             })
             .map_err(|e| {
-                debug!(?e, "failed to equate");
+                trace!(?e, "failed to equate");
                 NoSolution
             })
     }
@@ -743,11 +744,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
     /// Normally we emit a nested `AliasRelate` when equating an inference
     /// variable and an alias. This causes us to instead constrain the inference
     /// variable to the alias without emitting a nested alias relate goals.
-    #[instrument(level = "debug", skip(self, param_env), ret)]
+    #[instrument(level = "trace", skip(self, param_env), ret)]
     pub(super) fn relate_rigid_alias_non_alias(
         &mut self,
         param_env: ty::ParamEnv<'tcx>,
-        alias: ty::AliasTy<'tcx>,
+        alias: ty::AliasTerm<'tcx>,
         variance: ty::Variance,
         term: ty::Term<'tcx>,
     ) -> Result<(), NoSolution> {
@@ -764,13 +765,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             // Alternatively we could modify `Equate` for this case by adding another
             // variant to `StructurallyRelateAliases`.
             let identity_args = self.fresh_args_for_item(alias.def_id);
-            let rigid_ctor = ty::AliasTy::new(tcx, alias.def_id, identity_args);
-            let ctor_ty = rigid_ctor.to_ty(tcx);
+            let rigid_ctor = ty::AliasTerm::new(tcx, alias.def_id, identity_args);
+            let ctor_term = rigid_ctor.to_term(tcx);
             let InferOk { value: (), obligations } = self
                 .infcx
                 .at(&ObligationCause::dummy(), param_env)
-                .trace(term, ctor_ty.into())
-                .eq_structurally_relating_aliases(term, ctor_ty.into())?;
+                .trace(term, ctor_term)
+                .eq_structurally_relating_aliases(term, ctor_term)?;
             debug_assert!(obligations.is_empty());
             self.relate(param_env, alias, variance, rigid_ctor)
         } else {
@@ -781,7 +782,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
     /// This sohuld only be used when we're either instantiating a previously
     /// unconstrained "return value" or when we're sure that all aliases in
     /// the types are rigid.
-    #[instrument(level = "debug", skip(self, param_env), ret)]
+    #[instrument(level = "trace", skip(self, param_env), ret)]
     pub(super) fn eq_structurally_relating_aliases<T: ToTrace<'tcx>>(
         &mut self,
         param_env: ty::ParamEnv<'tcx>,
@@ -798,7 +799,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         Ok(())
     }
 
-    #[instrument(level = "debug", skip(self, param_env), ret)]
+    #[instrument(level = "trace", skip(self, param_env), ret)]
     pub(super) fn sub<T: ToTrace<'tcx>>(
         &mut self,
         param_env: ty::ParamEnv<'tcx>,
@@ -813,12 +814,12 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
                 self.add_goals(GoalSource::Misc, obligations.into_iter().map(|o| o.into()));
             })
             .map_err(|e| {
-                debug!(?e, "failed to subtype");
+                trace!(?e, "failed to subtype");
                 NoSolution
             })
     }
 
-    #[instrument(level = "debug", skip(self, param_env), ret)]
+    #[instrument(level = "trace", skip(self, param_env), ret)]
     pub(super) fn relate<T: ToTrace<'tcx>>(
         &mut self,
         param_env: ty::ParamEnv<'tcx>,
@@ -834,7 +835,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
                 self.add_goals(GoalSource::Misc, obligations.into_iter().map(|o| o.into()));
             })
             .map_err(|e| {
-                debug!(?e, "failed to relate");
+                trace!(?e, "failed to relate");
                 NoSolution
             })
     }
@@ -859,7 +860,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
                 obligations.into_iter().map(|o| o.into()).collect()
             })
             .map_err(|e| {
-                debug!(?e, "failed to equate");
+                trace!(?e, "failed to equate");
                 NoSolution
             })
     }
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs
index ee23f49939b..47109c8ad5d 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs
@@ -58,6 +58,7 @@ impl<'tcx, F> TraitProbeCtxt<'_, '_, 'tcx, F>
 where
     F: FnOnce(&QueryResult<'tcx>) -> inspect::ProbeKind<'tcx>,
 {
+    #[instrument(level = "debug", skip_all, fields(source = ?self.source))]
     pub(in crate::solve) fn enter(
         self,
         f: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> QueryResult<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
index 7efc951135b..6fda5f4af25 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
@@ -8,6 +8,7 @@ use rustc_infer::traits::{
     PolyTraitObligation, Selection, SelectionError, SelectionResult,
 };
 use rustc_macros::extension;
+use rustc_middle::{bug, span_bug};
 use rustc_span::Span;
 
 use crate::solve::inspect::{self, ProofTreeInferCtxtExt};
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
index 4cc041fca8c..3323f1bbf39 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -9,6 +9,7 @@ use rustc_infer::traits::{
     self, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, Obligation,
     ObligationCause, ObligationCauseCode, PredicateObligation, SelectionError, TraitEngine,
 };
+use rustc_middle::bug;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::symbol::sym;
@@ -119,7 +120,7 @@ impl<'tcx> FulfillmentCtxt<'tcx> {
 }
 
 impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
-    #[instrument(level = "debug", skip(self, infcx))]
+    #[instrument(level = "trace", skip(self, infcx))]
     fn register_predicate_obligation(
         &mut self,
         infcx: &InferCtxt<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/build.rs b/compiler/rustc_trait_selection/src/solve/inspect/build.rs
index 3c5505055a4..9dd681f09e7 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect/build.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect/build.rs
@@ -6,6 +6,7 @@
 use std::mem;
 
 use rustc_infer::infer::InferCtxt;
+use rustc_middle::bug;
 use rustc_middle::infer::canonical::CanonicalVarValues;
 use rustc_middle::traits::query::NoSolution;
 use rustc_middle::traits::solve::{
diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs
index b2b076e28e6..6c912db975a 100644
--- a/compiler/rustc_trait_selection/src/solve/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/mod.rs
@@ -17,6 +17,7 @@ use rustc_hir::def_id::DefId;
 use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues};
 use rustc_infer::traits::query::NoSolution;
 use rustc_macros::extension;
+use rustc_middle::bug;
 use rustc_middle::infer::canonical::CanonicalVarInfos;
 use rustc_middle::traits::solve::{
     CanonicalResponse, Certainty, ExternalConstraintsData, Goal, GoalSource, QueryResult, Response,
@@ -82,7 +83,7 @@ impl<'tcx> Canonical<'tcx, Response<'tcx>> {
 }
 
 impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
-    #[instrument(level = "debug", skip(self))]
+    #[instrument(level = "trace", skip(self))]
     fn compute_type_outlives_goal(
         &mut self,
         goal: Goal<'tcx, TypeOutlivesPredicate<'tcx>>,
@@ -92,7 +93,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
         self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
     }
 
-    #[instrument(level = "debug", skip(self))]
+    #[instrument(level = "trace", skip(self))]
     fn compute_region_outlives_goal(
         &mut self,
         goal: Goal<'tcx, RegionOutlivesPredicate<'tcx>>,
@@ -102,7 +103,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
         self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
     }
 
-    #[instrument(level = "debug", skip(self))]
+    #[instrument(level = "trace", skip(self))]
     fn compute_coerce_goal(
         &mut self,
         goal: Goal<'tcx, CoercePredicate<'tcx>>,
@@ -117,7 +118,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
         })
     }
 
-    #[instrument(level = "debug", skip(self))]
+    #[instrument(level = "trace", skip(self))]
     fn compute_subtype_goal(
         &mut self,
         goal: Goal<'tcx, SubtypePredicate<'tcx>>,
@@ -138,7 +139,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
         }
     }
 
-    #[instrument(level = "debug", skip(self))]
+    #[instrument(level = "trace", skip(self))]
     fn compute_well_formed_goal(
         &mut self,
         goal: Goal<'tcx, ty::GenericArg<'tcx>>,
@@ -152,7 +153,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
         }
     }
 
-    #[instrument(level = "debug", skip(self))]
+    #[instrument(level = "trace", skip(self))]
     fn compute_const_evaluatable_goal(
         &mut self,
         Goal { param_env, predicate: ct }: Goal<'tcx, ty::Const<'tcx>>,
@@ -189,7 +190,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
         }
     }
 
-    #[instrument(level = "debug", skip(self), ret)]
+    #[instrument(level = "trace", skip(self), ret)]
     fn compute_const_arg_has_type_goal(
         &mut self,
         goal: Goal<'tcx, (ty::Const<'tcx>, Ty<'tcx>)>,
@@ -201,7 +202,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
 }
 
 impl<'tcx> EvalCtxt<'_, 'tcx> {
-    #[instrument(level = "debug", skip(self, goals))]
+    #[instrument(level = "trace", skip(self, goals))]
     fn add_goals(
         &mut self,
         source: GoalSource,
@@ -215,7 +216,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
     /// Try to merge multiple possible ways to prove a goal, if that is not possible returns `None`.
     ///
     /// In this case we tend to flounder and return ambiguity by calling `[EvalCtxt::flounder]`.
-    #[instrument(level = "debug", skip(self), ret)]
+    #[instrument(level = "trace", skip(self), ret)]
     fn try_merge_responses(
         &mut self,
         responses: &[CanonicalResponse<'tcx>],
@@ -241,7 +242,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
     }
 
     /// If we fail to merge responses we flounder and return overflow or ambiguity.
-    #[instrument(level = "debug", skip(self), ret)]
+    #[instrument(level = "trace", skip(self), ret)]
     fn flounder(&mut self, responses: &[CanonicalResponse<'tcx>]) -> QueryResult<'tcx> {
         if responses.is_empty() {
             return Err(NoSolution);
@@ -263,7 +264,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
     /// This function is necessary in nearly all cases before matching on a type.
     /// Not doing so is likely to be incomplete and therefore unsound during
     /// coherence.
-    #[instrument(level = "debug", skip(self, param_env), ret)]
+    #[instrument(level = "trace", skip(self, param_env), ret)]
     fn structurally_normalize_ty(
         &mut self,
         param_env: ty::ParamEnv<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs
index cd1add9e0fa..5d5161e092e 100644
--- a/compiler/rustc_trait_selection/src/solve/normalize.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalize.rs
@@ -7,7 +7,7 @@ use rustc_infer::infer::InferCtxt;
 use rustc_infer::traits::TraitEngineExt;
 use rustc_infer::traits::{FulfillmentError, Obligation, TraitEngine};
 use rustc_middle::traits::ObligationCause;
-use rustc_middle::ty::{self, AliasTy, Ty, TyCtxt, UniverseIndex};
+use rustc_middle::ty::{self, Ty, TyCtxt, UniverseIndex};
 use rustc_middle::ty::{FallibleTypeFolder, TypeFolder, TypeSuperFoldable};
 use rustc_middle::ty::{TypeFoldable, TypeVisitableExt};
 
@@ -63,7 +63,7 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> {
             };
 
             self.at.infcx.err_ctxt().report_overflow_error(
-                OverflowCause::DeeplyNormalize(data),
+                OverflowCause::DeeplyNormalize(data.into()),
                 self.at.cause.span,
                 true,
                 |_| {},
@@ -108,7 +108,7 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> {
         let recursion_limit = tcx.recursion_limit();
         if !recursion_limit.value_within_limit(self.depth) {
             self.at.infcx.err_ctxt().report_overflow_error(
-                OverflowCause::DeeplyNormalize(ty::AliasTy::new(tcx, uv.def, uv.args)),
+                OverflowCause::DeeplyNormalize(uv.into()),
                 self.at.cause.span,
                 true,
                 |_| {},
@@ -122,10 +122,7 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> {
             tcx,
             self.at.cause.clone(),
             self.at.param_env,
-            ty::NormalizesTo {
-                alias: AliasTy::new(tcx, uv.def, uv.args),
-                term: new_infer_ct.into(),
-            },
+            ty::NormalizesTo { alias: uv.into(), term: new_infer_ct.into() },
         );
 
         let result = if infcx.predicate_may_hold(&obligation) {
@@ -162,7 +159,7 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for NormalizationFolder<'_, 'tcx> {
         Ok(t)
     }
 
-    #[instrument(level = "debug", skip(self), ret)]
+    #[instrument(level = "trace", skip(self), ret)]
     fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
         let infcx = self.at.infcx;
         debug_assert_eq!(ty, infcx.shallow_resolve(ty));
@@ -189,7 +186,7 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for NormalizationFolder<'_, 'tcx> {
         }
     }
 
-    #[instrument(level = "debug", skip(self), ret)]
+    #[instrument(level = "trace", skip(self), ret)]
     fn try_fold_const(&mut self, ct: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Self::Error> {
         let infcx = self.at.infcx;
         debug_assert_eq!(ct, infcx.shallow_resolve_const(ct));
diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/anon_const.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/anon_const.rs
index 37d56452893..94e078f5615 100644
--- a/compiler/rustc_trait_selection/src/solve/normalizes_to/anon_const.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/anon_const.rs
@@ -3,7 +3,7 @@ use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
 use rustc_middle::ty;
 
 impl<'tcx> EvalCtxt<'_, 'tcx> {
-    #[instrument(level = "debug", skip(self), ret)]
+    #[instrument(level = "trace", skip(self), ret)]
     pub(super) fn normalize_anon_const(
         &mut self,
         goal: Goal<'tcx, ty::NormalizesTo<'tcx>>,
diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/inherent.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/inherent.rs
index 439f9eec831..353bdb9caff 100644
--- a/compiler/rustc_trait_selection/src/solve/normalizes_to/inherent.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/inherent.rs
@@ -15,7 +15,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         goal: Goal<'tcx, ty::NormalizesTo<'tcx>>,
     ) -> QueryResult<'tcx> {
         let tcx = self.tcx();
-        let inherent = goal.predicate.alias;
+        let inherent = goal.predicate.alias.expect_ty(tcx);
 
         let impl_def_id = tcx.parent(inherent.def_id);
         let impl_args = self.fresh_args_for_item(impl_def_id);
diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
index 454c7a5f00f..6ec0ad9d29a 100644
--- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
@@ -17,6 +17,7 @@ use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
 use rustc_middle::ty::NormalizesTo;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::ty::{ToPredicate, TypeVisitableExt};
+use rustc_middle::{bug, span_bug};
 use rustc_span::{sym, ErrorGuaranteed, DUMMY_SP};
 
 mod anon_const;
@@ -25,7 +26,7 @@ mod opaque_types;
 mod weak_types;
 
 impl<'tcx> EvalCtxt<'_, 'tcx> {
-    #[instrument(level = "debug", skip(self), ret)]
+    #[instrument(level = "trace", skip(self), ret)]
     pub(super) fn compute_normalizes_to_goal(
         &mut self,
         goal: Goal<'tcx, NormalizesTo<'tcx>>,
@@ -40,26 +41,15 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             Ok(res) => Ok(res),
             Err(NoSolution) => {
                 let Goal { param_env, predicate: NormalizesTo { alias, term } } = goal;
-                if alias.opt_kind(self.tcx()).is_some() {
-                    self.relate_rigid_alias_non_alias(
-                        param_env,
-                        alias,
-                        ty::Variance::Invariant,
-                        term,
-                    )?;
-                    self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
-                } else {
-                    // FIXME(generic_const_exprs): we currently do not support rigid
-                    // unevaluated constants.
-                    Err(NoSolution)
-                }
+                self.relate_rigid_alias_non_alias(param_env, alias, ty::Variance::Invariant, term)?;
+                self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
             }
         }
     }
 
     /// Normalize the given alias by at least one step. If the alias is rigid, this
     /// returns `NoSolution`.
-    #[instrument(level = "debug", skip(self), ret)]
+    #[instrument(level = "trace", skip(self), ret)]
     fn normalize_at_least_one_step(
         &mut self,
         goal: Goal<'tcx, NormalizesTo<'tcx>>,
@@ -132,7 +122,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
                     ecx.eq(
                         goal.param_env,
                         goal.predicate.alias,
-                        assumption_projection_pred.projection_ty,
+                        assumption_projection_pred.projection_term,
                     )?;
 
                     ecx.instantiate_normalizes_to_term(goal, assumption_projection_pred.term);
@@ -373,7 +363,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
 
         let pred = tupled_inputs_and_output
             .map_bound(|(inputs, output)| ty::ProjectionPredicate {
-                projection_ty: ty::AliasTy::new(
+                projection_term: ty::AliasTerm::new(
                     tcx,
                     goal.predicate.def_id(),
                     [goal.predicate.self_ty(), inputs],
@@ -425,9 +415,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
                      output_coroutine_ty,
                      coroutine_return_ty,
                  }| {
-                    let (projection_ty, term) = match tcx.item_name(goal.predicate.def_id()) {
+                    let (projection_term, term) = match tcx.item_name(goal.predicate.def_id()) {
                         sym::CallOnceFuture => (
-                            ty::AliasTy::new(
+                            ty::AliasTerm::new(
                                 tcx,
                                 goal.predicate.def_id(),
                                 [goal.predicate.self_ty(), tupled_inputs_ty],
@@ -435,7 +425,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
                             output_coroutine_ty.into(),
                         ),
                         sym::CallRefFuture => (
-                            ty::AliasTy::new(
+                            ty::AliasTerm::new(
                                 tcx,
                                 goal.predicate.def_id(),
                                 [
@@ -447,7 +437,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
                             output_coroutine_ty.into(),
                         ),
                         sym::Output => (
-                            ty::AliasTy::new(
+                            ty::AliasTerm::new(
                                 tcx,
                                 goal.predicate.def_id(),
                                 [
@@ -459,7 +449,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
                         ),
                         name => bug!("no such associated type: {name}"),
                     };
-                    ty::ProjectionPredicate { projection_ty, term }
+                    ty::ProjectionPredicate { projection_term, term }
                 },
             )
             .to_predicate(tcx);
@@ -636,7 +626,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
             CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
             goal,
             ty::ProjectionPredicate {
-                projection_ty: ty::AliasTy::new(ecx.tcx(), goal.predicate.def_id(), [self_ty]),
+                projection_term: ty::AliasTerm::new(ecx.tcx(), goal.predicate.def_id(), [self_ty]),
                 term,
             }
             .to_predicate(tcx),
@@ -668,7 +658,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
             CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
             goal,
             ty::ProjectionPredicate {
-                projection_ty: ty::AliasTy::new(ecx.tcx(), goal.predicate.def_id(), [self_ty]),
+                projection_term: ty::AliasTerm::new(ecx.tcx(), goal.predicate.def_id(), [self_ty]),
                 term,
             }
             .to_predicate(tcx),
@@ -752,7 +742,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
             CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
             goal,
             ty::ProjectionPredicate {
-                projection_ty: ty::AliasTy::new(
+                projection_term: ty::AliasTerm::new(
                     ecx.tcx(),
                     goal.predicate.def_id(),
                     [self_ty, coroutine.resume_ty()],
@@ -897,7 +887,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
 ///
 /// FIXME: We should merge these 3 implementations as it's likely that they otherwise
 /// diverge.
-#[instrument(level = "debug", skip(ecx, param_env), ret)]
+#[instrument(level = "trace", skip(ecx, param_env), ret)]
 fn fetch_eligible_assoc_item_def<'tcx>(
     ecx: &EvalCtxt<'_, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
@@ -920,7 +910,7 @@ fn fetch_eligible_assoc_item_def<'tcx>(
             let poly_trait_ref = ecx.resolve_vars_if_possible(goal_trait_ref);
             !poly_trait_ref.still_further_specializable()
         } else {
-            debug!(?node_item.item.def_id, "not eligible due to default");
+            trace!(?node_item.item.def_id, "not eligible due to default");
             false
         }
     };
diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs
index 30ae385a8a0..0f1be1072a8 100644
--- a/compiler/rustc_trait_selection/src/solve/project_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs
@@ -5,25 +5,13 @@ use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
 use rustc_middle::ty::{self, ProjectionPredicate};
 
 impl<'tcx> EvalCtxt<'_, 'tcx> {
-    #[instrument(level = "debug", skip(self), ret)]
+    #[instrument(level = "trace", skip(self), ret)]
     pub(super) fn compute_projection_goal(
         &mut self,
         goal: Goal<'tcx, ProjectionPredicate<'tcx>>,
     ) -> QueryResult<'tcx> {
         let tcx = self.tcx();
-        let projection_term = match goal.predicate.term.unpack() {
-            ty::TermKind::Ty(_) => goal.predicate.projection_ty.to_ty(tcx).into(),
-            ty::TermKind::Const(_) => ty::Const::new_unevaluated(
-                tcx,
-                ty::UnevaluatedConst::new(
-                    goal.predicate.projection_ty.def_id,
-                    goal.predicate.projection_ty.args,
-                ),
-                tcx.type_of(goal.predicate.projection_ty.def_id)
-                    .instantiate(tcx, goal.predicate.projection_ty.args),
-            )
-            .into(),
-        };
+        let projection_term = goal.predicate.projection_term.to_term(tcx);
         let goal = goal.with(
             tcx,
             ty::PredicateKind::AliasRelate(
diff --git a/compiler/rustc_trait_selection/src/solve/search_graph.rs b/compiler/rustc_trait_selection/src/solve/search_graph.rs
index a48b2f2478b..60362aa01da 100644
--- a/compiler/rustc_trait_selection/src/solve/search_graph.rs
+++ b/compiler/rustc_trait_selection/src/solve/search_graph.rs
@@ -130,7 +130,7 @@ impl<'tcx> SearchGraph<'tcx> {
     }
 
     /// Update the stack and reached depths on cache hits.
-    #[instrument(level = "debug", skip(self))]
+    #[instrument(level = "trace", skip(self))]
     fn on_cache_hit(&mut self, additional_depth: usize, encountered_overflow: bool) {
         let reached_depth = self.stack.next_index().plus(additional_depth);
         if let Some(last) = self.stack.raw.last_mut() {
@@ -296,6 +296,7 @@ impl<'tcx> SearchGraph<'tcx> {
             }
 
             self.on_cache_hit(reached_depth, encountered_overflow);
+            debug!("global cache hit");
             return result;
         }
 
@@ -315,6 +316,7 @@ impl<'tcx> SearchGraph<'tcx> {
                     .filter(|p| !Self::stack_coinductive_from(tcx, &self.stack, p.head))
             })
         {
+            debug!("provisional cache hit");
             // We have a nested goal which is already in the provisional cache, use
             // its result. We do not provide any usage kind as that should have been
             // already set correctly while computing the cache entry.
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index 083cc0aa3c2..1cafa970b68 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -10,6 +10,7 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::{LangItem, Movability};
 use rustc_infer::traits::query::NoSolution;
 use rustc_infer::traits::solve::MaybeCause;
+use rustc_middle::bug;
 use rustc_middle::traits::solve::inspect::ProbeKind;
 use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal, QueryResult};
 use rustc_middle::traits::{BuiltinImplSource, Reveal};
@@ -1130,7 +1131,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
                     },
                 );
                 if let Some(def_id) = disqualifying_impl {
-                    debug!(?def_id, ?goal, "disqualified auto-trait implementation");
+                    trace!(?def_id, ?goal, "disqualified auto-trait implementation");
                     // No need to actually consider the candidate here,
                     // since we do that in `consider_impl_candidate`.
                     return Some(Err(NoSolution));
@@ -1171,7 +1172,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         })
     }
 
-    #[instrument(level = "debug", skip(self))]
+    #[instrument(level = "trace", skip(self))]
     pub(super) fn compute_trait_goal(
         &mut self,
         goal: Goal<'tcx, TraitPredicate<'tcx>>,
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index 053de2c673b..60562acfe93 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -540,11 +540,11 @@ impl<'tcx> AutoTraitFinder<'tcx> {
         finished_map
     }
 
-    fn is_param_no_infer(&self, args: GenericArgsRef<'_>) -> bool {
+    fn is_param_no_infer(&self, args: GenericArgsRef<'tcx>) -> bool {
         self.is_of_param(args.type_at(0)) && !args.types().any(|t| t.has_infer_types())
     }
 
-    pub fn is_of_param(&self, ty: Ty<'_>) -> bool {
+    pub fn is_of_param(&self, ty: Ty<'tcx>) -> bool {
         match ty.kind() {
             ty::Param(_) => true,
             ty::Alias(ty::Projection, p) => self.is_of_param(p.self_ty()),
@@ -552,9 +552,9 @@ impl<'tcx> AutoTraitFinder<'tcx> {
         }
     }
 
-    fn is_self_referential_projection(&self, p: ty::PolyProjectionPredicate<'_>) -> bool {
+    fn is_self_referential_projection(&self, p: ty::PolyProjectionPredicate<'tcx>) -> bool {
         if let Some(ty) = p.term().skip_binder().ty() {
-            matches!(ty.kind(), ty::Alias(ty::Projection, proj) if proj == &p.skip_binder().projection_ty)
+            matches!(ty.kind(), ty::Alias(ty::Projection, proj) if proj == &p.skip_binder().projection_term.expect_ty(self.tcx))
         } else {
             false
         }
@@ -612,7 +612,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
                     // an inference variable.
                     // Additionally, we check if we've seen this predicate before,
                     // to avoid rendering duplicate bounds to the user.
-                    if self.is_param_no_infer(p.skip_binder().projection_ty.args)
+                    if self.is_param_no_infer(p.skip_binder().projection_term.args)
                         && !p.term().skip_binder().has_infer_types()
                         && is_new_pred
                     {
@@ -684,7 +684,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
                     // and turn them into an explicit negative impl for our type.
                     debug!("Projecting and unifying projection predicate {:?}", predicate);
 
-                    match project::poly_project_and_unify_type(selcx, &obligation.with(self.tcx, p))
+                    match project::poly_project_and_unify_term(selcx, &obligation.with(self.tcx, p))
                     {
                         ProjectAndUnifyResult::MismatchedProjectionTypes(e) => {
                             debug!(
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index 59725ce9de0..ebdb032dc0e 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -20,6 +20,7 @@ use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, TyCtxtInferExt};
 use rustc_infer::traits::{util, FulfillmentErrorCode};
+use rustc_middle::bug;
 use rustc_middle::traits::query::NoSolution;
 use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal};
 use rustc_middle::traits::specialization_graph::OverlapMode;
@@ -1095,11 +1096,11 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> {
             Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr))) => tr.trait_ref,
             Some(ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)))
                 if matches!(
-                    infcx.tcx.def_kind(proj.projection_ty.def_id),
+                    infcx.tcx.def_kind(proj.projection_term.def_id),
                     DefKind::AssocTy | DefKind::AssocConst
                 ) =>
             {
-                proj.projection_ty.trait_ref(infcx.tcx)
+                proj.projection_term.trait_ref(infcx.tcx)
             }
             _ => return,
         };
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index a8be5627fed..8348482386f 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -11,6 +11,7 @@
 
 use rustc_hir::def::DefKind;
 use rustc_infer::infer::InferCtxt;
+use rustc_middle::bug;
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::abstract_const::NotConstEvaluatable;
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
index 040ce450aaf..7fc94b31b3b 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
@@ -10,6 +10,7 @@ use rustc_errors::{codes::*, struct_span_code_err, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_macros::{extension, LintDiagnostic};
+use rustc_middle::bug;
 use rustc_middle::ty::print::PrintTraitRefExt as _;
 use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt};
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 597effcbbf0..86610855441 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -34,6 +34,7 @@ use rustc_middle::ty::{
     InferTy, IsSuggestable, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
     TypeVisitableExt, TypeckResults,
 };
+use rustc_middle::{bug, span_bug};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{BytePos, DesugaringKind, ExpnKind, MacroKind, Span, DUMMY_SP};
@@ -45,7 +46,9 @@ use std::iter;
 use crate::infer::InferCtxtExt as _;
 use crate::traits::error_reporting::type_err_ctxt_ext::InferCtxtPrivExt;
 use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
-use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths};
+use rustc_middle::ty::print::{
+    with_forced_trimmed_paths, with_no_trimmed_paths, PrintTraitPredicateExt as _,
+};
 
 use itertools::EitherOrBoth;
 use itertools::Itertools;
@@ -1102,9 +1105,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                             .iter()
                             .find_map(|pred| {
                                 if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder()
-                        && Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output()
+                        && Some(proj.projection_term.def_id) == self.tcx.lang_items().fn_once_output()
                         // args tuple will always be args[1]
-                        && let ty::Tuple(args) = proj.projection_ty.args.type_at(1).kind()
+                        && let ty::Tuple(args) = proj.projection_term.args.type_at(1).kind()
                                 {
                                     Some((
                                         DefIdOrName::DefId(def_id),
@@ -1146,10 +1149,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                         };
                         param_env.caller_bounds().iter().find_map(|pred| {
                             if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder()
-                        && Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output()
-                        && proj.projection_ty.self_ty() == found
+                        && Some(proj.projection_term.def_id) == self.tcx.lang_items().fn_once_output()
+                        && proj.projection_term.self_ty() == found
                         // args tuple will always be args[1]
-                        && let ty::Tuple(args) = proj.projection_ty.args.type_at(1).kind()
+                        && let ty::Tuple(args) = proj.projection_term.args.type_at(1).kind()
                             {
                                 Some((
                                     name,
@@ -1205,8 +1208,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
 
         let code = match obligation.cause.code() {
             ObligationCauseCode::FunctionArg { parent_code, .. } => parent_code,
-            c @ ObligationCauseCode::WhereClause(_)
-            | c @ ObligationCauseCode::WhereClauseInExpr(..) => c,
+            // FIXME(compiler-errors): This is kind of a mess, but required for obligations
+            // that come from a path expr to affect the *call* expr.
+            c @ ObligationCauseCode::WhereClauseInExpr(_, _, hir_id, _)
+                if self.tcx.hir().span(*hir_id).lo() == span.lo() =>
+            {
+                c
+            }
             c if matches!(
                 span.ctxt().outer_expn_data().kind,
                 ExpnKind::Desugaring(DesugaringKind::ForLoop)
@@ -1262,8 +1270,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             let mut_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_mut_ref);
 
             let (ref_inner_ty_satisfies_pred, ref_inner_ty_mut) =
-                if let ObligationCauseCode::WhereClause(_)
-                | ObligationCauseCode::WhereClauseInExpr(..) = obligation.cause.code()
+                if let ObligationCauseCode::WhereClauseInExpr(..) = obligation.cause.code()
                     && let ty::Ref(_, ty, mutability) = old_pred.self_ty().skip_binder().kind()
                 {
                     (
@@ -1403,10 +1410,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
 
         if let ObligationCauseCode::ImplDerived(cause) = &*code {
             try_borrowing(cause.derived.parent_trait_pred, &[])
-        } else if let ObligationCauseCode::SpannedWhereClause(_, _)
-        | ObligationCauseCode::WhereClause(_)
-        | ObligationCauseCode::WhereClauseInExpr(..)
-        | ObligationCauseCode::SpannedWhereClauseInExpr(..) = code
+        } else if let ObligationCauseCode::WhereClause(..)
+        | ObligationCauseCode::WhereClauseInExpr(..) = code
         {
             try_borrowing(poly_trait_pred, &never_suggest_borrow)
         } else {
@@ -2102,10 +2107,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         cause: &ObligationCauseCode<'tcx>,
         err: &mut Diag<'tcx>,
     ) {
-        // First, look for an `SpannedWhereClauseInExpr`, which means we can get
+        // First, look for an `WhereClauseInExpr`, which means we can get
         // the uninstantiated predicate list of the called function. And check
         // that the predicate that we failed to satisfy is a `Fn`-like trait.
-        if let ObligationCauseCode::SpannedWhereClauseInExpr(def_id, _, _, idx) = cause
+        if let ObligationCauseCode::WhereClauseInExpr(def_id, _, _, idx) = cause
             && let predicates = self.tcx.predicates_of(def_id).instantiate_identity(self.tcx)
             && let Some(pred) = predicates.predicates.get(*idx)
             && let ty::ClauseKind::Trait(trait_pred) = pred.kind().skip_binder()
@@ -2746,12 +2751,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             ObligationCauseCode::TupleElem => {
                 err.note("only the last element of a tuple may have a dynamically sized type");
             }
-            ObligationCauseCode::WhereClause(_) | ObligationCauseCode::WhereClauseInExpr(..) => {
-                // We hold the `DefId` of the item introducing the obligation, but displaying it
-                // doesn't add user usable information. It always point at an associated item.
-            }
-            ObligationCauseCode::SpannedWhereClause(item_def_id, span)
-            | ObligationCauseCode::SpannedWhereClauseInExpr(item_def_id, span, ..) => {
+            ObligationCauseCode::WhereClause(item_def_id, span)
+            | ObligationCauseCode::WhereClauseInExpr(item_def_id, span, ..)
+                if !span.is_dummy() =>
+            {
                 let item_name = tcx.def_path_str(item_def_id);
                 let short_item_name = with_forced_trimmed_paths!(tcx.def_path_str(item_def_id));
                 let mut multispan = MultiSpan::from(span);
@@ -2882,6 +2885,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     err.help(help);
                 }
             }
+            ObligationCauseCode::WhereClause(..) | ObligationCauseCode::WhereClauseInExpr(..) => {
+                // We hold the `DefId` of the item introducing the obligation, but displaying it
+                // doesn't add user usable information. It always point at an associated item.
+            }
             ObligationCauseCode::Coercion { source, target } => {
                 let source =
                     tcx.short_ty_string(self.resolve_vars_if_possible(source), &mut long_ty_file);
@@ -3802,7 +3809,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             // to an associated type (as seen from `trait_pred`) in the predicate. Like in
             // trait_pred `S: Sum<<Self as Iterator>::Item>` and predicate `i32: Sum<&()>`
             let mut type_diffs = vec![];
-            if let ObligationCauseCode::SpannedWhereClauseInExpr(def_id, _, _, idx) = parent_code
+            if let ObligationCauseCode::WhereClauseInExpr(def_id, _, _, idx) = parent_code
                 && let Some(node_args) = typeck_results.node_args_opt(call_hir_id)
                 && let where_clauses =
                     self.tcx.predicates_of(def_id).instantiate(self.tcx, node_args)
@@ -3839,11 +3846,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     && let Some(found) = failed_pred.skip_binder().term.ty()
                 {
                     type_diffs = vec![Sorts(ty::error::ExpectedFound {
-                        expected: Ty::new_alias(
-                            self.tcx,
-                            ty::Projection,
-                            where_pred.skip_binder().projection_ty,
-                        ),
+                        expected: where_pred
+                            .skip_binder()
+                            .projection_term
+                            .expect_ty(self.tcx)
+                            .to_ty(self.tcx),
                         found,
                     })];
                 }
@@ -4268,7 +4275,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             // This corresponds to `<ExprTy as Iterator>::Item = _`.
             let projection = ty::Binder::dummy(ty::PredicateKind::Clause(
                 ty::ClauseKind::Projection(ty::ProjectionPredicate {
-                    projection_ty: ty::AliasTy::new(self.tcx, proj.def_id, args),
+                    projection_term: ty::AliasTerm::new(self.tcx, proj.def_id, args),
                     term: ty.into(),
                 }),
             ));
@@ -4965,7 +4972,7 @@ fn point_at_assoc_type_restriction<G: EmissionGuarantee>(
     let ty::ClauseKind::Projection(proj) = clause else {
         return;
     };
-    let name = tcx.item_name(proj.projection_ty.def_id);
+    let name = tcx.item_name(proj.projection_term.def_id);
     let mut predicates = generics.predicates.iter().peekable();
     let mut prev: Option<&hir::WhereBoundPredicate<'_>> = None;
     while let Some(pred) = predicates.next() {
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
index cdde12af8ea..f9824acdae0 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
@@ -38,12 +38,14 @@ use rustc_middle::ty::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::fold::{BottomUpFolder, TypeFolder, TypeSuperFoldable};
 use rustc_middle::ty::print::{
-    with_forced_trimmed_paths, FmtPrinter, Print, PrintTraitRefExt as _,
+    with_forced_trimmed_paths, FmtPrinter, Print, PrintTraitPredicateExt as _,
+    PrintTraitRefExt as _,
 };
 use rustc_middle::ty::{
     self, SubtypePredicate, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable,
     TypeVisitable, TypeVisitableExt,
 };
+use rustc_middle::{bug, span_bug};
 use rustc_session::config::DumpSolverProofTree;
 use rustc_session::Limit;
 use rustc_span::def_id::LOCAL_CRATE;
@@ -61,7 +63,7 @@ use super::{
 pub use rustc_infer::traits::error_reporting::*;
 
 pub enum OverflowCause<'tcx> {
-    DeeplyNormalize(ty::AliasTy<'tcx>),
+    DeeplyNormalize(ty::AliasTerm<'tcx>),
     TraitSolver(ty::Predicate<'tcx>),
 }
 
@@ -245,10 +247,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         }
 
         let mut err = match cause {
-            OverflowCause::DeeplyNormalize(alias_ty) => {
-                let alias_ty = self.resolve_vars_if_possible(alias_ty);
-                let kind = alias_ty.opt_kind(self.tcx).map_or("alias", |k| k.descr());
-                let alias_str = with_short_path(self.tcx, alias_ty);
+            OverflowCause::DeeplyNormalize(alias_term) => {
+                let alias_term = self.resolve_vars_if_possible(alias_term);
+                let kind = alias_term.kind(self.tcx).descr();
+                let alias_str = with_short_path(self.tcx, alias_term);
                 struct_span_code_err!(
                     self.dcx(),
                     span,
@@ -1467,7 +1469,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         );
 
         let param_env = ty::ParamEnv::empty();
-        self.can_eq(param_env, goal.projection_ty, assumption.projection_ty)
+        self.can_eq(param_env, goal.projection_term, assumption.projection_term)
             && self.can_eq(param_env, goal.term, assumption.term)
     }
 
@@ -1535,9 +1537,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     *err,
                 );
                 let code = error.obligation.cause.code().peel_derives().peel_match_impls();
-                if let ObligationCauseCode::SpannedWhereClause(..)
-                | ObligationCauseCode::WhereClause(..)
-                | ObligationCauseCode::SpannedWhereClauseInExpr(..)
+                if let ObligationCauseCode::WhereClause(..)
                 | ObligationCauseCode::WhereClauseInExpr(..) = code
                 {
                     self.note_obligation_cause_code(
@@ -1584,23 +1584,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     infer::BoundRegionConversionTime::HigherRankedType,
                     bound_predicate.rebind(data),
                 );
-                let unnormalized_term = match data.term.unpack() {
-                    ty::TermKind::Ty(_) => Ty::new_projection(
-                        self.tcx,
-                        data.projection_ty.def_id,
-                        data.projection_ty.args,
-                    )
-                    .into(),
-                    ty::TermKind::Const(ct) => ty::Const::new_unevaluated(
-                        self.tcx,
-                        ty::UnevaluatedConst {
-                            def: data.projection_ty.def_id,
-                            args: data.projection_ty.args,
-                        },
-                        ct.ty(),
-                    )
-                    .into(),
-                };
+                let unnormalized_term = data.projection_term.to_term(self.tcx);
                 // FIXME(-Znext-solver): For diagnostic purposes, it would be nice
                 // to deeply normalize this type.
                 let normalized_term =
@@ -1612,11 +1596,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
 
                 let is_normalized_term_expected = !matches!(
                     obligation.cause.code().peel_derives(),
-                    ObligationCauseCode::WhereClause(_)
-                        | ObligationCauseCode::SpannedWhereClause(_, _)
-                        | ObligationCauseCode::WhereClauseInExpr(..)
-                        | ObligationCauseCode::SpannedWhereClauseInExpr(..)
-                        | ObligationCauseCode::Coercion { .. }
+                    |ObligationCauseCode::WhereClause(..)| ObligationCauseCode::WhereClauseInExpr(
+                        ..
+                    ) | ObligationCauseCode::Coercion { .. }
                 );
 
                 let (expected, actual) = if is_normalized_term_expected {
@@ -1667,13 +1649,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     return None;
                 };
 
-                let trait_assoc_item = self.tcx.opt_associated_item(proj.projection_ty.def_id)?;
+                let trait_assoc_item = self.tcx.opt_associated_item(proj.projection_term.def_id)?;
                 let trait_assoc_ident = trait_assoc_item.ident(self.tcx);
 
                 let mut associated_items = vec![];
                 self.tcx.for_each_relevant_impl(
-                    self.tcx.trait_of_item(proj.projection_ty.def_id)?,
-                    proj.projection_ty.self_ty(),
+                    self.tcx.trait_of_item(proj.projection_term.def_id)?,
+                    proj.projection_term.self_ty(),
                     |impl_def_id| {
                         associated_items.extend(
                             self.tcx
@@ -1742,11 +1724,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         normalized_ty: ty::Term<'tcx>,
         expected_ty: ty::Term<'tcx>,
     ) -> Option<String> {
-        let trait_def_id = pred.projection_ty.trait_def_id(self.tcx);
-        let self_ty = pred.projection_ty.self_ty();
+        let trait_def_id = pred.projection_term.trait_def_id(self.tcx);
+        let self_ty = pred.projection_term.self_ty();
 
         with_forced_trimmed_paths! {
-            if Some(pred.projection_ty.def_id) == self.tcx.lang_items().fn_once_output() {
+            if Some(pred.projection_term.def_id) == self.tcx.lang_items().fn_once_output() {
                 let fn_kind = self_ty.prefix_string(self.tcx);
                 let item = match self_ty.kind() {
                     ty::FnDef(def, _) => self.tcx.item_name(*def).to_string(),
@@ -2447,7 +2429,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     }
                 }
 
-                if let ObligationCauseCode::WhereClause(def_id)
+                if let ObligationCauseCode::WhereClause(def_id, _)
                 | ObligationCauseCode::WhereClauseInExpr(def_id, ..) = *obligation.cause.code()
                 {
                     self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
@@ -2625,14 +2607,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 }
 
                 if let Err(guar) =
-                    self.tcx.ensure().coherent_trait(self.tcx.parent(data.projection_ty.def_id))
+                    self.tcx.ensure().coherent_trait(self.tcx.parent(data.projection_term.def_id))
                 {
                     // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case
                     // other `Foo` impls are incoherent.
                     return guar;
                 }
                 let arg = data
-                    .projection_ty
+                    .projection_term
                     .args
                     .iter()
                     .chain(Some(data.term.into_arg()))
@@ -2883,12 +2865,15 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         else {
             return;
         };
-        let (ObligationCauseCode::SpannedWhereClause(item_def_id, span)
-        | ObligationCauseCode::SpannedWhereClauseInExpr(item_def_id, span, ..)) =
+        let (ObligationCauseCode::WhereClause(item_def_id, span)
+        | ObligationCauseCode::WhereClauseInExpr(item_def_id, span, ..)) =
             *obligation.cause.code().peel_derives()
         else {
             return;
         };
+        if span.is_dummy() {
+            return;
+        }
         debug!(?pred, ?item_def_id, ?span);
 
         let (Some(node), true) = (
@@ -3181,10 +3166,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             ObligationCauseCode::RustCall => {
                 err.primary_message("functions with the \"rust-call\" ABI must take a single non-self tuple argument");
             }
-            ObligationCauseCode::SpannedWhereClause(def_id, _)
-            | ObligationCauseCode::WhereClause(def_id)
-                if self.tcx.is_fn_trait(*def_id) =>
-            {
+            ObligationCauseCode::WhereClause(def_id, _) if self.tcx.is_fn_trait(*def_id) => {
                 err.code(E0059);
                 err.primary_message(format!(
                     "type parameter to bare `{}` trait must be a tuple",
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index e3497c646db..07fcf109fda 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -8,6 +8,7 @@ use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProce
 use rustc_infer::infer::DefineOpaqueTypes;
 use rustc_infer::traits::ProjectionCacheKey;
 use rustc_infer::traits::{PolyTraitObligation, SelectionError, TraitEngine};
+use rustc_middle::bug;
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::ty::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
@@ -770,13 +771,13 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
             }
         }
 
-        match project::poly_project_and_unify_type(&mut self.selcx, &project_obligation) {
+        match project::poly_project_and_unify_term(&mut self.selcx, &project_obligation) {
             ProjectAndUnifyResult::Holds(os) => ProcessResult::Changed(mk_pending(os)),
             ProjectAndUnifyResult::FailedNormalization => {
                 stalled_on.clear();
                 stalled_on.extend(args_infer_vars(
                     &self.selcx,
-                    project_obligation.predicate.map_bound(|pred| pred.projection_ty.args),
+                    project_obligation.predicate.map_bound(|pred| pred.projection_term.args),
                 ));
                 ProcessResult::Unchanged
             }
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 56f8b4b9cdb..61f47bc1f23 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -31,6 +31,7 @@ use crate::traits::error_reporting::TypeErrCtxtExt as _;
 use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
 use rustc_errors::ErrorGuaranteed;
 use rustc_middle::query::Providers;
+use rustc_middle::span_bug;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
 use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFolder, TypeSuperVisitable};
@@ -51,7 +52,7 @@ pub use self::object_safety::hir_ty_lowering_object_safety_violations;
 pub use self::object_safety::is_vtable_safe_method;
 pub use self::object_safety::object_safety_violations_for_assoc_item;
 pub use self::object_safety::ObjectSafetyViolation;
-pub use self::project::{normalize_inherent_projection, normalize_projection_type};
+pub use self::project::{normalize_inherent_projection, normalize_projection_ty};
 pub use self::select::{EvaluationCache, SelectionCache, SelectionContext};
 pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError};
 pub use self::specialize::specialization_graph::FutureCompatOverlapError;
diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs
index 43f4fa8e81c..d10aee2d4e2 100644
--- a/compiler/rustc_trait_selection/src/traits/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/normalize.rs
@@ -213,7 +213,7 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
                         let recursion_limit = self.interner().recursion_limit();
                         if !recursion_limit.value_within_limit(self.depth) {
                             self.selcx.infcx.err_ctxt().report_overflow_error(
-                                OverflowCause::DeeplyNormalize(data),
+                                OverflowCause::DeeplyNormalize(data.into()),
                                 self.cause.span,
                                 true,
                                 |_| {},
@@ -238,7 +238,7 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
                 // register an obligation to *later* project, since we know
                 // there won't be bound vars there.
                 let data = data.fold_with(self);
-                let normalized_ty = project::normalize_projection_type(
+                let normalized_ty = project::normalize_projection_ty(
                     self.selcx,
                     self.param_env,
                     data,
@@ -273,10 +273,10 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
                 let (data, mapped_regions, mapped_types, mapped_consts) =
                     BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data);
                 let data = data.fold_with(self);
-                let normalized_ty = project::opt_normalize_projection_type(
+                let normalized_ty = project::opt_normalize_projection_term(
                     self.selcx,
                     self.param_env,
-                    data,
+                    data.into(),
                     self.cause.clone(),
                     self.depth,
                     self.obligations,
@@ -309,7 +309,7 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
                 let recursion_limit = self.interner().recursion_limit();
                 if !recursion_limit.value_within_limit(self.depth) {
                     self.selcx.infcx.err_ctxt().report_overflow_error(
-                        OverflowCause::DeeplyNormalize(data),
+                        OverflowCause::DeeplyNormalize(data.into()),
                         self.cause.span,
                         false,
                         |diag| {
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index 5cb61dff831..41080b3d9d3 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -18,7 +18,8 @@ use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{
-    self, EarlyBinder, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
+    self, EarlyBinder, ExistentialPredicateStableCmpExt as _, Ty, TyCtxt, TypeSuperVisitable,
+    TypeVisitable, TypeVisitor,
 };
 use rustc_middle::ty::{GenericArg, GenericArgs};
 use rustc_middle::ty::{ToPredicate, TypeVisitableExt};
@@ -304,7 +305,7 @@ fn predicate_references_self<'tcx>(
             //
             // This is ALT2 in issue #56288, see that for discussion of the
             // possible alternatives.
-            data.projection_ty.args[1..].iter().any(has_self_ty).then_some(sp)
+            data.projection_term.args[1..].iter().any(has_self_ty).then_some(sp)
         }
         ty::ClauseKind::ConstArgHasType(_ct, ty) => has_self_ty(&ty.into()).then_some(sp),
 
diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
index 1dd2ada3356..1dc2ebfaa7a 100644
--- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
@@ -5,6 +5,7 @@ use rustc_infer::infer::resolve::OpportunisticRegionResolver;
 use rustc_infer::infer::InferOk;
 use rustc_macros::extension;
 use rustc_middle::infer::canonical::{OriginalQueryValues, QueryRegionConstraints};
+use rustc_middle::span_bug;
 use rustc_middle::ty::{self, ParamEnv, Ty, TypeFolder, TypeVisitableExt};
 use rustc_span::def_id::LocalDefId;
 
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 1e78484f305..2e7d2790dc3 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -12,11 +12,12 @@ use super::PredicateObligation;
 use super::Selection;
 use super::SelectionContext;
 use super::SelectionError;
-use super::{Normalized, NormalizedTy, ProjectionCacheEntry, ProjectionCacheKey};
+use super::{Normalized, NormalizedTerm, ProjectionCacheEntry, ProjectionCacheKey};
 use rustc_infer::traits::ObligationCauseCode;
 use rustc_middle::traits::BuiltinImplSource;
 use rustc_middle::traits::ImplSource;
 use rustc_middle::traits::ImplSourceUserDefinedData;
+use rustc_middle::{bug, span_bug};
 
 use crate::errors::InherentProjectionNormalizationOverflow;
 use crate::infer::{BoundRegionConversionTime, InferOk};
@@ -43,7 +44,7 @@ pub type PolyProjectionObligation<'tcx> = Obligation<'tcx, ty::PolyProjectionPre
 
 pub type ProjectionObligation<'tcx> = Obligation<'tcx, ty::ProjectionPredicate<'tcx>>;
 
-pub type ProjectionTyObligation<'tcx> = Obligation<'tcx, ty::AliasTy<'tcx>>;
+pub type ProjectionTermObligation<'tcx> = Obligation<'tcx, ty::AliasTerm<'tcx>>;
 
 pub(super) struct InProgress;
 
@@ -181,7 +182,7 @@ pub(super) enum ProjectAndUnifyResult<'tcx> {
 /// If successful, this may result in additional obligations. Also returns
 /// the projection cache key used to track these additional obligations.
 #[instrument(level = "debug", skip(selcx))]
-pub(super) fn poly_project_and_unify_type<'cx, 'tcx>(
+pub(super) fn poly_project_and_unify_term<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
     obligation: &PolyProjectionObligation<'tcx>,
 ) -> ProjectAndUnifyResult<'tcx> {
@@ -192,7 +193,7 @@ pub(super) fn poly_project_and_unify_type<'cx, 'tcx>(
         let new_universe = infcx.universe();
 
         let placeholder_obligation = obligation.with(infcx.tcx, placeholder_predicate);
-        match project_and_unify_type(selcx, &placeholder_obligation) {
+        match project_and_unify_term(selcx, &placeholder_obligation) {
             ProjectAndUnifyResult::MismatchedProjectionTypes(e) => Err(e),
             ProjectAndUnifyResult::Holds(obligations)
                 if old_universe != new_universe
@@ -232,19 +233,19 @@ pub(super) fn poly_project_and_unify_type<'cx, 'tcx>(
 /// ```
 /// If successful, this may result in additional obligations.
 ///
-/// See [poly_project_and_unify_type] for an explanation of the return value.
+/// See [poly_project_and_unify_term] for an explanation of the return value.
 #[instrument(level = "debug", skip(selcx))]
-fn project_and_unify_type<'cx, 'tcx>(
+fn project_and_unify_term<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
     obligation: &ProjectionObligation<'tcx>,
 ) -> ProjectAndUnifyResult<'tcx> {
     let mut obligations = vec![];
 
     let infcx = selcx.infcx;
-    let normalized = match opt_normalize_projection_type(
+    let normalized = match opt_normalize_projection_term(
         selcx,
         obligation.param_env,
-        obligation.predicate.projection_ty,
+        obligation.predicate.projection_term,
         obligation.cause.clone(),
         obligation.recursion_depth,
         &mut obligations,
@@ -290,7 +291,7 @@ fn project_and_unify_type<'cx, 'tcx>(
 /// there are unresolved type variables in the projection, we will
 /// instantiate it with a fresh type variable `$X` and generate a new
 /// obligation `<T as Trait>::Item == $X` for later.
-pub fn normalize_projection_type<'a, 'b, 'tcx>(
+pub fn normalize_projection_ty<'a, 'b, 'tcx>(
     selcx: &'a mut SelectionContext<'b, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     projection_ty: ty::AliasTy<'tcx>,
@@ -298,10 +299,10 @@ pub fn normalize_projection_type<'a, 'b, 'tcx>(
     depth: usize,
     obligations: &mut Vec<PredicateObligation<'tcx>>,
 ) -> Term<'tcx> {
-    opt_normalize_projection_type(
+    opt_normalize_projection_term(
         selcx,
         param_env,
-        projection_ty,
+        projection_ty.into(),
         cause.clone(),
         depth,
         obligations,
@@ -313,7 +314,10 @@ pub fn normalize_projection_type<'a, 'b, 'tcx>(
         // and a deferred predicate to resolve this when more type
         // information is available.
 
-        selcx.infcx.infer_projection(param_env, projection_ty, cause, depth + 1, obligations).into()
+        selcx
+            .infcx
+            .projection_ty_to_infer(param_env, projection_ty, cause, depth + 1, obligations)
+            .into()
     })
 }
 
@@ -328,10 +332,10 @@ pub fn normalize_projection_type<'a, 'b, 'tcx>(
 /// function takes an obligations vector and appends to it directly, which is
 /// slightly uglier but avoids the need for an extra short-lived allocation.
 #[instrument(level = "debug", skip(selcx, param_env, cause, obligations))]
-pub(super) fn opt_normalize_projection_type<'a, 'b, 'tcx>(
+pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>(
     selcx: &'a mut SelectionContext<'b, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    projection_ty: ty::AliasTy<'tcx>,
+    projection_term: ty::AliasTerm<'tcx>,
     cause: ObligationCause<'tcx>,
     depth: usize,
     obligations: &mut Vec<PredicateObligation<'tcx>>,
@@ -343,8 +347,8 @@ pub(super) fn opt_normalize_projection_type<'a, 'b, 'tcx>(
     // mode, which could lead to using incorrect cache results.
     let use_cache = !selcx.is_intercrate();
 
-    let projection_ty = infcx.resolve_vars_if_possible(projection_ty);
-    let cache_key = ProjectionCacheKey::new(projection_ty, param_env);
+    let projection_term = infcx.resolve_vars_if_possible(projection_term);
+    let cache_key = ProjectionCacheKey::new(projection_term, param_env);
 
     // FIXME(#20304) For now, I am caching here, which is good, but it
     // means we don't capture the type variables that are created in
@@ -392,7 +396,7 @@ pub(super) fn opt_normalize_projection_type<'a, 'b, 'tcx>(
             debug!("recur cache");
             return Err(InProgress);
         }
-        Err(ProjectionCacheEntry::NormalizedTy { ty, complete: _ }) => {
+        Err(ProjectionCacheEntry::NormalizedTerm { ty, complete: _ }) => {
             // This is the hottest path in this function.
             //
             // If we find the value in the cache, then return it along
@@ -410,14 +414,14 @@ pub(super) fn opt_normalize_projection_type<'a, 'b, 'tcx>(
         }
         Err(ProjectionCacheEntry::Error) => {
             debug!("opt_normalize_projection_type: found error");
-            let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth);
+            let result = normalize_to_error(selcx, param_env, projection_term, cause, depth);
             obligations.extend(result.obligations);
             return Ok(Some(result.value.into()));
         }
     }
 
     let obligation =
-        Obligation::with_depth(selcx.tcx(), cause.clone(), depth, param_env, projection_ty);
+        Obligation::with_depth(selcx.tcx(), cause.clone(), depth, param_env, projection_term);
 
     match project(selcx, &obligation) {
         Ok(Projected::Progress(Progress {
@@ -480,7 +484,7 @@ pub(super) fn opt_normalize_projection_type<'a, 'b, 'tcx>(
             if use_cache {
                 infcx.inner.borrow_mut().projection_cache().error(cache_key);
             }
-            let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth);
+            let result = normalize_to_error(selcx, param_env, projection_term, cause, depth);
             obligations.extend(result.obligations);
             Ok(Some(result.value.into()))
         }
@@ -509,19 +513,33 @@ pub(super) fn opt_normalize_projection_type<'a, 'b, 'tcx>(
 fn normalize_to_error<'a, 'tcx>(
     selcx: &SelectionContext<'a, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    projection_ty: ty::AliasTy<'tcx>,
+    projection_term: ty::AliasTerm<'tcx>,
     cause: ObligationCause<'tcx>,
     depth: usize,
-) -> NormalizedTy<'tcx> {
-    let trait_ref = ty::Binder::dummy(projection_ty.trait_ref(selcx.tcx()));
+) -> NormalizedTerm<'tcx> {
+    let trait_ref = ty::Binder::dummy(projection_term.trait_ref(selcx.tcx()));
+    let new_value = match projection_term.kind(selcx.tcx()) {
+        ty::AliasTermKind::ProjectionTy
+        | ty::AliasTermKind::InherentTy
+        | ty::AliasTermKind::OpaqueTy
+        | ty::AliasTermKind::WeakTy => selcx.infcx.next_ty_var(cause.span).into(),
+        ty::AliasTermKind::UnevaluatedConst | ty::AliasTermKind::ProjectionConst => selcx
+            .infcx
+            .next_const_var(
+                selcx
+                    .tcx()
+                    .type_of(projection_term.def_id)
+                    .instantiate(selcx.tcx(), projection_term.args),
+                cause.span,
+            )
+            .into(),
+    };
     let trait_obligation = Obligation {
         cause,
         recursion_depth: depth,
         param_env,
         predicate: trait_ref.to_predicate(selcx.tcx()),
     };
-    let tcx = selcx.infcx.tcx;
-    let new_value = selcx.infcx.next_ty_var(tcx.def_span(projection_ty.def_id));
     Normalized { value: new_value, obligations: vec![trait_obligation] }
 }
 
@@ -573,11 +591,7 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>(
             // cause code, inherent projections will be printed with identity instantiation in
             // diagnostics which is not ideal.
             // Consider creating separate cause codes for this specific situation.
-            if span.is_dummy() {
-                ObligationCauseCode::WhereClause(alias_ty.def_id)
-            } else {
-                ObligationCauseCode::SpannedWhereClause(alias_ty.def_id, span)
-            },
+            ObligationCauseCode::WhereClause(alias_ty.def_id, span),
         );
 
         obligations.push(Obligation::with_depth(
@@ -679,7 +693,7 @@ impl<'tcx> Progress<'tcx> {
 #[instrument(level = "info", skip(selcx))]
 fn project<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
+    obligation: &ProjectionTermObligation<'tcx>,
 ) -> Result<Projected<'tcx>, ProjectionError<'tcx>> {
     if !selcx.tcx().recursion_limit().value_within_limit(obligation.recursion_depth) {
         // This should really be an immediate error, but some existing code
@@ -754,7 +768,7 @@ fn project<'cx, 'tcx>(
 /// there that can answer this question.
 fn assemble_candidates_from_param_env<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
+    obligation: &ProjectionTermObligation<'tcx>,
     candidate_set: &mut ProjectionCandidateSet<'tcx>,
 ) {
     assemble_candidates_from_predicates(
@@ -779,7 +793,7 @@ fn assemble_candidates_from_param_env<'cx, 'tcx>(
 /// Here, for example, we could conclude that the result is `i32`.
 fn assemble_candidates_from_trait_def<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
+    obligation: &ProjectionTermObligation<'tcx>,
     candidate_set: &mut ProjectionCandidateSet<'tcx>,
 ) {
     debug!("assemble_candidates_from_trait_def(..)");
@@ -837,7 +851,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
 /// `dyn Iterator<Item = ()>: Iterator` again.
 fn assemble_candidates_from_object_ty<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
+    obligation: &ProjectionTermObligation<'tcx>,
     candidate_set: &mut ProjectionCandidateSet<'tcx>,
 ) {
     debug!("assemble_candidates_from_object_ty(..)");
@@ -881,7 +895,7 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>(
 )]
 fn assemble_candidates_from_predicates<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
+    obligation: &ProjectionTermObligation<'tcx>,
     candidate_set: &mut ProjectionCandidateSet<'tcx>,
     ctor: fn(ty::PolyProjectionPredicate<'tcx>) -> ProjectionCandidate<'tcx>,
     env_predicates: impl Iterator<Item = ty::Clause<'tcx>>,
@@ -929,7 +943,7 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>(
 #[instrument(level = "debug", skip(selcx, obligation, candidate_set))]
 fn assemble_candidates_from_impls<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
+    obligation: &ProjectionTermObligation<'tcx>,
     candidate_set: &mut ProjectionCandidateSet<'tcx>,
 ) {
     // If we are resolving `<T as TraitRef<...>>::Item == Type`,
@@ -1257,7 +1271,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
 
 fn confirm_candidate<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
+    obligation: &ProjectionTermObligation<'tcx>,
     candidate: ProjectionCandidate<'tcx>,
 ) -> Progress<'tcx> {
     debug!(?obligation, ?candidate, "confirm_candidate");
@@ -1289,7 +1303,7 @@ fn confirm_candidate<'cx, 'tcx>(
 
 fn confirm_select_candidate<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
+    obligation: &ProjectionTermObligation<'tcx>,
     impl_source: Selection<'tcx>,
 ) -> Progress<'tcx> {
     match impl_source {
@@ -1337,7 +1351,7 @@ fn confirm_select_candidate<'cx, 'tcx>(
 
 fn confirm_coroutine_candidate<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
+    obligation: &ProjectionTermObligation<'tcx>,
     nested: Vec<PredicateObligation<'tcx>>,
 ) -> Progress<'tcx> {
     let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty());
@@ -1381,7 +1395,7 @@ fn confirm_coroutine_candidate<'cx, 'tcx>(
     };
 
     let predicate = ty::ProjectionPredicate {
-        projection_ty: ty::AliasTy::new(tcx, obligation.predicate.def_id, trait_ref.args),
+        projection_term: ty::AliasTerm::new(tcx, obligation.predicate.def_id, trait_ref.args),
         term: ty.into(),
     };
 
@@ -1392,7 +1406,7 @@ fn confirm_coroutine_candidate<'cx, 'tcx>(
 
 fn confirm_future_candidate<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
+    obligation: &ProjectionTermObligation<'tcx>,
     nested: Vec<PredicateObligation<'tcx>>,
 ) -> Progress<'tcx> {
     let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty());
@@ -1425,7 +1439,7 @@ fn confirm_future_candidate<'cx, 'tcx>(
     debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name, sym::Output);
 
     let predicate = ty::ProjectionPredicate {
-        projection_ty: ty::AliasTy::new(tcx, obligation.predicate.def_id, trait_ref.args),
+        projection_term: ty::AliasTerm::new(tcx, obligation.predicate.def_id, trait_ref.args),
         term: return_ty.into(),
     };
 
@@ -1436,7 +1450,7 @@ fn confirm_future_candidate<'cx, 'tcx>(
 
 fn confirm_iterator_candidate<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
+    obligation: &ProjectionTermObligation<'tcx>,
     nested: Vec<PredicateObligation<'tcx>>,
 ) -> Progress<'tcx> {
     let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty());
@@ -1467,7 +1481,7 @@ fn confirm_iterator_candidate<'cx, 'tcx>(
     debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name, sym::Item);
 
     let predicate = ty::ProjectionPredicate {
-        projection_ty: ty::AliasTy::new(tcx, obligation.predicate.def_id, trait_ref.args),
+        projection_term: ty::AliasTerm::new(tcx, obligation.predicate.def_id, trait_ref.args),
         term: yield_ty.into(),
     };
 
@@ -1478,7 +1492,7 @@ fn confirm_iterator_candidate<'cx, 'tcx>(
 
 fn confirm_async_iterator_candidate<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
+    obligation: &ProjectionTermObligation<'tcx>,
     nested: Vec<PredicateObligation<'tcx>>,
 ) -> Progress<'tcx> {
     let ty::Coroutine(_, args) = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind()
@@ -1517,7 +1531,7 @@ fn confirm_async_iterator_candidate<'cx, 'tcx>(
     let item_ty = args.type_at(0);
 
     let predicate = ty::ProjectionPredicate {
-        projection_ty: ty::AliasTy::new(tcx, obligation.predicate.def_id, trait_ref.args),
+        projection_term: ty::AliasTerm::new(tcx, obligation.predicate.def_id, trait_ref.args),
         term: item_ty.into(),
     };
 
@@ -1528,7 +1542,7 @@ fn confirm_async_iterator_candidate<'cx, 'tcx>(
 
 fn confirm_builtin_candidate<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
+    obligation: &ProjectionTermObligation<'tcx>,
     data: Vec<PredicateObligation<'tcx>>,
 ) -> Progress<'tcx> {
     let tcx = selcx.tcx();
@@ -1586,8 +1600,10 @@ fn confirm_builtin_candidate<'cx, 'tcx>(
         bug!("unexpected builtin trait with associated type: {:?}", obligation.predicate);
     };
 
-    let predicate =
-        ty::ProjectionPredicate { projection_ty: ty::AliasTy::new(tcx, item_def_id, args), term };
+    let predicate = ty::ProjectionPredicate {
+        projection_term: ty::AliasTerm::new(tcx, item_def_id, args),
+        term,
+    };
 
     confirm_param_env_candidate(selcx, obligation, ty::Binder::dummy(predicate), false)
         .with_addl_obligations(obligations)
@@ -1596,7 +1612,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>(
 
 fn confirm_fn_pointer_candidate<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
+    obligation: &ProjectionTermObligation<'tcx>,
     nested: Vec<PredicateObligation<'tcx>>,
 ) -> Progress<'tcx> {
     let tcx = selcx.tcx();
@@ -1632,7 +1648,7 @@ fn confirm_fn_pointer_candidate<'cx, 'tcx>(
 
 fn confirm_closure_candidate<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
+    obligation: &ProjectionTermObligation<'tcx>,
     nested: Vec<PredicateObligation<'tcx>>,
 ) -> Progress<'tcx> {
     let tcx = selcx.tcx();
@@ -1731,7 +1747,7 @@ fn confirm_closure_candidate<'cx, 'tcx>(
 
 fn confirm_callable_candidate<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
+    obligation: &ProjectionTermObligation<'tcx>,
     fn_sig: ty::PolyFnSig<'tcx>,
     flag: util::TupleArgumentsFlag,
     fn_host_effect: ty::Const<'tcx>,
@@ -1752,7 +1768,7 @@ fn confirm_callable_candidate<'cx, 'tcx>(
         fn_host_effect,
     )
     .map_bound(|(trait_ref, ret_type)| ty::ProjectionPredicate {
-        projection_ty: ty::AliasTy::new(tcx, fn_once_output_def_id, trait_ref.args),
+        projection_term: ty::AliasTerm::new(tcx, fn_once_output_def_id, trait_ref.args),
         term: ret_type.into(),
     });
 
@@ -1761,7 +1777,7 @@ fn confirm_callable_candidate<'cx, 'tcx>(
 
 fn confirm_async_closure_candidate<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
+    obligation: &ProjectionTermObligation<'tcx>,
     nested: Vec<PredicateObligation<'tcx>>,
 ) -> Progress<'tcx> {
     let tcx = selcx.tcx();
@@ -1840,13 +1856,13 @@ fn confirm_async_closure_candidate<'cx, 'tcx>(
                 sym::Output => sig.return_ty,
                 name => bug!("no such associated type: {name}"),
             };
-            let projection_ty = match item_name {
-                sym::CallOnceFuture | sym::Output => ty::AliasTy::new(
+            let projection_term = match item_name {
+                sym::CallOnceFuture | sym::Output => ty::AliasTerm::new(
                     tcx,
                     obligation.predicate.def_id,
                     [self_ty, sig.tupled_inputs_ty],
                 ),
-                sym::CallRefFuture => ty::AliasTy::new(
+                sym::CallRefFuture => ty::AliasTerm::new(
                     tcx,
                     obligation.predicate.def_id,
                     [ty::GenericArg::from(self_ty), sig.tupled_inputs_ty.into(), env_region.into()],
@@ -1855,7 +1871,7 @@ fn confirm_async_closure_candidate<'cx, 'tcx>(
             };
 
             args.coroutine_closure_sig()
-                .rebind(ty::ProjectionPredicate { projection_ty, term: term.into() })
+                .rebind(ty::ProjectionPredicate { projection_term, term: term.into() })
         }
         ty::FnDef(..) | ty::FnPtr(..) => {
             let bound_sig = self_ty.fn_sig(tcx);
@@ -1875,13 +1891,13 @@ fn confirm_async_closure_candidate<'cx, 'tcx>(
                 }
                 name => bug!("no such associated type: {name}"),
             };
-            let projection_ty = match item_name {
-                sym::CallOnceFuture | sym::Output => ty::AliasTy::new(
+            let projection_term = match item_name {
+                sym::CallOnceFuture | sym::Output => ty::AliasTerm::new(
                     tcx,
                     obligation.predicate.def_id,
                     [self_ty, Ty::new_tup(tcx, sig.inputs())],
                 ),
-                sym::CallRefFuture => ty::AliasTy::new(
+                sym::CallRefFuture => ty::AliasTerm::new(
                     tcx,
                     obligation.predicate.def_id,
                     [
@@ -1893,7 +1909,7 @@ fn confirm_async_closure_candidate<'cx, 'tcx>(
                 name => bug!("no such associated type: {name}"),
             };
 
-            bound_sig.rebind(ty::ProjectionPredicate { projection_ty, term: term.into() })
+            bound_sig.rebind(ty::ProjectionPredicate { projection_term, term: term.into() })
         }
         ty::Closure(_, args) => {
             let args = args.as_closure();
@@ -1914,11 +1930,11 @@ fn confirm_async_closure_candidate<'cx, 'tcx>(
                 }
                 name => bug!("no such associated type: {name}"),
             };
-            let projection_ty = match item_name {
+            let projection_term = match item_name {
                 sym::CallOnceFuture | sym::Output => {
-                    ty::AliasTy::new(tcx, obligation.predicate.def_id, [self_ty, sig.inputs()[0]])
+                    ty::AliasTerm::new(tcx, obligation.predicate.def_id, [self_ty, sig.inputs()[0]])
                 }
-                sym::CallRefFuture => ty::AliasTy::new(
+                sym::CallRefFuture => ty::AliasTerm::new(
                     tcx,
                     obligation.predicate.def_id,
                     [ty::GenericArg::from(self_ty), sig.inputs()[0].into(), env_region.into()],
@@ -1926,7 +1942,7 @@ fn confirm_async_closure_candidate<'cx, 'tcx>(
                 name => bug!("no such associated type: {name}"),
             };
 
-            bound_sig.rebind(ty::ProjectionPredicate { projection_ty, term: term.into() })
+            bound_sig.rebind(ty::ProjectionPredicate { projection_term, term: term.into() })
         }
         _ => bug!("expected callable type for AsyncFn candidate"),
     };
@@ -1937,7 +1953,7 @@ fn confirm_async_closure_candidate<'cx, 'tcx>(
 
 fn confirm_async_fn_kind_helper_candidate<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
+    obligation: &ProjectionTermObligation<'tcx>,
     nested: Vec<PredicateObligation<'tcx>>,
 ) -> Progress<'tcx> {
     let [
@@ -1954,7 +1970,7 @@ fn confirm_async_fn_kind_helper_candidate<'cx, 'tcx>(
     };
 
     let predicate = ty::ProjectionPredicate {
-        projection_ty: ty::AliasTy::new(
+        projection_term: ty::AliasTerm::new(
             selcx.tcx(),
             obligation.predicate.def_id,
             obligation.predicate.args,
@@ -1976,7 +1992,7 @@ fn confirm_async_fn_kind_helper_candidate<'cx, 'tcx>(
 
 fn confirm_param_env_candidate<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
+    obligation: &ProjectionTermObligation<'tcx>,
     poly_cache_entry: ty::PolyProjectionPredicate<'tcx>,
     potentially_unnormalized_candidate: bool,
 ) -> Progress<'tcx> {
@@ -1990,7 +2006,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>(
         poly_cache_entry,
     );
 
-    let cache_projection = cache_entry.projection_ty;
+    let cache_projection = cache_entry.projection_term;
     let mut nested_obligations = Vec::new();
     let obligation_projection = obligation.predicate;
     let obligation_projection = ensure_sufficient_stack(|| {
@@ -2045,7 +2061,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>(
 
 fn confirm_impl_candidate<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
+    obligation: &ProjectionTermObligation<'tcx>,
     impl_impl_source: ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>,
 ) -> Progress<'tcx> {
     let tcx = selcx.tcx();
@@ -2106,7 +2122,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
 // associated type itself.
 fn assoc_ty_own_obligations<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
+    obligation: &ProjectionTermObligation<'tcx>,
     nested: &mut Vec<PredicateObligation<'tcx>>,
 ) {
     let tcx = selcx.tcx();
@@ -2130,17 +2146,11 @@ fn assoc_ty_own_obligations<'cx, 'tcx>(
                 | ObligationCauseCode::AscribeUserTypeProvePredicate(..)
         ) {
             obligation.cause.clone()
-        } else if span.is_dummy() {
-            ObligationCause::new(
-                obligation.cause.span,
-                obligation.cause.body_id,
-                ObligationCauseCode::WhereClause(obligation.predicate.def_id),
-            )
         } else {
             ObligationCause::new(
                 obligation.cause.span,
                 obligation.cause.body_id,
-                ObligationCauseCode::SpannedWhereClause(obligation.predicate.def_id, span),
+                ObligationCauseCode::WhereClause(obligation.predicate.def_id, span),
             )
         };
         nested.push(Obligation::with_depth(
@@ -2174,7 +2184,7 @@ impl<'cx, 'tcx> ProjectionCacheKeyExt<'cx, 'tcx> for ProjectionCacheKey<'tcx> {
                 // from a specific call to `opt_normalize_projection_type` - if
                 // there's no precise match, the original cache entry is "stranded"
                 // anyway.
-                infcx.resolve_vars_if_possible(predicate.projection_ty),
+                infcx.resolve_vars_if_possible(predicate.projection_term),
                 obligation.param_env,
             )
         })
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 87d240cf8ac..692feee7395 100644
--- a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
@@ -1,4 +1,5 @@
 use rustc_macros::extension;
+use rustc_middle::span_bug;
 
 use crate::infer::canonical::OriginalQueryValues;
 use crate::infer::InferCtxt;
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index 8b39c23da56..1b5ffeebc01 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -222,7 +222,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
                                 .infcx
                                 .err_ctxt()
                                 .build_overflow_error(
-                                    OverflowCause::DeeplyNormalize(data),
+                                    OverflowCause::DeeplyNormalize(data.into()),
                                     self.cause.span,
                                     true,
                                 )
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 40d206b92b8..b9e853a0678 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -16,6 +16,7 @@ use rustc_infer::traits::ObligationCause;
 use rustc_infer::traits::{Obligation, PolyTraitObligation, SelectionError};
 use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
 use rustc_middle::ty::{self, ToPolyTraitRef, Ty, TypeVisitableExt};
+use rustc_middle::{bug, span_bug};
 
 use crate::traits;
 use crate::traits::query::evaluate_obligation::InferCtxtExt;
@@ -944,7 +945,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         }
 
         self.infcx.probe(|_| {
-            let ty = traits::normalize_projection_type(
+            let ty = traits::normalize_projection_ty(
                 self,
                 param_env,
                 ty::AliasTy::new(tcx, tcx.lang_items().deref_target()?, trait_ref.args),
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 69d11b45e60..24c6951a014 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -17,6 +17,7 @@ use rustc_middle::ty::{
     self, GenericArgs, GenericArgsRef, GenericParamDefKind, ToPolyTraitRef, ToPredicate,
     TraitPredicate, Ty, TyCtxt,
 };
+use rustc_middle::{bug, span_bug};
 use rustc_span::def_id::DefId;
 
 use crate::traits::normalize::{normalize_with_depth, normalize_with_depth_to};
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 7aa2aabed7f..5b25c62689f 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -8,7 +8,7 @@ use self::SelectionCandidate::*;
 use super::coherence::{self, Conflict};
 use super::const_evaluatable;
 use super::project;
-use super::project::ProjectionTyObligation;
+use super::project::ProjectionTermObligation;
 use super::util;
 use super::util::closure_trait_ref_and_return_type;
 use super::wf;
@@ -36,6 +36,7 @@ use rustc_infer::infer::BoundRegionConversionTime;
 use rustc_infer::infer::BoundRegionConversionTime::HigherRankedType;
 use rustc_infer::infer::DefineOpaqueTypes;
 use rustc_infer::traits::TraitObligation;
+use rustc_middle::bug;
 use rustc_middle::dep_graph::dep_kinds;
 use rustc_middle::dep_graph::DepNodeIndex;
 use rustc_middle::mir::interpret::ErrorHandled;
@@ -808,7 +809,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => {
                     let data = bound_predicate.rebind(data);
                     let project_obligation = obligation.with(self.tcx(), data);
-                    match project::poly_project_and_unify_type(self, &project_obligation) {
+                    match project::poly_project_and_unify_term(self, &project_obligation) {
                         ProjectAndUnifyResult::Holds(mut subobligations) => {
                             'compute_res: {
                                 // If we've previously marked this projection as 'complete', then
@@ -1733,7 +1734,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     /// in cases like #91762.
     pub(super) fn match_projection_projections(
         &mut self,
-        obligation: &ProjectionTyObligation<'tcx>,
+        obligation: &ProjectionTermObligation<'tcx>,
         env_predicate: PolyProjectionPredicate<'tcx>,
         potentially_unnormalized_candidates: bool,
     ) -> ProjectionMatchesProjection {
@@ -1752,12 +1753,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     obligation.param_env,
                     obligation.cause.clone(),
                     obligation.recursion_depth + 1,
-                    infer_predicate.projection_ty,
+                    infer_predicate.projection_term,
                     &mut nested_obligations,
                 )
             })
         } else {
-            infer_predicate.projection_ty
+            infer_predicate.projection_term
         };
 
         let is_match = self
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index fe3f66f3a3f..826bb706f48 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -23,6 +23,7 @@ use crate::traits::{
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_errors::{codes::*, DelayDm, Diag, EmissionGuarantee};
 use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_middle::bug;
 use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt, TypeVisitableExt};
 use rustc_middle::ty::{GenericArgs, GenericArgsRef};
 use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK;
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
index b6c2fcb46eb..90f2c7ad213 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
@@ -4,6 +4,7 @@ use crate::traits;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def_id::DefId;
 use rustc_macros::extension;
+use rustc_middle::bug;
 use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams};
 use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
 
diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs
index 6778ac81aea..d4535db951e 100644
--- a/compiler/rustc_trait_selection/src/traits/structural_match.rs
+++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs
@@ -1,5 +1,6 @@
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
+use rustc_middle::bug;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
 use std::ops::ControlFlow;
 
diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs
index b2ba7854f18..83edddb9a96 100644
--- a/compiler/rustc_trait_selection/src/traits/util.rs
+++ b/compiler/rustc_trait_selection/src/traits/util.rs
@@ -6,6 +6,7 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_errors::Diag;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::{InferCtxt, InferOk};
+use rustc_middle::bug;
 use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, ImplSubject, ToPredicate, Ty, TyCtxt, TypeVisitableExt};
 use rustc_middle::ty::{TypeFoldable, TypeFolder, TypeSuperFoldable};
diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs
index 3f1ba80acd3..8fd9889b4ea 100644
--- a/compiler/rustc_trait_selection/src/traits/vtable.rs
+++ b/compiler/rustc_trait_selection/src/traits/vtable.rs
@@ -4,6 +4,7 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
 use rustc_infer::traits::util::PredicateSet;
 use rustc_infer::traits::ImplSource;
+use rustc_middle::bug;
 use rustc_middle::query::Providers;
 use rustc_middle::traits::BuiltinImplSource;
 use rustc_middle::ty::visit::TypeVisitableExt;
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 2c2b84d4a87..6d84523da8a 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -3,6 +3,7 @@ use crate::traits;
 use rustc_hir as hir;
 use rustc_hir::lang_items::LangItem;
 use rustc_infer::traits::ObligationCauseCode;
+use rustc_middle::bug;
 use rustc_middle::ty::{
     self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
 };
@@ -165,11 +166,8 @@ pub fn clause_obligations<'tcx>(
             wf.compute(ty.into());
         }
         ty::ClauseKind::Projection(t) => {
-            wf.compute_alias(t.projection_ty);
-            wf.compute(match t.term.unpack() {
-                ty::TermKind::Ty(ty) => ty.into(),
-                ty::TermKind::Const(c) => c.into(),
-            })
+            wf.compute_alias_term(t.projection_term);
+            wf.compute(t.term.into_arg());
         }
         ty::ClauseKind::ConstArgHasType(ct, ty) => {
             wf.compute(ct.into());
@@ -439,7 +437,13 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
 
     /// Pushes the obligations required for an alias (except inherent) to be WF
     /// into `self.out`.
-    fn compute_alias(&mut self, data: ty::AliasTy<'tcx>) {
+    fn compute_alias_ty(&mut self, data: ty::AliasTy<'tcx>) {
+        self.compute_alias_term(data.into());
+    }
+
+    /// Pushes the obligations required for an alias (except inherent) to be WF
+    /// into `self.out`.
+    fn compute_alias_term(&mut self, data: ty::AliasTerm<'tcx>) {
         // A projection is well-formed if
         //
         // (a) its predicates hold (*)
@@ -568,11 +572,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
 
         iter::zip(predicates, origins.into_iter().rev())
             .map(|((pred, span), origin_def_id)| {
-                let code = if span.is_dummy() {
-                    ObligationCauseCode::WhereClause(origin_def_id)
-                } else {
-                    ObligationCauseCode::SpannedWhereClause(origin_def_id, span)
-                };
+                let code = ObligationCauseCode::WhereClause(origin_def_id, span);
                 let cause = self.cause(code);
                 traits::Obligation::with_depth(
                     self.tcx(),
@@ -702,7 +702,7 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
             }
 
             ty::Alias(ty::Projection | ty::Opaque | ty::Weak, data) => {
-                self.compute_alias(data);
+                self.compute_alias_ty(data);
                 return; // Subtree handled by compute_projection.
             }
             ty::Alias(ty::Inherent, data) => {
diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs
index 559c05eb3e7..fee13078250 100644
--- a/compiler/rustc_traits/src/normalize_projection_ty.rs
+++ b/compiler/rustc_traits/src/normalize_projection_ty.rs
@@ -34,14 +34,8 @@ fn normalize_canonicalized_projection_ty<'tcx>(
             let selcx = &mut SelectionContext::new(ocx.infcx);
             let cause = ObligationCause::dummy();
             let mut obligations = vec![];
-            let answer = traits::normalize_projection_type(
-                selcx,
-                param_env,
-                goal,
-                cause,
-                0,
-                &mut obligations,
-            );
+            let answer =
+                traits::normalize_projection_ty(selcx, param_env, goal, cause, 0, &mut obligations);
             ocx.register_obligations(obligations);
             // #112047: With projections and opaques, we are able to create opaques that
             // are recursive (given some generic parameters of the opaque's type variables).
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index c6b83628506..fd7e2fec389 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -1,5 +1,6 @@
 use rustc_hir as hir;
 use rustc_hir::lang_items::LangItem;
+use rustc_middle::bug;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::layout::{
     fn_can_unwind, FnAbiError, HasParamEnv, HasTyCtxt, LayoutCx, LayoutOf, TyAndLayout,
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index d3fe8291e03..4395eb57cd6 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -5,6 +5,7 @@ use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, ImplTraitInTraitData, TyCtxt};
+use rustc_middle::{bug, span_bug};
 use rustc_span::symbol::kw;
 
 pub(crate) fn provide(providers: &mut Providers) {
diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs
index acbcc3918b2..fec02f515ca 100644
--- a/compiler/rustc_ty_utils/src/consts.rs
+++ b/compiler/rustc_ty_utils/src/consts.rs
@@ -1,6 +1,7 @@
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
+use rustc_middle::bug;
 use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
 use rustc_middle::query::Providers;
 use rustc_middle::thir::visit;
diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs
index 862fb2e1663..e87058f9ba4 100644
--- a/compiler/rustc_ty_utils/src/implied_bounds.rs
+++ b/compiler/rustc_ty_utils/src/implied_bounds.rs
@@ -2,6 +2,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
+use rustc_middle::bug;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::Span;
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index d0aa4eb2e71..41f482d8a70 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -1,6 +1,7 @@
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::TyCtxtInferExt;
+use rustc_middle::bug;
 use rustc_middle::query::Providers;
 use rustc_middle::traits::{BuiltinImplSource, CodegenObligationError};
 use rustc_middle::ty::GenericArgsRef;
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index f78a28d16fd..1ef22497a8f 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -2,6 +2,7 @@ use hir::def_id::DefId;
 use rustc_hir as hir;
 use rustc_index::bit_set::BitSet;
 use rustc_index::{IndexSlice, IndexVec};
+use rustc_middle::bug;
 use rustc_middle::mir::{CoroutineLayout, CoroutineSavedLocal};
 use rustc_middle::query::Providers;
 use rustc_middle::ty::layout::{
diff --git a/compiler/rustc_ty_utils/src/layout_sanity_check.rs b/compiler/rustc_ty_utils/src/layout_sanity_check.rs
index 6332c614a90..ab7d1be226b 100644
--- a/compiler/rustc_ty_utils/src/layout_sanity_check.rs
+++ b/compiler/rustc_ty_utils/src/layout_sanity_check.rs
@@ -1,3 +1,4 @@
+use rustc_middle::bug;
 use rustc_middle::ty::{
     layout::{LayoutCx, TyAndLayout},
     TyCtxt,
diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs
index fd392d11e83..e8c5c54d3a0 100644
--- a/compiler/rustc_ty_utils/src/lib.rs
+++ b/compiler/rustc_ty_utils/src/lib.rs
@@ -17,8 +17,6 @@
 #![feature(never_type)]
 
 #[macro_use]
-extern crate rustc_middle;
-#[macro_use]
 extern crate tracing;
 
 use rustc_middle::query::Providers;
diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs
index ee930a78e77..4e23fb30383 100644
--- a/compiler/rustc_ty_utils/src/needs_drop.rs
+++ b/compiler/rustc_ty_utils/src/needs_drop.rs
@@ -2,6 +2,7 @@
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def_id::DefId;
+use rustc_middle::bug;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::util::{needs_drop_components, AlwaysRequiresDrop};
 use rustc_middle::ty::GenericArgsRef;
diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs
index d7d31a88c9b..be227ec8b9a 100644
--- a/compiler/rustc_ty_utils/src/opaque_types.rs
+++ b/compiler/rustc_ty_utils/src/opaque_types.rs
@@ -2,6 +2,7 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::{def::DefKind, def_id::LocalDefId};
 use rustc_hir::{intravisit, CRATE_HIR_ID};
+use rustc_middle::bug;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::util::{CheckRegions, NotUniqueParam};
 use rustc_middle::ty::{self, Ty, TyCtxt};
diff --git a/compiler/rustc_ty_utils/src/representability.rs b/compiler/rustc_ty_utils/src/representability.rs
index 446f16b4125..0ffb7f62496 100644
--- a/compiler/rustc_ty_utils/src/representability.rs
+++ b/compiler/rustc_ty_utils/src/representability.rs
@@ -1,5 +1,6 @@
 use rustc_hir::def::DefKind;
 use rustc_index::bit_set::BitSet;
+use rustc_middle::bug;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, Representability, Ty, TyCtxt};
 use rustc_span::def_id::LocalDefId;
diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs
index 19c092c5ddf..2d8c78267d9 100644
--- a/compiler/rustc_ty_utils/src/sig_types.rs
+++ b/compiler/rustc_ty_utils/src/sig_types.rs
@@ -4,6 +4,7 @@
 use rustc_ast_ir::try_visit;
 use rustc_ast_ir::visit::VisitorResult;
 use rustc_hir::{def::DefKind, def_id::LocalDefId};
+use rustc_middle::span_bug;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::Span;
 use rustc_type_ir::visit::TypeVisitable;
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index fa1085c7cd7..492cc1d55cb 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -3,6 +3,7 @@ use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::LangItem;
 use rustc_index::bit_set::BitSet;
+use rustc_middle::bug;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, EarlyBinder, Ty, TyCtxt, TypeVisitableExt, TypeVisitor};
 use rustc_middle::ty::{ToPredicate, TypeSuperVisitable, TypeVisitable};
@@ -214,7 +215,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
             self.predicates.push(
                 ty::Binder::bind_with_vars(
                     ty::ProjectionPredicate {
-                        projection_ty: shifted_alias_ty,
+                        projection_term: shifted_alias_ty.into(),
                         term: default_ty.into(),
                     },
                     self.bound_vars,
diff --git a/compiler/rustc_type_ir/Cargo.toml b/compiler/rustc_type_ir/Cargo.toml
index 79ff60802d2..cef3f4e8ce0 100644
--- a/compiler/rustc_type_ir/Cargo.toml
+++ b/compiler/rustc_type_ir/Cargo.toml
@@ -13,7 +13,8 @@ rustc_index = { path = "../rustc_index", default-features = false }
 rustc_macros = { path = "../rustc_macros", optional = true }
 rustc_serialize = { path = "../rustc_serialize", optional = true }
 rustc_span = { path = "../rustc_span", optional = true }
-smallvec = { version = "1.8.1" }
+rustc_type_ir_macros = { path = "../rustc_type_ir_macros" }
+smallvec = { version = "1.8.1", default-features = false }
 # tidy-alphabetical-end
 
 [features]
diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs
index f7c7ec242c1..efefd174cd6 100644
--- a/compiler/rustc_type_ir/src/canonical.rs
+++ b/compiler/rustc_type_ir/src/canonical.rs
@@ -1,20 +1,25 @@
-use rustc_ast_ir::try_visit;
-use rustc_ast_ir::visit::VisitorResult;
 #[cfg(feature = "nightly")]
 use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
+use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
 use std::fmt;
 use std::hash::Hash;
 
-use crate::fold::{FallibleTypeFolder, TypeFoldable};
 use crate::inherent::*;
-use crate::visit::{TypeVisitable, TypeVisitor};
 use crate::{Interner, UniverseIndex};
 
 /// A "canonicalized" type `V` is one where all free inference
 /// variables have been rewritten to "canonical vars". These are
 /// numbered starting from 0 in order of first appearance.
 #[derive(derivative::Derivative)]
-#[derivative(Clone(bound = "V: Clone"), Hash(bound = "V: Hash"))]
+#[derivative(
+    Clone(bound = "V: Clone"),
+    Hash(bound = "V: Hash"),
+    PartialEq(bound = "V: PartialEq"),
+    Eq(bound = "V: Eq"),
+    Debug(bound = "V: fmt::Debug"),
+    Copy(bound = "V: Copy")
+)]
+#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
 #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
 pub struct Canonical<I: Interner, V> {
     pub value: V,
@@ -64,18 +69,6 @@ impl<I: Interner, V> Canonical<I, V> {
     }
 }
 
-impl<I: Interner, V: Eq> Eq for Canonical<I, V> {}
-
-impl<I: Interner, V: PartialEq> PartialEq for Canonical<I, V> {
-    fn eq(&self, other: &Self) -> bool {
-        let Self { value, max_universe, variables, defining_opaque_types } = self;
-        *value == other.value
-            && *max_universe == other.max_universe
-            && *variables == other.variables
-            && *defining_opaque_types == other.defining_opaque_types
-    }
-}
-
 impl<I: Interner, V: fmt::Display> fmt::Display for Canonical<I, V> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let Self { value, max_universe, variables, defining_opaque_types } = self;
@@ -86,84 +79,25 @@ impl<I: Interner, V: fmt::Display> fmt::Display for Canonical<I, V> {
     }
 }
 
-impl<I: Interner, V: fmt::Debug> fmt::Debug for Canonical<I, V> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let Self { value, max_universe, variables, defining_opaque_types } = self;
-        f.debug_struct("Canonical")
-            .field("value", &value)
-            .field("max_universe", &max_universe)
-            .field("variables", &variables)
-            .field("defining_opaque_types", &defining_opaque_types)
-            .finish()
-    }
-}
-
-impl<I: Interner, V: Copy> Copy for Canonical<I, V> where I::CanonicalVars: Copy {}
-
-impl<I: Interner, V: TypeFoldable<I>> TypeFoldable<I> for Canonical<I, V>
-where
-    I::CanonicalVars: TypeFoldable<I>,
-{
-    fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
-        Ok(Canonical {
-            value: self.value.try_fold_with(folder)?,
-            max_universe: self.max_universe.try_fold_with(folder)?,
-            variables: self.variables.try_fold_with(folder)?,
-            defining_opaque_types: self.defining_opaque_types,
-        })
-    }
-}
-
-impl<I: Interner, V: TypeVisitable<I>> TypeVisitable<I> for Canonical<I, V>
-where
-    I::CanonicalVars: TypeVisitable<I>,
-{
-    fn visit_with<F: TypeVisitor<I>>(&self, folder: &mut F) -> F::Result {
-        let Self { value, max_universe, variables, defining_opaque_types } = self;
-        try_visit!(value.visit_with(folder));
-        try_visit!(max_universe.visit_with(folder));
-        try_visit!(defining_opaque_types.visit_with(folder));
-        variables.visit_with(folder)
-    }
-}
-
 /// Information about a canonical variable that is included with the
 /// canonical value. This is sufficient information for code to create
 /// a copy of the canonical value in some other inference context,
 /// with fresh inference variables replacing the canonical values.
 #[derive(derivative::Derivative)]
-#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""), Debug(bound = ""))]
+#[derivative(
+    Clone(bound = ""),
+    Copy(bound = ""),
+    Hash(bound = ""),
+    Debug(bound = ""),
+    Eq(bound = ""),
+    PartialEq(bound = "")
+)]
+#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
 #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
 pub struct CanonicalVarInfo<I: Interner> {
     pub kind: CanonicalVarKind<I>,
 }
 
-impl<I: Interner> PartialEq for CanonicalVarInfo<I> {
-    fn eq(&self, other: &Self) -> bool {
-        self.kind == other.kind
-    }
-}
-
-impl<I: Interner> Eq for CanonicalVarInfo<I> {}
-
-impl<I: Interner> TypeVisitable<I> for CanonicalVarInfo<I>
-where
-    I::Ty: TypeVisitable<I>,
-{
-    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
-        self.kind.visit_with(visitor)
-    }
-}
-
-impl<I: Interner> TypeFoldable<I> for CanonicalVarInfo<I>
-where
-    I::Ty: TypeFoldable<I>,
-{
-    fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
-        Ok(CanonicalVarInfo { kind: self.kind.try_fold_with(folder)? })
-    }
-}
-
 impl<I: Interner> CanonicalVarInfo<I> {
     pub fn universe(self) -> UniverseIndex {
         self.kind.universe()
@@ -216,6 +150,7 @@ impl<I: Interner> CanonicalVarInfo<I> {
 /// that analyzes type-like values.
 #[derive(derivative::Derivative)]
 #[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""), Debug(bound = ""))]
+#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
 #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
 pub enum CanonicalVarKind<I: Interner> {
     /// Some kind of type inference variable.
@@ -258,51 +193,6 @@ impl<I: Interner> PartialEq for CanonicalVarKind<I> {
     }
 }
 
-impl<I: Interner> Eq for CanonicalVarKind<I> {}
-
-impl<I: Interner> TypeVisitable<I> for CanonicalVarKind<I>
-where
-    I::Ty: TypeVisitable<I>,
-{
-    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
-        match self {
-            CanonicalVarKind::Ty(_)
-            | CanonicalVarKind::PlaceholderTy(_)
-            | CanonicalVarKind::Region(_)
-            | CanonicalVarKind::PlaceholderRegion(_)
-            | CanonicalVarKind::Effect => V::Result::output(),
-            CanonicalVarKind::Const(_, ty) | CanonicalVarKind::PlaceholderConst(_, ty) => {
-                ty.visit_with(visitor)
-            }
-        }
-    }
-}
-
-impl<I: Interner> TypeFoldable<I> for CanonicalVarKind<I>
-where
-    I::Ty: TypeFoldable<I>,
-{
-    fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
-        Ok(match self {
-            CanonicalVarKind::Ty(kind) => CanonicalVarKind::Ty(kind),
-            CanonicalVarKind::Region(kind) => CanonicalVarKind::Region(kind),
-            CanonicalVarKind::Const(kind, ty) => {
-                CanonicalVarKind::Const(kind, ty.try_fold_with(folder)?)
-            }
-            CanonicalVarKind::PlaceholderTy(placeholder) => {
-                CanonicalVarKind::PlaceholderTy(placeholder)
-            }
-            CanonicalVarKind::PlaceholderRegion(placeholder) => {
-                CanonicalVarKind::PlaceholderRegion(placeholder)
-            }
-            CanonicalVarKind::PlaceholderConst(placeholder, ty) => {
-                CanonicalVarKind::PlaceholderConst(placeholder, ty.try_fold_with(folder)?)
-            }
-            CanonicalVarKind::Effect => CanonicalVarKind::Effect,
-        })
-    }
-}
-
 impl<I: Interner> CanonicalVarKind<I> {
     pub fn universe(self) -> UniverseIndex {
         match self {
@@ -355,6 +245,7 @@ impl<I: Interner> CanonicalVarKind<I> {
 /// usize or f32). In order to faithfully reproduce a type, we need to
 /// know what set of types a given type variable can be unified with.
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
 #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
 pub enum CanonicalTyVarKind {
     /// General type variable `?T` that can be unified with arbitrary types.
diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs
index c1506f9252b..c748cdf6ed2 100644
--- a/compiler/rustc_type_ir/src/const_kind.rs
+++ b/compiler/rustc_type_ir/src/const_kind.rs
@@ -10,7 +10,7 @@ use self::ConstKind::*;
 
 /// Represents a constant in Rust.
 #[derive(derivative::Derivative)]
-#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""))]
+#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""), Eq(bound = ""))]
 #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
 pub enum ConstKind<I: Interner> {
     /// A const generic parameter.
@@ -58,8 +58,6 @@ impl<I: Interner> PartialEq for ConstKind<I> {
     }
 }
 
-impl<I: Interner> Eq for ConstKind<I> {}
-
 impl<I: Interner> fmt::Debug for ConstKind<I> {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         WithInfcx::with_no_infcx(self).fmt(f)
diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs
index 0fd34e0a65f..5e981636438 100644
--- a/compiler/rustc_type_ir/src/inherent.rs
+++ b/compiler/rustc_type_ir/src/inherent.rs
@@ -1,5 +1,6 @@
 use std::fmt::Debug;
 use std::hash::Hash;
+use std::ops::Deref;
 
 use crate::fold::TypeSuperFoldable;
 use crate::visit::{Flags, TypeSuperVisitable};
@@ -50,7 +51,12 @@ pub trait GenericsOf<I: Interner<GenericsOf = Self>> {
 }
 
 pub trait GenericArgs<I: Interner<GenericArgs = Self>>:
-    Copy + DebugWithInfcx<I> + Hash + Eq + IntoIterator<Item = I::GenericArg>
+    Copy
+    + DebugWithInfcx<I>
+    + Hash
+    + Eq
+    + IntoIterator<Item = I::GenericArg>
+    + Deref<Target: Deref<Target = [I::GenericArg]>>
 {
     fn type_at(self, i: usize) -> I::Ty;
 
@@ -83,3 +89,21 @@ pub trait BoundVars<I: Interner> {
 
     fn has_no_bound_vars(&self) -> bool;
 }
+
+pub trait AliasTerm<I: Interner>: Copy + DebugWithInfcx<I> + Hash + Eq + Sized {
+    fn new(
+        interner: I,
+        trait_def_id: I::DefId,
+        args: impl IntoIterator<Item: Into<I::GenericArg>>,
+    ) -> Self;
+
+    fn def_id(self) -> I::DefId;
+
+    fn args(self) -> I::GenericArgs;
+
+    fn trait_def_id(self, interner: I) -> I::DefId;
+
+    fn self_ty(self) -> I::Ty;
+
+    fn with_self_ty(self, tcx: I, self_ty: I::Ty) -> Self;
+}
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index c8bd7fea11b..af0e833b9e9 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -5,9 +5,23 @@ use std::hash::Hash;
 use crate::inherent::*;
 use crate::ir_print::IrPrint;
 use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
-use crate::{CanonicalVarInfo, DebugWithInfcx, TraitRef};
-
-pub trait Interner: Sized + Copy + IrPrint<TraitRef<Self>> {
+use crate::{
+    CanonicalVarInfo, CoercePredicate, DebugWithInfcx, ExistentialProjection, ExistentialTraitRef,
+    NormalizesTo, ProjectionPredicate, SubtypePredicate, TraitPredicate, TraitRef,
+};
+
+pub trait Interner:
+    Sized
+    + Copy
+    + IrPrint<TraitRef<Self>>
+    + IrPrint<TraitPredicate<Self>>
+    + IrPrint<ExistentialTraitRef<Self>>
+    + IrPrint<ExistentialProjection<Self>>
+    + IrPrint<ProjectionPredicate<Self>>
+    + IrPrint<NormalizesTo<Self>>
+    + IrPrint<SubtypePredicate<Self>>
+    + IrPrint<CoercePredicate<Self>>
+{
     type DefId: Copy + Debug + Hash + Eq;
     type DefiningOpaqueTypes: Copy + Debug + Hash + Default + Eq + TypeVisitable<Self>;
     type AdtDef: Copy + Debug + Hash + Eq;
@@ -25,7 +39,7 @@ pub trait Interner: Sized + Copy + IrPrint<TraitRef<Self>> {
     // Kinds of tys
     type Ty: Ty<Self>;
     type Tys: Copy + Debug + Hash + Eq + IntoIterator<Item = Self::Ty>;
-    type AliasTy: Copy + DebugWithInfcx<Self> + Hash + Eq;
+    type AliasTy: Copy + DebugWithInfcx<Self> + Hash + Eq + Sized;
     type ParamTy: Copy + Debug + Hash + Eq;
     type BoundTy: Copy + Debug + Hash + Eq;
     type PlaceholderTy: PlaceholderLike;
@@ -60,6 +74,7 @@ pub trait Interner: Sized + Copy + IrPrint<TraitRef<Self>> {
     type RegionOutlivesPredicate: Copy + Debug + Hash + Eq;
     type TypeOutlivesPredicate: Copy + Debug + Hash + Eq;
     type ProjectionPredicate: Copy + Debug + Hash + Eq;
+    type AliasTerm: AliasTerm<Self>;
     type NormalizesTo: Copy + Debug + Hash + Eq;
     type SubtypePredicate: Copy + Debug + Hash + Eq;
     type CoercePredicate: Copy + Debug + Hash + Eq;
@@ -71,11 +86,15 @@ pub trait Interner: Sized + Copy + IrPrint<TraitRef<Self>> {
     type GenericsOf: GenericsOf<Self>;
     fn generics_of(self, def_id: Self::DefId) -> Self::GenericsOf;
 
+    fn mk_args(self, args: &[Self::GenericArg]) -> Self::GenericArgs;
+
     fn check_and_mk_args(
         self,
         def_id: Self::DefId,
         args: impl IntoIterator<Item: Into<Self::GenericArg>>,
     ) -> Self::GenericArgs;
+
+    fn parent(self, def_id: Self::DefId) -> Self::DefId;
 }
 
 /// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter`
diff --git a/compiler/rustc_type_ir/src/ir_print.rs b/compiler/rustc_type_ir/src/ir_print.rs
index 84e889b486a..5885139754a 100644
--- a/compiler/rustc_type_ir/src/ir_print.rs
+++ b/compiler/rustc_type_ir/src/ir_print.rs
@@ -1,6 +1,9 @@
 use std::fmt;
 
-use crate::{Interner, TraitRef};
+use crate::{
+    CoercePredicate, ExistentialProjection, ExistentialTraitRef, Interner, NormalizesTo,
+    ProjectionPredicate, SubtypePredicate, TraitPredicate, TraitRef,
+};
 
 pub trait IrPrint<T> {
     fn print(t: &T, fmt: &mut fmt::Formatter<'_>) -> fmt::Result;
@@ -15,7 +18,13 @@ macro_rules! define_display_via_print {
                     <I as IrPrint<$ty<I>>>::print(self, fmt)
                 }
             }
+        )*
+    }
+}
 
+macro_rules! define_debug_via_print {
+    ($($ty:ident),+ $(,)?) => {
+        $(
             impl<I: Interner> fmt::Debug for $ty<I> {
                 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
                     <I as IrPrint<$ty<I>>>::print_debug(self, fmt)
@@ -25,4 +34,15 @@ macro_rules! define_display_via_print {
     }
 }
 
-define_display_via_print!(TraitRef,);
+define_display_via_print!(
+    TraitRef,
+    TraitPredicate,
+    ExistentialTraitRef,
+    ExistentialProjection,
+    ProjectionPredicate,
+    NormalizesTo,
+    SubtypePredicate,
+    CoercePredicate,
+);
+
+define_debug_via_print!(TraitRef, ExistentialTraitRef, ExistentialProjection);
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index 62efa32c9f2..4560a54da82 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -37,9 +37,9 @@ mod debug;
 mod flags;
 mod infcx;
 mod interner;
+mod predicate;
 mod predicate_kind;
 mod region_kind;
-mod trait_ref;
 
 pub use canonical::*;
 #[cfg(feature = "nightly")]
@@ -49,12 +49,12 @@ pub use debug::{DebugWithInfcx, WithInfcx};
 pub use flags::*;
 pub use infcx::InferCtxtLike;
 pub use interner::*;
+pub use predicate::*;
 pub use predicate_kind::*;
 pub use region_kind::*;
-pub use trait_ref::*;
 pub use ty_info::*;
 pub use ty_kind::*;
-pub use AliasKind::*;
+pub use AliasTyKind::*;
 pub use DynKind::*;
 pub use InferTy::*;
 pub use RegionKind::*;
diff --git a/compiler/rustc_type_ir/src/macros.rs b/compiler/rustc_type_ir/src/macros.rs
index 7dcc8851a43..f2f7b165de5 100644
--- a/compiler/rustc_type_ir/src/macros.rs
+++ b/compiler/rustc_type_ir/src/macros.rs
@@ -53,4 +53,5 @@ TrivialTypeTraversalImpls! {
     crate::UniverseIndex,
     rustc_ast_ir::Mutability,
     rustc_ast_ir::Movability,
+    crate::PredicatePolarity,
 }
diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs
new file mode 100644
index 00000000000..71f198d2b8e
--- /dev/null
+++ b/compiler/rustc_type_ir/src/predicate.rs
@@ -0,0 +1,469 @@
+use std::fmt;
+
+#[cfg(feature = "nightly")]
+use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable};
+use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
+
+use crate::inherent::*;
+use crate::visit::TypeVisitableExt as _;
+use crate::{DebugWithInfcx, Interner};
+
+/// A complete reference to a trait. These take numerous guises in syntax,
+/// but perhaps the most recognizable form is in a where-clause:
+/// ```ignore (illustrative)
+/// T: Foo<U>
+/// ```
+/// This would be represented by a trait-reference where the `DefId` is the
+/// `DefId` for the trait `Foo` and the args define `T` as parameter 0,
+/// and `U` as parameter 1.
+///
+/// Trait references also appear in object types like `Foo<U>`, but in
+/// that case the `Self` parameter is absent from the generic parameters.
+#[derive(derivative::Derivative)]
+#[derivative(
+    Clone(bound = ""),
+    Copy(bound = ""),
+    Hash(bound = ""),
+    PartialEq(bound = ""),
+    Eq(bound = "")
+)]
+#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
+#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
+pub struct TraitRef<I: Interner> {
+    pub def_id: I::DefId,
+    pub args: I::GenericArgs,
+    /// This field exists to prevent the creation of `TraitRef` without
+    /// calling [`TraitRef::new`].
+    _use_trait_ref_new_instead: (),
+}
+
+impl<I: Interner> TraitRef<I> {
+    pub fn new(
+        interner: I,
+        trait_def_id: I::DefId,
+        args: impl IntoIterator<Item: Into<I::GenericArg>>,
+    ) -> Self {
+        let args = interner.check_and_mk_args(trait_def_id, args);
+        Self { def_id: trait_def_id, args, _use_trait_ref_new_instead: () }
+    }
+
+    pub fn from_method(interner: I, trait_id: I::DefId, args: I::GenericArgs) -> TraitRef<I> {
+        let generics = interner.generics_of(trait_id);
+        TraitRef::new(interner, trait_id, args.into_iter().take(generics.count()))
+    }
+
+    /// Returns a `TraitRef` of the form `P0: Foo<P1..Pn>` where `Pi`
+    /// are the parameters defined on trait.
+    pub fn identity(interner: I, def_id: I::DefId) -> TraitRef<I> {
+        TraitRef::new(interner, def_id, I::GenericArgs::identity_for_item(interner, def_id))
+    }
+
+    pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
+        TraitRef::new(
+            interner,
+            self.def_id,
+            [self_ty.into()].into_iter().chain(self.args.into_iter().skip(1)),
+        )
+    }
+
+    #[inline]
+    pub fn self_ty(&self) -> I::Ty {
+        self.args.type_at(0)
+    }
+}
+
+#[derive(derivative::Derivative)]
+#[derivative(
+    Clone(bound = ""),
+    Copy(bound = ""),
+    Hash(bound = ""),
+    PartialEq(bound = ""),
+    Eq(bound = "")
+)]
+#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
+#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
+pub struct TraitPredicate<I: Interner> {
+    pub trait_ref: TraitRef<I>,
+
+    /// If polarity is Positive: we are proving that the trait is implemented.
+    ///
+    /// If polarity is Negative: we are proving that a negative impl of this trait
+    /// exists. (Note that coherence also checks whether negative impls of supertraits
+    /// exist via a series of predicates.)
+    ///
+    /// If polarity is Reserved: that's a bug.
+    pub polarity: PredicatePolarity,
+}
+
+impl<I: Interner> TraitPredicate<I> {
+    pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
+        Self { trait_ref: self.trait_ref.with_self_ty(interner, self_ty), polarity: self.polarity }
+    }
+
+    pub fn def_id(self) -> I::DefId {
+        self.trait_ref.def_id
+    }
+
+    pub fn self_ty(self) -> I::Ty {
+        self.trait_ref.self_ty()
+    }
+}
+
+impl<I: Interner> fmt::Debug for TraitPredicate<I> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        // FIXME(effects) printing?
+        write!(f, "TraitPredicate({:?}, polarity:{:?})", self.trait_ref, self.polarity)
+    }
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
+pub enum ImplPolarity {
+    /// `impl Trait for Type`
+    Positive,
+    /// `impl !Trait for Type`
+    Negative,
+    /// `#[rustc_reservation_impl] impl Trait for Type`
+    ///
+    /// This is a "stability hack", not a real Rust feature.
+    /// See #64631 for details.
+    Reservation,
+}
+
+impl fmt::Display for ImplPolarity {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Self::Positive => f.write_str("positive"),
+            Self::Negative => f.write_str("negative"),
+            Self::Reservation => f.write_str("reservation"),
+        }
+    }
+}
+
+/// Polarity for a trait predicate. May either be negative or positive.
+/// Distinguished from [`ImplPolarity`] since we never compute goals with
+/// "reservation" level.
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
+pub enum PredicatePolarity {
+    /// `Type: Trait`
+    Positive,
+    /// `Type: !Trait`
+    Negative,
+}
+
+impl PredicatePolarity {
+    /// Flips polarity by turning `Positive` into `Negative` and `Negative` into `Positive`.
+    pub fn flip(&self) -> PredicatePolarity {
+        match self {
+            PredicatePolarity::Positive => PredicatePolarity::Negative,
+            PredicatePolarity::Negative => PredicatePolarity::Positive,
+        }
+    }
+}
+
+impl fmt::Display for PredicatePolarity {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Self::Positive => f.write_str("positive"),
+            Self::Negative => f.write_str("negative"),
+        }
+    }
+}
+
+#[derive(derivative::Derivative)]
+#[derivative(
+    Clone(bound = ""),
+    Copy(bound = ""),
+    Hash(bound = ""),
+    PartialEq(bound = ""),
+    Eq(bound = ""),
+    Debug(bound = "")
+)]
+#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
+#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
+pub enum ExistentialPredicate<I: Interner> {
+    /// E.g., `Iterator`.
+    Trait(ExistentialTraitRef<I>),
+    /// E.g., `Iterator::Item = T`.
+    Projection(ExistentialProjection<I>),
+    /// E.g., `Send`.
+    AutoTrait(I::DefId),
+}
+
+// FIXME: Implement this the right way after
+impl<I: Interner> DebugWithInfcx<I> for ExistentialPredicate<I> {
+    fn fmt<Infcx: rustc_type_ir::InferCtxtLike<Interner = I>>(
+        this: rustc_type_ir::WithInfcx<'_, Infcx, &Self>,
+        f: &mut fmt::Formatter<'_>,
+    ) -> fmt::Result {
+        fmt::Debug::fmt(&this.data, f)
+    }
+}
+
+/// An existential reference to a trait, where `Self` is erased.
+/// For example, the trait object `Trait<'a, 'b, X, Y>` is:
+/// ```ignore (illustrative)
+/// exists T. T: Trait<'a, 'b, X, Y>
+/// ```
+/// The generic parameters don't include the erased `Self`, only trait
+/// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above).
+#[derive(derivative::Derivative)]
+#[derivative(
+    Clone(bound = ""),
+    Copy(bound = ""),
+    Hash(bound = ""),
+    PartialEq(bound = ""),
+    Eq(bound = "")
+)]
+#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
+#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
+pub struct ExistentialTraitRef<I: Interner> {
+    pub def_id: I::DefId,
+    pub args: I::GenericArgs,
+}
+
+impl<I: Interner> ExistentialTraitRef<I> {
+    pub fn erase_self_ty(interner: I, trait_ref: TraitRef<I>) -> ExistentialTraitRef<I> {
+        // Assert there is a Self.
+        trait_ref.args.type_at(0);
+
+        ExistentialTraitRef {
+            def_id: trait_ref.def_id,
+            args: interner.mk_args(&trait_ref.args[1..]),
+        }
+    }
+
+    /// Object types don't have a self type specified. Therefore, when
+    /// we convert the principal trait-ref into a normal trait-ref,
+    /// you must give *some* self type. A common choice is `mk_err()`
+    /// or some placeholder type.
+    pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> TraitRef<I> {
+        // otherwise the escaping vars would be captured by the binder
+        // debug_assert!(!self_ty.has_escaping_bound_vars());
+
+        TraitRef::new(
+            interner,
+            self.def_id,
+            [self_ty.into()].into_iter().chain(self.args.into_iter()),
+        )
+    }
+}
+
+/// A `ProjectionPredicate` for an `ExistentialTraitRef`.
+#[derive(derivative::Derivative)]
+#[derivative(
+    Clone(bound = ""),
+    Copy(bound = ""),
+    Hash(bound = ""),
+    PartialEq(bound = ""),
+    Eq(bound = "")
+)]
+#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
+#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
+pub struct ExistentialProjection<I: Interner> {
+    pub def_id: I::DefId,
+    pub args: I::GenericArgs,
+    pub term: I::Term,
+}
+
+impl<I: Interner> ExistentialProjection<I> {
+    /// Extracts the underlying existential trait reference from this projection.
+    /// For example, if this is a projection of `exists T. <T as Iterator>::Item == X`,
+    /// then this function would return an `exists T. T: Iterator` existential trait
+    /// reference.
+    pub fn trait_ref(&self, tcx: I) -> ExistentialTraitRef<I> {
+        let def_id = tcx.parent(self.def_id);
+        let args_count = tcx.generics_of(def_id).count() - 1;
+        let args = tcx.mk_args(&self.args[..args_count]);
+        ExistentialTraitRef { def_id, args }
+    }
+
+    pub fn with_self_ty(&self, tcx: I, self_ty: I::Ty) -> ProjectionPredicate<I> {
+        // otherwise the escaping regions would be captured by the binders
+        debug_assert!(!self_ty.has_escaping_bound_vars());
+
+        ProjectionPredicate {
+            projection_term: I::AliasTerm::new(
+                tcx,
+                self.def_id,
+                [self_ty.into()].into_iter().chain(self.args),
+            ),
+            term: self.term,
+        }
+    }
+
+    pub fn erase_self_ty(tcx: I, projection_predicate: ProjectionPredicate<I>) -> Self {
+        // Assert there is a Self.
+        projection_predicate.projection_term.args().type_at(0);
+
+        Self {
+            def_id: projection_predicate.projection_term.def_id(),
+            args: tcx.mk_args(&projection_predicate.projection_term.args()[1..]),
+            term: projection_predicate.term,
+        }
+    }
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))]
+pub enum AliasTermKind {
+    /// A projection `<Type as Trait>::AssocType`.
+    /// Can get normalized away if monomorphic enough.
+    ProjectionTy,
+    /// An associated type in an inherent `impl`
+    InherentTy,
+    /// An opaque type (usually from `impl Trait` in type aliases or function return types)
+    /// Can only be normalized away in RevealAll mode
+    OpaqueTy,
+    /// A type alias that actually checks its trait bounds.
+    /// Currently only used if the type alias references opaque types.
+    /// Can always be normalized away.
+    WeakTy,
+    /// An unevaluated const coming from a generic const expression.
+    UnevaluatedConst,
+    /// An unevaluated const coming from an associated const.
+    ProjectionConst,
+}
+
+impl AliasTermKind {
+    pub fn descr(self) -> &'static str {
+        match self {
+            AliasTermKind::ProjectionTy => "associated type",
+            AliasTermKind::ProjectionConst => "associated const",
+            AliasTermKind::InherentTy => "inherent associated type",
+            AliasTermKind::OpaqueTy => "opaque type",
+            AliasTermKind::WeakTy => "type alias",
+            AliasTermKind::UnevaluatedConst => "unevaluated constant",
+        }
+    }
+}
+
+/// This kind of predicate has no *direct* correspondent in the
+/// syntax, but it roughly corresponds to the syntactic forms:
+///
+/// 1. `T: TraitRef<..., Item = Type>`
+/// 2. `<T as TraitRef<...>>::Item == Type` (NYI)
+///
+/// In particular, form #1 is "desugared" to the combination of a
+/// normal trait predicate (`T: TraitRef<...>`) and one of these
+/// predicates. Form #2 is a broader form in that it also permits
+/// equality between arbitrary types. Processing an instance of
+/// Form #2 eventually yields one of these `ProjectionPredicate`
+/// instances to normalize the LHS.
+#[derive(derivative::Derivative)]
+#[derivative(
+    Clone(bound = ""),
+    Copy(bound = ""),
+    Hash(bound = ""),
+    PartialEq(bound = ""),
+    Eq(bound = "")
+)]
+#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
+#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
+pub struct ProjectionPredicate<I: Interner> {
+    pub projection_term: I::AliasTerm,
+    pub term: I::Term,
+}
+
+impl<I: Interner> ProjectionPredicate<I> {
+    pub fn self_ty(self) -> I::Ty {
+        self.projection_term.self_ty()
+    }
+
+    pub fn with_self_ty(self, tcx: I, self_ty: I::Ty) -> ProjectionPredicate<I> {
+        Self { projection_term: self.projection_term.with_self_ty(tcx, self_ty), ..self }
+    }
+
+    pub fn trait_def_id(self, tcx: I) -> I::DefId {
+        self.projection_term.trait_def_id(tcx)
+    }
+
+    pub fn def_id(self) -> I::DefId {
+        self.projection_term.def_id()
+    }
+}
+
+impl<I: Interner> fmt::Debug for ProjectionPredicate<I> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "ProjectionPredicate({:?}, {:?})", self.projection_term, self.term)
+    }
+}
+
+/// Used by the new solver. Unlike a `ProjectionPredicate` this can only be
+/// proven by actually normalizing `alias`.
+#[derive(derivative::Derivative)]
+#[derivative(
+    Clone(bound = ""),
+    Copy(bound = ""),
+    Hash(bound = ""),
+    PartialEq(bound = ""),
+    Eq(bound = "")
+)]
+#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
+#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
+pub struct NormalizesTo<I: Interner> {
+    pub alias: I::AliasTerm,
+    pub term: I::Term,
+}
+
+impl<I: Interner> NormalizesTo<I> {
+    pub fn self_ty(self) -> I::Ty {
+        self.alias.self_ty()
+    }
+
+    pub fn with_self_ty(self, tcx: I, self_ty: I::Ty) -> NormalizesTo<I> {
+        Self { alias: self.alias.with_self_ty(tcx, self_ty), ..self }
+    }
+
+    pub fn trait_def_id(self, tcx: I) -> I::DefId {
+        self.alias.trait_def_id(tcx)
+    }
+
+    pub fn def_id(self) -> I::DefId {
+        self.alias.def_id()
+    }
+}
+
+impl<I: Interner> fmt::Debug for NormalizesTo<I> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "NormalizesTo({:?}, {:?})", self.alias, self.term)
+    }
+}
+
+/// Encodes that `a` must be a subtype of `b`. The `a_is_expected` flag indicates
+/// whether the `a` type is the type that we should label as "expected" when
+/// presenting user diagnostics.
+#[derive(derivative::Derivative)]
+#[derivative(
+    Clone(bound = ""),
+    Copy(bound = ""),
+    Hash(bound = ""),
+    PartialEq(bound = ""),
+    Eq(bound = ""),
+    Debug(bound = "")
+)]
+#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
+#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
+pub struct SubtypePredicate<I: Interner> {
+    pub a_is_expected: bool,
+    pub a: I::Ty,
+    pub b: I::Ty,
+}
+
+/// Encodes that we have to coerce *from* the `a` type to the `b` type.
+#[derive(derivative::Derivative)]
+#[derivative(
+    Clone(bound = ""),
+    Copy(bound = ""),
+    Hash(bound = ""),
+    PartialEq(bound = ""),
+    Eq(bound = ""),
+    Debug(bound = "")
+)]
+#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
+#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
+pub struct CoercePredicate<I: Interner> {
+    pub a: I::Ty,
+    pub b: I::Ty,
+}
diff --git a/compiler/rustc_type_ir/src/predicate_kind.rs b/compiler/rustc_type_ir/src/predicate_kind.rs
index 5260d9061cf..c477ab14153 100644
--- a/compiler/rustc_type_ir/src/predicate_kind.rs
+++ b/compiler/rustc_type_ir/src/predicate_kind.rs
@@ -1,17 +1,15 @@
-use rustc_ast_ir::try_visit;
-use rustc_ast_ir::visit::VisitorResult;
 #[cfg(feature = "nightly")]
 use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable};
+use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
 use std::fmt;
 
-use crate::fold::{FallibleTypeFolder, TypeFoldable};
-use crate::visit::{TypeVisitable, TypeVisitor};
 use crate::Interner;
 
 /// A clause is something that can appear in where bounds or be inferred
 /// by implied bounds.
 #[derive(derivative::Derivative)]
-#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""))]
+#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""), Eq(bound = ""))]
+#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
 #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
 pub enum ClauseKind<I: Interner> {
     /// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be
@@ -55,61 +53,6 @@ impl<I: Interner> PartialEq for ClauseKind<I> {
     }
 }
 
-impl<I: Interner> Eq for ClauseKind<I> {}
-
-impl<I: Interner> TypeFoldable<I> for ClauseKind<I>
-where
-    I::Ty: TypeFoldable<I>,
-    I::Const: TypeFoldable<I>,
-    I::GenericArg: TypeFoldable<I>,
-    I::TraitPredicate: TypeFoldable<I>,
-    I::ProjectionPredicate: TypeFoldable<I>,
-    I::TypeOutlivesPredicate: TypeFoldable<I>,
-    I::RegionOutlivesPredicate: TypeFoldable<I>,
-{
-    fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
-        Ok(match self {
-            ClauseKind::Trait(p) => ClauseKind::Trait(p.try_fold_with(folder)?),
-            ClauseKind::RegionOutlives(p) => ClauseKind::RegionOutlives(p.try_fold_with(folder)?),
-            ClauseKind::TypeOutlives(p) => ClauseKind::TypeOutlives(p.try_fold_with(folder)?),
-            ClauseKind::Projection(p) => ClauseKind::Projection(p.try_fold_with(folder)?),
-            ClauseKind::ConstArgHasType(c, t) => {
-                ClauseKind::ConstArgHasType(c.try_fold_with(folder)?, t.try_fold_with(folder)?)
-            }
-            ClauseKind::WellFormed(p) => ClauseKind::WellFormed(p.try_fold_with(folder)?),
-            ClauseKind::ConstEvaluatable(p) => {
-                ClauseKind::ConstEvaluatable(p.try_fold_with(folder)?)
-            }
-        })
-    }
-}
-
-impl<I: Interner> TypeVisitable<I> for ClauseKind<I>
-where
-    I::Ty: TypeVisitable<I>,
-    I::Const: TypeVisitable<I>,
-    I::GenericArg: TypeVisitable<I>,
-    I::TraitPredicate: TypeVisitable<I>,
-    I::ProjectionPredicate: TypeVisitable<I>,
-    I::TypeOutlivesPredicate: TypeVisitable<I>,
-    I::RegionOutlivesPredicate: TypeVisitable<I>,
-{
-    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
-        match self {
-            ClauseKind::Trait(p) => p.visit_with(visitor),
-            ClauseKind::RegionOutlives(p) => p.visit_with(visitor),
-            ClauseKind::TypeOutlives(p) => p.visit_with(visitor),
-            ClauseKind::Projection(p) => p.visit_with(visitor),
-            ClauseKind::ConstArgHasType(c, t) => {
-                try_visit!(c.visit_with(visitor));
-                t.visit_with(visitor)
-            }
-            ClauseKind::WellFormed(p) => p.visit_with(visitor),
-            ClauseKind::ConstEvaluatable(p) => p.visit_with(visitor),
-        }
-    }
-}
-
 #[derive(derivative::Derivative)]
 #[derivative(
     Clone(bound = ""),
@@ -118,6 +61,7 @@ where
     PartialEq(bound = ""),
     Eq(bound = "")
 )]
+#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
 #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
 pub enum PredicateKind<I: Interner> {
     /// Prove a clause
@@ -167,69 +111,6 @@ pub enum PredicateKind<I: Interner> {
     AliasRelate(I::Term, I::Term, AliasRelationDirection),
 }
 
-impl<I: Interner> TypeFoldable<I> for PredicateKind<I>
-where
-    I::DefId: TypeFoldable<I>,
-    I::Const: TypeFoldable<I>,
-    I::GenericArgs: TypeFoldable<I>,
-    I::Term: TypeFoldable<I>,
-    I::CoercePredicate: TypeFoldable<I>,
-    I::SubtypePredicate: TypeFoldable<I>,
-    I::NormalizesTo: TypeFoldable<I>,
-    ClauseKind<I>: TypeFoldable<I>,
-{
-    fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
-        Ok(match self {
-            PredicateKind::Clause(c) => PredicateKind::Clause(c.try_fold_with(folder)?),
-            PredicateKind::ObjectSafe(d) => PredicateKind::ObjectSafe(d.try_fold_with(folder)?),
-            PredicateKind::Subtype(s) => PredicateKind::Subtype(s.try_fold_with(folder)?),
-            PredicateKind::Coerce(s) => PredicateKind::Coerce(s.try_fold_with(folder)?),
-            PredicateKind::ConstEquate(a, b) => {
-                PredicateKind::ConstEquate(a.try_fold_with(folder)?, b.try_fold_with(folder)?)
-            }
-            PredicateKind::Ambiguous => PredicateKind::Ambiguous,
-            PredicateKind::NormalizesTo(p) => PredicateKind::NormalizesTo(p.try_fold_with(folder)?),
-            PredicateKind::AliasRelate(a, b, d) => PredicateKind::AliasRelate(
-                a.try_fold_with(folder)?,
-                b.try_fold_with(folder)?,
-                d.try_fold_with(folder)?,
-            ),
-        })
-    }
-}
-
-impl<I: Interner> TypeVisitable<I> for PredicateKind<I>
-where
-    I::DefId: TypeVisitable<I>,
-    I::Const: TypeVisitable<I>,
-    I::GenericArgs: TypeVisitable<I>,
-    I::Term: TypeVisitable<I>,
-    I::CoercePredicate: TypeVisitable<I>,
-    I::SubtypePredicate: TypeVisitable<I>,
-    I::NormalizesTo: TypeVisitable<I>,
-    ClauseKind<I>: TypeVisitable<I>,
-{
-    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
-        match self {
-            PredicateKind::Clause(p) => p.visit_with(visitor),
-            PredicateKind::ObjectSafe(d) => d.visit_with(visitor),
-            PredicateKind::Subtype(s) => s.visit_with(visitor),
-            PredicateKind::Coerce(s) => s.visit_with(visitor),
-            PredicateKind::ConstEquate(a, b) => {
-                try_visit!(a.visit_with(visitor));
-                b.visit_with(visitor)
-            }
-            PredicateKind::Ambiguous => V::Result::output(),
-            PredicateKind::NormalizesTo(p) => p.visit_with(visitor),
-            PredicateKind::AliasRelate(a, b, d) => {
-                try_visit!(a.visit_with(visitor));
-                try_visit!(b.visit_with(visitor));
-                d.visit_with(visitor)
-            }
-        }
-    }
-}
-
 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
 #[cfg_attr(feature = "nightly", derive(HashStable_NoContext, Encodable, Decodable))]
 pub enum AliasRelationDirection {
diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs
index d1b86b495e9..eaae4ee0130 100644
--- a/compiler/rustc_type_ir/src/region_kind.rs
+++ b/compiler/rustc_type_ir/src/region_kind.rs
@@ -115,7 +115,7 @@ use self::RegionKind::*;
 /// [2]: https://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
 /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
 #[derive(derivative::Derivative)]
-#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""))]
+#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""), Eq(bound = ""))]
 #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))]
 pub enum RegionKind<I: Interner> {
     /// A region parameter; for example `'a` in `impl<'a> Trait for &'a ()`.
@@ -208,9 +208,6 @@ impl<I: Interner> PartialEq for RegionKind<I> {
     }
 }
 
-// This is manually implemented because a derive would require `I: Eq`
-impl<I: Interner> Eq for RegionKind<I> {}
-
 impl<I: Interner> DebugWithInfcx<I> for RegionKind<I> {
     fn fmt<Infcx: InferCtxtLike<Interner = I>>(
         this: WithInfcx<'_, Infcx, &Self>,
diff --git a/compiler/rustc_type_ir/src/trait_ref.rs b/compiler/rustc_type_ir/src/trait_ref.rs
deleted file mode 100644
index 4bd513ab7e1..00000000000
--- a/compiler/rustc_type_ir/src/trait_ref.rs
+++ /dev/null
@@ -1,109 +0,0 @@
-use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
-
-use crate::fold::{FallibleTypeFolder, TypeFoldable};
-use crate::inherent::*;
-use crate::lift::Lift;
-use crate::visit::{TypeVisitable, TypeVisitor};
-use crate::Interner;
-
-/// A complete reference to a trait. These take numerous guises in syntax,
-/// but perhaps the most recognizable form is in a where-clause:
-/// ```ignore (illustrative)
-/// T: Foo<U>
-/// ```
-/// This would be represented by a trait-reference where the `DefId` is the
-/// `DefId` for the trait `Foo` and the args define `T` as parameter 0,
-/// and `U` as parameter 1.
-///
-/// Trait references also appear in object types like `Foo<U>`, but in
-/// that case the `Self` parameter is absent from the generic parameters.
-#[derive(derivative::Derivative)]
-#[derivative(
-    Clone(bound = ""),
-    Copy(bound = ""),
-    Hash(bound = ""),
-    PartialEq(bound = ""),
-    Eq(bound = "")
-)]
-#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
-pub struct TraitRef<I: Interner> {
-    pub def_id: I::DefId,
-    pub args: I::GenericArgs,
-    /// This field exists to prevent the creation of `TraitRef` without
-    /// calling [`TraitRef::new`].
-    _use_trait_ref_new_instead: (),
-}
-
-impl<I: Interner> TraitRef<I> {
-    pub fn new(
-        interner: I,
-        trait_def_id: I::DefId,
-        args: impl IntoIterator<Item: Into<I::GenericArg>>,
-    ) -> Self {
-        let args = interner.check_and_mk_args(trait_def_id, args);
-        Self { def_id: trait_def_id, args, _use_trait_ref_new_instead: () }
-    }
-
-    pub fn from_method(interner: I, trait_id: I::DefId, args: I::GenericArgs) -> TraitRef<I> {
-        let generics = interner.generics_of(trait_id);
-        TraitRef::new(interner, trait_id, args.into_iter().take(generics.count()))
-    }
-
-    /// Returns a `TraitRef` of the form `P0: Foo<P1..Pn>` where `Pi`
-    /// are the parameters defined on trait.
-    pub fn identity(interner: I, def_id: I::DefId) -> TraitRef<I> {
-        TraitRef::new(interner, def_id, I::GenericArgs::identity_for_item(interner, def_id))
-    }
-
-    pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
-        TraitRef::new(
-            interner,
-            self.def_id,
-            [self_ty.into()].into_iter().chain(self.args.into_iter().skip(1)),
-        )
-    }
-
-    #[inline]
-    pub fn self_ty(&self) -> I::Ty {
-        self.args.type_at(0)
-    }
-}
-
-// FIXME(compiler-errors): Make this into a `Lift_Generic` impl.
-impl<I: Interner, U: Interner> Lift<U> for TraitRef<I>
-where
-    I::DefId: Lift<U, Lifted = U::DefId>,
-    I::GenericArgs: Lift<U, Lifted = U::GenericArgs>,
-{
-    type Lifted = TraitRef<U>;
-
-    fn lift_to_tcx(self, tcx: U) -> Option<Self::Lifted> {
-        Some(TraitRef {
-            def_id: self.def_id.lift_to_tcx(tcx)?,
-            args: self.args.lift_to_tcx(tcx)?,
-            _use_trait_ref_new_instead: (),
-        })
-    }
-}
-
-impl<I: Interner> TypeVisitable<I> for TraitRef<I>
-where
-    I::GenericArgs: TypeVisitable<I>,
-{
-    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
-        self.args.visit_with(visitor)
-    }
-}
-
-impl<I: Interner> TypeFoldable<I> for TraitRef<I>
-where
-    I::GenericArgs: TypeFoldable<I>,
-{
-    fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
-        Ok(TraitRef {
-            def_id: self.def_id,
-            args: self.args.try_fold_with(folder)?,
-            _use_trait_ref_new_instead: (),
-        })
-    }
-}
diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs
index f2e4afecc40..6e544d0e6ac 100644
--- a/compiler/rustc_type_ir/src/ty_kind.rs
+++ b/compiler/rustc_type_ir/src/ty_kind.rs
@@ -1,14 +1,12 @@
-use rustc_ast_ir::try_visit;
 #[cfg(feature = "nightly")]
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 #[cfg(feature = "nightly")]
 use rustc_data_structures::unify::{EqUnifyValue, UnifyKey};
 #[cfg(feature = "nightly")]
 use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable};
+use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
 use std::fmt;
 
-use crate::fold::{FallibleTypeFolder, TypeFoldable};
-use crate::visit::{TypeVisitable, TypeVisitor};
 use crate::Interner;
 use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, WithInfcx};
 
@@ -33,7 +31,7 @@ pub enum DynKind {
 
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
 #[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))]
-pub enum AliasKind {
+pub enum AliasTyKind {
     /// A projection `<Type as Trait>::AssocType`.
     /// Can get normalized away if monomorphic enough.
     Projection,
@@ -48,13 +46,13 @@ pub enum AliasKind {
     Weak,
 }
 
-impl AliasKind {
+impl AliasTyKind {
     pub fn descr(self) -> &'static str {
         match self {
-            AliasKind::Projection => "associated type",
-            AliasKind::Inherent => "inherent associated type",
-            AliasKind::Opaque => "opaque type",
-            AliasKind::Weak => "type alias",
+            AliasTyKind::Projection => "associated type",
+            AliasTyKind::Inherent => "inherent associated type",
+            AliasTyKind::Opaque => "opaque type",
+            AliasTyKind::Weak => "type alias",
         }
     }
 }
@@ -65,7 +63,7 @@ impl AliasKind {
 /// converted to this representation using `<dyn HirTyLowerer>::lower_ty`.
 #[cfg_attr(feature = "nightly", rustc_diagnostic_item = "IrTyKind")]
 #[derive(derivative::Derivative)]
-#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""))]
+#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""), Eq(bound = ""))]
 #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
 pub enum TyKind<I: Interner> {
     /// The primitive boolean type. Written as `bool`.
@@ -203,7 +201,7 @@ pub enum TyKind<I: Interner> {
     /// A projection, opaque type, weak type alias, or inherent associated type.
     /// All of these types are represented as pairs of def-id and args, and can
     /// be normalized, so they are grouped conceptually.
-    Alias(AliasKind, I::AliasTy),
+    Alias(AliasTyKind, I::AliasTy),
 
     /// A type parameter; for example, `T` in `fn f<T>(x: T) {}`.
     Param(I::ParamTy),
@@ -341,9 +339,6 @@ impl<I: Interner> PartialEq for TyKind<I> {
     }
 }
 
-// This is manually implemented because a derive would require `I: Eq`
-impl<I: Interner> Eq for TyKind<I> {}
-
 impl<I: Interner> DebugWithInfcx<I> for TyKind<I> {
     fn fmt<Infcx: InferCtxtLike<Interner = I>>(
         this: WithInfcx<'_, Infcx, &Self>,
@@ -804,29 +799,8 @@ impl<I: Interner> DebugWithInfcx<I> for InferTy {
     Debug(bound = "")
 )]
 #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
+#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
 pub struct TypeAndMut<I: Interner> {
     pub ty: I::Ty,
     pub mutbl: Mutability,
 }
-
-impl<I: Interner> TypeFoldable<I> for TypeAndMut<I>
-where
-    I::Ty: TypeFoldable<I>,
-{
-    fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
-        Ok(TypeAndMut {
-            ty: self.ty.try_fold_with(folder)?,
-            mutbl: self.mutbl.try_fold_with(folder)?,
-        })
-    }
-}
-
-impl<I: Interner> TypeVisitable<I> for TypeAndMut<I>
-where
-    I::Ty: TypeVisitable<I>,
-{
-    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
-        try_visit!(self.ty.visit_with(visitor));
-        self.mutbl.visit_with(visitor)
-    }
-}
diff --git a/compiler/rustc_type_ir_macros/Cargo.toml b/compiler/rustc_type_ir_macros/Cargo.toml
new file mode 100644
index 00000000000..cb95ca68346
--- /dev/null
+++ b/compiler/rustc_type_ir_macros/Cargo.toml
@@ -0,0 +1,15 @@
+[package]
+name = "rustc_type_ir_macros"
+version = "0.0.0"
+edition = "2021"
+
+[lib]
+proc-macro = true
+
+[dependencies]
+# tidy-alphabetical-start
+proc-macro2 = "1"
+quote = "1"
+syn = { version = "2.0.9", features = ["full"] }
+synstructure = "0.13.0"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_type_ir_macros/src/lib.rs b/compiler/rustc_type_ir_macros/src/lib.rs
new file mode 100644
index 00000000000..000bcf2d3b2
--- /dev/null
+++ b/compiler/rustc_type_ir_macros/src/lib.rs
@@ -0,0 +1,159 @@
+use quote::quote;
+use syn::{parse_quote, visit_mut::VisitMut};
+use synstructure::decl_derive;
+
+decl_derive!(
+    [TypeFoldable_Generic] => type_foldable_derive
+);
+decl_derive!(
+    [TypeVisitable_Generic] => type_visitable_derive
+);
+decl_derive!(
+    [Lift_Generic] => lift_derive
+);
+
+fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
+    if let syn::Data::Union(_) = s.ast().data {
+        panic!("cannot derive on union")
+    }
+
+    if !s.ast().generics.type_params().any(|ty| ty.ident == "I") {
+        s.add_impl_generic(parse_quote! { I });
+    }
+
+    s.add_where_predicate(parse_quote! { I: Interner });
+    s.add_bounds(synstructure::AddBounds::Fields);
+    s.bind_with(|_| synstructure::BindStyle::Move);
+    let body_fold = s.each_variant(|vi| {
+        let bindings = vi.bindings();
+        vi.construct(|_, index| {
+            let bind = &bindings[index];
+            quote! {
+                ::rustc_type_ir::fold::TypeFoldable::try_fold_with(#bind, __folder)?
+            }
+        })
+    });
+
+    s.bound_impl(
+        quote!(::rustc_type_ir::fold::TypeFoldable<I>),
+        quote! {
+            fn try_fold_with<__F: ::rustc_type_ir::fold::FallibleTypeFolder<I>>(
+                self,
+                __folder: &mut __F
+            ) -> Result<Self, __F::Error> {
+                Ok(match self { #body_fold })
+            }
+        },
+    )
+}
+
+fn lift_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
+    if let syn::Data::Union(_) = s.ast().data {
+        panic!("cannot derive on union")
+    }
+
+    if !s.ast().generics.type_params().any(|ty| ty.ident == "I") {
+        s.add_impl_generic(parse_quote! { I });
+    }
+
+    s.add_bounds(synstructure::AddBounds::None);
+    s.add_where_predicate(parse_quote! { I: Interner });
+    s.add_impl_generic(parse_quote! { J });
+    s.add_where_predicate(parse_quote! { J: Interner });
+
+    let mut wc = vec![];
+    s.bind_with(|_| synstructure::BindStyle::Move);
+    let body_fold = s.each_variant(|vi| {
+        let bindings = vi.bindings();
+        vi.construct(|field, index| {
+            let ty = field.ty.clone();
+            let lifted_ty = lift(ty.clone());
+            wc.push(parse_quote! { #ty: ::rustc_type_ir::lift::Lift<J, Lifted = #lifted_ty> });
+            let bind = &bindings[index];
+            quote! {
+                #bind.lift_to_tcx(interner)?
+            }
+        })
+    });
+    for wc in wc {
+        s.add_where_predicate(wc);
+    }
+
+    let (_, ty_generics, _) = s.ast().generics.split_for_impl();
+    let name = s.ast().ident.clone();
+    let self_ty: syn::Type = parse_quote! { #name #ty_generics };
+    let lifted_ty = lift(self_ty);
+
+    s.bound_impl(
+        quote!(::rustc_type_ir::lift::Lift<J>),
+        quote! {
+            type Lifted = #lifted_ty;
+
+            fn lift_to_tcx(
+                self,
+                interner: J,
+            ) -> Option<Self::Lifted> {
+                Some(match self { #body_fold })
+            }
+        },
+    )
+}
+
+fn lift(mut ty: syn::Type) -> syn::Type {
+    struct ItoJ;
+    impl VisitMut for ItoJ {
+        fn visit_type_path_mut(&mut self, i: &mut syn::TypePath) {
+            if i.qself.is_none() {
+                if let Some(first) = i.path.segments.first_mut() {
+                    if first.ident == "I" {
+                        *first = parse_quote! { J };
+                    }
+                }
+            }
+            syn::visit_mut::visit_type_path_mut(self, i);
+        }
+    }
+
+    ItoJ.visit_type_mut(&mut ty);
+
+    ty
+}
+
+fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
+    if let syn::Data::Union(_) = s.ast().data {
+        panic!("cannot derive on union")
+    }
+
+    if !s.ast().generics.type_params().any(|ty| ty.ident == "I") {
+        s.add_impl_generic(parse_quote! { I });
+    }
+
+    s.add_where_predicate(parse_quote! { I: Interner });
+    s.add_bounds(synstructure::AddBounds::Fields);
+    let body_visit = s.each(|bind| {
+        quote! {
+            match ::rustc_ast_ir::visit::VisitorResult::branch(
+                ::rustc_type_ir::visit::TypeVisitable::visit_with(#bind, __visitor)
+            ) {
+                ::core::ops::ControlFlow::Continue(()) => {},
+                ::core::ops::ControlFlow::Break(r) => {
+                    return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
+                },
+            }
+        }
+    });
+    s.bind_with(|_| synstructure::BindStyle::Move);
+
+    s.bound_impl(
+        quote!(::rustc_type_ir::visit::TypeVisitable<I>),
+        quote! {
+            fn visit_with<__V: ::rustc_type_ir::visit::TypeVisitor<I>>(
+                &self,
+                __visitor: &mut __V
+            ) -> __V::Result {
+                match *self { #body_visit }
+                <__V::Result as ::rustc_ast_ir::visit::VisitorResult>::output()
+            }
+        },
+    )
+}
diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs
index bc6fb34493a..56251613840 100644
--- a/compiler/stable_mir/src/ty.rs
+++ b/compiler/stable_mir/src/ty.rs
@@ -897,6 +897,12 @@ pub struct AliasTy {
     pub args: GenericArgs,
 }
 
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct AliasTerm {
+    pub def_id: AliasDef,
+    pub args: GenericArgs,
+}
+
 pub type PolyFnSig = Binder<FnSig>;
 
 #[derive(Clone, Debug, Eq, PartialEq)]
@@ -1350,7 +1356,7 @@ pub type TypeOutlivesPredicate = OutlivesPredicate<Ty, Region>;
 
 #[derive(Clone, Debug, Eq, PartialEq)]
 pub struct ProjectionPredicate {
-    pub projection_ty: AliasTy,
+    pub projection_term: AliasTerm,
     pub term: TermKind,
 }
 
diff --git a/config.example.toml b/config.example.toml
index 3b76952504f..224d079b206 100644
--- a/config.example.toml
+++ b/config.example.toml
@@ -213,17 +213,17 @@
 # the root of the repository.
 #build-dir = "build"
 
-# Instead of downloading the src/stage0.json version of Cargo specified, use
+# Instead of downloading the src/stage0 version of Cargo specified, use
 # this Cargo binary instead to build all Rust code
 # If you set this, you likely want to set `rustc` as well.
 #cargo = "/path/to/cargo"
 
-# Instead of downloading the src/stage0.json version of the compiler
+# Instead of downloading the src/stage0 version of the compiler
 # specified, use this rustc binary instead as the stage0 snapshot compiler.
 # If you set this, you likely want to set `cargo` as well.
 #rustc = "/path/to/rustc"
 
-# Instead of downloading the src/stage0.json version of rustfmt specified,
+# Instead of downloading the src/stage0 version of rustfmt specified,
 # use this rustfmt binary instead as the stage0 snapshot rustfmt.
 #rustfmt = "/path/to/rustfmt"
 
diff --git a/library/alloc/src/fmt.rs b/library/alloc/src/fmt.rs
index b9918752540..ae44cab8131 100644
--- a/library/alloc/src/fmt.rs
+++ b/library/alloc/src/fmt.rs
@@ -403,7 +403,7 @@
 //! is, a formatting implementation must and may only return an error if the
 //! passed-in [`Formatter`] returns an error. This is because, contrary to what
 //! the function signature might suggest, string formatting is an infallible
-//! operation. This function only returns a result because writing to the
+//! operation. This function only returns a [`Result`] because writing to the
 //! underlying stream might fail and it must provide a way to propagate the fact
 //! that an error has occurred back up the stack.
 //!
@@ -630,7 +630,9 @@ pub fn format(args: Arguments<'_>) -> string::String {
     fn format_inner(args: Arguments<'_>) -> string::String {
         let capacity = args.estimated_capacity();
         let mut output = string::String::with_capacity(capacity);
-        output.write_fmt(args).expect("a formatting trait implementation returned an error");
+        output
+            .write_fmt(args)
+            .expect("a formatting trait implementation returned an error when the underlying stream did not");
         output
     }
 
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index c245b42c3e8..45b20535675 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -366,6 +366,12 @@ impl<T: ?Sized, A: Allocator> Rc<T, A> {
     }
 
     #[inline]
+    fn into_inner_with_allocator(this: Self) -> (NonNull<RcBox<T>>, A) {
+        let this = mem::ManuallyDrop::new(this);
+        (this.ptr, unsafe { ptr::read(&this.alloc) })
+    }
+
+    #[inline]
     unsafe fn from_inner_in(ptr: NonNull<RcBox<T>>, alloc: A) -> Self {
         Self { ptr, phantom: PhantomData, alloc }
     }
@@ -1145,12 +1151,9 @@ impl<T, A: Allocator> Rc<mem::MaybeUninit<T>, A> {
     /// ```
     #[unstable(feature = "new_uninit", issue = "63291")]
     #[inline]
-    pub unsafe fn assume_init(self) -> Rc<T, A>
-    where
-        A: Clone,
-    {
-        let md_self = mem::ManuallyDrop::new(self);
-        unsafe { Rc::from_inner_in(md_self.ptr.cast(), md_self.alloc.clone()) }
+    pub unsafe fn assume_init(self) -> Rc<T, A> {
+        let (ptr, alloc) = Rc::into_inner_with_allocator(self);
+        unsafe { Rc::from_inner_in(ptr.cast(), alloc) }
     }
 }
 
@@ -1189,12 +1192,9 @@ impl<T, A: Allocator> Rc<[mem::MaybeUninit<T>], A> {
     /// ```
     #[unstable(feature = "new_uninit", issue = "63291")]
     #[inline]
-    pub unsafe fn assume_init(self) -> Rc<[T], A>
-    where
-        A: Clone,
-    {
-        let md_self = mem::ManuallyDrop::new(self);
-        unsafe { Rc::from_ptr_in(md_self.ptr.as_ptr() as _, md_self.alloc.clone()) }
+    pub unsafe fn assume_init(self) -> Rc<[T], A> {
+        let (ptr, alloc) = Rc::into_inner_with_allocator(self);
+        unsafe { Rc::from_ptr_in(ptr.as_ptr() as _, alloc) }
     }
 }
 
@@ -1809,7 +1809,9 @@ impl<T: Clone, A: Allocator + Clone> Rc<T, A> {
         // reference to the allocation.
         unsafe { &mut this.ptr.as_mut().value }
     }
+}
 
+impl<T: Clone, A: Allocator> Rc<T, A> {
     /// If we have the only reference to `T` then unwrap it. Otherwise, clone `T` and return the
     /// clone.
     ///
@@ -1845,7 +1847,7 @@ impl<T: Clone, A: Allocator + Clone> Rc<T, A> {
     }
 }
 
-impl<A: Allocator + Clone> Rc<dyn Any, A> {
+impl<A: Allocator> Rc<dyn Any, A> {
     /// Attempt to downcast the `Rc<dyn Any>` to a concrete type.
     ///
     /// # Examples
@@ -1869,10 +1871,8 @@ impl<A: Allocator + Clone> Rc<dyn Any, A> {
     pub fn downcast<T: Any>(self) -> Result<Rc<T, A>, Self> {
         if (*self).is::<T>() {
             unsafe {
-                let ptr = self.ptr.cast::<RcBox<T>>();
-                let alloc = self.alloc.clone();
-                forget(self);
-                Ok(Rc::from_inner_in(ptr, alloc))
+                let (ptr, alloc) = Rc::into_inner_with_allocator(self);
+                Ok(Rc::from_inner_in(ptr.cast(), alloc))
             }
         } else {
             Err(self)
@@ -1909,10 +1909,8 @@ impl<A: Allocator + Clone> Rc<dyn Any, A> {
     #[unstable(feature = "downcast_unchecked", issue = "90850")]
     pub unsafe fn downcast_unchecked<T: Any>(self) -> Rc<T, A> {
         unsafe {
-            let ptr = self.ptr.cast::<RcBox<T>>();
-            let alloc = self.alloc.clone();
-            mem::forget(self);
-            Rc::from_inner_in(ptr, alloc)
+            let (ptr, alloc) = Rc::into_inner_with_allocator(self);
+            Rc::from_inner_in(ptr.cast(), alloc)
         }
     }
 }
@@ -2661,12 +2659,13 @@ impl From<Rc<str>> for Rc<[u8]> {
 }
 
 #[stable(feature = "boxed_slice_try_from", since = "1.43.0")]
-impl<T, const N: usize> TryFrom<Rc<[T]>> for Rc<[T; N]> {
-    type Error = Rc<[T]>;
+impl<T, A: Allocator, const N: usize> TryFrom<Rc<[T], A>> for Rc<[T; N], A> {
+    type Error = Rc<[T], A>;
 
-    fn try_from(boxed_slice: Rc<[T]>) -> Result<Self, Self::Error> {
+    fn try_from(boxed_slice: Rc<[T], A>) -> Result<Self, Self::Error> {
         if boxed_slice.len() == N {
-            Ok(unsafe { Rc::from_raw(Rc::into_raw(boxed_slice) as *mut [T; N]) })
+            let (ptr, alloc) = Rc::into_inner_with_allocator(boxed_slice);
+            Ok(unsafe { Rc::from_inner_in(ptr.cast(), alloc) })
         } else {
             Err(boxed_slice)
         }
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 297a273d274..a35c99849b3 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -280,8 +280,8 @@ impl<T: ?Sized> Arc<T> {
 
 impl<T: ?Sized, A: Allocator> Arc<T, A> {
     #[inline]
-    fn internal_into_inner_with_allocator(self) -> (NonNull<ArcInner<T>>, A) {
-        let this = mem::ManuallyDrop::new(self);
+    fn into_inner_with_allocator(this: Self) -> (NonNull<ArcInner<T>>, A) {
+        let this = mem::ManuallyDrop::new(this);
         (this.ptr, unsafe { ptr::read(&this.alloc) })
     }
 
@@ -1290,7 +1290,7 @@ impl<T, A: Allocator> Arc<mem::MaybeUninit<T>, A> {
     #[must_use = "`self` will be dropped if the result is not used"]
     #[inline]
     pub unsafe fn assume_init(self) -> Arc<T, A> {
-        let (ptr, alloc) = self.internal_into_inner_with_allocator();
+        let (ptr, alloc) = Arc::into_inner_with_allocator(self);
         unsafe { Arc::from_inner_in(ptr.cast(), alloc) }
     }
 }
@@ -1332,7 +1332,7 @@ impl<T, A: Allocator> Arc<[mem::MaybeUninit<T>], A> {
     #[must_use = "`self` will be dropped if the result is not used"]
     #[inline]
     pub unsafe fn assume_init(self) -> Arc<[T], A> {
-        let (ptr, alloc) = self.internal_into_inner_with_allocator();
+        let (ptr, alloc) = Arc::into_inner_with_allocator(self);
         unsafe { Arc::from_ptr_in(ptr.as_ptr() as _, alloc) }
     }
 }
@@ -2227,7 +2227,9 @@ impl<T: Clone, A: Allocator + Clone> Arc<T, A> {
         // either unique to begin with, or became one upon cloning the contents.
         unsafe { Self::get_mut_unchecked(this) }
     }
+}
 
+impl<T: Clone, A: Allocator> Arc<T, A> {
     /// If we have the only reference to `T` then unwrap it. Otherwise, clone `T` and return the
     /// clone.
     ///
@@ -2499,7 +2501,7 @@ impl<A: Allocator> Arc<dyn Any + Send + Sync, A> {
     {
         if (*self).is::<T>() {
             unsafe {
-                let (ptr, alloc) = self.internal_into_inner_with_allocator();
+                let (ptr, alloc) = Arc::into_inner_with_allocator(self);
                 Ok(Arc::from_inner_in(ptr.cast(), alloc))
             }
         } else {
@@ -2540,7 +2542,7 @@ impl<A: Allocator> Arc<dyn Any + Send + Sync, A> {
         T: Any + Send + Sync,
     {
         unsafe {
-            let (ptr, alloc) = self.internal_into_inner_with_allocator();
+            let (ptr, alloc) = Arc::into_inner_with_allocator(self);
             Arc::from_inner_in(ptr.cast(), alloc)
         }
     }
@@ -3506,7 +3508,7 @@ impl<T, A: Allocator, const N: usize> TryFrom<Arc<[T], A>> for Arc<[T; N], A> {
 
     fn try_from(boxed_slice: Arc<[T], A>) -> Result<Self, Self::Error> {
         if boxed_slice.len() == N {
-            let (ptr, alloc) = boxed_slice.internal_into_inner_with_allocator();
+            let (ptr, alloc) = Arc::into_inner_with_allocator(boxed_slice);
             Ok(unsafe { Arc::from_inner_in(ptr.cast(), alloc) })
         } else {
             Err(boxed_slice)
diff --git a/library/core/src/fmt/fmt_trait_method_doc.md b/library/core/src/fmt/fmt_trait_method_doc.md
new file mode 100644
index 00000000000..493d929243d
--- /dev/null
+++ b/library/core/src/fmt/fmt_trait_method_doc.md
@@ -0,0 +1,8 @@
+Formats the value using the given formatter.
+
+# Errors
+
+This function should return [`Err`] if, and only if, the provided [`Formatter`] returns [`Err`].
+String formatting is considered an infallible operation; this function only
+returns a [`Result`] because writing to the underlying stream might fail and it must
+provide a way to propagate the fact that an error has occurred back up the stack.
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index ce0643a3f5e..9b372eac524 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -72,14 +72,24 @@ pub type Result = result::Result<(), Error>;
 /// The error type which is returned from formatting a message into a stream.
 ///
 /// This type does not support transmission of an error other than that an error
-/// occurred. Any extra information must be arranged to be transmitted through
-/// some other means.
-///
-/// An important thing to remember is that the type `fmt::Error` should not be
+/// occurred. This is because, despite the existence of this error,
+/// string formatting is considered an infallible operation.
+/// `fmt()` implementors should not return this `Error` unless they received it from their
+/// [`Formatter`]. The only time your code should create a new instance of this
+/// error is when implementing `fmt::Write`, in order to cancel the formatting operation when
+/// writing to the underlying stream fails.
+///
+/// Any extra information must be arranged to be transmitted through some other means,
+/// such as storing it in a field to be consulted after the formatting operation has been
+/// cancelled. (For example, this is how [`std::io::Write::write_fmt()`] propagates IO errors
+/// during writing.)
+///
+/// This type, `fmt::Error`, should not be
 /// confused with [`std::io::Error`] or [`std::error::Error`], which you may also
 /// have in scope.
 ///
 /// [`std::io::Error`]: ../../std/io/struct.Error.html
+/// [`std::io::Write::write_fmt()`]: ../../std/io/trait.Write.html#method.write_fmt
 /// [`std::error::Error`]: ../../std/error/trait.Error.html
 ///
 /// # Examples
@@ -118,8 +128,10 @@ pub trait Write {
     /// This function will return an instance of [`std::fmt::Error`][Error] on error.
     ///
     /// The purpose of that error is to abort the formatting operation when the underlying
-    /// destination encounters some error preventing it from accepting more text; it should
-    /// generally be propagated rather than handled, at least when implementing formatting traits.
+    /// destination encounters some error preventing it from accepting more text;
+    /// in particular, it does not communicate any information about *what* error occurred.
+    /// It should generally be propagated rather than handled, at least when implementing
+    /// formatting traits.
     ///
     /// # Examples
     ///
@@ -586,7 +598,7 @@ impl Display for Arguments<'_> {
 #[rustc_diagnostic_item = "Debug"]
 #[rustc_trivial_field_reads]
 pub trait Debug {
-    /// Formats the value using the given formatter.
+    #[doc = include_str!("fmt_trait_method_doc.md")]
     ///
     /// # Examples
     ///
@@ -703,7 +715,7 @@ pub use macros::Debug;
 #[rustc_diagnostic_item = "Display"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Display {
-    /// Formats the value using the given formatter.
+    #[doc = include_str!("fmt_trait_method_doc.md")]
     ///
     /// # Examples
     ///
@@ -777,7 +789,7 @@ pub trait Display {
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Octal {
-    /// Formats the value using the given formatter.
+    #[doc = include_str!("fmt_trait_method_doc.md")]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn fmt(&self, f: &mut Formatter<'_>) -> Result;
 }
@@ -836,7 +848,7 @@ pub trait Octal {
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Binary {
-    /// Formats the value using the given formatter.
+    #[doc = include_str!("fmt_trait_method_doc.md")]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn fmt(&self, f: &mut Formatter<'_>) -> Result;
 }
@@ -891,7 +903,7 @@ pub trait Binary {
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait LowerHex {
-    /// Formats the value using the given formatter.
+    #[doc = include_str!("fmt_trait_method_doc.md")]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn fmt(&self, f: &mut Formatter<'_>) -> Result;
 }
@@ -946,7 +958,7 @@ pub trait LowerHex {
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait UpperHex {
-    /// Formats the value using the given formatter.
+    #[doc = include_str!("fmt_trait_method_doc.md")]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn fmt(&self, f: &mut Formatter<'_>) -> Result;
 }
@@ -997,7 +1009,7 @@ pub trait UpperHex {
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_diagnostic_item = "Pointer"]
 pub trait Pointer {
-    /// Formats the value using the given formatter.
+    #[doc = include_str!("fmt_trait_method_doc.md")]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn fmt(&self, f: &mut Formatter<'_>) -> Result;
 }
@@ -1048,7 +1060,7 @@ pub trait Pointer {
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait LowerExp {
-    /// Formats the value using the given formatter.
+    #[doc = include_str!("fmt_trait_method_doc.md")]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn fmt(&self, f: &mut Formatter<'_>) -> Result;
 }
@@ -1099,7 +1111,7 @@ pub trait LowerExp {
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait UpperExp {
-    /// Formats the value using the given formatter.
+    #[doc = include_str!("fmt_trait_method_doc.md")]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn fmt(&self, f: &mut Formatter<'_>) -> Result;
 }
diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs
index 955efb9b0f9..e0c3b9f3b51 100644
--- a/library/core/src/mem/manually_drop.rs
+++ b/library/core/src/mem/manually_drop.rs
@@ -1,7 +1,7 @@
 use crate::ops::{Deref, DerefMut, DerefPure};
 use crate::ptr;
 
-/// A wrapper to inhibit compiler from automatically calling `T`’s destructor.
+/// A wrapper to inhibit the compiler from automatically calling `T`’s destructor.
 /// This wrapper is 0-cost.
 ///
 /// `ManuallyDrop<T>` is guaranteed to have the same layout and bit validity as
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index d8597369b9b..8283fdc459b 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -1467,8 +1467,9 @@ mod prim_usize {}
 /// For all types, `T: ?Sized`, and for all `t: &T` or `t: &mut T`, when such values cross an API
 /// boundary, the following invariants must generally be upheld:
 ///
+/// * `t` is non-null
 /// * `t` is aligned to `align_of_val(t)`
-/// * `t` is dereferenceable for `size_of_val(t)` many bytes
+/// * if `size_of_val(t) > 0`, then `t` is dereferenceable for `size_of_val(t)` many bytes
 ///
 /// If `t` points at address `a`, being "dereferenceable" for N bytes means that the memory range
 /// `[a, a + N)` is all contained within a single [allocated object].
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 8d7192c1b0f..f87b6bbfcfb 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -63,11 +63,39 @@
 //!
 //! ## Allocated object
 //!
-//! For several operations, such as [`offset`] or field projections (`expr.field`), the notion of an
-//! "allocated object" becomes relevant. An allocated object is a contiguous region of memory.
-//! Common examples of allocated objects include stack-allocated variables (each variable is a
-//! separate allocated object), heap allocations (each allocation created by the global allocator is
-//! a separate allocated object), and `static` variables.
+//! An *allocated object* is a subset of program memory which is addressable
+//! from Rust, and within which pointer arithmetic is possible. Examples of
+//! allocated objects include heap allocations, stack-allocated variables,
+//! statics, and consts. The safety preconditions of some Rust operations -
+//! such as `offset` and field projections (`expr.field`) - are defined in
+//! terms of the allocated objects on which they operate.
+//!
+//! An allocated object has a base address, a size, and a set of memory
+//! addresses. It is possible for an allocated object to have zero size, but
+//! such an allocated object will still have a base address. The base address
+//! of an allocated object is not necessarily unique. While it is currently the
+//! case that an allocated object always has a set of memory addresses which is
+//! fully contiguous (i.e., has no "holes"), there is no guarantee that this
+//! will not change in the future.
+//!
+//! For any allocated object with `base` address, `size`, and a set of
+//! `addresses`, the following are guaranteed:
+//! - For all addresses `a` in `addresses`, `a` is in the range `base .. (base +
+//!   size)` (note that this requires `a < base + size`, not `a <= base + size`)
+//! - `base` is not equal to [`null()`] (i.e., the address with the numerical
+//!   value 0)
+//! - `base + size <= usize::MAX`
+//! - `size <= isize::MAX`
+//!
+//! As a consequence of these guarantees, given any address `a` within the set
+//! of addresses of an allocated object:
+//! - It is guaranteed that `a - base` does not overflow `isize`
+//! - It is guaranteed that `a - base` is non-negative
+//! - It is guaranteed that, given `o = a - base` (i.e., the offset of `a` within
+//!   the allocated object), `base + o` will not wrap around the address space (in
+//!   other words, will not overflow `usize`)
+//!
+//! [`null()`]: null
 //!
 //! # Strict Provenance
 //!
diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs
index 5c4f0bf9b2b..8ad045275ad 100644
--- a/library/core/src/slice/ascii.rs
+++ b/library/core/src/slice/ascii.rs
@@ -114,18 +114,17 @@ impl [u8] {
     /// Returns a byte slice with leading ASCII whitespace bytes removed.
     ///
     /// 'Whitespace' refers to the definition used by
-    /// `u8::is_ascii_whitespace`.
+    /// [`u8::is_ascii_whitespace`].
     ///
     /// # Examples
     ///
     /// ```
-    /// #![feature(byte_slice_trim_ascii)]
-    ///
     /// assert_eq!(b" \t hello world\n".trim_ascii_start(), b"hello world\n");
     /// assert_eq!(b"  ".trim_ascii_start(), b"");
     /// assert_eq!(b"".trim_ascii_start(), b"");
     /// ```
-    #[unstable(feature = "byte_slice_trim_ascii", issue = "94035")]
+    #[stable(feature = "byte_slice_trim_ascii", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "byte_slice_trim_ascii", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub const fn trim_ascii_start(&self) -> &[u8] {
         let mut bytes = self;
@@ -144,18 +143,17 @@ impl [u8] {
     /// Returns a byte slice with trailing ASCII whitespace bytes removed.
     ///
     /// 'Whitespace' refers to the definition used by
-    /// `u8::is_ascii_whitespace`.
+    /// [`u8::is_ascii_whitespace`].
     ///
     /// # Examples
     ///
     /// ```
-    /// #![feature(byte_slice_trim_ascii)]
-    ///
     /// assert_eq!(b"\r hello world\n ".trim_ascii_end(), b"\r hello world");
     /// assert_eq!(b"  ".trim_ascii_end(), b"");
     /// assert_eq!(b"".trim_ascii_end(), b"");
     /// ```
-    #[unstable(feature = "byte_slice_trim_ascii", issue = "94035")]
+    #[stable(feature = "byte_slice_trim_ascii", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "byte_slice_trim_ascii", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub const fn trim_ascii_end(&self) -> &[u8] {
         let mut bytes = self;
@@ -175,18 +173,17 @@ impl [u8] {
     /// removed.
     ///
     /// 'Whitespace' refers to the definition used by
-    /// `u8::is_ascii_whitespace`.
+    /// [`u8::is_ascii_whitespace`].
     ///
     /// # Examples
     ///
     /// ```
-    /// #![feature(byte_slice_trim_ascii)]
-    ///
     /// assert_eq!(b"\r hello world\n ".trim_ascii(), b"hello world");
     /// assert_eq!(b"  ".trim_ascii(), b"");
     /// assert_eq!(b"".trim_ascii(), b"");
     /// ```
-    #[unstable(feature = "byte_slice_trim_ascii", issue = "94035")]
+    #[stable(feature = "byte_slice_trim_ascii", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "byte_slice_trim_ascii", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub const fn trim_ascii(&self) -> &[u8] {
         self.trim_ascii_start().trim_ascii_end()
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index b6f65907d3c..669cdc92e35 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -2531,15 +2531,14 @@ impl str {
     /// # Examples
     ///
     /// ```
-    /// #![feature(byte_slice_trim_ascii)]
-    ///
     /// assert_eq!(" \t \u{3000}hello world\n".trim_ascii_start(), "\u{3000}hello world\n");
     /// assert_eq!("  ".trim_ascii_start(), "");
     /// assert_eq!("".trim_ascii_start(), "");
     /// ```
-    #[unstable(feature = "byte_slice_trim_ascii", issue = "94035")]
     #[must_use = "this returns the trimmed string as a new slice, \
                   without modifying the original"]
+    #[stable(feature = "byte_slice_trim_ascii", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "byte_slice_trim_ascii", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub const fn trim_ascii_start(&self) -> &str {
         // SAFETY: Removing ASCII characters from a `&str` does not invalidate
@@ -2557,15 +2556,14 @@ impl str {
     /// # Examples
     ///
     /// ```
-    /// #![feature(byte_slice_trim_ascii)]
-    ///
     /// assert_eq!("\r hello world\u{3000}\n ".trim_ascii_end(), "\r hello world\u{3000}");
     /// assert_eq!("  ".trim_ascii_end(), "");
     /// assert_eq!("".trim_ascii_end(), "");
     /// ```
-    #[unstable(feature = "byte_slice_trim_ascii", issue = "94035")]
     #[must_use = "this returns the trimmed string as a new slice, \
                   without modifying the original"]
+    #[stable(feature = "byte_slice_trim_ascii", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "byte_slice_trim_ascii", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub const fn trim_ascii_end(&self) -> &str {
         // SAFETY: Removing ASCII characters from a `&str` does not invalidate
@@ -2584,15 +2582,14 @@ impl str {
     /// # Examples
     ///
     /// ```
-    /// #![feature(byte_slice_trim_ascii)]
-    ///
     /// assert_eq!("\r hello world\n ".trim_ascii(), "hello world");
     /// assert_eq!("  ".trim_ascii(), "");
     /// assert_eq!("".trim_ascii(), "");
     /// ```
-    #[unstable(feature = "byte_slice_trim_ascii", issue = "94035")]
     #[must_use = "this returns the trimmed string as a new slice, \
                   without modifying the original"]
+    #[stable(feature = "byte_slice_trim_ascii", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "byte_slice_trim_ascii", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub const fn trim_ascii(&self) -> &str {
         // SAFETY: Removing ASCII characters from a `&str` does not invalidate
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 52729ba1f84..1720fe84fa7 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -31,10 +31,11 @@ miniz_oxide = { version = "0.7.0", optional = true, default-features = false }
 addr2line = { version = "0.21.0", optional = true, default-features = false }
 
 [target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies]
-libc = { version = "0.2.153", default-features = false, features = ['rustc-dep-of-std'], public = true }
+libc = { version = "=0.2.153", default-features = false, features = ['rustc-dep-of-std'], public = true }
 
+# Pin libc (pending https://github.com/rust-lang/rust/pull/124560)
 [target.'cfg(all(windows, target_env = "msvc"))'.dependencies]
-libc = { version = "0.2.153", default-features = false }
+libc = { version = "=0.2.153", default-features = false }
 
 [target.'cfg(all(not(target_os = "aix"), not(all(windows, target_env = "msvc", not(target_vendor = "uwp")))))'.dependencies]
 object = { version = "0.32.0", default-features = false, optional = true, features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive'] }
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index af055152cbe..f55ec1588f9 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -1839,7 +1839,11 @@ pub trait Write {
                 if output.error.is_err() {
                     output.error
                 } else {
-                    Err(error::const_io_error!(ErrorKind::Uncategorized, "formatter error"))
+                    // This shouldn't happen: the underlying stream did not error, but somehow
+                    // the formatter still errored?
+                    panic!(
+                        "a formatting trait implementation returned an error when the underlying stream did not"
+                    );
                 }
             }
         }
@@ -2040,7 +2044,6 @@ pub trait Seek {
     /// # Example
     ///
     /// ```no_run
-    /// #![feature(seek_seek_relative)]
     /// use std::{
     ///     io::{self, Seek},
     ///     fs::File,
@@ -2055,7 +2058,7 @@ pub trait Seek {
     /// ```
     ///
     /// [`BufReader`]: crate::io::BufReader
-    #[unstable(feature = "seek_seek_relative", issue = "117374")]
+    #[stable(feature = "seek_seek_relative", since = "CURRENT_RUSTC_VERSION")]
     fn seek_relative(&mut self, offset: i64) -> Result<()> {
         self.seek(SeekFrom::Current(offset))?;
         Ok(())
diff --git a/library/std/src/sys/pal/unix/alloc.rs b/library/std/src/sys/pal/unix/alloc.rs
index 9938c0bac25..993bf55edcf 100644
--- a/library/std/src/sys/pal/unix/alloc.rs
+++ b/library/std/src/sys/pal/unix/alloc.rs
@@ -61,9 +61,7 @@ unsafe impl GlobalAlloc for System {
 cfg_if::cfg_if! {
     if #[cfg(any(
         target_os = "android",
-        target_os = "illumos",
         target_os = "redox",
-        target_os = "solaris",
         target_os = "espidf",
         target_os = "horizon",
         target_os = "vita",
diff --git a/library/std/src/sys/pal/unix/rand.rs b/library/std/src/sys/pal/unix/rand.rs
index d8f227b4ef4..e6df109a6b8 100644
--- a/library/std/src/sys/pal/unix/rand.rs
+++ b/library/std/src/sys/pal/unix/rand.rs
@@ -59,7 +59,14 @@ mod imp {
         unsafe { getrandom(buf.as_mut_ptr().cast(), buf.len(), libc::GRND_NONBLOCK) }
     }
 
-    #[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "freebsd", netbsd10))]
+    #[cfg(any(
+        target_os = "espidf",
+        target_os = "horizon",
+        target_os = "freebsd",
+        netbsd10,
+        target_os = "illumos",
+        target_os = "solaris"
+    ))]
     fn getrandom(buf: &mut [u8]) -> libc::ssize_t {
         unsafe { libc::getrandom(buf.as_mut_ptr().cast(), buf.len(), 0) }
     }
@@ -83,6 +90,8 @@ mod imp {
         target_os = "horizon",
         target_os = "freebsd",
         target_os = "dragonfly",
+        target_os = "solaris",
+        target_os = "illumos",
         netbsd10
     )))]
     fn getrandom_fill_bytes(_buf: &mut [u8]) -> bool {
@@ -96,6 +105,8 @@ mod imp {
         target_os = "horizon",
         target_os = "freebsd",
         target_os = "dragonfly",
+        target_os = "solaris",
+        target_os = "illumos",
         netbsd10
     ))]
     fn getrandom_fill_bytes(v: &mut [u8]) -> bool {
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index e464e444fea..e60e8f0aa1f 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -3,7 +3,6 @@ import argparse
 import contextlib
 import datetime
 import hashlib
-import json
 import os
 import re
 import shutil
@@ -52,7 +51,7 @@ def get(base, url, path, checksums, verbose=False):
 
     try:
         if url not in checksums:
-            raise RuntimeError(("src/stage0.json doesn't contain a checksum for {}. "
+            raise RuntimeError(("src/stage0 doesn't contain a checksum for {}. "
                                 "Pre-built artifacts might not be available for this "
                                 "target at this time, see https://doc.rust-lang.org/nightly"
                                 "/rustc/platform-support.html for more information.")
@@ -421,9 +420,9 @@ def output(filepath):
 
 
 class Stage0Toolchain:
-    def __init__(self, stage0_payload):
-        self.date = stage0_payload["date"]
-        self.version = stage0_payload["version"]
+    def __init__(self, date, version):
+        self.date = date
+        self.version = version
 
     def channel(self):
         return self.version + "-" + self.date
@@ -439,7 +438,7 @@ class DownloadInfo:
         bin_root,
         tarball_path,
         tarball_suffix,
-        checksums_sha256,
+        stage0_data,
         pattern,
         verbose,
     ):
@@ -448,7 +447,7 @@ class DownloadInfo:
         self.bin_root = bin_root
         self.tarball_path = tarball_path
         self.tarball_suffix = tarball_suffix
-        self.checksums_sha256 = checksums_sha256
+        self.stage0_data = stage0_data
         self.pattern = pattern
         self.verbose = verbose
 
@@ -458,7 +457,7 @@ def download_component(download_info):
             download_info.base_download_url,
             download_info.download_path,
             download_info.tarball_path,
-            download_info.checksums_sha256,
+            download_info.stage0_data,
             verbose=download_info.verbose,
         )
 
@@ -510,11 +509,12 @@ class RustBuild(object):
         build_dir = args.build_dir or self.get_toml('build-dir', 'build') or 'build'
         self.build_dir = os.path.abspath(build_dir)
 
-        with open(os.path.join(self.rust_root, "src", "stage0.json")) as f:
-            data = json.load(f)
-        self.checksums_sha256 = data["checksums_sha256"]
-        self.stage0_compiler = Stage0Toolchain(data["compiler"])
-        self.download_url = os.getenv("RUSTUP_DIST_SERVER") or data["config"]["dist_server"]
+        self.stage0_data = parse_stage0_file(os.path.join(self.rust_root, "src", "stage0"))
+        self.stage0_compiler = Stage0Toolchain(
+            self.stage0_data["compiler_date"],
+            self.stage0_data["compiler_version"]
+        )
+        self.download_url = os.getenv("RUSTUP_DIST_SERVER") or self.stage0_data["dist_server"]
 
         self.build = args.build or self.build_triple()
 
@@ -581,7 +581,7 @@ class RustBuild(object):
                     bin_root=self.bin_root(),
                     tarball_path=os.path.join(rustc_cache, filename),
                     tarball_suffix=tarball_suffix,
-                    checksums_sha256=self.checksums_sha256,
+                    stage0_data=self.stage0_data,
                     pattern=pattern,
                     verbose=self.verbose,
                 )
@@ -1071,6 +1071,16 @@ def parse_args(args):
 
     return parser.parse_known_args(args)[0]
 
+def parse_stage0_file(path):
+    result = {}
+    with open(path, 'r') as file:
+        for line in file:
+            line = line.strip()
+            if line and not line.startswith('#'):
+                key, value = line.split('=', 1)
+                result[key.strip()] = value.strip()
+    return result
+
 def bootstrap(args):
     """Configure, fetch, build and run the initial bootstrap"""
     rust_root = os.path.abspath(os.path.join(__file__, '../../..'))
diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs
index 77fa46da0c9..045cde56f41 100644
--- a/src/bootstrap/src/core/builder.rs
+++ b/src/bootstrap/src/core/builder.rs
@@ -320,11 +320,13 @@ const PATH_REMAP: &[(&str, &[&str])] = &[
     (
         "tests",
         &[
+            // tidy-alphabetical-start
             "tests/assembly",
             "tests/codegen",
             "tests/codegen-units",
             "tests/coverage",
             "tests/coverage-run-rustdoc",
+            "tests/crashes",
             "tests/debuginfo",
             "tests/incremental",
             "tests/mir-opt",
@@ -340,6 +342,7 @@ const PATH_REMAP: &[(&str, &[&str])] = &[
             "tests/rustdoc-ui",
             "tests/ui",
             "tests/ui-fulldeps",
+            // tidy-alphabetical-end
         ],
     ),
 ];
diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs
index 9898d495c02..9710365ef11 100644
--- a/src/bootstrap/src/core/builder/tests.rs
+++ b/src/bootstrap/src/core/builder/tests.rs
@@ -129,6 +129,26 @@ fn validate_path_remap() {
 }
 
 #[test]
+fn check_missing_paths_for_x_test_tests() {
+    let build = Build::new(configure("test", &["A-A"], &["A-A"]));
+
+    let (_, tests_remap_paths) =
+        PATH_REMAP.iter().find(|(target_path, _)| *target_path == "tests").unwrap();
+
+    let tests_dir = fs::read_dir(build.src.join("tests")).unwrap();
+    for dir in tests_dir {
+        let path = dir.unwrap().path();
+
+        // Skip if not a test directory.
+        if path.ends_with("tests/auxiliary") || !path.is_dir() {
+            continue
+        }
+
+        assert!(tests_remap_paths.iter().any(|item| path.ends_with(*item)), "{} is missing in PATH_REMAP tests list.", path.display());
+    }
+}
+
+#[test]
 fn test_exclude() {
     let mut config = configure("test", &["A-A"], &["A-A"]);
     config.skip = vec!["src/tools/tidy".into()];
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index 0167c51fc7e..bb51433a3dc 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -181,7 +181,7 @@ pub struct Config {
     pub test_compare_mode: bool,
     pub color: Color,
     pub patch_binaries_for_nix: Option<bool>,
-    pub stage0_metadata: Stage0Metadata,
+    pub stage0_metadata: build_helper::stage0_parser::Stage0,
     pub android_ndk: Option<PathBuf>,
     /// Whether to use the `c` feature of the `compiler_builtins` crate.
     pub optimized_compiler_builtins: bool,
@@ -351,34 +351,6 @@ pub struct Config {
     pub paths: Vec<PathBuf>,
 }
 
-#[derive(Default, Deserialize, Clone)]
-pub struct Stage0Metadata {
-    pub compiler: CompilerMetadata,
-    pub config: Stage0Config,
-    pub checksums_sha256: HashMap<String, String>,
-    pub rustfmt: Option<RustfmtMetadata>,
-}
-#[derive(Default, Deserialize, Clone)]
-pub struct CompilerMetadata {
-    pub date: String,
-    pub version: String,
-}
-
-#[derive(Default, Deserialize, Clone)]
-pub struct Stage0Config {
-    pub dist_server: String,
-    pub artifacts_server: String,
-    pub artifacts_with_llvm_assertions_server: String,
-    pub git_merge_commit_email: String,
-    pub git_repository: String,
-    pub nightly_branch: String,
-}
-#[derive(Default, Deserialize, Clone)]
-pub struct RustfmtMetadata {
-    pub date: String,
-    pub version: String,
-}
-
 #[derive(Clone, Debug, Default)]
 pub enum RustfmtState {
     SystemToolchain(PathBuf),
@@ -1298,13 +1270,13 @@ impl Config {
                 Some(p) => PathBuf::from(p),
                 None => git_root,
             };
-            // If this doesn't have at least `stage0.json`, we guessed wrong. This can happen when,
+            // If this doesn't have at least `stage0`, we guessed wrong. This can happen when,
             // for example, the build directory is inside of another unrelated git directory.
             // In that case keep the original `CARGO_MANIFEST_DIR` handling.
             //
             // NOTE: this implies that downloadable bootstrap isn't supported when the build directory is outside
             // the source directory. We could fix that by setting a variable from all three of python, ./x, and x.ps1.
-            if git_root.join("src").join("stage0.json").exists() {
+            if git_root.join("src").join("stage0").exists() {
                 config.src = git_root;
             }
         } else {
@@ -1322,9 +1294,7 @@ impl Config {
             .to_path_buf();
         }
 
-        let stage0_json = t!(std::fs::read(config.src.join("src").join("stage0.json")));
-
-        config.stage0_metadata = t!(serde_json::from_slice::<Stage0Metadata>(&stage0_json));
+        config.stage0_metadata = build_helper::stage0_parser::parse_stage0_file();
 
         // Read from `--config`, then `RUST_BOOTSTRAP_CONFIG`, then `./config.toml`, then `config.toml` in the root directory.
         let toml_path = flags
diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs
index 75e0f646da6..a074d53aa36 100644
--- a/src/bootstrap/src/core/download.rs
+++ b/src/bootstrap/src/core/download.rs
@@ -9,9 +9,9 @@ use std::{
 };
 
 use build_helper::ci::CiEnv;
+use build_helper::stage0_parser::VersionMetadata;
 use xz2::bufread::XzDecoder;
 
-use crate::core::config::RustfmtMetadata;
 use crate::utils::helpers::{check_run, exe, program_out_of_date};
 use crate::{core::build_steps::llvm::detect_llvm_sha, utils::helpers::hex_encode};
 use crate::{t, Config};
@@ -408,7 +408,7 @@ impl Config {
     /// NOTE: rustfmt is a completely different toolchain than the bootstrap compiler, so it can't
     /// reuse target directories or artifacts
     pub(crate) fn maybe_download_rustfmt(&self) -> Option<PathBuf> {
-        let RustfmtMetadata { date, version } = self.stage0_metadata.rustfmt.as_ref()?;
+        let VersionMetadata { date, version } = self.stage0_metadata.rustfmt.as_ref()?;
         let channel = format!("{version}-{date}");
 
         let host = self.build;
@@ -606,7 +606,7 @@ impl Config {
             DownloadSource::Dist => {
                 let dist_server = env::var("RUSTUP_DIST_SERVER")
                     .unwrap_or(self.stage0_metadata.config.dist_server.to_string());
-                // NOTE: make `dist` part of the URL because that's how it's stored in src/stage0.json
+                // NOTE: make `dist` part of the URL because that's how it's stored in src/stage0
                 (dist_server, format!("dist/{key}/{filename}"), true)
             }
         };
@@ -616,7 +616,7 @@ impl Config {
         // this on each and every nightly ...
         let checksum = if should_verify {
             let error = format!(
-                "src/stage0.json doesn't contain a checksum for {url}. \
+                "src/stage0 doesn't contain a checksum for {url}. \
                 Pre-built artifacts might not be available for this \
                 target at this time, see https://doc.rust-lang.org/nightly\
                 /rustc/platform-support.html for more information."
diff --git a/src/ci/docker/host-x86_64/dist-armv7-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-armv7-linux/Dockerfile
index dab0667ed55..e718437aaaa 100644
--- a/src/ci/docker/host-x86_64/dist-armv7-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-armv7-linux/Dockerfile
@@ -25,5 +25,5 @@ ENV CC_armv7_unknown_linux_gnueabihf=armv7-unknown-linux-gnueabihf-gcc \
 
 ENV HOSTS=armv7-unknown-linux-gnueabihf
 
-ENV RUST_CONFIGURE_ARGS --enable-full-tools --disable-docs
+ENV RUST_CONFIGURE_ARGS --enable-full-tools --enable-profiler --disable-docs
 ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index c9c0ee4067f..c7e3293e35a 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -74,6 +74,7 @@
     - [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md)
     - [\*-win7-windows-msvc](platform-support/win7-windows-msvc.md)
     - [x86_64-fortanix-unknown-sgx](platform-support/x86_64-fortanix-unknown-sgx.md)
+    - [x86_64-unknown-linux-none.md](platform-support/x86_64-unknown-linux-none.md)
     - [x86_64-unknown-none](platform-support/x86_64-unknown-none.md)
     - [x86_64h-apple-darwin](platform-support/x86_64h-apple-darwin.md)
 - [Targets](targets/index.md)
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 764798a80e6..8adc410455e 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -382,5 +382,6 @@ target | std | host | notes
 [`x86_64-win7-windows-msvc`](platform-support/win7-windows-msvc.md) | ✓ |   | 64-bit Windows 7 support
 `x86_64-wrs-vxworks` | ? |  |
 [`x86_64h-apple-darwin`](platform-support/x86_64h-apple-darwin.md) | ✓ | ✓ | macOS with late-gen Intel (at least Haswell)
+[`x86_64-unknown-linux-none`](platform-support/x86_64-unknown-linux-none.md) | * |  | 64-bit Linux with no libc
 
 [runs on NVIDIA GPUs]: https://github.com/japaric-archived/nvptx#targets
diff --git a/src/doc/rustc/src/platform-support/fuchsia.md b/src/doc/rustc/src/platform-support/fuchsia.md
index 9c2e05b57f5..3e1db692f50 100644
--- a/src/doc/rustc/src/platform-support/fuchsia.md
+++ b/src/doc/rustc/src/platform-support/fuchsia.md
@@ -387,7 +387,7 @@ meta/hello_fuchsia.cm=pkg/meta/hello_fuchsia.cm
 ```
 
 *Note: Relative manifest paths are resolved starting from the working directory
-of `pm`. Make sure to fill out `<SDK_PATH>` with the path to the downloaded
+of `ffx`. Make sure to fill out `<SDK_PATH>` with the path to the downloaded
 SDK.*
 
 The `.manifest` file will be used to describe the contents of the package by
@@ -459,12 +459,10 @@ hello_fuchsia/
 Next, we'll build a package manifest as defined by our manifest:
 
 ```sh
-${SDK_PATH}/tools/${ARCH}/pm \
-    -api-level $(${SDK_PATH}/tools/${ARCH}/ffx version -v | grep "api-level" | head -1 |  awk -F ' ' '{print $2}') \
-    -o pkg/hello_fuchsia_manifest \
-    -m pkg/hello_fuchsia.manifest \
-    build \
-    -output-package-manifest pkg/hello_fuchsia_package_manifest
+${SDK_PATH}/tools/${ARCH}/ffx package build \
+    --api-level $(${SDK_PATH}/tools/${ARCH}/ffx --machine json version | jq .tool_version.api_level) \
+    --out pkg/hello_fuchsia_manifest \
+    pkg/hello_fuchsia.manifest
 ```
 
 This will produce `pkg/hello_fuchsia_manifest/` which is a package manifest we can
@@ -498,8 +496,7 @@ to.
 We can set up our repository with:
 
 ```sh
-${SDK_PATH}/tools/${ARCH}/pm newrepo \
-    -repo pkg/repo
+${SDK_PATH}/tools/${ARCH}/ffx repository create pkg/repo
 ```
 
 **Current directory structure**
@@ -523,17 +520,17 @@ hello_fuchsia/
 We can publish our new package to that repository with:
 
 ```sh
-${SDK_PATH}/tools/${ARCH}/pm publish \
-    -repo pkg/repo \
-    -lp -f <(echo "pkg/hello_fuchsia_package_manifest")
+${SDK_PATH}/tools/${ARCH}/ffx repository publish \
+    --package pkg/hello_fuchsia_package_manifest \
+    pkg/repo
 ```
 
 Then we can add the repository to `ffx`'s package server as `hello-fuchsia` using:
 
 ```sh
 ${SDK_PATH}/tools/${ARCH}/ffx repository add-from-pm \
-    pkg/repo \
-    -r hello-fuchsia
+    --repository hello-fuchsia \
+    pkg/repo
 ```
 
 ## Running a Fuchsia component on an emulator
diff --git a/src/doc/rustc/src/platform-support/x86_64-unknown-linux-none.md b/src/doc/rustc/src/platform-support/x86_64-unknown-linux-none.md
new file mode 100644
index 00000000000..5608b5cb778
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/x86_64-unknown-linux-none.md
@@ -0,0 +1,40 @@
+# `x86_64-unknown-linux-none`
+
+**Tier: 3**
+
+Freestanding x86-64 linux binary with no dependency on libc.
+
+## Target maintainers
+
+- [morr0ne](https://github.com/morr0ne/)
+
+## Requirements
+
+This target is cross compiled and can be built from any host.
+
+This target has no support for host tools, std, or alloc.
+
+## Building the target
+
+The target can be built by enabling it for a `rustc` build:
+
+```toml
+[build]
+build-stage = 1
+target = ["x86_64-unknown-linux-none"]
+```
+
+## Building Rust programs
+
+Rust does not yet ship pre-compiled artifacts for this target. To compile for
+this target, you will either need to build Rust with the target enabled (see
+"Building the target" above), or build your own copy of `core` by using
+`build-std` or similar.
+
+## Testing
+
+Created binaries will run on linux without any external requirements
+
+## Cross-compilation toolchains and C code
+
+Support for C code is currently untested
diff --git a/src/doc/rustc/src/symbol-mangling/v0.md b/src/doc/rustc/src/symbol-mangling/v0.md
index 61f747fac83..763694a9fda 100644
--- a/src/doc/rustc/src/symbol-mangling/v0.md
+++ b/src/doc/rustc/src/symbol-mangling/v0.md
@@ -739,6 +739,8 @@ The type encodings based on the initial tag character are:
   * `z` — `!`
   * `p` — [placeholder] `_`
 
+Remaining primitives are encoded as a crate production, e.g. `C4f128`.
+
 * `A` — An [array][reference-array] `[T; N]`.
 
   > <span id="array-type">array-type</span> → `A` *[type]* *[const]*
diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md
index 822f341b370..69fb7e3313f 100644
--- a/src/doc/rustdoc/src/command-line-arguments.md
+++ b/src/doc/rustdoc/src/command-line-arguments.md
@@ -273,7 +273,7 @@ will be added.
 
 When rendering Rust files, this flag is ignored.
 
-## `--html-in-header`: include more HTML in <head>
+## `--html-in-header`: include more HTML in `<head>`
 
 Using this flag looks like this:
 
diff --git a/src/doc/style-guide/src/editions.md b/src/doc/style-guide/src/editions.md
index b9a89c20cee..9d593f80810 100644
--- a/src/doc/style-guide/src/editions.md
+++ b/src/doc/style-guide/src/editions.md
@@ -43,6 +43,7 @@ include:
 - Miscellaneous `rustfmt` bugfixes.
 - Use version-sort (sort `x8`, `x16`, `x32`, `x64`, `x128` in that order).
 - Change "ASCIIbetical" sort to Unicode-aware "non-lowercase before lowercase".
+- Format single associated type `where` clauses on the same line if they fit.
 
 ## Rust 2015/2018/2021 style edition
 
diff --git a/src/doc/style-guide/src/items.md b/src/doc/style-guide/src/items.md
index 0066a4bacb9..c0628691b77 100644
--- a/src/doc/style-guide/src/items.md
+++ b/src/doc/style-guide/src/items.md
@@ -295,8 +295,18 @@ Prefer to use single-letter names for generic parameters.
 
 These rules apply for `where` clauses on any item.
 
-If immediately following a closing bracket of any kind, write the keyword
-`where` on the same line, with a space before it.
+If a where clause is short, and appears on a short one-line function
+declaration with no body or on a short type with no `=`, format it on
+the same line as the declaration:
+
+```rust
+fn new(&self) -> Self where Self: Sized;
+
+type Item<'a>: SomeTrait where Self: 'a;
+```
+
+Otherwise, if immediately following a closing bracket of any kind, write the
+keyword `where` on the same line, with a space before it.
 
 Otherwise, put `where` on a new line at the same indentation level. Put each
 component of a `where` clause on its own line, block-indented. Use a trailing
@@ -347,7 +357,7 @@ where
 ```
 
 If a `where` clause is very short, prefer using an inline bound on the type
-parameter.
+parameter if possible.
 
 If a component of a `where` clause does not fit and contains `+`, break it
 before each `+` and block-indent the continuation lines. Put each bound on its
@@ -421,9 +431,21 @@ Format associated types like type aliases. Where an associated type has a
 bound, put a space after the colon but not before:
 
 ```rust
-pub type Foo: Bar;
+type Foo: Bar;
 ```
 
+If an associated type is short, has no `=`, and has a `where` clause with only
+one entry, format the entire type declaration including the `where` clause on
+the same line if it fits:
+
+```rust
+type Item<'a> where Self: 'a;
+type Item<'a>: PartialEq + Send where Self: 'a;
+```
+
+If the associated type has a `=`, or if the `where` clause contains multiple
+entries, format it across multiple lines as with a type alias.
+
 ## extern items
 
 When writing extern items (such as `extern "C" fn`), always specify the ABI.
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 90f2e3d09fe..0ab23d159a6 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -453,7 +453,15 @@ fn clean_projection_predicate<'tcx>(
     cx: &mut DocContext<'tcx>,
 ) -> WherePredicate {
     WherePredicate::EqPredicate {
-        lhs: clean_projection(pred.map_bound(|p| p.projection_ty), cx, None),
+        lhs: clean_projection(
+            pred.map_bound(|p| {
+                // FIXME: This needs to be made resilient for `AliasTerm`s that
+                // are associated consts.
+                p.projection_term.expect_ty(cx.tcx)
+            }),
+            cx,
+            None,
+        ),
         rhs: clean_middle_term(pred.map_bound(|p| p.term), cx),
     }
 }
@@ -838,7 +846,7 @@ fn clean_ty_generics<'tcx>(
                         }
                     }
                     ty::ClauseKind::Projection(p) => {
-                        if let ty::Param(param) = p.projection_ty.self_ty().kind() {
+                        if let ty::Param(param) = p.projection_term.self_ty().kind() {
                             projection = Some(bound_p.rebind(p));
                             return Some(param.index);
                         }
@@ -857,7 +865,15 @@ fn clean_ty_generics<'tcx>(
                 bounds.extend(pred.get_bounds().into_iter().flatten().cloned());
 
                 if let Some(proj) = projection
-                    && let lhs = clean_projection(proj.map_bound(|p| p.projection_ty), cx, None)
+                    && let lhs = clean_projection(
+                        proj.map_bound(|p| {
+                            // FIXME: This needs to be made resilient for `AliasTerm`s that
+                            // are associated consts.
+                            p.projection_term.expect_ty(cx.tcx)
+                        }),
+                        cx,
+                        None,
+                    )
                     && let Some((_, trait_did, name)) = lhs.projection()
                 {
                     impl_trait_proj.entry(param_idx).or_default().push((
@@ -2126,7 +2142,10 @@ pub(crate) fn clean_middle_ty<'tcx>(
                                 // HACK(compiler-errors): Doesn't actually matter what self
                                 // type we put here, because we're only using the GAT's args.
                                 .with_self_ty(cx.tcx, cx.tcx.types.self_param)
-                                .projection_ty
+                                .projection_term
+                                // FIXME: This needs to be made resilient for `AliasTerm`s
+                                // that are associated consts.
+                                .expect_ty(cx.tcx)
                         }),
                         cx,
                     ),
@@ -2284,10 +2303,12 @@ fn clean_middle_opaque_bounds<'tcx>(
                 .iter()
                 .filter_map(|bound| {
                     if let ty::ClauseKind::Projection(proj) = bound.kind().skip_binder() {
-                        if proj.projection_ty.trait_ref(cx.tcx) == trait_ref.skip_binder() {
+                        if proj.projection_term.trait_ref(cx.tcx) == trait_ref.skip_binder() {
                             Some(TypeBinding {
                                 assoc: projection_to_path_segment(
-                                    bound.kind().rebind(proj.projection_ty),
+                                    // FIXME: This needs to be made resilient for `AliasTerm`s that
+                                    // are associated consts.
+                                    bound.kind().rebind(proj.projection_term.expect_ty(cx.tcx)),
                                     cx,
                                 ),
                                 kind: TypeBindingKind::Equality {
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 0ad4c9c2346..19aa5ef949e 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -686,9 +686,9 @@ pub(crate) fn make_test(
                     }
                 }
 
-                // The supplied slice is only used for diagnostics,
+                // The supplied item is only used for diagnostics,
                 // which are swallowed here anyway.
-                parser.maybe_consume_incorrect_semicolon(&[]);
+                parser.maybe_consume_incorrect_semicolon(None);
             }
 
             // Reset errors so that they won't be reported as compiler bugs when dropping the
diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs
index 4eeaaa2bb70..3a71dd82db8 100644
--- a/src/librustdoc/passes/mod.rs
+++ b/src/librustdoc/passes/mod.rs
@@ -8,6 +8,9 @@ use crate::core::DocContext;
 mod stripper;
 pub(crate) use stripper::*;
 
+mod strip_aliased_non_local;
+pub(crate) use self::strip_aliased_non_local::STRIP_ALIASED_NON_LOCAL;
+
 mod strip_hidden;
 pub(crate) use self::strip_hidden::STRIP_HIDDEN;
 
@@ -71,6 +74,7 @@ pub(crate) enum Condition {
 pub(crate) const PASSES: &[Pass] = &[
     CHECK_CUSTOM_CODE_CLASSES,
     CHECK_DOC_TEST_VISIBILITY,
+    STRIP_ALIASED_NON_LOCAL,
     STRIP_HIDDEN,
     STRIP_PRIVATE,
     STRIP_PRIV_IMPORTS,
@@ -86,6 +90,7 @@ pub(crate) const DEFAULT_PASSES: &[ConditionalPass] = &[
     ConditionalPass::always(CHECK_CUSTOM_CODE_CLASSES),
     ConditionalPass::always(COLLECT_TRAIT_IMPLS),
     ConditionalPass::always(CHECK_DOC_TEST_VISIBILITY),
+    ConditionalPass::always(STRIP_ALIASED_NON_LOCAL),
     ConditionalPass::new(STRIP_HIDDEN, WhenNotDocumentHidden),
     ConditionalPass::new(STRIP_PRIVATE, WhenNotDocumentPrivate),
     ConditionalPass::new(STRIP_PRIV_IMPORTS, WhenDocumentPrivate),
diff --git a/src/librustdoc/passes/strip_aliased_non_local.rs b/src/librustdoc/passes/strip_aliased_non_local.rs
new file mode 100644
index 00000000000..848cbd5ed99
--- /dev/null
+++ b/src/librustdoc/passes/strip_aliased_non_local.rs
@@ -0,0 +1,57 @@
+use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::Visibility;
+
+use crate::clean;
+use crate::clean::Item;
+use crate::core::DocContext;
+use crate::fold::{strip_item, DocFolder};
+use crate::passes::Pass;
+
+pub(crate) const STRIP_ALIASED_NON_LOCAL: Pass = Pass {
+    name: "strip-aliased-non-local",
+    run: strip_aliased_non_local,
+    description: "strips all non-local private aliased items from the output",
+};
+
+fn strip_aliased_non_local(krate: clean::Crate, cx: &mut DocContext<'_>) -> clean::Crate {
+    let mut stripper = AliasedNonLocalStripper { tcx: cx.tcx };
+    stripper.fold_crate(krate)
+}
+
+struct AliasedNonLocalStripper<'tcx> {
+    tcx: TyCtxt<'tcx>,
+}
+
+impl<'tcx> DocFolder for AliasedNonLocalStripper<'tcx> {
+    fn fold_item(&mut self, i: Item) -> Option<Item> {
+        Some(match *i.kind {
+            clean::TypeAliasItem(..) => {
+                let mut stripper = NonLocalStripper { tcx: self.tcx };
+                // don't call `fold_item` as that could strip the type-alias it-self
+                // which we don't want to strip out
+                stripper.fold_item_recur(i)
+            }
+            _ => self.fold_item_recur(i),
+        })
+    }
+}
+
+struct NonLocalStripper<'tcx> {
+    tcx: TyCtxt<'tcx>,
+}
+
+impl<'tcx> DocFolder for NonLocalStripper<'tcx> {
+    fn fold_item(&mut self, i: Item) -> Option<Item> {
+        // If not local, we want to respect the original visibility of
+        // the field and not the one given by the user for the currrent crate.
+        //
+        // FIXME(#125009): Not-local should probably consider same Cargo workspace
+        if !i.def_id().map_or(true, |did| did.is_local()) {
+            if i.visibility(self.tcx) != Some(Visibility::Public) || i.is_doc_hidden() {
+                return Some(strip_item(i));
+            }
+        }
+
+        Some(self.fold_item_recur(i))
+    }
+}
diff --git a/src/stage0 b/src/stage0
new file mode 100644
index 00000000000..5ec8f5b715e
--- /dev/null
+++ b/src/stage0
@@ -0,0 +1,447 @@
+dist_server=https://static.rust-lang.org
+artifacts_server=https://ci-artifacts.rust-lang.org/rustc-builds
+artifacts_with_llvm_assertions_server=https://ci-artifacts.rust-lang.org/rustc-builds-alt
+git_merge_commit_email=bors@rust-lang.org
+git_repository=rust-lang/rust
+nightly_branch=master
+
+# The configuration above this comment is editable, and can be changed
+# by forks of the repository if they have alternate values.
+#
+# The section below is generated by `./x.py run src/tools/bump-stage0`,
+# run that command again to update the bootstrap compiler.
+#
+# All changes below this comment will be overridden the next time the
+# tool is executed.
+            
+compiler_date=2024-04-29
+compiler_version=beta
+rustfmt_date=2024-04-29
+rustfmt_version=nightly
+
+dist/2024-04-29/cargo-beta-aarch64-apple-darwin.tar.gz=5a8c5e48a88e7c7b41eb720d60fbd2e879b97639c7ff83710526e8e6caaf8afb
+dist/2024-04-29/cargo-beta-aarch64-apple-darwin.tar.xz=0d237535ae8d435d99104fa5b9dbf41878e2304bb0f2eb574bf17dd685caadc2
+dist/2024-04-29/cargo-beta-aarch64-pc-windows-msvc.tar.gz=c56733bb6198af0a9b0df9a44ef979150e00de33b70853c239cccfcce23c328f
+dist/2024-04-29/cargo-beta-aarch64-pc-windows-msvc.tar.xz=7da5f887151215ddec640684077d98551fe2aed75a3ece2c73b20698754a70bb
+dist/2024-04-29/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=73851e304a539d41bedc0d8a5d98800c8279ae623d3e58e863f8c1f8b458b01c
+dist/2024-04-29/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=db9c28841344b0154756e19a21795ef6e0c4e27c7844be9996824f1039edaa81
+dist/2024-04-29/cargo-beta-aarch64-unknown-linux-musl.tar.gz=a706c8c7e37b9e80d7faa000c5d179a772746eef071387fb2879fdeab1f1f891
+dist/2024-04-29/cargo-beta-aarch64-unknown-linux-musl.tar.xz=2060634afe1b4a19bae874c6ce3cf4256e613af26e06104b45da5bd71cfb133c
+dist/2024-04-29/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=7af61e74faea669fdd41793e4b88eb6a37bfacf845af364ee02bb7cf08c612c7
+dist/2024-04-29/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=4759fb3e3d89ead605c4eeba23be5cb9b3ac98086a9de20f8dbfdfa9282ee486
+dist/2024-04-29/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=4cab18df2d94702e8b551357373bcae60d1023e644148f0f82e8971023362121
+dist/2024-04-29/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=7de4f0d72b4e5770376ede82b02d6bcfd450788a40375fad34d75524c941d72c
+dist/2024-04-29/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=6401391a426cf33d6c58f07e7b2828b178720cb4f2b8577ae932b5f5b7d6744e
+dist/2024-04-29/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=c3f6729bc769325046f0f62c51b5bed30068c37dc2a36a6283e50565d8cb7d5c
+dist/2024-04-29/cargo-beta-i686-pc-windows-gnu.tar.gz=d116c97c1242220c7972b63010aee1ed36bf5353e84a06d3561cd5fe9d7dae84
+dist/2024-04-29/cargo-beta-i686-pc-windows-gnu.tar.xz=65eba577f7775b3eef36e7f000b5007264392b20a7759f8ed567f3a45b2877db
+dist/2024-04-29/cargo-beta-i686-pc-windows-msvc.tar.gz=d418a3371b3631328bde2b1e0c3159700f12424e83b1d8ece1349fea90f9e403
+dist/2024-04-29/cargo-beta-i686-pc-windows-msvc.tar.xz=23ae73c776fdb0795944656d743444e3b4c440f45084028206c1aec52333b1ba
+dist/2024-04-29/cargo-beta-i686-unknown-linux-gnu.tar.gz=b6bbdeb7c8bfac2e8a083adb4782caf5321799f47acb4eaf81da32bd11730e9c
+dist/2024-04-29/cargo-beta-i686-unknown-linux-gnu.tar.xz=6b409691da6ddb8c04409667b2c3d9d6429c6b5bf53ad18177248406a5f06cb9
+dist/2024-04-29/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=24cd888d14a788e8fb5b886735f3c07a028a8681df48a777b2bb971c62a175ae
+dist/2024-04-29/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=e8eece6412936fe4dc863a5e19e6766fbb20e81da0069ad7831465e638db23da
+dist/2024-04-29/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=8f007a2aa02e35c5ddb2152cc7589092a0e3083211c6aa23e676e3a3ad5a4b8d
+dist/2024-04-29/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=3e423e693dd0813f5d87d9eded94894076258ece56684f3598321cd013aeef3c
+dist/2024-04-29/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=2eec5e45e389a52b526a5cf683d56a9df92004f6095936b16cd8d7d63722cc6c
+dist/2024-04-29/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=64c5135cbff9d4fa9575074c55e79d85f72cb1783498a72e1f77865b9b2d1ba3
+dist/2024-04-29/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=d64552a80ca386728e42f00d7f1c700b5e30e5a6939f32ffa15a7ce715d4c8e9
+dist/2024-04-29/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=fe91adce8ba35bf06251448b5214ed112556dc8814de92e66bc5dc51193c442f
+dist/2024-04-29/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=77aafa8b63a4bf4475e82cd777646be5254e1f62d44b2a8fbd40066fdd7020d3
+dist/2024-04-29/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=c38f0b4adcc8e48f70b475636bbd5851406bba296d66df12e1ba54888a4bf21a
+dist/2024-04-29/cargo-beta-s390x-unknown-linux-gnu.tar.gz=c05df24d7e8dff26c01055ad40f9e81e6fcb3ae634ecc1f7cc43c3108677fa0e
+dist/2024-04-29/cargo-beta-s390x-unknown-linux-gnu.tar.xz=47e8f4ec4d996600e60ddc49daeeb43d4c21e0583a86c12395c16eddc7db76ee
+dist/2024-04-29/cargo-beta-x86_64-apple-darwin.tar.gz=f024bd225b77160dc2fabde78002c8deac5cbb9a35345340964c3b988b0d1791
+dist/2024-04-29/cargo-beta-x86_64-apple-darwin.tar.xz=96c9e44bd9f0c85c793e3dd6043cc4f89fbeeab5ddf0fdb5daefca8f690bce05
+dist/2024-04-29/cargo-beta-x86_64-pc-windows-gnu.tar.gz=517889f222b62150fe16bcfd3a0eb5f353956b0084d85713480197bff4558145
+dist/2024-04-29/cargo-beta-x86_64-pc-windows-gnu.tar.xz=a6653ea4aec51569c1300c044d8bf2517a1f5111f710d12cd352190425b8f317
+dist/2024-04-29/cargo-beta-x86_64-pc-windows-msvc.tar.gz=4cb5b5054dffe6721efbbf29192a67e59cda69ea4ab4791aaec6f314eefa5a5e
+dist/2024-04-29/cargo-beta-x86_64-pc-windows-msvc.tar.xz=08bc45be22e9e4f615d1c9e70500046c8db89045f5d40dcde853c610591712a7
+dist/2024-04-29/cargo-beta-x86_64-unknown-freebsd.tar.gz=9661357ee8ea8973016fdbaa2de3cb98713136dcd25f07aa9f9d101180276815
+dist/2024-04-29/cargo-beta-x86_64-unknown-freebsd.tar.xz=7fab806227d1a3be817602abb121ac7e039ba0bbf81e0a1d47bdcccca74203c6
+dist/2024-04-29/cargo-beta-x86_64-unknown-illumos.tar.gz=4c79bb48cfe64bd38af7fe3660cd8bdc99ec90738a0d8fdf80843ecda910dab0
+dist/2024-04-29/cargo-beta-x86_64-unknown-illumos.tar.xz=0fb9edfdafde1820ccb25c22369cafb0e75e68795effeb615cb284a5837c75ba
+dist/2024-04-29/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=c1902a072e61ab5ae9737a1092732e3972deee426424bc85fcf8702adffdd41d
+dist/2024-04-29/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=d39ea1195dcc95e428bd540abd2db5b5d4c997a7661a41a4c0ca41cbdd18d27e
+dist/2024-04-29/cargo-beta-x86_64-unknown-linux-musl.tar.gz=0edfdb6f6bb2a4a1a96a5e95cec897c444c936e6624bb4a530ffed4847b97445
+dist/2024-04-29/cargo-beta-x86_64-unknown-linux-musl.tar.xz=70c264b7845febdee45d0c6e44b65d47ba7f367ef33ec906a9fd7f992ba7cc13
+dist/2024-04-29/cargo-beta-x86_64-unknown-netbsd.tar.gz=f1bd6417a54f3b53d572ce4af799242db7c11265c71201cc09c78d71be38c13a
+dist/2024-04-29/cargo-beta-x86_64-unknown-netbsd.tar.xz=53569810469c483785333759f86434706ee5368d5e18270ee13a17817ad57d40
+dist/2024-04-29/clippy-beta-aarch64-apple-darwin.tar.gz=7b693bde61a090854527a145455ff774314c65ec0cd47d25a19c76c6a166d96c
+dist/2024-04-29/clippy-beta-aarch64-apple-darwin.tar.xz=2494e9fdd8d342b6bc3e55eecfd555c43e3cca8421f3236df2d5a366288fec62
+dist/2024-04-29/clippy-beta-aarch64-pc-windows-msvc.tar.gz=90307f09c6fcb0c1fbe3ad1522a5381a17e2f69637c6d00f4a2cb5f3149bf736
+dist/2024-04-29/clippy-beta-aarch64-pc-windows-msvc.tar.xz=f7e0dec4a4862bd85d894252366152b3b6a7627e7e5a25ce323fa2db3bd87c2b
+dist/2024-04-29/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=7c719e38f2a1030ae61985205df52f9a0c37b659463a5e2dea8e60e632de2d73
+dist/2024-04-29/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=181ff4ae6adced6522a4c29869be3cc5dac8b961c7c88f2957cd31f831490807
+dist/2024-04-29/clippy-beta-aarch64-unknown-linux-musl.tar.gz=4e0e63e6f200386995e369a2673867d1bc3005d51d6a57c00ca80056dd85316b
+dist/2024-04-29/clippy-beta-aarch64-unknown-linux-musl.tar.xz=3d5b22a13aed6821482e60d9cc8571e2da9d95d82104284b77c56985a35a9c4e
+dist/2024-04-29/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=9f788db76a5d55b3ecdd04a70b0e2be466959f76ae9fd3497ca2c503504e0c03
+dist/2024-04-29/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=f4d8fc103807fba61d71d88b8e25a7016bfbd1a2905330f9a9fb3d7ba082713a
+dist/2024-04-29/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=d61bec3d017dd0be43e48350190ad18c0a0269e43d964600b62e1f7fd4f84399
+dist/2024-04-29/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=c00cbdc41a4da0c313a1a282b0158b059dd34f640b582cb7ca18e3d290ca8fa5
+dist/2024-04-29/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=52143a530ca5274fbb760beecddff16f860ea787443d3dc708dda7c8f32ca9bd
+dist/2024-04-29/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=c6d2dfeac6f40811bc9b4cec3c23f9c3bb46f761e006257b9313aa7c1a647b5a
+dist/2024-04-29/clippy-beta-i686-pc-windows-gnu.tar.gz=325d39e426b1907fa17d93c0752d3d73bd95750f4f967c2a84aab2c5dac8a588
+dist/2024-04-29/clippy-beta-i686-pc-windows-gnu.tar.xz=536f591d4da455302029384ed196932d71119ef0160ac5415617d6b777c51123
+dist/2024-04-29/clippy-beta-i686-pc-windows-msvc.tar.gz=c3684c9bf471669d444853bf484880d17e150ecb0e7505de90883382023e343b
+dist/2024-04-29/clippy-beta-i686-pc-windows-msvc.tar.xz=0b00e6132f73d5dc762e359b0005fceab0cf7b01337d8f4aa9eacfb4552f9245
+dist/2024-04-29/clippy-beta-i686-unknown-linux-gnu.tar.gz=c91c1eadfc4cbae360a0eecf11c32d2509b68aca86c7b1de3b102944f43e1511
+dist/2024-04-29/clippy-beta-i686-unknown-linux-gnu.tar.xz=6f7a5a287dd6226c203bb674ff02ec773e5d0813091b2af744b88ecd6997a304
+dist/2024-04-29/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=58383f094995823ea6db6a87b9ad4b33bdae2264d29bab88ab71ec60ccab3b93
+dist/2024-04-29/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=dbf4680a6fd4dca54acca5503a7fd94502b8e85819bc02346ae9cecd275e4514
+dist/2024-04-29/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=e28eb32cda42654c0f0247aa8e15f01f73770b36f7626c8d6f1b7659accc56e6
+dist/2024-04-29/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=fcc48a83b748e1e46f9daef40563f8e5abbb0e3f014a168b04f3c700c2ace2b8
+dist/2024-04-29/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=b626faf3275fcd196cd627e8a36c67721bae16a56f61cd080c79d137b3ec7737
+dist/2024-04-29/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=2c599d2dc719d69f67625f3c6573fcc4f1ea3266801557dd3892bdb7c761b4cf
+dist/2024-04-29/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=0bc1f546fe0cef2b9516231ab608de68d55f72022fbc9ced5101b600e005f8c4
+dist/2024-04-29/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=993294f2ae5202785ab242c1c6567df9c8ab1ef44ad35748c526b7fe854fb94e
+dist/2024-04-29/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=210a4f0d208e0c8e13a57fb3b3e6c98ab5f620e4988d10a127ff1424ac1d5ca9
+dist/2024-04-29/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=f10f7df41a13ee2ecdc25d60e697cba2342129a912ef20d8bfca5f611a9ec97f
+dist/2024-04-29/clippy-beta-s390x-unknown-linux-gnu.tar.gz=3e24d2af65f0c9667c9997ce091711b2be48e673de3707cddfd8cda455dfecc7
+dist/2024-04-29/clippy-beta-s390x-unknown-linux-gnu.tar.xz=0e7b8fbd0207489e38c78c2ae1aa0df4fcbdd84741aa50a86379e4d7ede286b1
+dist/2024-04-29/clippy-beta-x86_64-apple-darwin.tar.gz=9c0c47fd97ce72abcd6126315834c62aa7297fe09d447ee4cefa1eb46a116326
+dist/2024-04-29/clippy-beta-x86_64-apple-darwin.tar.xz=49dd65c5340fd804399edfa2402cf255fd9bfce1f4aa7fbb3c193c11bc03f8af
+dist/2024-04-29/clippy-beta-x86_64-pc-windows-gnu.tar.gz=6c1c3bdf097a1846ae08b098c555c0c5e9e9b646c744d6bb5a855789196b8bf6
+dist/2024-04-29/clippy-beta-x86_64-pc-windows-gnu.tar.xz=0a7319d1062f73af1c8f0efe6ad970d10d02259162c5bc84bb1f3a10f3911bcb
+dist/2024-04-29/clippy-beta-x86_64-pc-windows-msvc.tar.gz=52fef3f8a64fa58934a633bd4944e8ba9e15f2c2766d0f302dea1a6523864dab
+dist/2024-04-29/clippy-beta-x86_64-pc-windows-msvc.tar.xz=8fdbe7590e62ab68a2e463b14da2595e8c4592744f578a813f64d430ed7db4b6
+dist/2024-04-29/clippy-beta-x86_64-unknown-freebsd.tar.gz=509bf535622bd26385184ee0c17e4e27a5061a8aeebf5759f24bd578692b2f5d
+dist/2024-04-29/clippy-beta-x86_64-unknown-freebsd.tar.xz=2fcd10ada329ba7633616bebc584dca13f11c465e7cf513e76efeb0c3174486f
+dist/2024-04-29/clippy-beta-x86_64-unknown-illumos.tar.gz=ea8cea0d4a2379bcd0693f6174b25bc1f90a016dbe8280159cbb61d859806fb0
+dist/2024-04-29/clippy-beta-x86_64-unknown-illumos.tar.xz=5a243df8d1345db6bd18e4386ba628e6d302bce1cc572fb447cca4264fda3ee9
+dist/2024-04-29/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=2ee560d3c1e306e103eb06d8e8033cd1489b3f6ff9df3bd8a95e25e977befa27
+dist/2024-04-29/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=aaf6e54184a65ad6592bf03955a84ad12b561afd86064b1ac5fa03cf637052f8
+dist/2024-04-29/clippy-beta-x86_64-unknown-linux-musl.tar.gz=1b3877424a0a0eb507675a50e9d2c793f00ab85f6f12b1e27f871331070325b8
+dist/2024-04-29/clippy-beta-x86_64-unknown-linux-musl.tar.xz=6df5eaae5afb64557ba5c3a53ee3e56dab85455838a6044c7671c1180acfeaf9
+dist/2024-04-29/clippy-beta-x86_64-unknown-netbsd.tar.gz=1ac05ed7b607fff8b77ff203a663e9f4f2487779bc25e2dcd454cdf5b7583328
+dist/2024-04-29/clippy-beta-x86_64-unknown-netbsd.tar.xz=da502375b3cee8b254ab5999809f522692c2d1d90ea0544ad03c0ca514c65ef4
+dist/2024-04-29/rust-std-beta-aarch64-apple-darwin.tar.gz=2fdd35ca3b3e3d6f548f11c93337f5bf2e3c088bc78a79881e6f8e230b38b9a5
+dist/2024-04-29/rust-std-beta-aarch64-apple-darwin.tar.xz=bc16b3a1ab6ed69f0121a117c50cbcd201500dae4d72ad0dab148913d04cc529
+dist/2024-04-29/rust-std-beta-aarch64-apple-ios-sim.tar.gz=9375c786703c17baae1c2066f8d972ac316bc840e478ecd1b94288a1d428324e
+dist/2024-04-29/rust-std-beta-aarch64-apple-ios-sim.tar.xz=50d6818a8dd3ab7a3ddbbd7a062b538d9ff3ceb6eada031d1c22ab1dc7ba512c
+dist/2024-04-29/rust-std-beta-aarch64-apple-ios.tar.gz=56c3a01e8fd5c2ed75df811993b0b724709fb5473cc308ac09e7f5644468f751
+dist/2024-04-29/rust-std-beta-aarch64-apple-ios.tar.xz=3527d1f2c99c806479fb4b3801335dc921b514f171b82cd252cbbfc9ed30b163
+dist/2024-04-29/rust-std-beta-aarch64-linux-android.tar.gz=bf8cae7c66489f1aa27f1dea1b37f0d0ae514a6e21b93ff2dc6400dc88feca03
+dist/2024-04-29/rust-std-beta-aarch64-linux-android.tar.xz=46799f0bc1b3c13877f6cb732774cb3b33e0d8a081bfb56d0f877e79482aa1de
+dist/2024-04-29/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=9f90fadab5104e1d415edf3b4edfaf7222f9f0d55f849851efdec74ffee16f8d
+dist/2024-04-29/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=87ed6774202b18691bd6884df6944c7e9fe9c944b57a2837e7a7647518bf94e8
+dist/2024-04-29/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=4a0692ad28f7f130b472ffa4aa766b745ba01fb75aa921f2da6622c9c68750df
+dist/2024-04-29/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=a3d45962489a1e18a87e567cbbc8d3665f38809d0ad2ef15bcf0ff9fb9f470a4
+dist/2024-04-29/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=c724f4eb135f73b9c79618f27a1ab35dc7b9d26ca62ed796accce68f9e747a66
+dist/2024-04-29/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=8eab25782d16bcee75f86ecbb826346beb4a7525b220b45b3ba05a567c6d4391
+dist/2024-04-29/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=33ab1f8410edf590570d7468dbe2ebb5a0907125bbc8d360a928dcb355f0d0e6
+dist/2024-04-29/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=d3d870209a55ac96391affaa347c04f48cf98c089ac5056f340b8bb38bcc8e60
+dist/2024-04-29/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=4d2bb72b898c30a2fc8d5d3333c2e99a8e30c15891fab641b6a519dc9f0cb611
+dist/2024-04-29/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=fa343e6b6110fcd0c5dae4287ff1a799de5d7e4a805dbf4e9a034bbaed2bf269
+dist/2024-04-29/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=f1ec4139783169fd83e1b0184518ed25d26cee7b21f196deecc74e83a1d78725
+dist/2024-04-29/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=d100be2f6f0346c4b1f5b41aec0c13a47426bf4d49127f2341c8332903e4e782
+dist/2024-04-29/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=bab6051e1071a58cd126580f6644decf16edb4473fe4be6a34791610d820a294
+dist/2024-04-29/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=d9b68f06ff23629063e92dfc42aa3115a858238d368e4b52b35c1ea4491b1402
+dist/2024-04-29/rust-std-beta-aarch64-unknown-none.tar.gz=96804c2d9accd3242bdc22dad688b2ccee071952477b9c592f099377aee6c591
+dist/2024-04-29/rust-std-beta-aarch64-unknown-none.tar.xz=3fed6812d84bdaf787e85c37e23ba729b81a6d25a2b33fed75320e66e6641c89
+dist/2024-04-29/rust-std-beta-aarch64-unknown-uefi.tar.gz=8da5f301bff35fc067ec7cfb878ebfa5607af7dbc276a6b34a77404432c700d2
+dist/2024-04-29/rust-std-beta-aarch64-unknown-uefi.tar.xz=80d643189dc9af98b6410a01261ce6ad34b1325f3aebf3ff61fb43f1261b41ff
+dist/2024-04-29/rust-std-beta-arm-linux-androideabi.tar.gz=2e86b54b0d1f7fefead11d6383bdc80fe0a7b3ccf58381d2a731e6f1c62926de
+dist/2024-04-29/rust-std-beta-arm-linux-androideabi.tar.xz=9831a0270457cad2798b5ae4fe956c257c7e10ce5ad211793dc467577cdec29e
+dist/2024-04-29/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=f96bc303c0c2be9cf589f00aa63b2cf3fb8585ca9dd8860fe525821bfa1fe19a
+dist/2024-04-29/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=e57a053b1c2bb6fad93dfaffedce7f48fa292196fc8ba6fd2f0c74dc810a13a9
+dist/2024-04-29/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=49b2cb2ba5296871b5fac5ad9a74a2891e8b78321078a455ba4a65e003bebd40
+dist/2024-04-29/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=0f9c15d834a9d282a4018934759f7b48ef3d275e09679a68c5fd1b3f047d02e4
+dist/2024-04-29/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=e59f92827241e670c1aa92b35235ad12340869d59327fb83084b5f4149acbe06
+dist/2024-04-29/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=ad1cf96bb1fcceaa016e29e8ad34b4cfd711d2e0bd7cabb9cd7cc28abf64d894
+dist/2024-04-29/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=14a6d318af85bb9fa5c229e45a88a32a71f44ed02cd90a24bb67921eb64dee41
+dist/2024-04-29/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=ed6b48502ab9169818bceb300b4e6b4fd63366ad5808b047bf9988dae04c2729
+dist/2024-04-29/rust-std-beta-armebv7r-none-eabi.tar.gz=345e8a023be55e3b88a0c2677ea28c7bb4fcc5f3ab707638de76065c7592c2d5
+dist/2024-04-29/rust-std-beta-armebv7r-none-eabi.tar.xz=6d9b11d08f2d62611327a893b45ba07c36df11f077250496ab0881eb7ac84c65
+dist/2024-04-29/rust-std-beta-armebv7r-none-eabihf.tar.gz=a2ae1bf003a8a12b2ecb6bde9868a978820f184af523f0e4c3fc935edd509423
+dist/2024-04-29/rust-std-beta-armebv7r-none-eabihf.tar.xz=3d1dcf8308f9d4590b429f6abbf8f42f04496ab490ccf4ed8c9e381e6d886cae
+dist/2024-04-29/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=a54106d27e4ce97463e7867ceff9dd22ba456f840ec23229e6909b37d48ad554
+dist/2024-04-29/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=e6abfaa0905a00efeaee85b9f93793bab93e2cf4e172c9d829c5ba85006c688a
+dist/2024-04-29/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=cbed18e5dc61fcecb2920affc3890c3b8ae46b7fe5a80b3288689e18d490f3f4
+dist/2024-04-29/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=2b58bb0dd5cd2c5f7f93f4c6e9135090b931e0ffa27ff9efe2b8ff9fbbb7e48c
+dist/2024-04-29/rust-std-beta-armv7-linux-androideabi.tar.gz=6a371c2ececd349dfa76a02563069912fc91577ac4446d36c22f96723d7f5e9f
+dist/2024-04-29/rust-std-beta-armv7-linux-androideabi.tar.xz=9325daf41ddab02fa845971c10a5e0538a18c7bea14e66fa0f5f6fb16654c7ae
+dist/2024-04-29/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=7f5ba76cfb7c85333c8dab76fb4ad3f12ddc254b95f9ee07fadb8e1270a4f767
+dist/2024-04-29/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=f853b7f929b7a309ed6c08ff8c57d583ce0ccb19270674fb30e63a873834dc87
+dist/2024-04-29/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=0680005d0a12498b687afc583d4f36bd67d0877cd9d3323bfd2df50d15c27afe
+dist/2024-04-29/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=a494b78fcad01c83df9522d460ac2d35d2d00736a921381f2c611dc516edaa16
+dist/2024-04-29/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=cfa555db31b5470e878b0f53d86617e7342e8bf018fe62cb0271dfe13db95f51
+dist/2024-04-29/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=0a8ccd6d88cbe79a855111fbda45aa1a728de655b6927f3d429d901d2afc6503
+dist/2024-04-29/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=eac53424001c884a540c42f0b68447349ec5d0601a030c060aaed76d54895728
+dist/2024-04-29/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=42d78fca62361ff28db5bc43bb01cef7af5c6f4ab2110fe6170c3dce4707aab8
+dist/2024-04-29/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=c88de9f2e667da73177fb9c9309d7f1f467e31c18e3ae50d722c71ec8dd876a4
+dist/2024-04-29/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=24b3c04a42d511cdc8c6107b597be38981114f0574eced493d0e90fc748094bc
+dist/2024-04-29/rust-std-beta-armv7a-none-eabi.tar.gz=cd4ad182a098c61550265879ccc04733c39110827f7ef62eecfb8c120ae4ece8
+dist/2024-04-29/rust-std-beta-armv7a-none-eabi.tar.xz=8499a014dfdf448f474a58f148784c2eef245dc909587d876d2fb9ddc6a4ec3f
+dist/2024-04-29/rust-std-beta-armv7r-none-eabi.tar.gz=e8e1870e5b12b3d8643d712efb91eb86b2081284cada4a140c1526692ab183c4
+dist/2024-04-29/rust-std-beta-armv7r-none-eabi.tar.xz=d6029121eacc44bd4dcd9ef6dd3cd0d775cb6e9a3d99f3d62d746fcbf8981cab
+dist/2024-04-29/rust-std-beta-armv7r-none-eabihf.tar.gz=1e0fc42c3802e205130c01ca90f92d793c1c5427b34da66fe77b97cf67b4a5c1
+dist/2024-04-29/rust-std-beta-armv7r-none-eabihf.tar.xz=4c8cfdb11bb686111fa4842d13430c86d9d14ada30e9df334b3777fe899233e0
+dist/2024-04-29/rust-std-beta-i586-pc-windows-msvc.tar.gz=ff895c1b39b84587f10903f4be13d275b545e690da6761190d12c01acc25c6d8
+dist/2024-04-29/rust-std-beta-i586-pc-windows-msvc.tar.xz=fdcbcff7b740235bb16e44174fff9080a7c0a31be358c8abc41805c02c20c3b2
+dist/2024-04-29/rust-std-beta-i586-unknown-linux-gnu.tar.gz=6b227f3b9001e148b66b7001f753a6f88fef9677e39d8fcf4d9c35fe8d345568
+dist/2024-04-29/rust-std-beta-i586-unknown-linux-gnu.tar.xz=1e29297beb8de3778ba958731294823d9a93aac1e0d8833abc5aa99e2935965b
+dist/2024-04-29/rust-std-beta-i586-unknown-linux-musl.tar.gz=26481ad5f22a319830d42f69b1c0195bd65900ebe112e659432334b3468f3d0e
+dist/2024-04-29/rust-std-beta-i586-unknown-linux-musl.tar.xz=c8a837e0d9da8ad976fc1539541c085365aac9dd28b34e4a289d38a823d1b065
+dist/2024-04-29/rust-std-beta-i686-linux-android.tar.gz=f05e28a52f17e22f36ffc70018012a1fe6a07f4b461e774b36464f32bc8f8dea
+dist/2024-04-29/rust-std-beta-i686-linux-android.tar.xz=f9501b2691c51e54a6f4cc6fb72e41901eb551d3a7be5f82a94ce2d3e217828b
+dist/2024-04-29/rust-std-beta-i686-pc-windows-gnu.tar.gz=8d9a782d4f7450bca536aab45147c6ef08bc3847b43fdd171c6449e29762eda0
+dist/2024-04-29/rust-std-beta-i686-pc-windows-gnu.tar.xz=4008712e03fb6494eaba3d79051c5e3fdd93d4c52ae8d86cf8f344b5f051cbca
+dist/2024-04-29/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=cfb23242e495834a3d0f7ffa3da4a0b206dcae35872b1455b11faeee5511ba5f
+dist/2024-04-29/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=95415742c0171945ffc2b67c913ebd1330e29634af238f5ccc843a965340374a
+dist/2024-04-29/rust-std-beta-i686-pc-windows-msvc.tar.gz=e9354d69e39ecfac1d2928664d17d73f808256a4076b849171a9667705c0aa08
+dist/2024-04-29/rust-std-beta-i686-pc-windows-msvc.tar.xz=a34bb0a91170d84195f35ba52afa4c9be8a2f2706dbeea02bd6e8908e08ac65e
+dist/2024-04-29/rust-std-beta-i686-unknown-freebsd.tar.gz=d65f286de399ccc9e9acaf7a4dc4f885357c750231d54a144ba9a59181814f11
+dist/2024-04-29/rust-std-beta-i686-unknown-freebsd.tar.xz=4c93a7da70a69b2ebbac01df64af16344e523d16470b29e57237b1d0925f7721
+dist/2024-04-29/rust-std-beta-i686-unknown-linux-gnu.tar.gz=1b978bfd1a9234be7ef197c8c98c5a6b625f6fbb7b0fca58695986768bdca176
+dist/2024-04-29/rust-std-beta-i686-unknown-linux-gnu.tar.xz=98d4eb5b89a593c8c4f86244c9a7c737d9c18c0168aebe5923b8d9145adcf89a
+dist/2024-04-29/rust-std-beta-i686-unknown-linux-musl.tar.gz=dbf9b3c5b54b3eb0727f976f5632c5b0fcb2f90ac7453962d6cef20f7dae4284
+dist/2024-04-29/rust-std-beta-i686-unknown-linux-musl.tar.xz=f209ade093753342dda6e710ee832a538dbdaa08a24d606f9a2a1bc59b83da29
+dist/2024-04-29/rust-std-beta-i686-unknown-uefi.tar.gz=3c3ca7f34569b2c70c6b223754418a535dd7dfa087ab6e28ed2ec78d20065887
+dist/2024-04-29/rust-std-beta-i686-unknown-uefi.tar.xz=72a7cd0f430ab40d80e93f409b8e26a181010ab4bb75d151e829d51ccdcf8c62
+dist/2024-04-29/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=b7dfa59bb05cf806c87854d6fce5ef0f160697052fdf6e5a0cad121499108608
+dist/2024-04-29/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=88bc22f68bab3367cdfa91676418ce1ffc0ec002afb32aed7def880bdd4be402
+dist/2024-04-29/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=d61019048b941064a99d19e46ff3236a88a2e8fcfb963cedd1d9d1c47963c170
+dist/2024-04-29/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=7474bda08134c676d74afe5263317af3f271963d8ceaa5efbfa1b657f885c572
+dist/2024-04-29/rust-std-beta-loongarch64-unknown-none.tar.gz=e089c77d433d838ca02d7531d6f4a1770fb4a0568acbd96c8f43034d76f2990b
+dist/2024-04-29/rust-std-beta-loongarch64-unknown-none.tar.xz=364ae6c89c7a930098286e55193d2f5ee3d5ea80b7cca73046e41725f4a8a2f9
+dist/2024-04-29/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=c17bfad87d16f3a8d26646525dc59a352718db9e7572acb583b68a18cfdc338a
+dist/2024-04-29/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=f5c4ecef1c08d19ba6fddbd359a0ce94e46888021cae057fce969276026d086c
+dist/2024-04-29/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=3e7e13b0d2e804d228e1e3a9dac0205d294ae29dcc37132f15fb1e218861eb39
+dist/2024-04-29/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=ea31b7678e6f64c2f9c28a9af120be04ed6f2a25a496e40afbf6e9aa0dd20b60
+dist/2024-04-29/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=f0e1b314c3d5ad1676c68c112581dce62fa06ad557cd5f61034e147b064ed270
+dist/2024-04-29/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=8ab7bbea6e2f72df1286facc7d306d01809a4dd9f8901dfdec7e50b594658d49
+dist/2024-04-29/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=48f6abda1c7dac185858744aa2cdc3513cdfb6552535282ee83cf9c5365573c7
+dist/2024-04-29/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=d920d97f15b56ba6ea81e08b3c29dc7f44f5f30b7513c53446edf95843c332af
+dist/2024-04-29/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=0a198a770f6e6043e923b0ab1a508fd8b190612d0370c33c8dd2c5f63b6f19dd
+dist/2024-04-29/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=424a93313cfe2d85acf956be3d9ac71ea8e34ee61617a550ad6ff5360e1dff52
+dist/2024-04-29/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=2e2b0a8e41f4ea774d665d6248cbc2fdbe3e582206efeb87d250786ebaad0b1a
+dist/2024-04-29/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=2da372c091017b7096e473e5c7016a504d2e041e14173d2520086cb43e0a615a
+dist/2024-04-29/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=69d3b21403181b2df14243816388169db2466477ec34bcca5693fb017703686c
+dist/2024-04-29/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=281b9c20f8641a3d1b349e762b7f713fb0b91da0d21eec798e639e36a0ea3dab
+dist/2024-04-29/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=dd9bfd3fd8446d35180fe781139dfb4e04dd658b112eb2a749e8f4aea14f0271
+dist/2024-04-29/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=b1366375e0c5f53da581741dec91972b0c46d7d466052539207e8feaab0ba3ec
+dist/2024-04-29/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=7c6650d8cf8abd51547010e8211af3ef3195099ef43a563460ad4780de20ba17
+dist/2024-04-29/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=bab46f3c0078ce346de563bb7a248ca92f15dbdc73bf5a3bc520486118442320
+dist/2024-04-29/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=01735b4ad5bc0a53087dd0ccaef2cf174b27e45bf4d2e3c15e64f7522f059c63
+dist/2024-04-29/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=0bb272c2c235583ed3e9ec151b3bfc601f8cd07822c2fe47a1258b358be507f0
+dist/2024-04-29/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=b2c7f8ee0efe6d0812e4b5dd0979f60f105b84d34d4f600ef75f2eacd954893d
+dist/2024-04-29/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=0d5301fc553a6911af6643ab7f57b6438bf649ffcd050d486278c0c5fe38eeba
+dist/2024-04-29/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=0d1d35ecb88ee717720ad8e74bd5b602fd6011fe321baddb939f3b161e9cd8c5
+dist/2024-04-29/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=a5cf0b98596e68e6f72be2e83c61b8aaa19ead42f248ee2408a3b8f4e97a6657
+dist/2024-04-29/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=629ed749cdae110668ad9ddbc5c61e99e8d400f3dd0981146c3820deadc360f6
+dist/2024-04-29/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=192819438ed27a565cdb67b51d2f5caeb6ae258de86191d6922574327f132acd
+dist/2024-04-29/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=84286f6cf6f00f3c92dc881f64a31e1ec5910102d8d3d4faf6fc7e2ddf1544a7
+dist/2024-04-29/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=304b5f876b47dcbb7c3483c49295b822e8ba83234bb568ce67896ae4773ae2fa
+dist/2024-04-29/rust-std-beta-sparcv9-sun-solaris.tar.gz=25062159b859e21dda76ca22d4a31d3aba4fcdb0def78bc5b5cf9887c07c1be9
+dist/2024-04-29/rust-std-beta-sparcv9-sun-solaris.tar.xz=5d557ee86457f288462603fe53bcc2e092d84faee543659419fa68c1bd88f554
+dist/2024-04-29/rust-std-beta-thumbv6m-none-eabi.tar.gz=a9663048aad82ef832b2cf82fa9fb94be047f77e283e8aa3e2df6ad957d0782d
+dist/2024-04-29/rust-std-beta-thumbv6m-none-eabi.tar.xz=4c4b703a846b4123d09c1eace6322e82784a004b278f1f3b1ca1279e96207f18
+dist/2024-04-29/rust-std-beta-thumbv7em-none-eabi.tar.gz=32907c33f240abb1cb17ac438da42c5fa3932b270ad08fd6914775c5b59a02f5
+dist/2024-04-29/rust-std-beta-thumbv7em-none-eabi.tar.xz=112583227d2b6abfef6eeb78d980bf2efef392f3b66e433c4959a642d72ffc7b
+dist/2024-04-29/rust-std-beta-thumbv7em-none-eabihf.tar.gz=7ba0084527a18479c4b6f6a0dba8ae23a0ed50e9fc5fbfce23cae1babb5a1e12
+dist/2024-04-29/rust-std-beta-thumbv7em-none-eabihf.tar.xz=49eb4e2efe3a76713ce1fecacaf915717eeed8552912b92895c7fee068a85a36
+dist/2024-04-29/rust-std-beta-thumbv7m-none-eabi.tar.gz=518a532b52f2dad2825158614cd00b12aac6c6e1983a1ad53e2b0e26d1f1b845
+dist/2024-04-29/rust-std-beta-thumbv7m-none-eabi.tar.xz=2895e5796a29fd016462694d880e38eb191cb92c9bdb14414c1d6e63b23d3394
+dist/2024-04-29/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=2af590c063344c4c3f65d704fa255232b5f5954872d03c4c55d48662cbe6bb17
+dist/2024-04-29/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=a09df5f38183d9fe6116c807619f812410763ddedf06055bfe8040b5794104d3
+dist/2024-04-29/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=eac22c4972bde3a57cf2ec4e31b43db3c4b7d961ae31475d8942e898c07640cc
+dist/2024-04-29/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=104f2c6490e30cc47833edbd806c2efe6256d1194600b2278339612f94704d45
+dist/2024-04-29/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=b3c9c9d7ce8c1db6f20e8ede542e67aacd6047c52882a5d06c4f96a40a7304d9
+dist/2024-04-29/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=76bfb114bc7674792934a4892d2db41fdc8f5bd30c3aa96c43e8055199157476
+dist/2024-04-29/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=1308335fe80dcafaba511ee589959d461145533de5f76118fee29a7e9a15841f
+dist/2024-04-29/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=cb8acdb8920983c03b9495cf3506a3014384b4d2f6a53e7907924d38a0baf7f0
+dist/2024-04-29/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=9dd2e5ce7534ab4fbb93ff652196e877f4e9eea3863920c3d34a05d9a3598c81
+dist/2024-04-29/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=4b6e962facf7c54846965a8d6880e4a980804459151f2e22ac5af79bc79e26bb
+dist/2024-04-29/rust-std-beta-wasm32-unknown-emscripten.tar.gz=731603392b6e3d36b3a4956928d084e293ef18c8b8593efa756e753a2a309709
+dist/2024-04-29/rust-std-beta-wasm32-unknown-emscripten.tar.xz=8b681b3af47855eb63c4ffe06a2bc6bc4f365354ffbc171ce8cbd8c2a3588a07
+dist/2024-04-29/rust-std-beta-wasm32-unknown-unknown.tar.gz=7b87e59391493c3147c03794061111e25bdae669aea58190a951cdef111e75e0
+dist/2024-04-29/rust-std-beta-wasm32-unknown-unknown.tar.xz=d15eaadb101027906c2fce15b95a3f820bdbc4cf145b705bafc2ac5291289c3b
+dist/2024-04-29/rust-std-beta-wasm32-wasi.tar.gz=07390ec742b79ec11b2c3ec65f60efe5d7c616f50c33058fce346f6e9ad21af3
+dist/2024-04-29/rust-std-beta-wasm32-wasi.tar.xz=79e34d46621c298cadb98c00ce3b25d97474aec300d85255153b47e21b7bb744
+dist/2024-04-29/rust-std-beta-wasm32-wasip1-threads.tar.gz=b916dc9051b0278f820ea0b093db3ecae2e27de641ef67a9b508df75dc92c938
+dist/2024-04-29/rust-std-beta-wasm32-wasip1-threads.tar.xz=2867922a39da3b02ebdb93fb78b010695daf468f87485ad8ab79c7f3eeb18b11
+dist/2024-04-29/rust-std-beta-wasm32-wasip1.tar.gz=792b718c0a72e97ba85a17ba67ee09e55b85de829fe4021f828ce54ff8cb31e0
+dist/2024-04-29/rust-std-beta-wasm32-wasip1.tar.xz=abff86499119bddfeda9059004549941dbcd3d911702d4a9c198b94f60e60f4e
+dist/2024-04-29/rust-std-beta-x86_64-apple-darwin.tar.gz=0bcc7698efafb42a37f20815f5660e39829a42a2776304e7129d0a4ec0c7520b
+dist/2024-04-29/rust-std-beta-x86_64-apple-darwin.tar.xz=c437626e250b0d06c05dc828ab81d0d2c543ffce4b100567910508974ea50045
+dist/2024-04-29/rust-std-beta-x86_64-apple-ios.tar.gz=7c98c9f491bfc837111769a45c10ce2f1ef73c22377158ef9ae80b38034892c0
+dist/2024-04-29/rust-std-beta-x86_64-apple-ios.tar.xz=f4bda724e6e382e02ddf4e4e7a479120420666a5a1ad3c87a85d4d3c763f2cb2
+dist/2024-04-29/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=01efbb2e48045318e18bfc7b6c190b461a219e81fc1cca6c855bf0c658aef556
+dist/2024-04-29/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=9bff316c6d2fbb3c0889f9ffe4eae496b293fb3afaf8d597155e6badbf0c6a8e
+dist/2024-04-29/rust-std-beta-x86_64-linux-android.tar.gz=5da713547a8af2c86da7db5d8aa4c27188dea1089fded81ffbbeb0f78952a10f
+dist/2024-04-29/rust-std-beta-x86_64-linux-android.tar.xz=9d6a45d6af395360c63ce97bcfc2f9a2967c708afcd979f17fa447239703a92b
+dist/2024-04-29/rust-std-beta-x86_64-pc-solaris.tar.gz=d1a71110bee002c8edfbcc00e0f5eede5afa005b09944bb2cde469c658049e70
+dist/2024-04-29/rust-std-beta-x86_64-pc-solaris.tar.xz=6b8d18c83b9fffdddf9e55c807dc7d5784cc6d7ae90a57c29b87d707f0656964
+dist/2024-04-29/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=28921ee14426f54aa09523547516437130654b2d9814120d286f209666c88533
+dist/2024-04-29/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=7c3125cce30978ca2619e9aab150cb5b9b2535fbb6274d4ac1b1d4342c7b0220
+dist/2024-04-29/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=ee5c237f092f8a4ba797c4c7769dfd4da81b5c86d2f4b88704d127642d222a22
+dist/2024-04-29/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=30c84b04bd2d4d33abf1875cfee5f227ef6484edc67b3cc4c9c96d92c8406d6f
+dist/2024-04-29/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=81274050e72c5a8ffdead83f7be62434f35a65517a1b3c6f7d9d14d0d59da710
+dist/2024-04-29/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=215e20c78a2a4edf9b8368a29a09af5f4cf8d0edd1995de3bbf2eff01127cab7
+dist/2024-04-29/rust-std-beta-x86_64-unknown-freebsd.tar.gz=340131cba121827a9753e19cb3a4b9ba2ebe30569fb20d7f9300b4dbe2a15cf4
+dist/2024-04-29/rust-std-beta-x86_64-unknown-freebsd.tar.xz=69626178bc5309afc8a02c941bd77e70e1aa6917ffb6bf0d67a57d921b5c664a
+dist/2024-04-29/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=22c6c90533dad3a731ad8a6696e6cdc1b15579e25c658fa2b094185e1893934f
+dist/2024-04-29/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=30d7ef6684fa98e28037b69d4220cba40489c23e80fe7793c98b388dc161757d
+dist/2024-04-29/rust-std-beta-x86_64-unknown-illumos.tar.gz=9d7192d32eaa6b6ccb0f615da0f4cd80827ba6484eabeaf401d8217678f1e313
+dist/2024-04-29/rust-std-beta-x86_64-unknown-illumos.tar.xz=7a3fb35e0bb252d5f90773136d1417c26d5601beadb77d6da6f5ad3081977f07
+dist/2024-04-29/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=e987635519c1edc8a1d147ca4a86283637e4dbd0a49736b01d605e45a3a14e8f
+dist/2024-04-29/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=c3ab6b97dccc0038c68494b03b6d444d534e447226a2b2e140af54c94fca0b2d
+dist/2024-04-29/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=72e8113687be8f947c50befb42b0957dd564f01693cf4d68d749a9e074032ada
+dist/2024-04-29/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=867b24f33b19f40727c71818c8a002718d44d4cd4ceca44314331e19c1adc1a4
+dist/2024-04-29/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=f9b0fd9605bd4e264f5303bd740d9a0195bc147132969965b221f9da0d7875bf
+dist/2024-04-29/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=022dcf4887df41d776ba2666858b9aaab479758134a71f7c6b2172ed7c1a1752
+dist/2024-04-29/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=b5ff4a0ecd7e0f71a9557b6096bb907e5cbc8982431f0d9b01d8e1a895d8b37e
+dist/2024-04-29/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=e40d5bfb46aadf6faf849df548154db3f35f356f8b98037a056802a235922b8a
+dist/2024-04-29/rust-std-beta-x86_64-unknown-netbsd.tar.gz=57cfb1fa472dd9c01fc0caf605a55b7248375d616acf84ec12f6430d5e07e2ee
+dist/2024-04-29/rust-std-beta-x86_64-unknown-netbsd.tar.xz=e4121f060b917c811d971e85ce02495e83150ddcceb2204615edff24bd55bfa6
+dist/2024-04-29/rust-std-beta-x86_64-unknown-none.tar.gz=d63559803c8eb47e0d10d9f3a2284477b570a2536bb541762774271451e1f0ce
+dist/2024-04-29/rust-std-beta-x86_64-unknown-none.tar.xz=5388cf8ecaa234d507e505e8c6d433c5de8811b2717aa254e4caac9f4aa6cd97
+dist/2024-04-29/rust-std-beta-x86_64-unknown-redox.tar.gz=0f027163f37618df4330ecd82afece432b0a509ab20333d7b787c0d139ea89c2
+dist/2024-04-29/rust-std-beta-x86_64-unknown-redox.tar.xz=b1c722e894b145c2183183fa58762c64402fac077419dc7874f8b08eee665651
+dist/2024-04-29/rust-std-beta-x86_64-unknown-uefi.tar.gz=24e2ac0d44619ef9b76cb1af6178103d65ab12e2677b366e8aee0604798fe5f1
+dist/2024-04-29/rust-std-beta-x86_64-unknown-uefi.tar.xz=1d8a45f1bfe6650edc5ddfc8683190eff5a74384abcb2f73eb3d1e88d566ccfc
+dist/2024-04-29/rustc-beta-aarch64-apple-darwin.tar.gz=ea113c567692d54983ab6c376761651b6dcf9bedad5b5d822d28c0d0d0733cf2
+dist/2024-04-29/rustc-beta-aarch64-apple-darwin.tar.xz=e36363f1ea531d2fd563f471758e387de37a34e7ef6f4c12175979657333c5b4
+dist/2024-04-29/rustc-beta-aarch64-pc-windows-msvc.tar.gz=52d77d540fc3f83d82f35f358ccd9055fb75453af3e3bee4b11636742559db13
+dist/2024-04-29/rustc-beta-aarch64-pc-windows-msvc.tar.xz=843c56f5431c1feda85ceaeef0daf988e8ae020b3556326fb1f75ea7968bf2df
+dist/2024-04-29/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=ba2fe37dda1a487a2c75151895f4f6e886e9476a992272ce26e9b5fd7adb11f9
+dist/2024-04-29/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=ccb7be3935de1920509d2061d38f92f1fb8d2a5dd6cef392492242a929363fa9
+dist/2024-04-29/rustc-beta-aarch64-unknown-linux-musl.tar.gz=40636e0936bd311803317825c5fb6b446cdb5536ada1db097b567df04a86d7dd
+dist/2024-04-29/rustc-beta-aarch64-unknown-linux-musl.tar.xz=804ef68f24bc0ba5150177d8b8515daa54aa82fcb61472385ef1a1d897c5c3e1
+dist/2024-04-29/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=a320c2869d1d2c92b698397d4467c8498cad9481f38d28ac810bd165399ca46b
+dist/2024-04-29/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=7ce92211d87068d9c223806929adc34ca611a1321cd58b5bd81aabb0ec3ff085
+dist/2024-04-29/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=79c16b902884301882d16be36fe75ecb32a8e49abde0038ce21cfbee883c2c3a
+dist/2024-04-29/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=9384eb9bdbb585b414b6c04c592a79e90a0c0ebfeeb970e5e1b920cb638807cc
+dist/2024-04-29/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=ff99de5b819a4fb9adce9386a309b9841bd33632eb7d5079415a6ca6fc86b9dd
+dist/2024-04-29/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=55635cde13af11dd8cc007d2e0499bfee493bdfba87b6efd7b1fa4115f5728dc
+dist/2024-04-29/rustc-beta-i686-pc-windows-gnu.tar.gz=de82ac745275f069225b84574ed145afaf9f54abde5246592e49d5d1cf40cac1
+dist/2024-04-29/rustc-beta-i686-pc-windows-gnu.tar.xz=a8a7bf64d33c95a2f94265fba8dd9ac50bbb727f4bc3e79be5bf61212cb5d22b
+dist/2024-04-29/rustc-beta-i686-pc-windows-msvc.tar.gz=88967a99c993d6e0c3c7948308510644286ac826266dbd3d89aaa083100711db
+dist/2024-04-29/rustc-beta-i686-pc-windows-msvc.tar.xz=1804f75786482946258ff0e827274357c49e90a7f2f568add7353249f2ab78b9
+dist/2024-04-29/rustc-beta-i686-unknown-linux-gnu.tar.gz=3cb7e02c61d4a21d8289289b874b25e8b020c1d553e5af950160bffc14f51c18
+dist/2024-04-29/rustc-beta-i686-unknown-linux-gnu.tar.xz=2ad4b1311a0e39c359798375912faa91b4e13cd473bd59efd1e4f721777d254f
+dist/2024-04-29/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=ab19efb741a127615b9022dedf1d895b53c69740cc3da745f9b9888bade9d98b
+dist/2024-04-29/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=492cc11d54df410c2547890803930fc65950e6b81ced512e24bef56c3e70f3d2
+dist/2024-04-29/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=c5a631a41f417336f3f65c85adefd1fb0bacc02465485f37d29fc1223c9f6cec
+dist/2024-04-29/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=0701183b615d9eec9daea724d4cd8fa98dede2260cfb6b137d6cbf8ad6b29a4f
+dist/2024-04-29/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=cb70e92d5275862b500614d79eaea3d19319b96798f4850cb19dea9a8038a651
+dist/2024-04-29/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=908cbe562d82cca1bf176fdc99af867966ea423d244c4a50e14bad19f6878201
+dist/2024-04-29/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=8580a3eb6d6df1774f4b6ca06dc1195c42b1e2a463488a5d851e99b0ca6d0249
+dist/2024-04-29/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=2627948036e905f2e280663c56c86c172e2b0d057311ade7ca238953b7e0c36a
+dist/2024-04-29/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=526e4f129fdb4b2c8f4317c57105a09ff03e71771d6d6bbbc9380917b5440d71
+dist/2024-04-29/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=fd9dcf60838376478d7cc505ec7fc39f86f9d042646a3b836e9c06825927c7eb
+dist/2024-04-29/rustc-beta-s390x-unknown-linux-gnu.tar.gz=664c1255a9435d1ad086329a3c215974b9302d481762240cc9d0328d9f1b8c9a
+dist/2024-04-29/rustc-beta-s390x-unknown-linux-gnu.tar.xz=a585ce7684e4174f03adb09df17221e1729e8179dbc91b9a0f8813c3ecc0822d
+dist/2024-04-29/rustc-beta-x86_64-apple-darwin.tar.gz=59a1d91009b506a5bce3c276993cb8acfd71f73d01f9eaf4195b36114ac822c3
+dist/2024-04-29/rustc-beta-x86_64-apple-darwin.tar.xz=f86f3309cf2784b076f14e7da9e921c294a7701ea92d378c609061deccbc6bff
+dist/2024-04-29/rustc-beta-x86_64-pc-windows-gnu.tar.gz=f5c074461409b33a9791325d4014e6861ad36f99b9e48e54ecceb73986450be1
+dist/2024-04-29/rustc-beta-x86_64-pc-windows-gnu.tar.xz=045431eec6f839b1c40b5a75c5000f80bd6351274a59b29d962833495324ecb6
+dist/2024-04-29/rustc-beta-x86_64-pc-windows-msvc.tar.gz=a3abfb68e60544170f47209bbf048f1374e5bb75901a529e2ac2f315758155f8
+dist/2024-04-29/rustc-beta-x86_64-pc-windows-msvc.tar.xz=398c41a3219781c7cf1a907406506526b672abca6d3ab59c30556390a5f992c9
+dist/2024-04-29/rustc-beta-x86_64-unknown-freebsd.tar.gz=38895e615efd0bf75ca14b0ab0a085527cca64fae17631d1780a8f51acd26d17
+dist/2024-04-29/rustc-beta-x86_64-unknown-freebsd.tar.xz=786f40030dbe5e6897aafe4bda44770920b2010b93fc5ce86574774e531e2eff
+dist/2024-04-29/rustc-beta-x86_64-unknown-illumos.tar.gz=7003cab7650dae7e3d29032422a57782a2c146024c437a6466ae1dd2b61a6618
+dist/2024-04-29/rustc-beta-x86_64-unknown-illumos.tar.xz=bed3cc10203e8bd4d43b6245928c8a607acc5b6e633635caea45eb4eef4bda56
+dist/2024-04-29/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=84cdea91c9f1e848ea17f554229ca80d18d093fc609641d8f003c4f2d4871866
+dist/2024-04-29/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=a20fce7512f7c8cc6230a0f63f12855b04370d25e621183f71aa444c90c36b4b
+dist/2024-04-29/rustc-beta-x86_64-unknown-linux-musl.tar.gz=87e0c484ade99efab57c655ef96dbabf7a02314540575b65a14372ab5496c36c
+dist/2024-04-29/rustc-beta-x86_64-unknown-linux-musl.tar.xz=469757d8f35c9f4210aefd2ba660ee249e4409d47b908a6c68c1e650ee81ae67
+dist/2024-04-29/rustc-beta-x86_64-unknown-netbsd.tar.gz=4a38000480fe78fd5da7f9b71d36f296a6ae103254d932c4de6b902354e86bbf
+dist/2024-04-29/rustc-beta-x86_64-unknown-netbsd.tar.xz=45945d6af237fe4c91fde7db02ca19e99bac56a911b8db79be9b6ab8bb3934e1
+dist/2024-04-29/rustc-nightly-aarch64-apple-darwin.tar.gz=0b07375a9a6507fd4932a05b5aaf28ed349fe2040103f1cb69c8a2494437258f
+dist/2024-04-29/rustc-nightly-aarch64-apple-darwin.tar.xz=143bd7ed3ca7b913ddd0cea7cda8d1a0e4c29cc2ccbb7d29f0e45c2a87c3ec46
+dist/2024-04-29/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=9404c111b91fd092367b88adbc37dce10a98c443bd8d9e13a860e1fb4e3af96e
+dist/2024-04-29/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=f9f432907c276edcae5ad8ade0264f3c03109be02e791a814edc8ad3d229637a
+dist/2024-04-29/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=33425c90427424f0b30fa2a6331a3b59c680f1c1bd0d8845d7e6bc1e2f80292d
+dist/2024-04-29/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=03792890c64c72f30143849894b15f0eb3d6ad735fceede9092abd900ee733e4
+dist/2024-04-29/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=cf6f2bffa0db1b4b9b8e95801bf415dcce413f902e26f4c1831dff1a00752b99
+dist/2024-04-29/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=9192fdb668df8d4cab776623db7d01e35af42fea94098c1d4ba53190825d81a8
+dist/2024-04-29/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=a174e7e08da2abc6b84499360670188f5cc61b6d055967e04bf602ff3d831f45
+dist/2024-04-29/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=5a59811027586863852b15fc2b603e7e69b19841f4c10d2527ef1fc5b77d8af2
+dist/2024-04-29/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=645bb5dd7a96bb9292b9956cb9705e9aed2408e47728f245564f1f7404ede783
+dist/2024-04-29/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=1fe34911b082c3a5ca4f24656675c095d2cf56f8005be9ca2517d0ef7d0a2b37
+dist/2024-04-29/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=f2d6403d81bb0afe2e14956828987a0bb044c95f2d9566e1d792dd922dad7914
+dist/2024-04-29/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=d93fdafcbbfd50c88c3f4feb4c68b053882ccae02c45e1615aeeae5a86f4aa98
+dist/2024-04-29/rustc-nightly-i686-pc-windows-gnu.tar.gz=a9e997b03559b3dfa2a0eba6ed7a142d7651ea7f4ba4e788d9de807b50558e58
+dist/2024-04-29/rustc-nightly-i686-pc-windows-gnu.tar.xz=4412b5fbfab8c5b31e57cf8c4ce9a9d13cfc9c0a8174ea1fc8a7c05281e1cb54
+dist/2024-04-29/rustc-nightly-i686-pc-windows-msvc.tar.gz=1725c41500dbf6bea554f3d4acaba70167f0e89087aaa3eb3c0f8a99047c55c4
+dist/2024-04-29/rustc-nightly-i686-pc-windows-msvc.tar.xz=27db022494afebbe05605f134191e8b2e78bfdeaa638d4215174038ca9dd2fd7
+dist/2024-04-29/rustc-nightly-i686-unknown-linux-gnu.tar.gz=dc1a05d49b773dba06808c1c50653ecac506b3433f0f6dfa307109a7c621cc1a
+dist/2024-04-29/rustc-nightly-i686-unknown-linux-gnu.tar.xz=cc58ce3af8f5481ada4dc129079cd558664717526b2f7f9a02bde6bafb6f45ad
+dist/2024-04-29/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=34cfe803126ae9218b17adfe833a55c697dfa50729ac83b642529f3682d12d15
+dist/2024-04-29/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=c752dc8962656c09047151fd24166f3134fbeed85006b5d22496691079c7fb9c
+dist/2024-04-29/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=386b086b8aad922050c813dd58bb79a52ef806b2d1413e2e9cc46d6e43b81d7c
+dist/2024-04-29/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=d9eec9ab7c265444ac5f04d4ec9e77d4c0c3c2e34c5804db8abf5f94c8fd2272
+dist/2024-04-29/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=91df129046443554bfb836d25886aa9807b917acbc9dcf30f6531cde7bf912fa
+dist/2024-04-29/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=ca9b574b9f2e914b5a6d9e011aba805d1e6f9b687dc1a1868e88f0e4d9e4401c
+dist/2024-04-29/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=8b44f96a1ccd6d501b0af3960edb2c1a6c93957676a1c2cdb831e614de398f8b
+dist/2024-04-29/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=f8a10a6767b80bf24f73223b9e46e1b18b6bf6746ad2115eb8968a0e482f0e4e
+dist/2024-04-29/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=a197208807503a9cfbc6df938d614a192da48884b2e4892f7b1d234579091be1
+dist/2024-04-29/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=af3a1a33942bd8a3417593dc118abb1db0373f5410f54771713c05bb86724fed
+dist/2024-04-29/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=5a3a3aa73b6a0f21c63b9a40bdbd0bb4dc59bd75add0a06e292ced791fad31be
+dist/2024-04-29/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=6d7903f1c9fc95a23448717326d667dce59e54aaff821443d3cd9137cf3537fb
+dist/2024-04-29/rustc-nightly-x86_64-apple-darwin.tar.gz=64eede54da4bf88b0a42ecf7f7a4bf8002b5550e60a64e1e48244c7f5b04768c
+dist/2024-04-29/rustc-nightly-x86_64-apple-darwin.tar.xz=0a8f95e3bb0bebf9bcc8116b91bab3ba97cb6ff4021713586280aaceed9da030
+dist/2024-04-29/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=58f9e0dd9c1aadde2dfd869528adadd4acc29ab0850236f3cee5f023d4211939
+dist/2024-04-29/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=a211a962093e0d09358d51a6eb48da0966a02383c6b00c8acc077b5663d7d707
+dist/2024-04-29/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=5631926874dc54204c319137a77a89de5e6f408de2a832109e2be71ea79f27d1
+dist/2024-04-29/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=a8cf87bc663b5e3dbcc97b0eb58bb1b9b5b0100aacb47dc0c372fe1612517244
+dist/2024-04-29/rustc-nightly-x86_64-unknown-freebsd.tar.gz=1011f98197a9fe82d6095f4521934a06eea5f7e9719a6e4c9e3bf13d68f799ca
+dist/2024-04-29/rustc-nightly-x86_64-unknown-freebsd.tar.xz=79599b3f91f9372262e97a417f4e104ef5192c0f6f8df204aea9c8b3ee39430e
+dist/2024-04-29/rustc-nightly-x86_64-unknown-illumos.tar.gz=7179a453bdcb17e401c0af8f4ab86cb5a4752a8ec80b0cbdd4cf1854c7f36a35
+dist/2024-04-29/rustc-nightly-x86_64-unknown-illumos.tar.xz=d565fc366fdbc305fbfe59e72b971c58f201d69e03a9ffa667d2ca0735cdb7f3
+dist/2024-04-29/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=ae6bd8e20560d48519290d78e3d21f84b983403ca1f8f466a85496276d7866da
+dist/2024-04-29/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=c7c0f8f44b0275456a27952178caa04c32eb9a1507056ddc05926a0730e17359
+dist/2024-04-29/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=3246797ddbc9118de819b13b005b83748338f3c825a7436ebd5aa79ca55539c0
+dist/2024-04-29/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=c7e784e77dbabedad88d24d2ae6dc4abb68bc04b1cd6c9d45f6dc28b6d0e2edc
+dist/2024-04-29/rustc-nightly-x86_64-unknown-netbsd.tar.gz=c9452de4b3f15f0cf0b7d737b217b2cc7b88a96543bd8ce587ee14be1e21a90a
+dist/2024-04-29/rustc-nightly-x86_64-unknown-netbsd.tar.xz=de9b05278a5c69d53ccbb31223526ea2aa2275c0fb3f046d1c1b4d67c0b0c275
+dist/2024-04-29/rustfmt-nightly-aarch64-apple-darwin.tar.gz=3734353a58dbf6c3831cc6b4ea606357140c191c89e8dfca1d7aa2f3fb8ac53d
+dist/2024-04-29/rustfmt-nightly-aarch64-apple-darwin.tar.xz=e5e3a6e609fbfd537aa4acfefd3681d4b6c8029e2801a1ef23e8b09cf5a47bfe
+dist/2024-04-29/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=22f54857e01d759301d099b67547cdc485596499088d0d749d38058c28e0f752
+dist/2024-04-29/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=db48a9d45dc7c7aad4c9bb0d20789dd35fb6ef7a966948c44fbbae132de4c16b
+dist/2024-04-29/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=fa5d1fb9f3627e7d59269a1f8008d780c685ea04975473f1808287134e7bc5a7
+dist/2024-04-29/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=61ab625b47fa9097af90a79a1e75a2f2492a415f4009c9043cf453bd4128f031
+dist/2024-04-29/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=cc79969341fc60991059d0e3f13a69489c1e0915ea5787a88b8605ed5b7f3cd0
+dist/2024-04-29/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=bbdb75f922b4b1716b033d91c76c4c0aa53061d6e7fa53a9bf16fe076814bbb2
+dist/2024-04-29/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=13ca68afc3f3970a37951504664b58035102e1ae06d10a744389603b2f7499f5
+dist/2024-04-29/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=04b174aa724945b6359a555892506c6a742a7c427464e8206433bb3f9a65fc02
+dist/2024-04-29/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=430333380a590a9de211c8d735989fedb89321cf9f5f9a0b1ef651ec8b598691
+dist/2024-04-29/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=924713e648806945cd56e54d4c11dc74b65241c8dbf6cc7b401c5c93d0f7ffdb
+dist/2024-04-29/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=bb6e5a8b5cc88099e613aa5f4d926165976d8e4a7fccbecf4ac3b0eb966d7a0f
+dist/2024-04-29/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=34d5e970304e1734aacb26c095e926c27a07e1a41fe70db9fa2997bef97ad3ec
+dist/2024-04-29/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=835447a1d9d60659e99903275f327641809fc0148f35149f980d1a17ff87cc9a
+dist/2024-04-29/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=ddd84a7f900aa239f93711f7da71e57aaedeeba2c9c8a8f23608acc7e48613c0
+dist/2024-04-29/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=02f0af2bdae167c6091099a9b54ceb150c22b0f20dc861587a02cac78deb0b39
+dist/2024-04-29/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=822f78f39dcbe3282bf7888a8cdae04efe7b023ded026a7e7f430e4ff15e7942
+dist/2024-04-29/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=68a6189652c11a2c142c5339e2f5fb09d5f3e85d860bff063f62d5d3a3d111bf
+dist/2024-04-29/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=6740ea882effa2fb87dd72744c08888ce5ec59c9797c00369156b24847bb180e
+dist/2024-04-29/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=0bb365e2d895ef3c39c4899a01187a23f9b7c5195c30bf845da3917f62f5eafd
+dist/2024-04-29/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=2e54c9887bc6ed1eb09b9f69c8425da843ea12bf33248fa0ccdc0d14387c1c57
+dist/2024-04-29/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=b0c0fe437921d17e2f50cbff87beeac067efa3d5211a241fb6f4c10b8ab500ac
+dist/2024-04-29/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=64e7282c0cf4a714b11eed1d28be3a64ba0ccc6d899211a872a5a7809d514c08
+dist/2024-04-29/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=100cfde057c81460b8cfde2047fe83ddde360a6df1ff178da5a968b17ecc9df8
+dist/2024-04-29/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=38e8712e98fa0bc6962ab2fd2e3b96a2a5dcaa6c16161d8caf71131a1ca5031e
+dist/2024-04-29/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=4dab52b50e19348fb39fdad39ab44189c27c10f80b5fbe2cc4723b644611fa87
+dist/2024-04-29/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=36d1b2c9150fafc5976c296200ba3fac3e923df3e6f18032068200e2a887146c
+dist/2024-04-29/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=7cb4a536320c23d305ce3bd3b7a954d951bf4d358ef3732be75b9b290c4818a5
+dist/2024-04-29/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=ede1afc7dc5892ef6f780e987737e145c4b4d00495da8c2e9902182a3a174e20
+dist/2024-04-29/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=e2d2d561cbfa0add0e5349682976216d3a7cff4094372c1ed26854bb4e4d93fd
+dist/2024-04-29/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=e0380e65e83e4131f6aa7ee4e185689add4372b0c1653312e2ffd56072fdd0fe
+dist/2024-04-29/rustfmt-nightly-x86_64-apple-darwin.tar.gz=73a140c7ed9c80f209ff976c63b0a34d625d651553c38692c91f048f4e0ae470
+dist/2024-04-29/rustfmt-nightly-x86_64-apple-darwin.tar.xz=9946b7120465181e05916b8023bc075b32bd85cf45a3b1d8bfba2f94ac78d927
+dist/2024-04-29/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=eda273f27714b1e45adcc2388149f48de0e32a9104db0b9d1a02f6d37de43fef
+dist/2024-04-29/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=f2955a4b696d050c219a96c093162b42a2fab921f9f3cb7570f8462928306c6d
+dist/2024-04-29/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=ec900cc2d3c6d45ef039653f4418f9b9a4a5fddd5d7e8077c3fb08b36c539a28
+dist/2024-04-29/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=04e6999a3405acc79f5fdcafeeab52880e5eeeedd3909b5f3c57e7647c86ef99
+dist/2024-04-29/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=0730c5ebd576fec5371085f9fac0adde9424e1d7626456ed33bc66351b0ad307
+dist/2024-04-29/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=90cbd84b8d48f0235a1954166f5edd53dc3031532ec6dfcb364f9a9624c9ce11
+dist/2024-04-29/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=5f5c62d321db27eb495f6ea312ef8bea0bf17a7a501a44e062986c416951700f
+dist/2024-04-29/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=a3bf64e2f22436e4484fc818f69d2f750fddd05a96463fd4abfcf655edce36b9
+dist/2024-04-29/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=a847a6f9c7a3ce71c7cd8d81bdfcfcd8e4d128aa28ba0dafea89b0cc37c6c36c
+dist/2024-04-29/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=21fa794456566c64d08f629a385f89b3cfe9d9b69f317ae85fbe7425419108ff
+dist/2024-04-29/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=b3f792f10a98993b4b55d1df951727a4422102d51b1145e51824268d48587ad0
+dist/2024-04-29/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=d791f0ec3c004e7baa0381962bf8ca2f18a3c861152702de5301d0149260e7fa
+dist/2024-04-29/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=9807b2887e976d29f0c04484f8459175b4f6b70ef000037cdc4dada48e3cbd74
+dist/2024-04-29/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=019920d64778af62879e2146c2c13d9f6e2165a38bbfa1982694bfb48864d308
\ No newline at end of file
diff --git a/src/stage0.json b/src/stage0.json
deleted file mode 100644
index a9a53a7528f..00000000000
--- a/src/stage0.json
+++ /dev/null
@@ -1,456 +0,0 @@
-{
-  "config": {
-    "dist_server": "https://static.rust-lang.org",
-    "artifacts_server": "https://ci-artifacts.rust-lang.org/rustc-builds",
-    "artifacts_with_llvm_assertions_server": "https://ci-artifacts.rust-lang.org/rustc-builds-alt",
-    "git_merge_commit_email": "bors@rust-lang.org",
-    "git_repository": "rust-lang/rust",
-    "nightly_branch": "master"
-  },
-  "__comments": [
-    "The configuration above this comment is editable, and can be changed",
-    "by forks of the repository if they have alternate values.",
-    "",
-    "The section below is generated by `./x.py run src/tools/bump-stage0`,",
-    "run that command again to update the bootstrap compiler.",
-    "",
-    "All changes below this comment will be overridden the next time the",
-    "tool is executed."
-  ],
-  "compiler": {
-    "date": "2024-04-29",
-    "version": "beta"
-  },
-  "rustfmt": {
-    "date": "2024-04-29",
-    "version": "nightly"
-  },
-  "checksums_sha256": {
-    "dist/2024-04-29/cargo-beta-aarch64-apple-darwin.tar.gz": "5a8c5e48a88e7c7b41eb720d60fbd2e879b97639c7ff83710526e8e6caaf8afb",
-    "dist/2024-04-29/cargo-beta-aarch64-apple-darwin.tar.xz": "0d237535ae8d435d99104fa5b9dbf41878e2304bb0f2eb574bf17dd685caadc2",
-    "dist/2024-04-29/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "c56733bb6198af0a9b0df9a44ef979150e00de33b70853c239cccfcce23c328f",
-    "dist/2024-04-29/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "7da5f887151215ddec640684077d98551fe2aed75a3ece2c73b20698754a70bb",
-    "dist/2024-04-29/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "73851e304a539d41bedc0d8a5d98800c8279ae623d3e58e863f8c1f8b458b01c",
-    "dist/2024-04-29/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "db9c28841344b0154756e19a21795ef6e0c4e27c7844be9996824f1039edaa81",
-    "dist/2024-04-29/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "a706c8c7e37b9e80d7faa000c5d179a772746eef071387fb2879fdeab1f1f891",
-    "dist/2024-04-29/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "2060634afe1b4a19bae874c6ce3cf4256e613af26e06104b45da5bd71cfb133c",
-    "dist/2024-04-29/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "7af61e74faea669fdd41793e4b88eb6a37bfacf845af364ee02bb7cf08c612c7",
-    "dist/2024-04-29/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "4759fb3e3d89ead605c4eeba23be5cb9b3ac98086a9de20f8dbfdfa9282ee486",
-    "dist/2024-04-29/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "4cab18df2d94702e8b551357373bcae60d1023e644148f0f82e8971023362121",
-    "dist/2024-04-29/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "7de4f0d72b4e5770376ede82b02d6bcfd450788a40375fad34d75524c941d72c",
-    "dist/2024-04-29/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "6401391a426cf33d6c58f07e7b2828b178720cb4f2b8577ae932b5f5b7d6744e",
-    "dist/2024-04-29/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "c3f6729bc769325046f0f62c51b5bed30068c37dc2a36a6283e50565d8cb7d5c",
-    "dist/2024-04-29/cargo-beta-i686-pc-windows-gnu.tar.gz": "d116c97c1242220c7972b63010aee1ed36bf5353e84a06d3561cd5fe9d7dae84",
-    "dist/2024-04-29/cargo-beta-i686-pc-windows-gnu.tar.xz": "65eba577f7775b3eef36e7f000b5007264392b20a7759f8ed567f3a45b2877db",
-    "dist/2024-04-29/cargo-beta-i686-pc-windows-msvc.tar.gz": "d418a3371b3631328bde2b1e0c3159700f12424e83b1d8ece1349fea90f9e403",
-    "dist/2024-04-29/cargo-beta-i686-pc-windows-msvc.tar.xz": "23ae73c776fdb0795944656d743444e3b4c440f45084028206c1aec52333b1ba",
-    "dist/2024-04-29/cargo-beta-i686-unknown-linux-gnu.tar.gz": "b6bbdeb7c8bfac2e8a083adb4782caf5321799f47acb4eaf81da32bd11730e9c",
-    "dist/2024-04-29/cargo-beta-i686-unknown-linux-gnu.tar.xz": "6b409691da6ddb8c04409667b2c3d9d6429c6b5bf53ad18177248406a5f06cb9",
-    "dist/2024-04-29/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz": "24cd888d14a788e8fb5b886735f3c07a028a8681df48a777b2bb971c62a175ae",
-    "dist/2024-04-29/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz": "e8eece6412936fe4dc863a5e19e6766fbb20e81da0069ad7831465e638db23da",
-    "dist/2024-04-29/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "8f007a2aa02e35c5ddb2152cc7589092a0e3083211c6aa23e676e3a3ad5a4b8d",
-    "dist/2024-04-29/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "3e423e693dd0813f5d87d9eded94894076258ece56684f3598321cd013aeef3c",
-    "dist/2024-04-29/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "2eec5e45e389a52b526a5cf683d56a9df92004f6095936b16cd8d7d63722cc6c",
-    "dist/2024-04-29/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "64c5135cbff9d4fa9575074c55e79d85f72cb1783498a72e1f77865b9b2d1ba3",
-    "dist/2024-04-29/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "d64552a80ca386728e42f00d7f1c700b5e30e5a6939f32ffa15a7ce715d4c8e9",
-    "dist/2024-04-29/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "fe91adce8ba35bf06251448b5214ed112556dc8814de92e66bc5dc51193c442f",
-    "dist/2024-04-29/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "77aafa8b63a4bf4475e82cd777646be5254e1f62d44b2a8fbd40066fdd7020d3",
-    "dist/2024-04-29/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "c38f0b4adcc8e48f70b475636bbd5851406bba296d66df12e1ba54888a4bf21a",
-    "dist/2024-04-29/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "c05df24d7e8dff26c01055ad40f9e81e6fcb3ae634ecc1f7cc43c3108677fa0e",
-    "dist/2024-04-29/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "47e8f4ec4d996600e60ddc49daeeb43d4c21e0583a86c12395c16eddc7db76ee",
-    "dist/2024-04-29/cargo-beta-x86_64-apple-darwin.tar.gz": "f024bd225b77160dc2fabde78002c8deac5cbb9a35345340964c3b988b0d1791",
-    "dist/2024-04-29/cargo-beta-x86_64-apple-darwin.tar.xz": "96c9e44bd9f0c85c793e3dd6043cc4f89fbeeab5ddf0fdb5daefca8f690bce05",
-    "dist/2024-04-29/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "517889f222b62150fe16bcfd3a0eb5f353956b0084d85713480197bff4558145",
-    "dist/2024-04-29/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "a6653ea4aec51569c1300c044d8bf2517a1f5111f710d12cd352190425b8f317",
-    "dist/2024-04-29/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "4cb5b5054dffe6721efbbf29192a67e59cda69ea4ab4791aaec6f314eefa5a5e",
-    "dist/2024-04-29/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "08bc45be22e9e4f615d1c9e70500046c8db89045f5d40dcde853c610591712a7",
-    "dist/2024-04-29/cargo-beta-x86_64-unknown-freebsd.tar.gz": "9661357ee8ea8973016fdbaa2de3cb98713136dcd25f07aa9f9d101180276815",
-    "dist/2024-04-29/cargo-beta-x86_64-unknown-freebsd.tar.xz": "7fab806227d1a3be817602abb121ac7e039ba0bbf81e0a1d47bdcccca74203c6",
-    "dist/2024-04-29/cargo-beta-x86_64-unknown-illumos.tar.gz": "4c79bb48cfe64bd38af7fe3660cd8bdc99ec90738a0d8fdf80843ecda910dab0",
-    "dist/2024-04-29/cargo-beta-x86_64-unknown-illumos.tar.xz": "0fb9edfdafde1820ccb25c22369cafb0e75e68795effeb615cb284a5837c75ba",
-    "dist/2024-04-29/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "c1902a072e61ab5ae9737a1092732e3972deee426424bc85fcf8702adffdd41d",
-    "dist/2024-04-29/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "d39ea1195dcc95e428bd540abd2db5b5d4c997a7661a41a4c0ca41cbdd18d27e",
-    "dist/2024-04-29/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "0edfdb6f6bb2a4a1a96a5e95cec897c444c936e6624bb4a530ffed4847b97445",
-    "dist/2024-04-29/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "70c264b7845febdee45d0c6e44b65d47ba7f367ef33ec906a9fd7f992ba7cc13",
-    "dist/2024-04-29/cargo-beta-x86_64-unknown-netbsd.tar.gz": "f1bd6417a54f3b53d572ce4af799242db7c11265c71201cc09c78d71be38c13a",
-    "dist/2024-04-29/cargo-beta-x86_64-unknown-netbsd.tar.xz": "53569810469c483785333759f86434706ee5368d5e18270ee13a17817ad57d40",
-    "dist/2024-04-29/clippy-beta-aarch64-apple-darwin.tar.gz": "7b693bde61a090854527a145455ff774314c65ec0cd47d25a19c76c6a166d96c",
-    "dist/2024-04-29/clippy-beta-aarch64-apple-darwin.tar.xz": "2494e9fdd8d342b6bc3e55eecfd555c43e3cca8421f3236df2d5a366288fec62",
-    "dist/2024-04-29/clippy-beta-aarch64-pc-windows-msvc.tar.gz": "90307f09c6fcb0c1fbe3ad1522a5381a17e2f69637c6d00f4a2cb5f3149bf736",
-    "dist/2024-04-29/clippy-beta-aarch64-pc-windows-msvc.tar.xz": "f7e0dec4a4862bd85d894252366152b3b6a7627e7e5a25ce323fa2db3bd87c2b",
-    "dist/2024-04-29/clippy-beta-aarch64-unknown-linux-gnu.tar.gz": "7c719e38f2a1030ae61985205df52f9a0c37b659463a5e2dea8e60e632de2d73",
-    "dist/2024-04-29/clippy-beta-aarch64-unknown-linux-gnu.tar.xz": "181ff4ae6adced6522a4c29869be3cc5dac8b961c7c88f2957cd31f831490807",
-    "dist/2024-04-29/clippy-beta-aarch64-unknown-linux-musl.tar.gz": "4e0e63e6f200386995e369a2673867d1bc3005d51d6a57c00ca80056dd85316b",
-    "dist/2024-04-29/clippy-beta-aarch64-unknown-linux-musl.tar.xz": "3d5b22a13aed6821482e60d9cc8571e2da9d95d82104284b77c56985a35a9c4e",
-    "dist/2024-04-29/clippy-beta-arm-unknown-linux-gnueabi.tar.gz": "9f788db76a5d55b3ecdd04a70b0e2be466959f76ae9fd3497ca2c503504e0c03",
-    "dist/2024-04-29/clippy-beta-arm-unknown-linux-gnueabi.tar.xz": "f4d8fc103807fba61d71d88b8e25a7016bfbd1a2905330f9a9fb3d7ba082713a",
-    "dist/2024-04-29/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz": "d61bec3d017dd0be43e48350190ad18c0a0269e43d964600b62e1f7fd4f84399",
-    "dist/2024-04-29/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz": "c00cbdc41a4da0c313a1a282b0158b059dd34f640b582cb7ca18e3d290ca8fa5",
-    "dist/2024-04-29/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz": "52143a530ca5274fbb760beecddff16f860ea787443d3dc708dda7c8f32ca9bd",
-    "dist/2024-04-29/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz": "c6d2dfeac6f40811bc9b4cec3c23f9c3bb46f761e006257b9313aa7c1a647b5a",
-    "dist/2024-04-29/clippy-beta-i686-pc-windows-gnu.tar.gz": "325d39e426b1907fa17d93c0752d3d73bd95750f4f967c2a84aab2c5dac8a588",
-    "dist/2024-04-29/clippy-beta-i686-pc-windows-gnu.tar.xz": "536f591d4da455302029384ed196932d71119ef0160ac5415617d6b777c51123",
-    "dist/2024-04-29/clippy-beta-i686-pc-windows-msvc.tar.gz": "c3684c9bf471669d444853bf484880d17e150ecb0e7505de90883382023e343b",
-    "dist/2024-04-29/clippy-beta-i686-pc-windows-msvc.tar.xz": "0b00e6132f73d5dc762e359b0005fceab0cf7b01337d8f4aa9eacfb4552f9245",
-    "dist/2024-04-29/clippy-beta-i686-unknown-linux-gnu.tar.gz": "c91c1eadfc4cbae360a0eecf11c32d2509b68aca86c7b1de3b102944f43e1511",
-    "dist/2024-04-29/clippy-beta-i686-unknown-linux-gnu.tar.xz": "6f7a5a287dd6226c203bb674ff02ec773e5d0813091b2af744b88ecd6997a304",
-    "dist/2024-04-29/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz": "58383f094995823ea6db6a87b9ad4b33bdae2264d29bab88ab71ec60ccab3b93",
-    "dist/2024-04-29/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz": "dbf4680a6fd4dca54acca5503a7fd94502b8e85819bc02346ae9cecd275e4514",
-    "dist/2024-04-29/clippy-beta-powerpc-unknown-linux-gnu.tar.gz": "e28eb32cda42654c0f0247aa8e15f01f73770b36f7626c8d6f1b7659accc56e6",
-    "dist/2024-04-29/clippy-beta-powerpc-unknown-linux-gnu.tar.xz": "fcc48a83b748e1e46f9daef40563f8e5abbb0e3f014a168b04f3c700c2ace2b8",
-    "dist/2024-04-29/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz": "b626faf3275fcd196cd627e8a36c67721bae16a56f61cd080c79d137b3ec7737",
-    "dist/2024-04-29/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz": "2c599d2dc719d69f67625f3c6573fcc4f1ea3266801557dd3892bdb7c761b4cf",
-    "dist/2024-04-29/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz": "0bc1f546fe0cef2b9516231ab608de68d55f72022fbc9ced5101b600e005f8c4",
-    "dist/2024-04-29/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz": "993294f2ae5202785ab242c1c6567df9c8ab1ef44ad35748c526b7fe854fb94e",
-    "dist/2024-04-29/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz": "210a4f0d208e0c8e13a57fb3b3e6c98ab5f620e4988d10a127ff1424ac1d5ca9",
-    "dist/2024-04-29/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz": "f10f7df41a13ee2ecdc25d60e697cba2342129a912ef20d8bfca5f611a9ec97f",
-    "dist/2024-04-29/clippy-beta-s390x-unknown-linux-gnu.tar.gz": "3e24d2af65f0c9667c9997ce091711b2be48e673de3707cddfd8cda455dfecc7",
-    "dist/2024-04-29/clippy-beta-s390x-unknown-linux-gnu.tar.xz": "0e7b8fbd0207489e38c78c2ae1aa0df4fcbdd84741aa50a86379e4d7ede286b1",
-    "dist/2024-04-29/clippy-beta-x86_64-apple-darwin.tar.gz": "9c0c47fd97ce72abcd6126315834c62aa7297fe09d447ee4cefa1eb46a116326",
-    "dist/2024-04-29/clippy-beta-x86_64-apple-darwin.tar.xz": "49dd65c5340fd804399edfa2402cf255fd9bfce1f4aa7fbb3c193c11bc03f8af",
-    "dist/2024-04-29/clippy-beta-x86_64-pc-windows-gnu.tar.gz": "6c1c3bdf097a1846ae08b098c555c0c5e9e9b646c744d6bb5a855789196b8bf6",
-    "dist/2024-04-29/clippy-beta-x86_64-pc-windows-gnu.tar.xz": "0a7319d1062f73af1c8f0efe6ad970d10d02259162c5bc84bb1f3a10f3911bcb",
-    "dist/2024-04-29/clippy-beta-x86_64-pc-windows-msvc.tar.gz": "52fef3f8a64fa58934a633bd4944e8ba9e15f2c2766d0f302dea1a6523864dab",
-    "dist/2024-04-29/clippy-beta-x86_64-pc-windows-msvc.tar.xz": "8fdbe7590e62ab68a2e463b14da2595e8c4592744f578a813f64d430ed7db4b6",
-    "dist/2024-04-29/clippy-beta-x86_64-unknown-freebsd.tar.gz": "509bf535622bd26385184ee0c17e4e27a5061a8aeebf5759f24bd578692b2f5d",
-    "dist/2024-04-29/clippy-beta-x86_64-unknown-freebsd.tar.xz": "2fcd10ada329ba7633616bebc584dca13f11c465e7cf513e76efeb0c3174486f",
-    "dist/2024-04-29/clippy-beta-x86_64-unknown-illumos.tar.gz": "ea8cea0d4a2379bcd0693f6174b25bc1f90a016dbe8280159cbb61d859806fb0",
-    "dist/2024-04-29/clippy-beta-x86_64-unknown-illumos.tar.xz": "5a243df8d1345db6bd18e4386ba628e6d302bce1cc572fb447cca4264fda3ee9",
-    "dist/2024-04-29/clippy-beta-x86_64-unknown-linux-gnu.tar.gz": "2ee560d3c1e306e103eb06d8e8033cd1489b3f6ff9df3bd8a95e25e977befa27",
-    "dist/2024-04-29/clippy-beta-x86_64-unknown-linux-gnu.tar.xz": "aaf6e54184a65ad6592bf03955a84ad12b561afd86064b1ac5fa03cf637052f8",
-    "dist/2024-04-29/clippy-beta-x86_64-unknown-linux-musl.tar.gz": "1b3877424a0a0eb507675a50e9d2c793f00ab85f6f12b1e27f871331070325b8",
-    "dist/2024-04-29/clippy-beta-x86_64-unknown-linux-musl.tar.xz": "6df5eaae5afb64557ba5c3a53ee3e56dab85455838a6044c7671c1180acfeaf9",
-    "dist/2024-04-29/clippy-beta-x86_64-unknown-netbsd.tar.gz": "1ac05ed7b607fff8b77ff203a663e9f4f2487779bc25e2dcd454cdf5b7583328",
-    "dist/2024-04-29/clippy-beta-x86_64-unknown-netbsd.tar.xz": "da502375b3cee8b254ab5999809f522692c2d1d90ea0544ad03c0ca514c65ef4",
-    "dist/2024-04-29/rust-std-beta-aarch64-apple-darwin.tar.gz": "2fdd35ca3b3e3d6f548f11c93337f5bf2e3c088bc78a79881e6f8e230b38b9a5",
-    "dist/2024-04-29/rust-std-beta-aarch64-apple-darwin.tar.xz": "bc16b3a1ab6ed69f0121a117c50cbcd201500dae4d72ad0dab148913d04cc529",
-    "dist/2024-04-29/rust-std-beta-aarch64-apple-ios-sim.tar.gz": "9375c786703c17baae1c2066f8d972ac316bc840e478ecd1b94288a1d428324e",
-    "dist/2024-04-29/rust-std-beta-aarch64-apple-ios-sim.tar.xz": "50d6818a8dd3ab7a3ddbbd7a062b538d9ff3ceb6eada031d1c22ab1dc7ba512c",
-    "dist/2024-04-29/rust-std-beta-aarch64-apple-ios.tar.gz": "56c3a01e8fd5c2ed75df811993b0b724709fb5473cc308ac09e7f5644468f751",
-    "dist/2024-04-29/rust-std-beta-aarch64-apple-ios.tar.xz": "3527d1f2c99c806479fb4b3801335dc921b514f171b82cd252cbbfc9ed30b163",
-    "dist/2024-04-29/rust-std-beta-aarch64-linux-android.tar.gz": "bf8cae7c66489f1aa27f1dea1b37f0d0ae514a6e21b93ff2dc6400dc88feca03",
-    "dist/2024-04-29/rust-std-beta-aarch64-linux-android.tar.xz": "46799f0bc1b3c13877f6cb732774cb3b33e0d8a081bfb56d0f877e79482aa1de",
-    "dist/2024-04-29/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz": "9f90fadab5104e1d415edf3b4edfaf7222f9f0d55f849851efdec74ffee16f8d",
-    "dist/2024-04-29/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz": "87ed6774202b18691bd6884df6944c7e9fe9c944b57a2837e7a7647518bf94e8",
-    "dist/2024-04-29/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "4a0692ad28f7f130b472ffa4aa766b745ba01fb75aa921f2da6622c9c68750df",
-    "dist/2024-04-29/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "a3d45962489a1e18a87e567cbbc8d3665f38809d0ad2ef15bcf0ff9fb9f470a4",
-    "dist/2024-04-29/rust-std-beta-aarch64-unknown-fuchsia.tar.gz": "c724f4eb135f73b9c79618f27a1ab35dc7b9d26ca62ed796accce68f9e747a66",
-    "dist/2024-04-29/rust-std-beta-aarch64-unknown-fuchsia.tar.xz": "8eab25782d16bcee75f86ecbb826346beb4a7525b220b45b3ba05a567c6d4391",
-    "dist/2024-04-29/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "33ab1f8410edf590570d7468dbe2ebb5a0907125bbc8d360a928dcb355f0d0e6",
-    "dist/2024-04-29/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "d3d870209a55ac96391affaa347c04f48cf98c089ac5056f340b8bb38bcc8e60",
-    "dist/2024-04-29/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "4d2bb72b898c30a2fc8d5d3333c2e99a8e30c15891fab641b6a519dc9f0cb611",
-    "dist/2024-04-29/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "fa343e6b6110fcd0c5dae4287ff1a799de5d7e4a805dbf4e9a034bbaed2bf269",
-    "dist/2024-04-29/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz": "f1ec4139783169fd83e1b0184518ed25d26cee7b21f196deecc74e83a1d78725",
-    "dist/2024-04-29/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz": "d100be2f6f0346c4b1f5b41aec0c13a47426bf4d49127f2341c8332903e4e782",
-    "dist/2024-04-29/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "bab6051e1071a58cd126580f6644decf16edb4473fe4be6a34791610d820a294",
-    "dist/2024-04-29/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "d9b68f06ff23629063e92dfc42aa3115a858238d368e4b52b35c1ea4491b1402",
-    "dist/2024-04-29/rust-std-beta-aarch64-unknown-none.tar.gz": "96804c2d9accd3242bdc22dad688b2ccee071952477b9c592f099377aee6c591",
-    "dist/2024-04-29/rust-std-beta-aarch64-unknown-none.tar.xz": "3fed6812d84bdaf787e85c37e23ba729b81a6d25a2b33fed75320e66e6641c89",
-    "dist/2024-04-29/rust-std-beta-aarch64-unknown-uefi.tar.gz": "8da5f301bff35fc067ec7cfb878ebfa5607af7dbc276a6b34a77404432c700d2",
-    "dist/2024-04-29/rust-std-beta-aarch64-unknown-uefi.tar.xz": "80d643189dc9af98b6410a01261ce6ad34b1325f3aebf3ff61fb43f1261b41ff",
-    "dist/2024-04-29/rust-std-beta-arm-linux-androideabi.tar.gz": "2e86b54b0d1f7fefead11d6383bdc80fe0a7b3ccf58381d2a731e6f1c62926de",
-    "dist/2024-04-29/rust-std-beta-arm-linux-androideabi.tar.xz": "9831a0270457cad2798b5ae4fe956c257c7e10ce5ad211793dc467577cdec29e",
-    "dist/2024-04-29/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "f96bc303c0c2be9cf589f00aa63b2cf3fb8585ca9dd8860fe525821bfa1fe19a",
-    "dist/2024-04-29/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "e57a053b1c2bb6fad93dfaffedce7f48fa292196fc8ba6fd2f0c74dc810a13a9",
-    "dist/2024-04-29/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "49b2cb2ba5296871b5fac5ad9a74a2891e8b78321078a455ba4a65e003bebd40",
-    "dist/2024-04-29/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "0f9c15d834a9d282a4018934759f7b48ef3d275e09679a68c5fd1b3f047d02e4",
-    "dist/2024-04-29/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "e59f92827241e670c1aa92b35235ad12340869d59327fb83084b5f4149acbe06",
-    "dist/2024-04-29/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "ad1cf96bb1fcceaa016e29e8ad34b4cfd711d2e0bd7cabb9cd7cc28abf64d894",
-    "dist/2024-04-29/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "14a6d318af85bb9fa5c229e45a88a32a71f44ed02cd90a24bb67921eb64dee41",
-    "dist/2024-04-29/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "ed6b48502ab9169818bceb300b4e6b4fd63366ad5808b047bf9988dae04c2729",
-    "dist/2024-04-29/rust-std-beta-armebv7r-none-eabi.tar.gz": "345e8a023be55e3b88a0c2677ea28c7bb4fcc5f3ab707638de76065c7592c2d5",
-    "dist/2024-04-29/rust-std-beta-armebv7r-none-eabi.tar.xz": "6d9b11d08f2d62611327a893b45ba07c36df11f077250496ab0881eb7ac84c65",
-    "dist/2024-04-29/rust-std-beta-armebv7r-none-eabihf.tar.gz": "a2ae1bf003a8a12b2ecb6bde9868a978820f184af523f0e4c3fc935edd509423",
-    "dist/2024-04-29/rust-std-beta-armebv7r-none-eabihf.tar.xz": "3d1dcf8308f9d4590b429f6abbf8f42f04496ab490ccf4ed8c9e381e6d886cae",
-    "dist/2024-04-29/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "a54106d27e4ce97463e7867ceff9dd22ba456f840ec23229e6909b37d48ad554",
-    "dist/2024-04-29/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "e6abfaa0905a00efeaee85b9f93793bab93e2cf4e172c9d829c5ba85006c688a",
-    "dist/2024-04-29/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "cbed18e5dc61fcecb2920affc3890c3b8ae46b7fe5a80b3288689e18d490f3f4",
-    "dist/2024-04-29/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "2b58bb0dd5cd2c5f7f93f4c6e9135090b931e0ffa27ff9efe2b8ff9fbbb7e48c",
-    "dist/2024-04-29/rust-std-beta-armv7-linux-androideabi.tar.gz": "6a371c2ececd349dfa76a02563069912fc91577ac4446d36c22f96723d7f5e9f",
-    "dist/2024-04-29/rust-std-beta-armv7-linux-androideabi.tar.xz": "9325daf41ddab02fa845971c10a5e0538a18c7bea14e66fa0f5f6fb16654c7ae",
-    "dist/2024-04-29/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "7f5ba76cfb7c85333c8dab76fb4ad3f12ddc254b95f9ee07fadb8e1270a4f767",
-    "dist/2024-04-29/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "f853b7f929b7a309ed6c08ff8c57d583ce0ccb19270674fb30e63a873834dc87",
-    "dist/2024-04-29/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "0680005d0a12498b687afc583d4f36bd67d0877cd9d3323bfd2df50d15c27afe",
-    "dist/2024-04-29/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "a494b78fcad01c83df9522d460ac2d35d2d00736a921381f2c611dc516edaa16",
-    "dist/2024-04-29/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "cfa555db31b5470e878b0f53d86617e7342e8bf018fe62cb0271dfe13db95f51",
-    "dist/2024-04-29/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "0a8ccd6d88cbe79a855111fbda45aa1a728de655b6927f3d429d901d2afc6503",
-    "dist/2024-04-29/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "eac53424001c884a540c42f0b68447349ec5d0601a030c060aaed76d54895728",
-    "dist/2024-04-29/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "42d78fca62361ff28db5bc43bb01cef7af5c6f4ab2110fe6170c3dce4707aab8",
-    "dist/2024-04-29/rust-std-beta-armv7-unknown-linux-ohos.tar.gz": "c88de9f2e667da73177fb9c9309d7f1f467e31c18e3ae50d722c71ec8dd876a4",
-    "dist/2024-04-29/rust-std-beta-armv7-unknown-linux-ohos.tar.xz": "24b3c04a42d511cdc8c6107b597be38981114f0574eced493d0e90fc748094bc",
-    "dist/2024-04-29/rust-std-beta-armv7a-none-eabi.tar.gz": "cd4ad182a098c61550265879ccc04733c39110827f7ef62eecfb8c120ae4ece8",
-    "dist/2024-04-29/rust-std-beta-armv7a-none-eabi.tar.xz": "8499a014dfdf448f474a58f148784c2eef245dc909587d876d2fb9ddc6a4ec3f",
-    "dist/2024-04-29/rust-std-beta-armv7r-none-eabi.tar.gz": "e8e1870e5b12b3d8643d712efb91eb86b2081284cada4a140c1526692ab183c4",
-    "dist/2024-04-29/rust-std-beta-armv7r-none-eabi.tar.xz": "d6029121eacc44bd4dcd9ef6dd3cd0d775cb6e9a3d99f3d62d746fcbf8981cab",
-    "dist/2024-04-29/rust-std-beta-armv7r-none-eabihf.tar.gz": "1e0fc42c3802e205130c01ca90f92d793c1c5427b34da66fe77b97cf67b4a5c1",
-    "dist/2024-04-29/rust-std-beta-armv7r-none-eabihf.tar.xz": "4c8cfdb11bb686111fa4842d13430c86d9d14ada30e9df334b3777fe899233e0",
-    "dist/2024-04-29/rust-std-beta-i586-pc-windows-msvc.tar.gz": "ff895c1b39b84587f10903f4be13d275b545e690da6761190d12c01acc25c6d8",
-    "dist/2024-04-29/rust-std-beta-i586-pc-windows-msvc.tar.xz": "fdcbcff7b740235bb16e44174fff9080a7c0a31be358c8abc41805c02c20c3b2",
-    "dist/2024-04-29/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "6b227f3b9001e148b66b7001f753a6f88fef9677e39d8fcf4d9c35fe8d345568",
-    "dist/2024-04-29/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "1e29297beb8de3778ba958731294823d9a93aac1e0d8833abc5aa99e2935965b",
-    "dist/2024-04-29/rust-std-beta-i586-unknown-linux-musl.tar.gz": "26481ad5f22a319830d42f69b1c0195bd65900ebe112e659432334b3468f3d0e",
-    "dist/2024-04-29/rust-std-beta-i586-unknown-linux-musl.tar.xz": "c8a837e0d9da8ad976fc1539541c085365aac9dd28b34e4a289d38a823d1b065",
-    "dist/2024-04-29/rust-std-beta-i686-linux-android.tar.gz": "f05e28a52f17e22f36ffc70018012a1fe6a07f4b461e774b36464f32bc8f8dea",
-    "dist/2024-04-29/rust-std-beta-i686-linux-android.tar.xz": "f9501b2691c51e54a6f4cc6fb72e41901eb551d3a7be5f82a94ce2d3e217828b",
-    "dist/2024-04-29/rust-std-beta-i686-pc-windows-gnu.tar.gz": "8d9a782d4f7450bca536aab45147c6ef08bc3847b43fdd171c6449e29762eda0",
-    "dist/2024-04-29/rust-std-beta-i686-pc-windows-gnu.tar.xz": "4008712e03fb6494eaba3d79051c5e3fdd93d4c52ae8d86cf8f344b5f051cbca",
-    "dist/2024-04-29/rust-std-beta-i686-pc-windows-gnullvm.tar.gz": "cfb23242e495834a3d0f7ffa3da4a0b206dcae35872b1455b11faeee5511ba5f",
-    "dist/2024-04-29/rust-std-beta-i686-pc-windows-gnullvm.tar.xz": "95415742c0171945ffc2b67c913ebd1330e29634af238f5ccc843a965340374a",
-    "dist/2024-04-29/rust-std-beta-i686-pc-windows-msvc.tar.gz": "e9354d69e39ecfac1d2928664d17d73f808256a4076b849171a9667705c0aa08",
-    "dist/2024-04-29/rust-std-beta-i686-pc-windows-msvc.tar.xz": "a34bb0a91170d84195f35ba52afa4c9be8a2f2706dbeea02bd6e8908e08ac65e",
-    "dist/2024-04-29/rust-std-beta-i686-unknown-freebsd.tar.gz": "d65f286de399ccc9e9acaf7a4dc4f885357c750231d54a144ba9a59181814f11",
-    "dist/2024-04-29/rust-std-beta-i686-unknown-freebsd.tar.xz": "4c93a7da70a69b2ebbac01df64af16344e523d16470b29e57237b1d0925f7721",
-    "dist/2024-04-29/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "1b978bfd1a9234be7ef197c8c98c5a6b625f6fbb7b0fca58695986768bdca176",
-    "dist/2024-04-29/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "98d4eb5b89a593c8c4f86244c9a7c737d9c18c0168aebe5923b8d9145adcf89a",
-    "dist/2024-04-29/rust-std-beta-i686-unknown-linux-musl.tar.gz": "dbf9b3c5b54b3eb0727f976f5632c5b0fcb2f90ac7453962d6cef20f7dae4284",
-    "dist/2024-04-29/rust-std-beta-i686-unknown-linux-musl.tar.xz": "f209ade093753342dda6e710ee832a538dbdaa08a24d606f9a2a1bc59b83da29",
-    "dist/2024-04-29/rust-std-beta-i686-unknown-uefi.tar.gz": "3c3ca7f34569b2c70c6b223754418a535dd7dfa087ab6e28ed2ec78d20065887",
-    "dist/2024-04-29/rust-std-beta-i686-unknown-uefi.tar.xz": "72a7cd0f430ab40d80e93f409b8e26a181010ab4bb75d151e829d51ccdcf8c62",
-    "dist/2024-04-29/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz": "b7dfa59bb05cf806c87854d6fce5ef0f160697052fdf6e5a0cad121499108608",
-    "dist/2024-04-29/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz": "88bc22f68bab3367cdfa91676418ce1ffc0ec002afb32aed7def880bdd4be402",
-    "dist/2024-04-29/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz": "d61019048b941064a99d19e46ff3236a88a2e8fcfb963cedd1d9d1c47963c170",
-    "dist/2024-04-29/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz": "7474bda08134c676d74afe5263317af3f271963d8ceaa5efbfa1b657f885c572",
-    "dist/2024-04-29/rust-std-beta-loongarch64-unknown-none.tar.gz": "e089c77d433d838ca02d7531d6f4a1770fb4a0568acbd96c8f43034d76f2990b",
-    "dist/2024-04-29/rust-std-beta-loongarch64-unknown-none.tar.xz": "364ae6c89c7a930098286e55193d2f5ee3d5ea80b7cca73046e41725f4a8a2f9",
-    "dist/2024-04-29/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "c17bfad87d16f3a8d26646525dc59a352718db9e7572acb583b68a18cfdc338a",
-    "dist/2024-04-29/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "f5c4ecef1c08d19ba6fddbd359a0ce94e46888021cae057fce969276026d086c",
-    "dist/2024-04-29/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "3e7e13b0d2e804d228e1e3a9dac0205d294ae29dcc37132f15fb1e218861eb39",
-    "dist/2024-04-29/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "ea31b7678e6f64c2f9c28a9af120be04ed6f2a25a496e40afbf6e9aa0dd20b60",
-    "dist/2024-04-29/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "f0e1b314c3d5ad1676c68c112581dce62fa06ad557cd5f61034e147b064ed270",
-    "dist/2024-04-29/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "8ab7bbea6e2f72df1286facc7d306d01809a4dd9f8901dfdec7e50b594658d49",
-    "dist/2024-04-29/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "48f6abda1c7dac185858744aa2cdc3513cdfb6552535282ee83cf9c5365573c7",
-    "dist/2024-04-29/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "d920d97f15b56ba6ea81e08b3c29dc7f44f5f30b7513c53446edf95843c332af",
-    "dist/2024-04-29/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "0a198a770f6e6043e923b0ab1a508fd8b190612d0370c33c8dd2c5f63b6f19dd",
-    "dist/2024-04-29/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "424a93313cfe2d85acf956be3d9ac71ea8e34ee61617a550ad6ff5360e1dff52",
-    "dist/2024-04-29/rust-std-beta-riscv32im-unknown-none-elf.tar.gz": "2e2b0a8e41f4ea774d665d6248cbc2fdbe3e582206efeb87d250786ebaad0b1a",
-    "dist/2024-04-29/rust-std-beta-riscv32im-unknown-none-elf.tar.xz": "2da372c091017b7096e473e5c7016a504d2e041e14173d2520086cb43e0a615a",
-    "dist/2024-04-29/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "69d3b21403181b2df14243816388169db2466477ec34bcca5693fb017703686c",
-    "dist/2024-04-29/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "281b9c20f8641a3d1b349e762b7f713fb0b91da0d21eec798e639e36a0ea3dab",
-    "dist/2024-04-29/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz": "dd9bfd3fd8446d35180fe781139dfb4e04dd658b112eb2a749e8f4aea14f0271",
-    "dist/2024-04-29/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz": "b1366375e0c5f53da581741dec91972b0c46d7d466052539207e8feaab0ba3ec",
-    "dist/2024-04-29/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "7c6650d8cf8abd51547010e8211af3ef3195099ef43a563460ad4780de20ba17",
-    "dist/2024-04-29/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "bab46f3c0078ce346de563bb7a248ca92f15dbdc73bf5a3bc520486118442320",
-    "dist/2024-04-29/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "01735b4ad5bc0a53087dd0ccaef2cf174b27e45bf4d2e3c15e64f7522f059c63",
-    "dist/2024-04-29/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "0bb272c2c235583ed3e9ec151b3bfc601f8cd07822c2fe47a1258b358be507f0",
-    "dist/2024-04-29/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "b2c7f8ee0efe6d0812e4b5dd0979f60f105b84d34d4f600ef75f2eacd954893d",
-    "dist/2024-04-29/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "0d5301fc553a6911af6643ab7f57b6438bf649ffcd050d486278c0c5fe38eeba",
-    "dist/2024-04-29/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "0d1d35ecb88ee717720ad8e74bd5b602fd6011fe321baddb939f3b161e9cd8c5",
-    "dist/2024-04-29/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "a5cf0b98596e68e6f72be2e83c61b8aaa19ead42f248ee2408a3b8f4e97a6657",
-    "dist/2024-04-29/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "629ed749cdae110668ad9ddbc5c61e99e8d400f3dd0981146c3820deadc360f6",
-    "dist/2024-04-29/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "192819438ed27a565cdb67b51d2f5caeb6ae258de86191d6922574327f132acd",
-    "dist/2024-04-29/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "84286f6cf6f00f3c92dc881f64a31e1ec5910102d8d3d4faf6fc7e2ddf1544a7",
-    "dist/2024-04-29/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "304b5f876b47dcbb7c3483c49295b822e8ba83234bb568ce67896ae4773ae2fa",
-    "dist/2024-04-29/rust-std-beta-sparcv9-sun-solaris.tar.gz": "25062159b859e21dda76ca22d4a31d3aba4fcdb0def78bc5b5cf9887c07c1be9",
-    "dist/2024-04-29/rust-std-beta-sparcv9-sun-solaris.tar.xz": "5d557ee86457f288462603fe53bcc2e092d84faee543659419fa68c1bd88f554",
-    "dist/2024-04-29/rust-std-beta-thumbv6m-none-eabi.tar.gz": "a9663048aad82ef832b2cf82fa9fb94be047f77e283e8aa3e2df6ad957d0782d",
-    "dist/2024-04-29/rust-std-beta-thumbv6m-none-eabi.tar.xz": "4c4b703a846b4123d09c1eace6322e82784a004b278f1f3b1ca1279e96207f18",
-    "dist/2024-04-29/rust-std-beta-thumbv7em-none-eabi.tar.gz": "32907c33f240abb1cb17ac438da42c5fa3932b270ad08fd6914775c5b59a02f5",
-    "dist/2024-04-29/rust-std-beta-thumbv7em-none-eabi.tar.xz": "112583227d2b6abfef6eeb78d980bf2efef392f3b66e433c4959a642d72ffc7b",
-    "dist/2024-04-29/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "7ba0084527a18479c4b6f6a0dba8ae23a0ed50e9fc5fbfce23cae1babb5a1e12",
-    "dist/2024-04-29/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "49eb4e2efe3a76713ce1fecacaf915717eeed8552912b92895c7fee068a85a36",
-    "dist/2024-04-29/rust-std-beta-thumbv7m-none-eabi.tar.gz": "518a532b52f2dad2825158614cd00b12aac6c6e1983a1ad53e2b0e26d1f1b845",
-    "dist/2024-04-29/rust-std-beta-thumbv7m-none-eabi.tar.xz": "2895e5796a29fd016462694d880e38eb191cb92c9bdb14414c1d6e63b23d3394",
-    "dist/2024-04-29/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "2af590c063344c4c3f65d704fa255232b5f5954872d03c4c55d48662cbe6bb17",
-    "dist/2024-04-29/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "a09df5f38183d9fe6116c807619f812410763ddedf06055bfe8040b5794104d3",
-    "dist/2024-04-29/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "eac22c4972bde3a57cf2ec4e31b43db3c4b7d961ae31475d8942e898c07640cc",
-    "dist/2024-04-29/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "104f2c6490e30cc47833edbd806c2efe6256d1194600b2278339612f94704d45",
-    "dist/2024-04-29/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "b3c9c9d7ce8c1db6f20e8ede542e67aacd6047c52882a5d06c4f96a40a7304d9",
-    "dist/2024-04-29/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "76bfb114bc7674792934a4892d2db41fdc8f5bd30c3aa96c43e8055199157476",
-    "dist/2024-04-29/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "1308335fe80dcafaba511ee589959d461145533de5f76118fee29a7e9a15841f",
-    "dist/2024-04-29/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "cb8acdb8920983c03b9495cf3506a3014384b4d2f6a53e7907924d38a0baf7f0",
-    "dist/2024-04-29/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "9dd2e5ce7534ab4fbb93ff652196e877f4e9eea3863920c3d34a05d9a3598c81",
-    "dist/2024-04-29/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "4b6e962facf7c54846965a8d6880e4a980804459151f2e22ac5af79bc79e26bb",
-    "dist/2024-04-29/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "731603392b6e3d36b3a4956928d084e293ef18c8b8593efa756e753a2a309709",
-    "dist/2024-04-29/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "8b681b3af47855eb63c4ffe06a2bc6bc4f365354ffbc171ce8cbd8c2a3588a07",
-    "dist/2024-04-29/rust-std-beta-wasm32-unknown-unknown.tar.gz": "7b87e59391493c3147c03794061111e25bdae669aea58190a951cdef111e75e0",
-    "dist/2024-04-29/rust-std-beta-wasm32-unknown-unknown.tar.xz": "d15eaadb101027906c2fce15b95a3f820bdbc4cf145b705bafc2ac5291289c3b",
-    "dist/2024-04-29/rust-std-beta-wasm32-wasi.tar.gz": "07390ec742b79ec11b2c3ec65f60efe5d7c616f50c33058fce346f6e9ad21af3",
-    "dist/2024-04-29/rust-std-beta-wasm32-wasi.tar.xz": "79e34d46621c298cadb98c00ce3b25d97474aec300d85255153b47e21b7bb744",
-    "dist/2024-04-29/rust-std-beta-wasm32-wasip1-threads.tar.gz": "b916dc9051b0278f820ea0b093db3ecae2e27de641ef67a9b508df75dc92c938",
-    "dist/2024-04-29/rust-std-beta-wasm32-wasip1-threads.tar.xz": "2867922a39da3b02ebdb93fb78b010695daf468f87485ad8ab79c7f3eeb18b11",
-    "dist/2024-04-29/rust-std-beta-wasm32-wasip1.tar.gz": "792b718c0a72e97ba85a17ba67ee09e55b85de829fe4021f828ce54ff8cb31e0",
-    "dist/2024-04-29/rust-std-beta-wasm32-wasip1.tar.xz": "abff86499119bddfeda9059004549941dbcd3d911702d4a9c198b94f60e60f4e",
-    "dist/2024-04-29/rust-std-beta-x86_64-apple-darwin.tar.gz": "0bcc7698efafb42a37f20815f5660e39829a42a2776304e7129d0a4ec0c7520b",
-    "dist/2024-04-29/rust-std-beta-x86_64-apple-darwin.tar.xz": "c437626e250b0d06c05dc828ab81d0d2c543ffce4b100567910508974ea50045",
-    "dist/2024-04-29/rust-std-beta-x86_64-apple-ios.tar.gz": "7c98c9f491bfc837111769a45c10ce2f1ef73c22377158ef9ae80b38034892c0",
-    "dist/2024-04-29/rust-std-beta-x86_64-apple-ios.tar.xz": "f4bda724e6e382e02ddf4e4e7a479120420666a5a1ad3c87a85d4d3c763f2cb2",
-    "dist/2024-04-29/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "01efbb2e48045318e18bfc7b6c190b461a219e81fc1cca6c855bf0c658aef556",
-    "dist/2024-04-29/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "9bff316c6d2fbb3c0889f9ffe4eae496b293fb3afaf8d597155e6badbf0c6a8e",
-    "dist/2024-04-29/rust-std-beta-x86_64-linux-android.tar.gz": "5da713547a8af2c86da7db5d8aa4c27188dea1089fded81ffbbeb0f78952a10f",
-    "dist/2024-04-29/rust-std-beta-x86_64-linux-android.tar.xz": "9d6a45d6af395360c63ce97bcfc2f9a2967c708afcd979f17fa447239703a92b",
-    "dist/2024-04-29/rust-std-beta-x86_64-pc-solaris.tar.gz": "d1a71110bee002c8edfbcc00e0f5eede5afa005b09944bb2cde469c658049e70",
-    "dist/2024-04-29/rust-std-beta-x86_64-pc-solaris.tar.xz": "6b8d18c83b9fffdddf9e55c807dc7d5784cc6d7ae90a57c29b87d707f0656964",
-    "dist/2024-04-29/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "28921ee14426f54aa09523547516437130654b2d9814120d286f209666c88533",
-    "dist/2024-04-29/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "7c3125cce30978ca2619e9aab150cb5b9b2535fbb6274d4ac1b1d4342c7b0220",
-    "dist/2024-04-29/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz": "ee5c237f092f8a4ba797c4c7769dfd4da81b5c86d2f4b88704d127642d222a22",
-    "dist/2024-04-29/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz": "30c84b04bd2d4d33abf1875cfee5f227ef6484edc67b3cc4c9c96d92c8406d6f",
-    "dist/2024-04-29/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "81274050e72c5a8ffdead83f7be62434f35a65517a1b3c6f7d9d14d0d59da710",
-    "dist/2024-04-29/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "215e20c78a2a4edf9b8368a29a09af5f4cf8d0edd1995de3bbf2eff01127cab7",
-    "dist/2024-04-29/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "340131cba121827a9753e19cb3a4b9ba2ebe30569fb20d7f9300b4dbe2a15cf4",
-    "dist/2024-04-29/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "69626178bc5309afc8a02c941bd77e70e1aa6917ffb6bf0d67a57d921b5c664a",
-    "dist/2024-04-29/rust-std-beta-x86_64-unknown-fuchsia.tar.gz": "22c6c90533dad3a731ad8a6696e6cdc1b15579e25c658fa2b094185e1893934f",
-    "dist/2024-04-29/rust-std-beta-x86_64-unknown-fuchsia.tar.xz": "30d7ef6684fa98e28037b69d4220cba40489c23e80fe7793c98b388dc161757d",
-    "dist/2024-04-29/rust-std-beta-x86_64-unknown-illumos.tar.gz": "9d7192d32eaa6b6ccb0f615da0f4cd80827ba6484eabeaf401d8217678f1e313",
-    "dist/2024-04-29/rust-std-beta-x86_64-unknown-illumos.tar.xz": "7a3fb35e0bb252d5f90773136d1417c26d5601beadb77d6da6f5ad3081977f07",
-    "dist/2024-04-29/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "e987635519c1edc8a1d147ca4a86283637e4dbd0a49736b01d605e45a3a14e8f",
-    "dist/2024-04-29/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "c3ab6b97dccc0038c68494b03b6d444d534e447226a2b2e140af54c94fca0b2d",
-    "dist/2024-04-29/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "72e8113687be8f947c50befb42b0957dd564f01693cf4d68d749a9e074032ada",
-    "dist/2024-04-29/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "867b24f33b19f40727c71818c8a002718d44d4cd4ceca44314331e19c1adc1a4",
-    "dist/2024-04-29/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "f9b0fd9605bd4e264f5303bd740d9a0195bc147132969965b221f9da0d7875bf",
-    "dist/2024-04-29/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "022dcf4887df41d776ba2666858b9aaab479758134a71f7c6b2172ed7c1a1752",
-    "dist/2024-04-29/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz": "b5ff4a0ecd7e0f71a9557b6096bb907e5cbc8982431f0d9b01d8e1a895d8b37e",
-    "dist/2024-04-29/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz": "e40d5bfb46aadf6faf849df548154db3f35f356f8b98037a056802a235922b8a",
-    "dist/2024-04-29/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "57cfb1fa472dd9c01fc0caf605a55b7248375d616acf84ec12f6430d5e07e2ee",
-    "dist/2024-04-29/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "e4121f060b917c811d971e85ce02495e83150ddcceb2204615edff24bd55bfa6",
-    "dist/2024-04-29/rust-std-beta-x86_64-unknown-none.tar.gz": "d63559803c8eb47e0d10d9f3a2284477b570a2536bb541762774271451e1f0ce",
-    "dist/2024-04-29/rust-std-beta-x86_64-unknown-none.tar.xz": "5388cf8ecaa234d507e505e8c6d433c5de8811b2717aa254e4caac9f4aa6cd97",
-    "dist/2024-04-29/rust-std-beta-x86_64-unknown-redox.tar.gz": "0f027163f37618df4330ecd82afece432b0a509ab20333d7b787c0d139ea89c2",
-    "dist/2024-04-29/rust-std-beta-x86_64-unknown-redox.tar.xz": "b1c722e894b145c2183183fa58762c64402fac077419dc7874f8b08eee665651",
-    "dist/2024-04-29/rust-std-beta-x86_64-unknown-uefi.tar.gz": "24e2ac0d44619ef9b76cb1af6178103d65ab12e2677b366e8aee0604798fe5f1",
-    "dist/2024-04-29/rust-std-beta-x86_64-unknown-uefi.tar.xz": "1d8a45f1bfe6650edc5ddfc8683190eff5a74384abcb2f73eb3d1e88d566ccfc",
-    "dist/2024-04-29/rustc-beta-aarch64-apple-darwin.tar.gz": "ea113c567692d54983ab6c376761651b6dcf9bedad5b5d822d28c0d0d0733cf2",
-    "dist/2024-04-29/rustc-beta-aarch64-apple-darwin.tar.xz": "e36363f1ea531d2fd563f471758e387de37a34e7ef6f4c12175979657333c5b4",
-    "dist/2024-04-29/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "52d77d540fc3f83d82f35f358ccd9055fb75453af3e3bee4b11636742559db13",
-    "dist/2024-04-29/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "843c56f5431c1feda85ceaeef0daf988e8ae020b3556326fb1f75ea7968bf2df",
-    "dist/2024-04-29/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "ba2fe37dda1a487a2c75151895f4f6e886e9476a992272ce26e9b5fd7adb11f9",
-    "dist/2024-04-29/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "ccb7be3935de1920509d2061d38f92f1fb8d2a5dd6cef392492242a929363fa9",
-    "dist/2024-04-29/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "40636e0936bd311803317825c5fb6b446cdb5536ada1db097b567df04a86d7dd",
-    "dist/2024-04-29/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "804ef68f24bc0ba5150177d8b8515daa54aa82fcb61472385ef1a1d897c5c3e1",
-    "dist/2024-04-29/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "a320c2869d1d2c92b698397d4467c8498cad9481f38d28ac810bd165399ca46b",
-    "dist/2024-04-29/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "7ce92211d87068d9c223806929adc34ca611a1321cd58b5bd81aabb0ec3ff085",
-    "dist/2024-04-29/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "79c16b902884301882d16be36fe75ecb32a8e49abde0038ce21cfbee883c2c3a",
-    "dist/2024-04-29/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "9384eb9bdbb585b414b6c04c592a79e90a0c0ebfeeb970e5e1b920cb638807cc",
-    "dist/2024-04-29/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "ff99de5b819a4fb9adce9386a309b9841bd33632eb7d5079415a6ca6fc86b9dd",
-    "dist/2024-04-29/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "55635cde13af11dd8cc007d2e0499bfee493bdfba87b6efd7b1fa4115f5728dc",
-    "dist/2024-04-29/rustc-beta-i686-pc-windows-gnu.tar.gz": "de82ac745275f069225b84574ed145afaf9f54abde5246592e49d5d1cf40cac1",
-    "dist/2024-04-29/rustc-beta-i686-pc-windows-gnu.tar.xz": "a8a7bf64d33c95a2f94265fba8dd9ac50bbb727f4bc3e79be5bf61212cb5d22b",
-    "dist/2024-04-29/rustc-beta-i686-pc-windows-msvc.tar.gz": "88967a99c993d6e0c3c7948308510644286ac826266dbd3d89aaa083100711db",
-    "dist/2024-04-29/rustc-beta-i686-pc-windows-msvc.tar.xz": "1804f75786482946258ff0e827274357c49e90a7f2f568add7353249f2ab78b9",
-    "dist/2024-04-29/rustc-beta-i686-unknown-linux-gnu.tar.gz": "3cb7e02c61d4a21d8289289b874b25e8b020c1d553e5af950160bffc14f51c18",
-    "dist/2024-04-29/rustc-beta-i686-unknown-linux-gnu.tar.xz": "2ad4b1311a0e39c359798375912faa91b4e13cd473bd59efd1e4f721777d254f",
-    "dist/2024-04-29/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz": "ab19efb741a127615b9022dedf1d895b53c69740cc3da745f9b9888bade9d98b",
-    "dist/2024-04-29/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz": "492cc11d54df410c2547890803930fc65950e6b81ced512e24bef56c3e70f3d2",
-    "dist/2024-04-29/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "c5a631a41f417336f3f65c85adefd1fb0bacc02465485f37d29fc1223c9f6cec",
-    "dist/2024-04-29/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "0701183b615d9eec9daea724d4cd8fa98dede2260cfb6b137d6cbf8ad6b29a4f",
-    "dist/2024-04-29/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "cb70e92d5275862b500614d79eaea3d19319b96798f4850cb19dea9a8038a651",
-    "dist/2024-04-29/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "908cbe562d82cca1bf176fdc99af867966ea423d244c4a50e14bad19f6878201",
-    "dist/2024-04-29/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "8580a3eb6d6df1774f4b6ca06dc1195c42b1e2a463488a5d851e99b0ca6d0249",
-    "dist/2024-04-29/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "2627948036e905f2e280663c56c86c172e2b0d057311ade7ca238953b7e0c36a",
-    "dist/2024-04-29/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "526e4f129fdb4b2c8f4317c57105a09ff03e71771d6d6bbbc9380917b5440d71",
-    "dist/2024-04-29/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "fd9dcf60838376478d7cc505ec7fc39f86f9d042646a3b836e9c06825927c7eb",
-    "dist/2024-04-29/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "664c1255a9435d1ad086329a3c215974b9302d481762240cc9d0328d9f1b8c9a",
-    "dist/2024-04-29/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "a585ce7684e4174f03adb09df17221e1729e8179dbc91b9a0f8813c3ecc0822d",
-    "dist/2024-04-29/rustc-beta-x86_64-apple-darwin.tar.gz": "59a1d91009b506a5bce3c276993cb8acfd71f73d01f9eaf4195b36114ac822c3",
-    "dist/2024-04-29/rustc-beta-x86_64-apple-darwin.tar.xz": "f86f3309cf2784b076f14e7da9e921c294a7701ea92d378c609061deccbc6bff",
-    "dist/2024-04-29/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "f5c074461409b33a9791325d4014e6861ad36f99b9e48e54ecceb73986450be1",
-    "dist/2024-04-29/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "045431eec6f839b1c40b5a75c5000f80bd6351274a59b29d962833495324ecb6",
-    "dist/2024-04-29/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "a3abfb68e60544170f47209bbf048f1374e5bb75901a529e2ac2f315758155f8",
-    "dist/2024-04-29/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "398c41a3219781c7cf1a907406506526b672abca6d3ab59c30556390a5f992c9",
-    "dist/2024-04-29/rustc-beta-x86_64-unknown-freebsd.tar.gz": "38895e615efd0bf75ca14b0ab0a085527cca64fae17631d1780a8f51acd26d17",
-    "dist/2024-04-29/rustc-beta-x86_64-unknown-freebsd.tar.xz": "786f40030dbe5e6897aafe4bda44770920b2010b93fc5ce86574774e531e2eff",
-    "dist/2024-04-29/rustc-beta-x86_64-unknown-illumos.tar.gz": "7003cab7650dae7e3d29032422a57782a2c146024c437a6466ae1dd2b61a6618",
-    "dist/2024-04-29/rustc-beta-x86_64-unknown-illumos.tar.xz": "bed3cc10203e8bd4d43b6245928c8a607acc5b6e633635caea45eb4eef4bda56",
-    "dist/2024-04-29/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "84cdea91c9f1e848ea17f554229ca80d18d093fc609641d8f003c4f2d4871866",
-    "dist/2024-04-29/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "a20fce7512f7c8cc6230a0f63f12855b04370d25e621183f71aa444c90c36b4b",
-    "dist/2024-04-29/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "87e0c484ade99efab57c655ef96dbabf7a02314540575b65a14372ab5496c36c",
-    "dist/2024-04-29/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "469757d8f35c9f4210aefd2ba660ee249e4409d47b908a6c68c1e650ee81ae67",
-    "dist/2024-04-29/rustc-beta-x86_64-unknown-netbsd.tar.gz": "4a38000480fe78fd5da7f9b71d36f296a6ae103254d932c4de6b902354e86bbf",
-    "dist/2024-04-29/rustc-beta-x86_64-unknown-netbsd.tar.xz": "45945d6af237fe4c91fde7db02ca19e99bac56a911b8db79be9b6ab8bb3934e1",
-    "dist/2024-04-29/rustc-nightly-aarch64-apple-darwin.tar.gz": "0b07375a9a6507fd4932a05b5aaf28ed349fe2040103f1cb69c8a2494437258f",
-    "dist/2024-04-29/rustc-nightly-aarch64-apple-darwin.tar.xz": "143bd7ed3ca7b913ddd0cea7cda8d1a0e4c29cc2ccbb7d29f0e45c2a87c3ec46",
-    "dist/2024-04-29/rustc-nightly-aarch64-pc-windows-msvc.tar.gz": "9404c111b91fd092367b88adbc37dce10a98c443bd8d9e13a860e1fb4e3af96e",
-    "dist/2024-04-29/rustc-nightly-aarch64-pc-windows-msvc.tar.xz": "f9f432907c276edcae5ad8ade0264f3c03109be02e791a814edc8ad3d229637a",
-    "dist/2024-04-29/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz": "33425c90427424f0b30fa2a6331a3b59c680f1c1bd0d8845d7e6bc1e2f80292d",
-    "dist/2024-04-29/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz": "03792890c64c72f30143849894b15f0eb3d6ad735fceede9092abd900ee733e4",
-    "dist/2024-04-29/rustc-nightly-aarch64-unknown-linux-musl.tar.gz": "cf6f2bffa0db1b4b9b8e95801bf415dcce413f902e26f4c1831dff1a00752b99",
-    "dist/2024-04-29/rustc-nightly-aarch64-unknown-linux-musl.tar.xz": "9192fdb668df8d4cab776623db7d01e35af42fea94098c1d4ba53190825d81a8",
-    "dist/2024-04-29/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz": "a174e7e08da2abc6b84499360670188f5cc61b6d055967e04bf602ff3d831f45",
-    "dist/2024-04-29/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz": "5a59811027586863852b15fc2b603e7e69b19841f4c10d2527ef1fc5b77d8af2",
-    "dist/2024-04-29/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz": "645bb5dd7a96bb9292b9956cb9705e9aed2408e47728f245564f1f7404ede783",
-    "dist/2024-04-29/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz": "1fe34911b082c3a5ca4f24656675c095d2cf56f8005be9ca2517d0ef7d0a2b37",
-    "dist/2024-04-29/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "f2d6403d81bb0afe2e14956828987a0bb044c95f2d9566e1d792dd922dad7914",
-    "dist/2024-04-29/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "d93fdafcbbfd50c88c3f4feb4c68b053882ccae02c45e1615aeeae5a86f4aa98",
-    "dist/2024-04-29/rustc-nightly-i686-pc-windows-gnu.tar.gz": "a9e997b03559b3dfa2a0eba6ed7a142d7651ea7f4ba4e788d9de807b50558e58",
-    "dist/2024-04-29/rustc-nightly-i686-pc-windows-gnu.tar.xz": "4412b5fbfab8c5b31e57cf8c4ce9a9d13cfc9c0a8174ea1fc8a7c05281e1cb54",
-    "dist/2024-04-29/rustc-nightly-i686-pc-windows-msvc.tar.gz": "1725c41500dbf6bea554f3d4acaba70167f0e89087aaa3eb3c0f8a99047c55c4",
-    "dist/2024-04-29/rustc-nightly-i686-pc-windows-msvc.tar.xz": "27db022494afebbe05605f134191e8b2e78bfdeaa638d4215174038ca9dd2fd7",
-    "dist/2024-04-29/rustc-nightly-i686-unknown-linux-gnu.tar.gz": "dc1a05d49b773dba06808c1c50653ecac506b3433f0f6dfa307109a7c621cc1a",
-    "dist/2024-04-29/rustc-nightly-i686-unknown-linux-gnu.tar.xz": "cc58ce3af8f5481ada4dc129079cd558664717526b2f7f9a02bde6bafb6f45ad",
-    "dist/2024-04-29/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz": "34cfe803126ae9218b17adfe833a55c697dfa50729ac83b642529f3682d12d15",
-    "dist/2024-04-29/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz": "c752dc8962656c09047151fd24166f3134fbeed85006b5d22496691079c7fb9c",
-    "dist/2024-04-29/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz": "386b086b8aad922050c813dd58bb79a52ef806b2d1413e2e9cc46d6e43b81d7c",
-    "dist/2024-04-29/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz": "d9eec9ab7c265444ac5f04d4ec9e77d4c0c3c2e34c5804db8abf5f94c8fd2272",
-    "dist/2024-04-29/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz": "91df129046443554bfb836d25886aa9807b917acbc9dcf30f6531cde7bf912fa",
-    "dist/2024-04-29/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz": "ca9b574b9f2e914b5a6d9e011aba805d1e6f9b687dc1a1868e88f0e4d9e4401c",
-    "dist/2024-04-29/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "8b44f96a1ccd6d501b0af3960edb2c1a6c93957676a1c2cdb831e614de398f8b",
-    "dist/2024-04-29/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "f8a10a6767b80bf24f73223b9e46e1b18b6bf6746ad2115eb8968a0e482f0e4e",
-    "dist/2024-04-29/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "a197208807503a9cfbc6df938d614a192da48884b2e4892f7b1d234579091be1",
-    "dist/2024-04-29/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "af3a1a33942bd8a3417593dc118abb1db0373f5410f54771713c05bb86724fed",
-    "dist/2024-04-29/rustc-nightly-s390x-unknown-linux-gnu.tar.gz": "5a3a3aa73b6a0f21c63b9a40bdbd0bb4dc59bd75add0a06e292ced791fad31be",
-    "dist/2024-04-29/rustc-nightly-s390x-unknown-linux-gnu.tar.xz": "6d7903f1c9fc95a23448717326d667dce59e54aaff821443d3cd9137cf3537fb",
-    "dist/2024-04-29/rustc-nightly-x86_64-apple-darwin.tar.gz": "64eede54da4bf88b0a42ecf7f7a4bf8002b5550e60a64e1e48244c7f5b04768c",
-    "dist/2024-04-29/rustc-nightly-x86_64-apple-darwin.tar.xz": "0a8f95e3bb0bebf9bcc8116b91bab3ba97cb6ff4021713586280aaceed9da030",
-    "dist/2024-04-29/rustc-nightly-x86_64-pc-windows-gnu.tar.gz": "58f9e0dd9c1aadde2dfd869528adadd4acc29ab0850236f3cee5f023d4211939",
-    "dist/2024-04-29/rustc-nightly-x86_64-pc-windows-gnu.tar.xz": "a211a962093e0d09358d51a6eb48da0966a02383c6b00c8acc077b5663d7d707",
-    "dist/2024-04-29/rustc-nightly-x86_64-pc-windows-msvc.tar.gz": "5631926874dc54204c319137a77a89de5e6f408de2a832109e2be71ea79f27d1",
-    "dist/2024-04-29/rustc-nightly-x86_64-pc-windows-msvc.tar.xz": "a8cf87bc663b5e3dbcc97b0eb58bb1b9b5b0100aacb47dc0c372fe1612517244",
-    "dist/2024-04-29/rustc-nightly-x86_64-unknown-freebsd.tar.gz": "1011f98197a9fe82d6095f4521934a06eea5f7e9719a6e4c9e3bf13d68f799ca",
-    "dist/2024-04-29/rustc-nightly-x86_64-unknown-freebsd.tar.xz": "79599b3f91f9372262e97a417f4e104ef5192c0f6f8df204aea9c8b3ee39430e",
-    "dist/2024-04-29/rustc-nightly-x86_64-unknown-illumos.tar.gz": "7179a453bdcb17e401c0af8f4ab86cb5a4752a8ec80b0cbdd4cf1854c7f36a35",
-    "dist/2024-04-29/rustc-nightly-x86_64-unknown-illumos.tar.xz": "d565fc366fdbc305fbfe59e72b971c58f201d69e03a9ffa667d2ca0735cdb7f3",
-    "dist/2024-04-29/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz": "ae6bd8e20560d48519290d78e3d21f84b983403ca1f8f466a85496276d7866da",
-    "dist/2024-04-29/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz": "c7c0f8f44b0275456a27952178caa04c32eb9a1507056ddc05926a0730e17359",
-    "dist/2024-04-29/rustc-nightly-x86_64-unknown-linux-musl.tar.gz": "3246797ddbc9118de819b13b005b83748338f3c825a7436ebd5aa79ca55539c0",
-    "dist/2024-04-29/rustc-nightly-x86_64-unknown-linux-musl.tar.xz": "c7e784e77dbabedad88d24d2ae6dc4abb68bc04b1cd6c9d45f6dc28b6d0e2edc",
-    "dist/2024-04-29/rustc-nightly-x86_64-unknown-netbsd.tar.gz": "c9452de4b3f15f0cf0b7d737b217b2cc7b88a96543bd8ce587ee14be1e21a90a",
-    "dist/2024-04-29/rustc-nightly-x86_64-unknown-netbsd.tar.xz": "de9b05278a5c69d53ccbb31223526ea2aa2275c0fb3f046d1c1b4d67c0b0c275",
-    "dist/2024-04-29/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "3734353a58dbf6c3831cc6b4ea606357140c191c89e8dfca1d7aa2f3fb8ac53d",
-    "dist/2024-04-29/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "e5e3a6e609fbfd537aa4acfefd3681d4b6c8029e2801a1ef23e8b09cf5a47bfe",
-    "dist/2024-04-29/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "22f54857e01d759301d099b67547cdc485596499088d0d749d38058c28e0f752",
-    "dist/2024-04-29/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "db48a9d45dc7c7aad4c9bb0d20789dd35fb6ef7a966948c44fbbae132de4c16b",
-    "dist/2024-04-29/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "fa5d1fb9f3627e7d59269a1f8008d780c685ea04975473f1808287134e7bc5a7",
-    "dist/2024-04-29/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "61ab625b47fa9097af90a79a1e75a2f2492a415f4009c9043cf453bd4128f031",
-    "dist/2024-04-29/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "cc79969341fc60991059d0e3f13a69489c1e0915ea5787a88b8605ed5b7f3cd0",
-    "dist/2024-04-29/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "bbdb75f922b4b1716b033d91c76c4c0aa53061d6e7fa53a9bf16fe076814bbb2",
-    "dist/2024-04-29/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "13ca68afc3f3970a37951504664b58035102e1ae06d10a744389603b2f7499f5",
-    "dist/2024-04-29/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "04b174aa724945b6359a555892506c6a742a7c427464e8206433bb3f9a65fc02",
-    "dist/2024-04-29/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "430333380a590a9de211c8d735989fedb89321cf9f5f9a0b1ef651ec8b598691",
-    "dist/2024-04-29/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "924713e648806945cd56e54d4c11dc74b65241c8dbf6cc7b401c5c93d0f7ffdb",
-    "dist/2024-04-29/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "bb6e5a8b5cc88099e613aa5f4d926165976d8e4a7fccbecf4ac3b0eb966d7a0f",
-    "dist/2024-04-29/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "34d5e970304e1734aacb26c095e926c27a07e1a41fe70db9fa2997bef97ad3ec",
-    "dist/2024-04-29/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "835447a1d9d60659e99903275f327641809fc0148f35149f980d1a17ff87cc9a",
-    "dist/2024-04-29/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "ddd84a7f900aa239f93711f7da71e57aaedeeba2c9c8a8f23608acc7e48613c0",
-    "dist/2024-04-29/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "02f0af2bdae167c6091099a9b54ceb150c22b0f20dc861587a02cac78deb0b39",
-    "dist/2024-04-29/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "822f78f39dcbe3282bf7888a8cdae04efe7b023ded026a7e7f430e4ff15e7942",
-    "dist/2024-04-29/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "68a6189652c11a2c142c5339e2f5fb09d5f3e85d860bff063f62d5d3a3d111bf",
-    "dist/2024-04-29/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "6740ea882effa2fb87dd72744c08888ce5ec59c9797c00369156b24847bb180e",
-    "dist/2024-04-29/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz": "0bb365e2d895ef3c39c4899a01187a23f9b7c5195c30bf845da3917f62f5eafd",
-    "dist/2024-04-29/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz": "2e54c9887bc6ed1eb09b9f69c8425da843ea12bf33248fa0ccdc0d14387c1c57",
-    "dist/2024-04-29/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "b0c0fe437921d17e2f50cbff87beeac067efa3d5211a241fb6f4c10b8ab500ac",
-    "dist/2024-04-29/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "64e7282c0cf4a714b11eed1d28be3a64ba0ccc6d899211a872a5a7809d514c08",
-    "dist/2024-04-29/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "100cfde057c81460b8cfde2047fe83ddde360a6df1ff178da5a968b17ecc9df8",
-    "dist/2024-04-29/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "38e8712e98fa0bc6962ab2fd2e3b96a2a5dcaa6c16161d8caf71131a1ca5031e",
-    "dist/2024-04-29/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "4dab52b50e19348fb39fdad39ab44189c27c10f80b5fbe2cc4723b644611fa87",
-    "dist/2024-04-29/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "36d1b2c9150fafc5976c296200ba3fac3e923df3e6f18032068200e2a887146c",
-    "dist/2024-04-29/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "7cb4a536320c23d305ce3bd3b7a954d951bf4d358ef3732be75b9b290c4818a5",
-    "dist/2024-04-29/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "ede1afc7dc5892ef6f780e987737e145c4b4d00495da8c2e9902182a3a174e20",
-    "dist/2024-04-29/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "e2d2d561cbfa0add0e5349682976216d3a7cff4094372c1ed26854bb4e4d93fd",
-    "dist/2024-04-29/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "e0380e65e83e4131f6aa7ee4e185689add4372b0c1653312e2ffd56072fdd0fe",
-    "dist/2024-04-29/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "73a140c7ed9c80f209ff976c63b0a34d625d651553c38692c91f048f4e0ae470",
-    "dist/2024-04-29/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "9946b7120465181e05916b8023bc075b32bd85cf45a3b1d8bfba2f94ac78d927",
-    "dist/2024-04-29/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "eda273f27714b1e45adcc2388149f48de0e32a9104db0b9d1a02f6d37de43fef",
-    "dist/2024-04-29/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "f2955a4b696d050c219a96c093162b42a2fab921f9f3cb7570f8462928306c6d",
-    "dist/2024-04-29/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "ec900cc2d3c6d45ef039653f4418f9b9a4a5fddd5d7e8077c3fb08b36c539a28",
-    "dist/2024-04-29/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "04e6999a3405acc79f5fdcafeeab52880e5eeeedd3909b5f3c57e7647c86ef99",
-    "dist/2024-04-29/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "0730c5ebd576fec5371085f9fac0adde9424e1d7626456ed33bc66351b0ad307",
-    "dist/2024-04-29/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "90cbd84b8d48f0235a1954166f5edd53dc3031532ec6dfcb364f9a9624c9ce11",
-    "dist/2024-04-29/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "5f5c62d321db27eb495f6ea312ef8bea0bf17a7a501a44e062986c416951700f",
-    "dist/2024-04-29/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "a3bf64e2f22436e4484fc818f69d2f750fddd05a96463fd4abfcf655edce36b9",
-    "dist/2024-04-29/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "a847a6f9c7a3ce71c7cd8d81bdfcfcd8e4d128aa28ba0dafea89b0cc37c6c36c",
-    "dist/2024-04-29/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "21fa794456566c64d08f629a385f89b3cfe9d9b69f317ae85fbe7425419108ff",
-    "dist/2024-04-29/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "b3f792f10a98993b4b55d1df951727a4422102d51b1145e51824268d48587ad0",
-    "dist/2024-04-29/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "d791f0ec3c004e7baa0381962bf8ca2f18a3c861152702de5301d0149260e7fa",
-    "dist/2024-04-29/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "9807b2887e976d29f0c04484f8459175b4f6b70ef000037cdc4dada48e3cbd74",
-    "dist/2024-04-29/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "019920d64778af62879e2146c2c13d9f6e2165a38bbfa1982694bfb48864d308"
-  }
-}
diff --git a/src/tools/build_helper/src/lib.rs b/src/tools/build_helper/src/lib.rs
index 575f3677155..6a4e86eb1df 100644
--- a/src/tools/build_helper/src/lib.rs
+++ b/src/tools/build_helper/src/lib.rs
@@ -2,3 +2,4 @@ pub mod ci;
 pub mod git;
 pub mod metrics;
 pub mod util;
+pub mod stage0_parser;
diff --git a/src/tools/build_helper/src/stage0_parser.rs b/src/tools/build_helper/src/stage0_parser.rs
new file mode 100644
index 00000000000..ff05b116989
--- /dev/null
+++ b/src/tools/build_helper/src/stage0_parser.rs
@@ -0,0 +1,76 @@
+use std::collections::BTreeMap;
+
+#[derive(Default, Clone)]
+pub struct Stage0 {
+    pub compiler: VersionMetadata,
+    pub rustfmt: Option<VersionMetadata>,
+    pub config: Stage0Config,
+    pub checksums_sha256: BTreeMap<String, String>,
+}
+
+#[derive(Default, Clone)]
+pub struct VersionMetadata {
+    pub date: String,
+    pub version: String,
+}
+
+#[derive(Default, Clone)]
+pub struct Stage0Config {
+    pub dist_server: String,
+    pub artifacts_server: String,
+    pub artifacts_with_llvm_assertions_server: String,
+    pub git_merge_commit_email: String,
+    pub git_repository: String,
+    pub nightly_branch: String,
+}
+
+pub fn parse_stage0_file() -> Stage0 {
+    let stage0_content = include_str!("../../../stage0");
+
+    let mut stage0 = Stage0::default();
+    for line in stage0_content.lines() {
+        let line = line.trim();
+
+        if line.is_empty() {
+            continue;
+        }
+
+        // Ignore comments
+        if line.starts_with('#') {
+            continue;
+        }
+
+        let (key, value) = line.split_once('=').unwrap();
+
+        match key {
+            "dist_server" => stage0.config.dist_server = value.to_owned(),
+            "artifacts_server" => stage0.config.artifacts_server = value.to_owned(),
+            "artifacts_with_llvm_assertions_server" => {
+                stage0.config.artifacts_with_llvm_assertions_server = value.to_owned()
+            }
+            "git_merge_commit_email" => stage0.config.git_merge_commit_email = value.to_owned(),
+            "git_repository" => stage0.config.git_repository = value.to_owned(),
+            "nightly_branch" => stage0.config.nightly_branch = value.to_owned(),
+
+            "compiler_date" => stage0.compiler.date = value.to_owned(),
+            "compiler_version" => stage0.compiler.version = value.to_owned(),
+
+            "rustfmt_date" => {
+                stage0.rustfmt.get_or_insert(VersionMetadata::default()).date = value.to_owned();
+            }
+            "rustfmt_version" => {
+                stage0.rustfmt.get_or_insert(VersionMetadata::default()).version = value.to_owned();
+            }
+
+            dist if dist.starts_with("dist") => {
+                stage0.checksums_sha256.insert(key.to_owned(), value.to_owned());
+            }
+
+            unsupported => {
+                println!("'{unsupported}' field is not supported.");
+            }
+        }
+    }
+
+    stage0
+}
diff --git a/src/tools/bump-stage0/Cargo.toml b/src/tools/bump-stage0/Cargo.toml
index 4680a7ab661..de5d821133d 100644
--- a/src/tools/bump-stage0/Cargo.toml
+++ b/src/tools/bump-stage0/Cargo.toml
@@ -7,8 +7,8 @@ edition = "2021"
 
 [dependencies]
 anyhow = "1.0.34"
+build_helper = { path = "../build_helper" }
 curl = "0.4.38"
 indexmap = { version = "2.0.0", features = ["serde"] }
 serde = { version = "1.0.125", features = ["derive"] }
-serde_json = { version = "1.0.59", features = ["preserve_order"] }
 toml = "0.5.7"
diff --git a/src/tools/bump-stage0/src/main.rs b/src/tools/bump-stage0/src/main.rs
index bd97b4eaa3e..bb06e113c0e 100644
--- a/src/tools/bump-stage0/src/main.rs
+++ b/src/tools/bump-stage0/src/main.rs
@@ -1,15 +1,17 @@
+#![deny(unused_variables)]
+
 use anyhow::{Context, Error};
+use build_helper::stage0_parser::{parse_stage0_file, Stage0Config, VersionMetadata};
 use curl::easy::Easy;
 use indexmap::IndexMap;
 use std::collections::HashMap;
 
-const PATH: &str = "src/stage0.json";
+const PATH: &str = "src/stage0";
 const COMPILER_COMPONENTS: &[&str] = &["rustc", "rust-std", "cargo", "clippy-preview"];
 const RUSTFMT_COMPONENTS: &[&str] = &["rustfmt-preview", "rustc"];
 
 struct Tool {
-    config: Config,
-    comments: Vec<String>,
+    config: Stage0Config,
 
     channel: Channel,
     date: Option<String>,
@@ -35,37 +37,64 @@ impl Tool {
             .try_into()
             .map_err(|_| anyhow::anyhow!("failed to parse version"))?;
 
-        let existing: Stage0 = serde_json::from_slice(&std::fs::read(PATH)?)?;
+        let existing = parse_stage0_file();
 
-        Ok(Self {
-            channel,
-            version,
-            date,
-            config: existing.config,
-            comments: existing.comments,
-            checksums: IndexMap::new(),
-        })
+        Ok(Self { channel, version, date, config: existing.config, checksums: IndexMap::new() })
     }
 
-    fn update_json(mut self) -> Result<(), Error> {
-        std::fs::write(
-            PATH,
-            format!(
-                "{}\n",
-                serde_json::to_string_pretty(&Stage0 {
-                    compiler: self.detect_compiler()?,
-                    rustfmt: self.detect_rustfmt()?,
-                    checksums_sha256: {
-                        // Keys are sorted here instead of beforehand because values in this map
-                        // are added while filling the other struct fields just above this block.
-                        self.checksums.sort_keys();
-                        self.checksums
-                    },
-                    config: self.config,
-                    comments: self.comments,
-                })?
-            ),
-        )?;
+    fn update_stage0_file(mut self) -> Result<(), Error> {
+        const COMMENTS: &str = r#"# The configuration above this comment is editable, and can be changed
+# by forks of the repository if they have alternate values.
+#
+# The section below is generated by `./x.py run src/tools/bump-stage0`,
+# run that command again to update the bootstrap compiler.
+#
+# All changes below this comment will be overridden the next time the
+# tool is executed.
+            "#;
+
+        let mut file_content = String::new();
+
+        // Destructure `Stage0Config` here to ensure the stage0 file is synced with any new
+        // fields when they are added.
+        let Stage0Config {
+            dist_server,
+            artifacts_server,
+            artifacts_with_llvm_assertions_server,
+            git_merge_commit_email,
+            git_repository,
+            nightly_branch,
+        } = &self.config;
+
+        file_content.push_str(&format!("dist_server={}", dist_server));
+        file_content.push_str(&format!("\nartifacts_server={}", artifacts_server));
+        file_content.push_str(&format!(
+            "\nartifacts_with_llvm_assertions_server={}",
+            artifacts_with_llvm_assertions_server
+        ));
+        file_content.push_str(&format!("\ngit_merge_commit_email={}", git_merge_commit_email));
+        file_content.push_str(&format!("\ngit_repository={}", git_repository));
+        file_content.push_str(&format!("\nnightly_branch={}", nightly_branch));
+
+        file_content.push_str("\n\n");
+        file_content.push_str(COMMENTS);
+
+        let compiler = self.detect_compiler()?;
+        file_content.push_str(&format!("\ncompiler_date={}", compiler.date));
+        file_content.push_str(&format!("\ncompiler_version={}", compiler.version));
+
+        if let Some(rustfmt) = self.detect_rustfmt()? {
+            file_content.push_str(&format!("\nrustfmt_date={}", rustfmt.date));
+            file_content.push_str(&format!("\nrustfmt_version={}", rustfmt.version));
+        }
+
+        file_content.push_str("\n");
+
+        for (key, value) in self.checksums {
+            file_content.push_str(&format!("\n{}={}", key, value));
+        }
+
+        std::fs::write(PATH, file_content)?;
         Ok(())
     }
 
@@ -76,7 +105,7 @@ impl Tool {
     // On the master branch the compiler version is configured to `beta` whereas if you're looking
     // at the beta or stable channel you'll likely see `1.x.0` as the version, with the previous
     // release's version number.
-    fn detect_compiler(&mut self) -> Result<Stage0Toolchain, Error> {
+    fn detect_compiler(&mut self) -> Result<VersionMetadata, Error> {
         let channel = match self.channel {
             Channel::Stable | Channel::Beta => {
                 // The 1.XX manifest points to the latest point release of that minor release.
@@ -87,7 +116,7 @@ impl Tool {
 
         let manifest = fetch_manifest(&self.config, &channel, self.date.as_deref())?;
         self.collect_checksums(&manifest, COMPILER_COMPONENTS)?;
-        Ok(Stage0Toolchain {
+        Ok(VersionMetadata {
             date: manifest.date,
             version: if self.channel == Channel::Nightly {
                 "beta".to_string()
@@ -106,14 +135,14 @@ impl Tool {
     /// We use a nightly rustfmt to format the source because it solves some bootstrapping issues
     /// with use of new syntax in this repo. For the beta/stable channels rustfmt is not provided,
     /// as we don't want to depend on rustfmt from nightly there.
-    fn detect_rustfmt(&mut self) -> Result<Option<Stage0Toolchain>, Error> {
+    fn detect_rustfmt(&mut self) -> Result<Option<VersionMetadata>, Error> {
         if self.channel != Channel::Nightly {
             return Ok(None);
         }
 
         let manifest = fetch_manifest(&self.config, "nightly", self.date.as_deref())?;
         self.collect_checksums(&manifest, RUSTFMT_COMPONENTS)?;
-        Ok(Some(Stage0Toolchain { date: manifest.date, version: "nightly".into() }))
+        Ok(Some(VersionMetadata { date: manifest.date, version: "nightly".into() }))
     }
 
     fn collect_checksums(&mut self, manifest: &Manifest, components: &[&str]) -> Result<(), Error> {
@@ -143,11 +172,15 @@ impl Tool {
 
 fn main() -> Result<(), Error> {
     let tool = Tool::new(std::env::args().nth(1))?;
-    tool.update_json()?;
+    tool.update_stage0_file()?;
     Ok(())
 }
 
-fn fetch_manifest(config: &Config, channel: &str, date: Option<&str>) -> Result<Manifest, Error> {
+fn fetch_manifest(
+    config: &Stage0Config,
+    channel: &str,
+    date: Option<&str>,
+) -> Result<Manifest, Error> {
     let url = if let Some(date) = date {
         format!("{}/dist/{}/channel-rust-{}.toml", config.dist_server, date, channel)
     } else {
@@ -181,42 +214,6 @@ enum Channel {
 }
 
 #[derive(Debug, serde::Serialize, serde::Deserialize)]
-struct Stage0 {
-    config: Config,
-    // Comments are explicitly below the config, do not move them above.
-    //
-    // Downstream forks of the compiler codebase can change the configuration values defined above,
-    // but doing so would risk merge conflicts whenever they import new changes that include a
-    // bootstrap compiler bump.
-    //
-    // To lessen the pain, a big block of comments is placed between the configuration and the
-    // auto-generated parts of the file, preventing git diffs of the config to include parts of the
-    // auto-generated content and vice versa. This should prevent merge conflicts.
-    #[serde(rename = "__comments")]
-    comments: Vec<String>,
-    compiler: Stage0Toolchain,
-    rustfmt: Option<Stage0Toolchain>,
-    checksums_sha256: IndexMap<String, String>,
-}
-
-#[derive(Debug, serde::Serialize, serde::Deserialize)]
-struct Config {
-    dist_server: String,
-    // There are other fields in the configuration, which will be read by src/bootstrap or other
-    // tools consuming stage0.json. To avoid the need to update bump-stage0 every time a new field
-    // is added, we collect all the fields in an untyped Value and serialize them back with the
-    // same order and structure they were deserialized in.
-    #[serde(flatten)]
-    other: serde_json::Value,
-}
-
-#[derive(Debug, serde::Serialize, serde::Deserialize)]
-struct Stage0Toolchain {
-    date: String,
-    version: String,
-}
-
-#[derive(Debug, serde::Serialize, serde::Deserialize)]
 struct Manifest {
     date: String,
     pkg: HashMap<String, ManifestPackage>,
diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs
index 386d4c3c317..6715de52649 100644
--- a/src/tools/clippy/clippy_lints/src/escape.rs
+++ b/src/tools/clippy/clippy_lints/src/escape.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_hir;
 use rustc_hir::{intravisit, AssocItemKind, Body, FnDecl, HirId, HirIdSet, Impl, ItemKind, Node, Pat, PatKind};
 use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
-use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::mir::FakeReadCause;
 use rustc_middle::ty::layout::LayoutOf;
@@ -105,8 +104,7 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal {
             too_large_for_stack: self.too_large_for_stack,
         };
 
-        let infcx = cx.tcx.infer_ctxt().build();
-        ExprUseVisitor::new(&mut v, &infcx, fn_def_id, cx.param_env, cx.typeck_results()).consume_body(body);
+        ExprUseVisitor::for_clippy(cx, fn_def_id, &mut v).consume_body(body).into_ok();
 
         for node in v.set {
             span_lint_hir(
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 2c44c3881aa..a8bfbbdd9ec 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -8,6 +8,7 @@
 #![feature(never_type)]
 #![feature(rustc_private)]
 #![feature(stmt_expr_attributes)]
+#![feature(unwrap_infallible)]
 #![recursion_limit = "512"]
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
 #![allow(
diff --git a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
index 5047092192f..6b9ecf5f141 100644
--- a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
@@ -4,7 +4,6 @@ use clippy_utils::{get_enclosing_block, higher, path_to_local};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{BindingMode, Expr, ExprKind, HirId, Node, PatKind};
 use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
-use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::LateContext;
 use rustc_middle::mir::FakeReadCause;
 use rustc_middle::ty;
@@ -61,15 +60,12 @@ fn check_for_mutation(
         span_low: None,
         span_high: None,
     };
-    let infcx = cx.tcx.infer_ctxt().build();
-    ExprUseVisitor::new(
-        &mut delegate,
-        &infcx,
+    ExprUseVisitor::for_clippy(
+        cx,
         body.hir_id.owner.def_id,
-        cx.param_env,
-        cx.typeck_results(),
+        &mut delegate,
     )
-    .walk_expr(body);
+    .walk_expr(body).into_ok();
 
     delegate.mutation_span()
 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs b/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs
index deac159457a..a52d38790a2 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs
@@ -9,7 +9,6 @@ use rustc_lint::LateContext;
 use rustc_middle::mir::{FakeReadCause, Mutability};
 use rustc_middle::ty::{self, BorrowKind};
 use rustc_span::sym;
-use rustc_trait_selection::infer::TyCtxtInferExt;
 
 use super::ITER_OVEREAGER_CLONED;
 use crate::redundant_clone::REDUNDANT_CLONE;
@@ -69,16 +68,13 @@ pub(super) fn check<'tcx>(
             let mut delegate = MoveDelegate {
                 used_move: HirIdSet::default(),
             };
-            let infcx = cx.tcx.infer_ctxt().build();
 
-            ExprUseVisitor::new(
+            ExprUseVisitor::for_clippy(
+                cx,
+                closure.def_id,
                 &mut delegate,
-                &infcx,
-                closure.body.hir_id.owner.def_id,
-                cx.param_env,
-                cx.typeck_results(),
             )
-            .consume_body(body);
+            .consume_body(body).into_ok();
 
             let mut to_be_discarded = 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 d3347466be9..ae9aa83efd6 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
@@ -417,7 +417,7 @@ fn get_input_traits_and_projections<'tcx>(
                 }
             },
             ClauseKind::Projection(projection_predicate) => {
-                if projection_predicate.projection_ty.self_ty() == input {
+                if projection_predicate.projection_term.self_ty() == input {
                     projection_predicates.push(projection_predicate);
                 }
             },
diff --git a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs
index e6c6a15b8d4..ae6cf992ef7 100644
--- a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs
@@ -320,11 +320,11 @@ fn is_mixed_projection_predicate<'tcx>(
         && (term_param_ty.index as usize) < generics.parent_count
     {
         // The inner-most self type is a type parameter from the current function.
-        let mut projection_ty = projection_predicate.projection_ty;
+        let mut projection_term = projection_predicate.projection_term;
         loop {
-            match projection_ty.self_ty().kind() {
+            match *projection_term.self_ty().kind() {
                 ty::Alias(ty::Projection, inner_projection_ty) => {
-                    projection_ty = *inner_projection_ty;
+                    projection_term = inner_projection_ty.into();
                 },
                 ty::Param(param_ty) => {
                     return (param_ty.index as usize) >= generics.parent_count;
@@ -404,14 +404,11 @@ fn replace_types<'tcx>(
         // The `replaced.insert(...)` check provides some protection against infinite loops.
         if replaced.insert(param_ty.index) {
             for projection_predicate in projection_predicates {
-                if projection_predicate.projection_ty.self_ty() == param_ty.to_ty(cx.tcx)
+                if projection_predicate.projection_term.self_ty() == param_ty.to_ty(cx.tcx)
                     && let Some(term_ty) = projection_predicate.term.ty()
                     && let ty::Param(term_param_ty) = term_ty.kind()
                 {
-                    let projection = cx.tcx.mk_ty_from_kind(ty::Alias(
-                        ty::Projection,
-                        projection_predicate.projection_ty.with_self_ty(cx.tcx, new_ty),
-                    ));
+                    let projection = projection_predicate.projection_term.with_self_ty(cx.tcx, new_ty).expect_ty(cx.tcx).to_ty(cx.tcx);
 
                     if let Ok(projected_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, projection)
                         && args[term_param_ty.index as usize] != GenericArg::from(projected_ty)
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
index 9e47c3ad0b7..9b852f52ea1 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
@@ -11,7 +11,6 @@ use rustc_hir::{
     PatKind,
 };
 use rustc_hir_typeck::expr_use_visitor as euv;
-use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::mir::FakeReadCause;
 use rustc_middle::ty::{self, Ty, TyCtxt, UpvarId, UpvarPath};
@@ -102,7 +101,6 @@ fn should_skip<'tcx>(
 fn check_closures<'tcx>(
     ctx: &mut MutablyUsedVariablesCtxt<'tcx>,
     cx: &LateContext<'tcx>,
-    infcx: &InferCtxt<'tcx>,
     checked_closures: &mut FxHashSet<LocalDefId>,
     closures: FxHashSet<LocalDefId>,
 ) {
@@ -119,7 +117,7 @@ fn check_closures<'tcx>(
             .associated_body()
             .map(|(_, body_id)| hir.body(body_id))
         {
-            euv::ExprUseVisitor::new(ctx, infcx, closure, cx.param_env, cx.typeck_results()).consume_body(body);
+            euv::ExprUseVisitor::for_clippy(cx, closure, &mut *ctx).consume_body(body).into_ok();
         }
     }
 }
@@ -196,8 +194,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> {
                 async_closures: FxHashSet::default(),
                 tcx: cx.tcx,
             };
-            let infcx = cx.tcx.infer_ctxt().build();
-            euv::ExprUseVisitor::new(&mut ctx, &infcx, fn_def_id, cx.param_env, cx.typeck_results()).consume_body(body);
+            euv::ExprUseVisitor::for_clippy(cx, fn_def_id, &mut ctx).consume_body(body).into_ok();
 
             let mut checked_closures = FxHashSet::default();
 
@@ -210,13 +207,13 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> {
                 }
                 ControlFlow::<()>::Continue(())
             });
-            check_closures(&mut ctx, cx, &infcx, &mut checked_closures, closures);
+            check_closures(&mut ctx, cx, &mut checked_closures, closures);
 
             if is_async {
                 while !ctx.async_closures.is_empty() {
                     let async_closures = ctx.async_closures.clone();
                     ctx.async_closures.clear();
-                    check_closures(&mut ctx, cx, &infcx, &mut checked_closures, async_closures);
+                    check_closures(&mut ctx, cx, &mut checked_closures, async_closures);
                 }
             }
             ctx.generate_mutably_used_ids_from_aliases()
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 39d374d0d27..0986571d0f2 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
@@ -13,7 +13,6 @@ use rustc_hir::{
     TyKind,
 };
 use rustc_hir_typeck::expr_use_visitor as euv;
-use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::mir::FakeReadCause;
 use rustc_middle::ty::{self, Ty, TypeVisitableExt};
@@ -134,8 +133,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
         // function body.
         let MovedVariablesCtxt { moved_vars } = {
             let mut ctx = MovedVariablesCtxt::default();
-            let infcx = cx.tcx.infer_ctxt().build();
-            euv::ExprUseVisitor::new(&mut ctx, &infcx, fn_def_id, cx.param_env, cx.typeck_results()).consume_body(body);
+            euv::ExprUseVisitor::for_clippy(cx, fn_def_id, &mut ctx).consume_body(body).into_ok();
             ctx
         };
 
diff --git a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
index 435eb9048f5..910e584a7a0 100644
--- a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
@@ -11,7 +11,6 @@ use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, Pl
 use rustc_lint::LateContext;
 use rustc_middle::mir::FakeReadCause;
 use rustc_middle::ty::BorrowKind;
-use rustc_trait_selection::infer::TyCtxtInferExt;
 
 use super::ASSIGN_OP_PATTERN;
 
@@ -119,15 +118,8 @@ fn imm_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> HirIdSet {
     }
 
     let mut s = S(HirIdSet::default());
-    let infcx = cx.tcx.infer_ctxt().build();
-    let mut v = ExprUseVisitor::new(
-        &mut s,
-        &infcx,
-        cx.tcx.hir().body_owner_def_id(cx.enclosing_body.unwrap()),
-        cx.param_env,
-        cx.typeck_results(),
-    );
-    v.consume_expr(e);
+    let v = ExprUseVisitor::for_clippy(cx, e.hir_id.owner.def_id, &mut s);
+    v.consume_expr(e).into_ok();
     s.0
 }
 
@@ -151,14 +143,7 @@ fn mut_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> HirIdSet {
     }
 
     let mut s = S(HirIdSet::default());
-    let infcx = cx.tcx.infer_ctxt().build();
-    let mut v = ExprUseVisitor::new(
-        &mut s,
-        &infcx,
-        cx.tcx.hir().body_owner_def_id(cx.enclosing_body.unwrap()),
-        cx.param_env,
-        cx.typeck_results(),
-    );
-    v.consume_expr(e);
+    let v = ExprUseVisitor::for_clippy(cx, e.hir_id.owner.def_id, &mut s);
+    v.consume_expr(e).into_ok();
     s.0
 }
diff --git a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
index 214b69dc925..f0d1458a59b 100644
--- a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
+++ b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
@@ -66,7 +66,7 @@ fn get_projection_pred<'tcx>(
             let projection_pred = cx
                 .tcx
                 .instantiate_bound_regions_with_erased(proj_pred.kind().rebind(pred));
-            if projection_pred.projection_ty.args == trait_pred.trait_ref.args {
+            if projection_pred.projection_term.args == trait_pred.trait_ref.args {
                 return Some(projection_pred);
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/unwrap.rs b/src/tools/clippy/clippy_lints/src/unwrap.rs
index 2622abd59cb..5b2841dcd83 100644
--- a/src/tools/clippy/clippy_lints/src/unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/unwrap.rs
@@ -6,7 +6,6 @@ use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, Visitor};
 use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, HirId, Node, PathSegment, UnOp};
 use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceWithHirId};
-use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::lint::in_external_macro;
@@ -252,16 +251,13 @@ impl<'a, 'tcx> UnwrappableVariablesVisitor<'a, 'tcx> {
                 local_id: unwrap_info.local_id,
             };
 
-            let infcx = self.cx.tcx.infer_ctxt().build();
-            let mut vis = ExprUseVisitor::new(
-                &mut delegate,
-                &infcx,
+            let vis = ExprUseVisitor::for_clippy(
+                self.cx,
                 cond.hir_id.owner.def_id,
-                self.cx.param_env,
-                self.cx.typeck_results(),
+                &mut delegate,
             );
-            vis.walk_expr(cond);
-            vis.walk_expr(branch);
+            vis.walk_expr(cond).into_ok();
+            vis.walk_expr(branch).into_ok();
 
             if delegate.is_mutated {
                 // if the variable is mutated, we don't know whether it can be unwrapped.
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index a49414a058b..99d7aba2f7a 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -7,6 +7,7 @@
 #![feature(never_type)]
 #![feature(rustc_private)]
 #![feature(assert_matches)]
+#![feature(unwrap_infallible)]
 #![recursion_limit = "512"]
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
 #![allow(
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index 8d6057272c4..bf03c6c1601 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -11,7 +11,6 @@ use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::{Closure, ExprKind, HirId, MutTy, TyKind};
 use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
-use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{EarlyContext, LateContext, LintContext};
 use rustc_middle::hir::place::ProjectionKind;
 use rustc_middle::mir::{FakeReadCause, Mutability};
@@ -831,8 +830,9 @@ pub fn deref_closure_args(cx: &LateContext<'_>, closure: &hir::Expr<'_>) -> Opti
             applicability: Applicability::MachineApplicable,
         };
 
-        let infcx = cx.tcx.infer_ctxt().build();
-        ExprUseVisitor::new(&mut visitor, &infcx, def_id, cx.param_env, cx.typeck_results()).consume_body(closure_body);
+        ExprUseVisitor::for_clippy(cx, def_id, &mut visitor)
+            .consume_body(closure_body)
+            .into_ok();
 
         if !visitor.suggestion_start.is_empty() {
             return Some(DerefClosure {
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index 97bba8648c5..e3ab42c3107 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -795,7 +795,7 @@ fn sig_from_bounds<'tcx>(
                 inputs = Some(i);
             },
             ty::ClauseKind::Projection(p)
-                if Some(p.projection_ty.def_id) == lang_items.fn_once_output() && p.projection_ty.self_ty() == ty =>
+                if Some(p.projection_term.def_id) == lang_items.fn_once_output() && p.projection_term.self_ty() == ty =>
             {
                 if output.is_some() {
                     // Multiple different fn trait impls. Is this even allowed?
@@ -834,7 +834,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option
                 }
                 inputs = Some(i);
             },
-            ty::ClauseKind::Projection(p) if Some(p.projection_ty.def_id) == lang_items.fn_once_output() => {
+            ty::ClauseKind::Projection(p) if Some(p.projection_term.def_id) == lang_items.fn_once_output() => {
                 if output.is_some() {
                     // Multiple different fn trait impls. Is this even allowed?
                     return None;
diff --git a/src/tools/clippy/clippy_utils/src/usage.rs b/src/tools/clippy/clippy_utils/src/usage.rs
index a145920aa85..9abb4ef9b8d 100644
--- a/src/tools/clippy/clippy_utils/src/usage.rs
+++ b/src/tools/clippy/clippy_utils/src/usage.rs
@@ -5,7 +5,6 @@ use hir::def::Res;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{self as hir, Expr, ExprKind, HirId, HirIdSet};
 use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, Place, PlaceBase, PlaceWithHirId};
-use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::LateContext;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::mir::FakeReadCause;
@@ -17,15 +16,13 @@ pub fn mutated_variables<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) ->
         used_mutably: HirIdSet::default(),
         skip: false,
     };
-    let infcx = cx.tcx.infer_ctxt().build();
-    ExprUseVisitor::new(
-        &mut delegate,
-        &infcx,
+    ExprUseVisitor::for_clippy(
+        cx,
         expr.hir_id.owner.def_id,
-        cx.param_env,
-        cx.typeck_results(),
+        &mut delegate,
     )
-    .walk_expr(expr);
+    .walk_expr(expr)
+    .into_ok();
 
     if delegate.skip {
         return None;
diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs
index 9888ca2d1ed..cc81d23a8ff 100644
--- a/src/tools/run-make-support/src/lib.rs
+++ b/src/tools/run-make-support/src/lib.rs
@@ -54,6 +54,15 @@ pub fn static_lib(name: &str) -> PathBuf {
     tmp_dir().join(static_lib_name(name))
 }
 
+pub fn python_command() -> Command {
+    let python_path = std::env::var("PYTHON").expect("PYTHON environment variable does not exist");
+    Command::new(python_path)
+}
+
+pub fn source_path() -> PathBuf {
+    std::env::var("S").expect("S variable does not exist").into()
+}
+
 /// Construct the static library name based on the platform.
 pub fn static_lib_name(name: &str) -> String {
     // See tools.mk (irrelevant lines omitted):
diff --git a/src/tools/run-make-support/src/rustc.rs b/src/tools/run-make-support/src/rustc.rs
index de773d688ef..1671a01860a 100644
--- a/src/tools/run-make-support/src/rustc.rs
+++ b/src/tools/run-make-support/src/rustc.rs
@@ -1,5 +1,5 @@
 use std::env;
-use std::ffi::OsString;
+use std::ffi::{OsStr, OsString};
 use std::io::Write;
 use std::path::Path;
 use std::process::{Command, Output, Stdio};
@@ -176,6 +176,13 @@ impl Rustc {
         self
     }
 
+    /// Specify the crate name.
+    pub fn crate_name<S: AsRef<OsStr>>(&mut self, name: S) -> &mut Self {
+        self.cmd.arg("--crate-name");
+        self.cmd.arg(name.as_ref());
+        self
+    }
+
     /// Get the [`Output`][::std::process::Output] of the finished process.
     #[track_caller]
     pub fn command_output(&mut self) -> ::std::process::Output {
diff --git a/src/tools/run-make-support/src/rustdoc.rs b/src/tools/run-make-support/src/rustdoc.rs
index aa3c7dcf0e3..c4f4e9f9bd2 100644
--- a/src/tools/run-make-support/src/rustdoc.rs
+++ b/src/tools/run-make-support/src/rustdoc.rs
@@ -1,4 +1,5 @@
 use std::env;
+use std::ffi::OsStr;
 use std::io::Write;
 use std::path::Path;
 use std::process::{Command, Output, Stdio};
@@ -45,6 +46,21 @@ impl Rustdoc {
         Self { cmd, stdin: None }
     }
 
+    /// Specify where an external library is located.
+    pub fn extern_<P: AsRef<Path>>(&mut self, crate_name: &str, path: P) -> &mut Self {
+        assert!(
+            !crate_name.contains(|c: char| c.is_whitespace() || c == '\\' || c == '/'),
+            "crate name cannot contain whitespace or path separators"
+        );
+
+        let path = path.as_ref().to_string_lossy();
+
+        self.cmd.arg("--extern");
+        self.cmd.arg(format!("{crate_name}={path}"));
+
+        self
+    }
+
     /// Specify path to the input file.
     pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
         self.cmd.arg(path.as_ref());
@@ -107,6 +123,34 @@ impl Rustdoc {
         self
     }
 
+    /// Specify the target triple, or a path to a custom target json spec file.
+    pub fn target(&mut self, target: &str) -> &mut Self {
+        self.cmd.arg(format!("--target={target}"));
+        self
+    }
+
+    /// Specify the crate type.
+    pub fn crate_type(&mut self, crate_type: &str) -> &mut Self {
+        self.cmd.arg("--crate-type");
+        self.cmd.arg(crate_type);
+        self
+    }
+
+    /// Specify the crate name.
+    pub fn crate_name<S: AsRef<OsStr>>(&mut self, name: S) -> &mut Self {
+        self.cmd.arg("--crate-name");
+        self.cmd.arg(name.as_ref());
+        self
+    }
+
+    /// Add a directory to the library search path. It corresponds to the `-L`
+    /// rustdoc option.
+    pub fn library_search_path<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
+        self.cmd.arg("-L");
+        self.cmd.arg(path.as_ref());
+        self
+    }
+
     #[track_caller]
     pub fn run_fail_assert_exit_code(&mut self, code: i32) -> Output {
         let caller_location = std::panic::Location::caller();
diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index e87950b36d9..83a3ea84b24 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -1,6 +1,3 @@
-run-make/alloc-no-oom-handling/Makefile
-run-make/alloc-no-rc/Makefile
-run-make/alloc-no-sync/Makefile
 run-make/allocator-shim-circular-deps/Makefile
 run-make/allow-non-lint-warnings-cmdline/Makefile
 run-make/allow-warnings-cmdline-stability/Makefile
@@ -12,7 +9,6 @@ run-make/c-dynamic-dylib/Makefile
 run-make/c-dynamic-rlib/Makefile
 run-make/c-link-to-rust-dylib/Makefile
 run-make/c-link-to-rust-staticlib/Makefile
-run-make/c-link-to-rust-va-list-fn/Makefile
 run-make/c-static-dylib/Makefile
 run-make/c-static-rlib/Makefile
 run-make/c-unwind-abi-catch-lib-panic/Makefile
@@ -248,12 +244,9 @@ run-make/rustdoc-io-error/Makefile
 run-make/rustdoc-scrape-examples-invalid-expr/Makefile
 run-make/rustdoc-scrape-examples-macros/Makefile
 run-make/rustdoc-scrape-examples-multiple/Makefile
-run-make/rustdoc-scrape-examples-ordering/Makefile
 run-make/rustdoc-scrape-examples-remap/Makefile
 run-make/rustdoc-scrape-examples-test/Makefile
 run-make/rustdoc-scrape-examples-whitespace/Makefile
-run-make/rustdoc-shared-flags/Makefile
-run-make/rustdoc-target-spec-json-path/Makefile
 run-make/rustdoc-themes/Makefile
 run-make/rustdoc-verify-output-files/Makefile
 run-make/rustdoc-with-out-dir-option/Makefile
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 1d24c59b356..1b73b67b755 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -395,6 +395,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "windows_aarch64_gnullvm",
     "windows_aarch64_msvc",
     "windows_i686_gnu",
+    "windows_i686_gnullvm",
     "windows_i686_msvc",
     "windows_x86_64_gnu",
     "windows_x86_64_gnullvm",
diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs
index 3563aec6d80..0db2a358002 100644
--- a/tests/assembly/targets/targets-elf.rs
+++ b/tests/assembly/targets/targets-elf.rs
@@ -555,6 +555,9 @@
 //@ revisions: x86_64_unknown_linux_ohos
 //@ [x86_64_unknown_linux_ohos] compile-flags: --target x86_64-unknown-linux-ohos
 //@ [x86_64_unknown_linux_ohos] needs-llvm-components: x86
+//@ revisions: x86_64_unknown_linux_none
+//@ [x86_64_unknown_linux_none] compile-flags: --target x86_64-unknown-linux-none
+//@ [x86_64_unknown_linux_none] needs-llvm-components: x86
 //@ revisions: x86_64_unknown_netbsd
 //@ [x86_64_unknown_netbsd] compile-flags: --target x86_64-unknown-netbsd
 //@ [x86_64_unknown_netbsd] needs-llvm-components: x86
diff --git a/tests/auxiliary/rust_test_helpers.c b/tests/auxiliary/rust_test_helpers.c
index 965df44c676..34cc7fd5dfb 100644
--- a/tests/auxiliary/rust_test_helpers.c
+++ b/tests/auxiliary/rust_test_helpers.c
@@ -27,10 +27,10 @@ rust_dbg_extern_identity_u8(char u) {
     return u;
 }
 
-typedef void *(*dbg_callback)(void*);
+typedef uint64_t (*dbg_callback)(uint64_t);
 
-void *
-rust_dbg_call(dbg_callback cb, void *data) {
+uint64_t
+rust_dbg_call(dbg_callback cb, uint64_t data) {
     return cb(data);
 }
 
diff --git a/tests/codegen-units/partitioning/extern-drop-glue.rs b/tests/codegen-units/partitioning/extern-drop-glue.rs
index 84eb802f264..d3bce7b4223 100644
--- a/tests/codegen-units/partitioning/extern-drop-glue.rs
+++ b/tests/codegen-units/partitioning/extern-drop-glue.rs
@@ -1,7 +1,4 @@
-//
-
-// We specify incremental here because we want to test the partitioning for
-//@ incremental compilation
+// We specify incremental here because we want to test the partitioning for incremental compilation
 // We specify opt-level=0 because `drop_in_place` is `Internal` when optimizing
 //@ incremental
 //@ compile-flags:-Zprint-mono-items=lazy
diff --git a/tests/codegen-units/partitioning/extern-generic.rs b/tests/codegen-units/partitioning/extern-generic.rs
index abd3918094d..0e4b6a37f71 100644
--- a/tests/codegen-units/partitioning/extern-generic.rs
+++ b/tests/codegen-units/partitioning/extern-generic.rs
@@ -1,6 +1,4 @@
-//
-// We specify incremental here because we want to test the partitioning for
-//@ incremental compilation
+// We specify incremental here because we want to test the partitioning for incremental compilation
 //@ incremental
 //@ compile-flags:-Zprint-mono-items=eager -Zshare-generics=y
 
diff --git a/tests/codegen-units/partitioning/incremental-merging.rs b/tests/codegen-units/partitioning/incremental-merging.rs
index b44090c866a..6834bb2bebf 100644
--- a/tests/codegen-units/partitioning/incremental-merging.rs
+++ b/tests/codegen-units/partitioning/incremental-merging.rs
@@ -1,5 +1,4 @@
-// We specify incremental here because we want to test the partitioning for
-//@ incremental compilation
+// We specify incremental here because we want to test the partitioning for incremental compilation
 //@ incremental
 //@ compile-flags:-Zprint-mono-items=lazy
 //@ compile-flags:-Ccodegen-units=3
diff --git a/tests/codegen-units/partitioning/inlining-from-extern-crate.rs b/tests/codegen-units/partitioning/inlining-from-extern-crate.rs
index 74734d3cf38..d021f467f1f 100644
--- a/tests/codegen-units/partitioning/inlining-from-extern-crate.rs
+++ b/tests/codegen-units/partitioning/inlining-from-extern-crate.rs
@@ -1,6 +1,4 @@
-//
-// We specify incremental here because we want to test the partitioning for
-//@ incremental compilation
+// We specify incremental here because we want to test the partitioning for incremental compilation
 //@ incremental
 //@ compile-flags:-Zprint-mono-items=lazy
 //@ compile-flags:-Zinline-in-all-cgus
diff --git a/tests/codegen-units/partitioning/local-drop-glue.rs b/tests/codegen-units/partitioning/local-drop-glue.rs
index 0974187ade0..5fa1df95cbc 100644
--- a/tests/codegen-units/partitioning/local-drop-glue.rs
+++ b/tests/codegen-units/partitioning/local-drop-glue.rs
@@ -1,6 +1,4 @@
-//
-// We specify incremental here because we want to test the partitioning for
-//@ incremental compilation
+// We specify incremental here because we want to test the partitioning for incremental compilation
 // We specify opt-level=0 because `drop_in_place` is `Internal` when optimizing
 //@ incremental
 //@ compile-flags:-Zprint-mono-items=lazy
diff --git a/tests/codegen-units/partitioning/local-generic.rs b/tests/codegen-units/partitioning/local-generic.rs
index 2cfdc27ccb1..06f46b23db6 100644
--- a/tests/codegen-units/partitioning/local-generic.rs
+++ b/tests/codegen-units/partitioning/local-generic.rs
@@ -1,5 +1,4 @@
-// We specify incremental here because we want to test the partitioning for
-//@ incremental compilation
+// We specify incremental here because we want to test the partitioning for incremental compilation
 //@ incremental
 //@ compile-flags:-Zprint-mono-items=eager
 
diff --git a/tests/codegen-units/partitioning/local-inlining-but-not-all.rs b/tests/codegen-units/partitioning/local-inlining-but-not-all.rs
index 49a2ce7c5d9..2f9cbe83f1d 100644
--- a/tests/codegen-units/partitioning/local-inlining-but-not-all.rs
+++ b/tests/codegen-units/partitioning/local-inlining-but-not-all.rs
@@ -1,6 +1,4 @@
-//
-// We specify incremental here because we want to test the partitioning for
-//@ incremental compilation
+// We specify incremental here because we want to test the partitioning for incremental compilation
 //@ incremental
 //@ compile-flags:-Zprint-mono-items=lazy
 //@ compile-flags:-Zinline-in-all-cgus=no
diff --git a/tests/codegen-units/partitioning/local-inlining.rs b/tests/codegen-units/partitioning/local-inlining.rs
index 726cf2b87d2..2329a876c96 100644
--- a/tests/codegen-units/partitioning/local-inlining.rs
+++ b/tests/codegen-units/partitioning/local-inlining.rs
@@ -1,6 +1,4 @@
-//
-// We specify incremental here because we want to test the partitioning for
-//@ incremental compilation
+// We specify incremental here because we want to test the partitioning for incremental compilation
 //@ incremental
 //@ compile-flags:-Zprint-mono-items=lazy
 //@ compile-flags:-Zinline-in-all-cgus
diff --git a/tests/codegen-units/partitioning/local-transitive-inlining.rs b/tests/codegen-units/partitioning/local-transitive-inlining.rs
index 355eb6cf395..4ccc53aea1d 100644
--- a/tests/codegen-units/partitioning/local-transitive-inlining.rs
+++ b/tests/codegen-units/partitioning/local-transitive-inlining.rs
@@ -1,6 +1,4 @@
-//
-// We specify incremental here because we want to test the partitioning for
-//@ incremental compilation
+// We specify incremental here because we want to test the partitioning for incremental compilation
 //@ incremental
 //@ compile-flags:-Zprint-mono-items=lazy
 //@ compile-flags:-Zinline-in-all-cgus
diff --git a/tests/codegen-units/partitioning/methods-are-with-self-type.rs b/tests/codegen-units/partitioning/methods-are-with-self-type.rs
index 2e54725ff28..3ba53334cc9 100644
--- a/tests/codegen-units/partitioning/methods-are-with-self-type.rs
+++ b/tests/codegen-units/partitioning/methods-are-with-self-type.rs
@@ -3,9 +3,7 @@
 // much sense at the moment.
 //@ ignore-test
 
-//
-// We specify incremental here because we want to test the partitioning for
-//@ incremental compilation
+// We specify incremental here because we want to test the partitioning for incremental compilation
 //@ incremental
 //@ compile-flags:-Zprint-mono-items=lazy
 
diff --git a/tests/codegen-units/partitioning/regular-modules.rs b/tests/codegen-units/partitioning/regular-modules.rs
index 0eb0848e454..68601975d06 100644
--- a/tests/codegen-units/partitioning/regular-modules.rs
+++ b/tests/codegen-units/partitioning/regular-modules.rs
@@ -1,5 +1,4 @@
-// We specify incremental here because we want to test the partitioning for
-//@ incremental compilation
+// We specify incremental here because we want to test the partitioning for incremental compilation
 //@ incremental
 //@ compile-flags:-Zprint-mono-items=eager
 
diff --git a/tests/codegen-units/partitioning/shared-generics.rs b/tests/codegen-units/partitioning/shared-generics.rs
index 25ea7fab735..5b78794316c 100644
--- a/tests/codegen-units/partitioning/shared-generics.rs
+++ b/tests/codegen-units/partitioning/shared-generics.rs
@@ -1,4 +1,3 @@
-//
 //@ no-prefer-dynamic
 // NOTE: We always compile this test with -Copt-level=0 because higher opt-levels
 //       prevent drop-glue from participating in share-generics.
diff --git a/tests/codegen-units/partitioning/statics.rs b/tests/codegen-units/partitioning/statics.rs
index 9503a91b0ab..c7eef1f3789 100644
--- a/tests/codegen-units/partitioning/statics.rs
+++ b/tests/codegen-units/partitioning/statics.rs
@@ -1,5 +1,4 @@
-// We specify incremental here because we want to test the partitioning for
-//@ incremental compilation
+// We specify incremental here because we want to test the partitioning for incremental compilation
 //@ incremental
 //@ compile-flags:-Zprint-mono-items=lazy
 
diff --git a/tests/codegen-units/partitioning/vtable-through-const.rs b/tests/codegen-units/partitioning/vtable-through-const.rs
index 111b4fa1b9a..ca4d3822b54 100644
--- a/tests/codegen-units/partitioning/vtable-through-const.rs
+++ b/tests/codegen-units/partitioning/vtable-through-const.rs
@@ -1,7 +1,4 @@
-//
-
-// We specify incremental here because we want to test the partitioning for
-//@ incremental compilation
+// We specify incremental here because we want to test the partitioning for incremental compilation
 //@ incremental
 //@ compile-flags:-Zprint-mono-items=lazy
 //@ compile-flags:-Zinline-in-all-cgus
diff --git a/tests/codegen/mir-aggregate-no-alloca.rs b/tests/codegen/mir-aggregate-no-alloca.rs
index a7752d714fe..c0e7e1a05e3 100644
--- a/tests/codegen/mir-aggregate-no-alloca.rs
+++ b/tests/codegen/mir-aggregate-no-alloca.rs
@@ -55,7 +55,7 @@ pub fn make_cell_of_bool(b: bool) -> std::cell::Cell<bool> {
     std::cell::Cell::new(b)
 }
 
-// CHECK-LABLE: { i8, i16 } @make_cell_of_bool_and_short(i1 noundef zeroext %b, i16 noundef %s)
+// CHECK-LABEL: { i8, i16 } @make_cell_of_bool_and_short(i1 noundef zeroext %b, i16 noundef %s)
 #[no_mangle]
 pub fn make_cell_of_bool_and_short(b: bool, s: u16) -> std::cell::Cell<(bool, u16)> {
     // CHECK-NOT: alloca
diff --git a/tests/codegen/option-niche-eq.rs b/tests/codegen/option-niche-eq.rs
index 7b955332fd3..25ea5dd595c 100644
--- a/tests/codegen/option-niche-eq.rs
+++ b/tests/codegen/option-niche-eq.rs
@@ -7,7 +7,7 @@ use core::cmp::Ordering;
 use core::ptr::NonNull;
 use core::num::NonZero;
 
-// CHECK-lABEL: @non_zero_eq
+// CHECK-LABEL: @non_zero_eq
 #[no_mangle]
 pub fn non_zero_eq(l: Option<NonZero<u32>>, r: Option<NonZero<u32>>) -> bool {
     // CHECK: start:
@@ -16,7 +16,7 @@ pub fn non_zero_eq(l: Option<NonZero<u32>>, r: Option<NonZero<u32>>) -> bool {
     l == r
 }
 
-// CHECK-lABEL: @non_zero_signed_eq
+// CHECK-LABEL: @non_zero_signed_eq
 #[no_mangle]
 pub fn non_zero_signed_eq(l: Option<NonZero<i64>>, r: Option<NonZero<i64>>) -> bool {
     // CHECK: start:
@@ -25,7 +25,7 @@ pub fn non_zero_signed_eq(l: Option<NonZero<i64>>, r: Option<NonZero<i64>>) -> b
     l == r
 }
 
-// CHECK-lABEL: @non_null_eq
+// CHECK-LABEL: @non_null_eq
 #[no_mangle]
 pub fn non_null_eq(l: Option<NonNull<u8>>, r: Option<NonNull<u8>>) -> bool {
     // CHECK: start:
@@ -34,7 +34,7 @@ pub fn non_null_eq(l: Option<NonNull<u8>>, r: Option<NonNull<u8>>) -> bool {
     l == r
 }
 
-// CHECK-lABEL: @ordering_eq
+// CHECK-LABEL: @ordering_eq
 #[no_mangle]
 pub fn ordering_eq(l: Option<Ordering>, r: Option<Ordering>) -> bool {
     // CHECK: start:
@@ -54,7 +54,7 @@ pub enum EnumWithNiche {
     G,
 }
 
-// CHECK-lABEL: @niche_eq
+// CHECK-LABEL: @niche_eq
 #[no_mangle]
 pub fn niche_eq(l: Option<EnumWithNiche>, r: Option<EnumWithNiche>) -> bool {
     // CHECK: start:
@@ -64,7 +64,7 @@ pub fn niche_eq(l: Option<EnumWithNiche>, r: Option<EnumWithNiche>) -> bool {
 }
 
 // FIXME: This should work too
-// // FIXME-CHECK-lABEL: @bool_eq
+// // FIXME-CHECK-LABEL: @bool_eq
 // #[no_mangle]
 // pub fn bool_eq(l: Option<bool>, r: Option<bool>) -> bool {
 //     // FIXME-CHECK: start:
diff --git a/tests/codegen/sanitizer/no-sanitize-inlining.rs b/tests/codegen/sanitizer/no-sanitize-inlining.rs
index 623bfa608ca..d5e47884f85 100644
--- a/tests/codegen/sanitizer/no-sanitize-inlining.rs
+++ b/tests/codegen/sanitizer/no-sanitize-inlining.rs
@@ -16,7 +16,7 @@
 // ASAN:       }
 //
 // LSAN-LABEL: define void @test
-// LSAN-NO:      call
+// LSAN-NOT:     call
 // LSAN:       }
 #[no_mangle]
 pub fn test(n: &mut u32) {
diff --git a/tests/codegen/simd/issue-120720-reduce-nan.rs b/tests/codegen/simd/issue-120720-reduce-nan.rs
index 2c6098c0489..0372582bf7f 100644
--- a/tests/codegen/simd/issue-120720-reduce-nan.rs
+++ b/tests/codegen/simd/issue-120720-reduce-nan.rs
@@ -8,7 +8,7 @@
 #![feature(stdarch_x86_avx512, avx512_target_feature)]
 use std::arch::x86_64::*;
 
-// CHECK-label: @demo(
+// CHECK-LABEL: @demo(
 #[no_mangle]
 #[target_feature(enable = "avx512f")] // Function-level target feature mismatches inhibit inlining
 pub unsafe fn demo() -> bool {
diff --git a/tests/crashes/123901.rs b/tests/crashes/123901.rs
deleted file mode 100644
index 06722f0bf29..00000000000
--- a/tests/crashes/123901.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-//@ known-bug: #123901
-//@ edition:2021
-
-pub fn test(test: &u64, temp: &u64) {
-    async |check, a, b| {
-        temp.abs_diff(12);
-    };
-}
diff --git a/tests/run-make/alloc-no-oom-handling/Makefile b/tests/run-make/alloc-no-oom-handling/Makefile
deleted file mode 100644
index 7c3ae90b58d..00000000000
--- a/tests/run-make/alloc-no-oom-handling/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-# This test checks that alloc can still compile correctly when the unstable no_global_oom_handling feature is turned on.
-# See https://github.com/rust-lang/rust/pull/84266
-
-include ../tools.mk
-
-all:
-	$(RUSTC) --edition=2021 -Dwarnings --crate-type=rlib ../../../library/alloc/src/lib.rs --cfg no_global_oom_handling
diff --git a/tests/run-make/alloc-no-oom-handling/rmake.rs b/tests/run-make/alloc-no-oom-handling/rmake.rs
new file mode 100644
index 00000000000..fec3c653294
--- /dev/null
+++ b/tests/run-make/alloc-no-oom-handling/rmake.rs
@@ -0,0 +1,15 @@
+// This test checks that alloc can still compile correctly
+// when the unstable no_global_oom_handling feature is turned on.
+// See https://github.com/rust-lang/rust/pull/84266
+
+use run_make_support::rustc;
+
+fn main() {
+    rustc()
+        .edition("2021")
+        .arg("-Dwarnings")
+        .crate_type("rlib")
+        .input("../../../library/alloc/src/lib.rs")
+        .cfg("no_global_oom_handling")
+        .run();
+}
diff --git a/tests/run-make/alloc-no-rc/Makefile b/tests/run-make/alloc-no-rc/Makefile
deleted file mode 100644
index fcfe1603b6c..00000000000
--- a/tests/run-make/alloc-no-rc/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-# This test checks that alloc can still compile correctly when the unstable no_rc feature is turned on.
-# See https://github.com/rust-lang/rust/pull/89891
-
-include ../tools.mk
-
-all:
-	$(RUSTC) --edition=2021 -Dwarnings --crate-type=rlib ../../../library/alloc/src/lib.rs --cfg no_rc
diff --git a/tests/run-make/alloc-no-rc/rmake.rs b/tests/run-make/alloc-no-rc/rmake.rs
new file mode 100644
index 00000000000..c5744a3f5ee
--- /dev/null
+++ b/tests/run-make/alloc-no-rc/rmake.rs
@@ -0,0 +1,15 @@
+// This test checks that alloc can still compile correctly
+// when the unstable no_rc feature is turned on.
+// See https://github.com/rust-lang/rust/pull/84266
+
+use run_make_support::rustc;
+
+fn main() {
+    rustc()
+        .edition("2021")
+        .arg("-Dwarnings")
+        .crate_type("rlib")
+        .input("../../../library/alloc/src/lib.rs")
+        .cfg("no_rc")
+        .run();
+}
diff --git a/tests/run-make/alloc-no-sync/Makefile b/tests/run-make/alloc-no-sync/Makefile
deleted file mode 100644
index 997dbcf6603..00000000000
--- a/tests/run-make/alloc-no-sync/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-# This test checks that alloc can still compile correctly when the unstable no_sync feature is turned on.
-# See https://github.com/rust-lang/rust/pull/89891
-
-include ../tools.mk
-
-all:
-	$(RUSTC) --edition=2021 -Dwarnings --crate-type=rlib ../../../library/alloc/src/lib.rs --cfg no_sync
diff --git a/tests/run-make/alloc-no-sync/rmake.rs b/tests/run-make/alloc-no-sync/rmake.rs
new file mode 100644
index 00000000000..6410eca80ab
--- /dev/null
+++ b/tests/run-make/alloc-no-sync/rmake.rs
@@ -0,0 +1,15 @@
+// This test checks that alloc can still compile correctly
+// when the unstable no_sync feature is turned on.
+// See https://github.com/rust-lang/rust/pull/84266
+
+use run_make_support::rustc;
+
+fn main() {
+    rustc()
+        .edition("2021")
+        .arg("-Dwarnings")
+        .crate_type("rlib")
+        .input("../../../library/alloc/src/lib.rs")
+        .cfg("no_sync")
+        .run();
+}
diff --git a/tests/run-make/c-link-to-rust-va-list-fn/Makefile b/tests/run-make/c-link-to-rust-va-list-fn/Makefile
deleted file mode 100644
index 596c0fce3ce..00000000000
--- a/tests/run-make/c-link-to-rust-va-list-fn/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-all:
-	$(RUSTC) checkrust.rs
-	$(CC) test.c $(call STATICLIB,checkrust) $(call OUT_EXE,test) $(EXTRACFLAGS)
-	$(call RUN,test)
diff --git a/tests/run-make/c-link-to-rust-va-list-fn/rmake.rs b/tests/run-make/c-link-to-rust-va-list-fn/rmake.rs
new file mode 100644
index 00000000000..7a450efff94
--- /dev/null
+++ b/tests/run-make/c-link-to-rust-va-list-fn/rmake.rs
@@ -0,0 +1,18 @@
+// test.c and its static library checkrust.rs make use of variadic functions (VaList).
+// This test checks that the use of this feature does not
+// prevent the creation of a functional binary.
+// See https://github.com/rust-lang/rust/pull/49878
+
+//@ ignore-cross-compile
+
+use run_make_support::{cc, extra_c_flags, run, rustc, static_lib};
+
+fn main() {
+    rustc().input("checkrust.rs").run();
+    cc().input("test.c")
+        .input(static_lib("checkrust"))
+        .out_exe("test")
+        .args(&extra_c_flags())
+        .run();
+    run("test");
+}
diff --git a/tests/run-make/core-no-fp-fmt-parse/rmake.rs b/tests/run-make/core-no-fp-fmt-parse/rmake.rs
index e3484888ca5..aef28fd2528 100644
--- a/tests/run-make/core-no-fp-fmt-parse/rmake.rs
+++ b/tests/run-make/core-no-fp-fmt-parse/rmake.rs
@@ -2,7 +2,6 @@
 // support for formatting and parsing floating-point numbers.
 
 use run_make_support::rustc;
-use std::path::PathBuf;
 
 fn main() {
     rustc()
diff --git a/tests/run-make/rustdoc-scrape-examples-ordering/Makefile b/tests/run-make/rustdoc-scrape-examples-ordering/Makefile
deleted file mode 100644
index bf45b8148c0..00000000000
--- a/tests/run-make/rustdoc-scrape-examples-ordering/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-deps := ex1 ex2
-
-include ../rustdoc-scrape-examples-multiple/scrape.mk
-
-all: scrape
diff --git a/tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs b/tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs
new file mode 100644
index 00000000000..edcf3406d47
--- /dev/null
+++ b/tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs
@@ -0,0 +1,55 @@
+use run_make_support::{python_command, rustc, rustdoc, source_path, tmp_dir};
+use std::fs::read_dir;
+use std::path::Path;
+
+fn main() {
+    let lib_dir = tmp_dir();
+    let out_dir = tmp_dir().join("rustdoc");
+    let crate_name = "foobar";
+    let deps = read_dir("examples")
+        .unwrap()
+        .filter_map(|entry| entry.ok().map(|e| e.path()))
+        .filter(|path| path.is_file() && path.extension().is_some_and(|ext| ext == "rs"))
+        .collect::<Vec<_>>();
+
+    rustc().input("src/lib.rs").crate_name(crate_name).crate_type("lib").emit("metadata").run();
+
+    let mut out_deps = Vec::with_capacity(deps.len());
+    for dep in deps {
+        let dep_stem = dep.file_stem().unwrap();
+        let out_example = out_dir.join(format!("{}.calls", dep_stem.to_str().unwrap()));
+        rustdoc()
+            .input(&dep)
+            .crate_name(&dep_stem)
+            .crate_type("bin")
+            .output(&out_dir)
+            .extern_(crate_name, lib_dir.join(format!("lib{crate_name}.rmeta")))
+            .arg("-Zunstable-options")
+            .arg("--scrape-examples-output-path")
+            .arg(&out_example)
+            .arg("--scrape-examples-target-crate")
+            .arg(crate_name)
+            .run();
+        out_deps.push(out_example);
+    }
+
+    let mut rustdoc = rustdoc();
+    rustdoc
+        .input("src/lib.rs")
+        .output(&out_dir)
+        .crate_name(crate_name)
+        .crate_type("lib")
+        .arg("-Zunstable-options");
+    for dep in out_deps {
+        rustdoc.arg("--with-examples").arg(dep);
+    }
+    rustdoc.run();
+
+    python_command()
+        .arg(source_path().join("/src/etc/htmldocck.py"))
+        .arg(out_dir)
+        .arg("src/lib.rs")
+        .status()
+        .unwrap()
+        .success();
+}
diff --git a/tests/run-make/rustdoc-shared-flags/Makefile b/tests/run-make/rustdoc-shared-flags/Makefile
deleted file mode 100644
index a2a7d7b3634..00000000000
--- a/tests/run-make/rustdoc-shared-flags/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-include ../tools.mk
-
-all: z_help c_help list_passes
-
-c_help:
-	$(RUSTC) -C help > $(TMPDIR)/rustc.c_help.txt
-	$(RUSTDOC) -C help > $(TMPDIR)/rustdoc.c_help.txt
-	$(DIFF) $(TMPDIR)/rustc.c_help.txt $(TMPDIR)/rustdoc.c_help.txt
-
-z_help:
-	$(RUSTC) -Z help > $(TMPDIR)/rustc.z_help.txt
-	$(RUSTDOC) -Z help > $(TMPDIR)/rustdoc.z_help.txt
-	$(DIFF) $(TMPDIR)/rustc.z_help.txt $(TMPDIR)/rustdoc.z_help.txt
-
-list_passes:
-	$(RUSTC) -C passes=list > $(TMPDIR)/rustc.passes.txt
-	$(RUSTDOC) -C passes=list > $(TMPDIR)/rustdoc.passes.txt
-	$(DIFF) $(TMPDIR)/rustc.passes.txt $(TMPDIR)/rustdoc.passes.txt
diff --git a/tests/run-make/rustdoc-shared-flags/rmake.rs b/tests/run-make/rustdoc-shared-flags/rmake.rs
new file mode 100644
index 00000000000..2db613f7817
--- /dev/null
+++ b/tests/run-make/rustdoc-shared-flags/rmake.rs
@@ -0,0 +1,14 @@
+use run_make_support::{rustc, rustdoc, Diff};
+
+fn compare_outputs(args: &[&str]) {
+    let rustc_output = String::from_utf8(rustc().args(args).command_output().stdout).unwrap();
+    let rustdoc_output = String::from_utf8(rustdoc().args(args).command_output().stdout).unwrap();
+
+    Diff::new().expected_text("rustc", rustc_output).actual_text("rustdoc", rustdoc_output).run();
+}
+
+fn main() {
+    compare_outputs(&["-C", "help"]);
+    compare_outputs(&["-Z", "help"]);
+    compare_outputs(&["-C", "passes=list"]);
+}
diff --git a/tests/run-make/rustdoc-target-spec-json-path/Makefile b/tests/run-make/rustdoc-target-spec-json-path/Makefile
deleted file mode 100644
index 6d0bc4186f2..00000000000
--- a/tests/run-make/rustdoc-target-spec-json-path/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-include ../tools.mk
-
-# Test that rustdoc will properly canonicalize the target spec json path just like rustc
-
-OUTPUT_DIR := "$(TMPDIR)/rustdoc-target-spec-json-path"
-
-all:
-	$(RUSTC) --crate-type lib dummy_core.rs --target target.json
-	$(RUSTDOC) -o $(OUTPUT_DIR) -L $(TMPDIR) my_crate.rs --target target.json
diff --git a/tests/run-make/rustdoc-target-spec-json-path/rmake.rs b/tests/run-make/rustdoc-target-spec-json-path/rmake.rs
new file mode 100644
index 00000000000..66530a4f08e
--- /dev/null
+++ b/tests/run-make/rustdoc-target-spec-json-path/rmake.rs
@@ -0,0 +1,14 @@
+// Test that rustdoc will properly canonicalize the target spec json path just like rustc.
+
+use run_make_support::{rustc, rustdoc, tmp_dir};
+
+fn main() {
+    let out_dir = tmp_dir().join("rustdoc-target-spec-json-path");
+    rustc().crate_type("lib").input("dummy_core.rs").target("target.json").run();
+    rustdoc()
+        .input("my_crate.rs")
+        .output(out_dir)
+        .library_search_path(tmp_dir())
+        .target("target.json")
+        .run();
+}
diff --git a/tests/rustdoc-ui/issues/issue-91713.stdout b/tests/rustdoc-ui/issues/issue-91713.stdout
index bbea7e5c212..cc3c8385d9a 100644
--- a/tests/rustdoc-ui/issues/issue-91713.stdout
+++ b/tests/rustdoc-ui/issues/issue-91713.stdout
@@ -1,6 +1,7 @@
 Available passes for running rustdoc:
 check-custom-code-classes - check for custom code classes without the feature-gate enabled
 check_doc_test_visibility - run various visibility-related lints on doctests
+strip-aliased-non-local - strips all non-local private aliased items from the output
         strip-hidden - strips all `#[doc(hidden)]` items from the output
        strip-private - strips all private items from a crate which cannot be seen externally, implies strip-priv-imports
   strip-priv-imports - strips all private import statements (`use`, `extern crate`) from a crate
@@ -14,6 +15,7 @@ Default passes for rustdoc:
 check-custom-code-classes
  collect-trait-impls
 check_doc_test_visibility
+strip-aliased-non-local
         strip-hidden  (when not --document-hidden-items)
        strip-private  (when not --document-private-items)
   strip-priv-imports  (when --document-private-items)
diff --git a/tests/rustdoc/inline_cross/assoc-const-equality.rs b/tests/rustdoc/inline_cross/assoc-const-equality.rs
index 89ed808de62..cdf74389e76 100644
--- a/tests/rustdoc/inline_cross/assoc-const-equality.rs
+++ b/tests/rustdoc/inline_cross/assoc-const-equality.rs
@@ -1,5 +1,6 @@
 //@ aux-crate:assoc_const_equality=assoc-const-equality.rs
 //@ edition:2021
+//@ ignore-test (FIXME: #125092)
 
 #![crate_name = "user"]
 
diff --git a/tests/rustdoc/private-non-local-fields-2.rs b/tests/rustdoc/private-non-local-fields-2.rs
new file mode 100644
index 00000000000..615b957f697
--- /dev/null
+++ b/tests/rustdoc/private-non-local-fields-2.rs
@@ -0,0 +1,11 @@
+//! This test makes sure that with never show the inner fields in the
+//! aliased type view of type alias.
+
+//@ compile-flags: -Z unstable-options --document-private-items
+
+#![crate_name = "foo"]
+
+use std::collections::BTreeMap;
+
+// @has 'foo/type.FooBar.html' '//*[@class="rust item-decl"]/code' 'struct FooBar { /* private fields */ }'
+pub type FooBar = BTreeMap<u32, String>;
diff --git a/tests/rustdoc/private-non-local-fields.rs b/tests/rustdoc/private-non-local-fields.rs
new file mode 100644
index 00000000000..7922ce074dd
--- /dev/null
+++ b/tests/rustdoc/private-non-local-fields.rs
@@ -0,0 +1,9 @@
+//! This test makes sure that with never show the inner fields in the
+//! aliased type view of type alias.
+
+#![crate_name = "foo"]
+
+use std::collections::BTreeMap;
+
+// @has 'foo/type.FooBar.html' '//*[@class="rust item-decl"]/code' 'struct FooBar { /* private fields */ }'
+pub type FooBar = BTreeMap<u32, String>;
diff --git a/tests/ui/abi/extern/auxiliary/extern-crosscrate-source.rs b/tests/ui/abi/extern/auxiliary/extern-crosscrate-source.rs
index 9c61518b941..6b218771096 100644
--- a/tests/ui/abi/extern/auxiliary/extern-crosscrate-source.rs
+++ b/tests/ui/abi/extern/auxiliary/extern-crosscrate-source.rs
@@ -1,28 +1,21 @@
 #![crate_name = "externcallback"]
 #![crate_type = "lib"]
-#![feature(rustc_private)]
 
-extern crate libc;
-
-pub mod rustrt {
-    extern crate libc;
-
-    #[link(name = "rust_test_helpers", kind = "static")]
-    extern "C" {
-        pub fn rust_dbg_call(
-            cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t,
-            data: libc::uintptr_t,
-        ) -> libc::uintptr_t;
-    }
+#[link(name = "rust_test_helpers", kind = "static")]
+extern "C" {
+    pub fn rust_dbg_call(
+        cb: extern "C" fn(u64) -> u64,
+        data: u64,
+    ) -> u64;
 }
 
-pub fn fact(n: libc::uintptr_t) -> libc::uintptr_t {
+pub fn fact(n: u64) -> u64 {
     unsafe {
         println!("n = {}", n);
-        rustrt::rust_dbg_call(cb, n)
+        rust_dbg_call(cb, n)
     }
 }
 
-pub extern "C" fn cb(data: libc::uintptr_t) -> libc::uintptr_t {
+pub extern "C" fn cb(data: u64) -> u64 {
     if data == 1 { data } else { fact(data - 1) * data }
 }
diff --git a/tests/ui/abi/extern/extern-call-deep.rs b/tests/ui/abi/extern/extern-call-deep.rs
index 062e70b1b6e..40457ae5720 100644
--- a/tests/ui/abi/extern/extern-call-deep.rs
+++ b/tests/ui/abi/extern/extern-call-deep.rs
@@ -1,35 +1,27 @@
 //@ run-pass
 //@ ignore-emscripten blows the JS stack
 
-#![feature(rustc_private)]
-
-extern crate libc;
-
-mod rustrt {
-    extern crate libc;
-
-    #[link(name = "rust_test_helpers", kind = "static")]
-    extern "C" {
-        pub fn rust_dbg_call(
-            cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t,
-            data: libc::uintptr_t,
-        ) -> libc::uintptr_t;
-    }
+#[link(name = "rust_test_helpers", kind = "static")]
+extern "C" {
+    pub fn rust_dbg_call(
+        cb: extern "C" fn(u64) -> u64,
+        data: u64,
+    ) -> u64;
 }
 
-extern "C" fn cb(data: libc::uintptr_t) -> libc::uintptr_t {
+extern "C" fn cb(data: u64) -> u64 {
     if data == 1 { data } else { count(data - 1) + 1 }
 }
 
-fn count(n: libc::uintptr_t) -> libc::uintptr_t {
+fn count(n: u64) -> u64 {
     unsafe {
         println!("n = {}", n);
-        rustrt::rust_dbg_call(cb, n)
+        rust_dbg_call(cb, n)
     }
 }
 
 pub fn main() {
     let result = count(1000);
-    println!("result = {}", result);
+    println!("result = {:?}", result);
     assert_eq!(result, 1000);
 }
diff --git a/tests/ui/abi/extern/extern-call-deep2.rs b/tests/ui/abi/extern/extern-call-deep2.rs
index c021bc22348..91ca28d80c8 100644
--- a/tests/ui/abi/extern/extern-call-deep2.rs
+++ b/tests/ui/abi/extern/extern-call-deep2.rs
@@ -1,31 +1,24 @@
 //@ run-pass
-#![allow(unused_must_use)]
 //@ needs-threads
-#![feature(rustc_private)]
 
-extern crate libc;
 use std::thread;
 
-mod rustrt {
-    extern crate libc;
-
-    #[link(name = "rust_test_helpers", kind = "static")]
-    extern "C" {
-        pub fn rust_dbg_call(
-            cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t,
-            data: libc::uintptr_t,
-        ) -> libc::uintptr_t;
-    }
+#[link(name = "rust_test_helpers", kind = "static")]
+extern "C" {
+    pub fn rust_dbg_call(
+        cb: extern "C" fn(u64) -> u64,
+        data: u64,
+    ) -> u64;
 }
 
-extern "C" fn cb(data: libc::uintptr_t) -> libc::uintptr_t {
-    if data == 1 { data } else { count(data - 1) + 1 }
+extern "C" fn cb(data: u64) -> u64 {
+    if data == 1 { data } else { count(data - 1 ) + 1 }
 }
 
-fn count(n: libc::uintptr_t) -> libc::uintptr_t {
+fn count(n: u64) -> u64 {
     unsafe {
         println!("n = {}", n);
-        rustrt::rust_dbg_call(cb, n)
+        rust_dbg_call(cb, n)
     }
 }
 
@@ -37,5 +30,5 @@ pub fn main() {
         println!("result = {}", result);
         assert_eq!(result, 1000);
     })
-    .join();
+    .join().unwrap();
 }
diff --git a/tests/ui/abi/extern/extern-call-indirect.rs b/tests/ui/abi/extern/extern-call-indirect.rs
index 18fb07d8c8b..ef1e8ae5e76 100644
--- a/tests/ui/abi/extern/extern-call-indirect.rs
+++ b/tests/ui/abi/extern/extern-call-indirect.rs
@@ -1,29 +1,21 @@
 //@ run-pass
 
-#![feature(rustc_private)]
-
-extern crate libc;
-
-mod rustrt {
-    extern crate libc;
-
-    #[link(name = "rust_test_helpers", kind = "static")]
-    extern "C" {
-        pub fn rust_dbg_call(
-            cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t,
-            data: libc::uintptr_t,
-        ) -> libc::uintptr_t;
-    }
+#[link(name = "rust_test_helpers", kind = "static")]
+extern "C" {
+    pub fn rust_dbg_call(
+        cb: extern "C" fn(u64) -> u64,
+        data: u64,
+    ) -> u64;
 }
 
-extern "C" fn cb(data: libc::uintptr_t) -> libc::uintptr_t {
+extern "C" fn cb(data: u64) -> u64 {
     if data == 1 { data } else { fact(data - 1) * data }
 }
 
-fn fact(n: libc::uintptr_t) -> libc::uintptr_t {
+fn fact(n: u64) -> u64 {
     unsafe {
         println!("n = {}", n);
-        rustrt::rust_dbg_call(cb, n)
+        rust_dbg_call(cb, n)
     }
 }
 
diff --git a/tests/ui/abi/extern/extern-call-scrub.rs b/tests/ui/abi/extern/extern-call-scrub.rs
index 7edf8975ad8..7df3a8f04ef 100644
--- a/tests/ui/abi/extern/extern-call-scrub.rs
+++ b/tests/ui/abi/extern/extern-call-scrub.rs
@@ -1,35 +1,27 @@
 //@ run-pass
-#![allow(unused_must_use)]
+//@ needs-threads
 // This time we're testing repeatedly going up and down both stacks to
 // make sure the stack pointers are maintained properly in both
 // directions
 
-//@ needs-threads
-#![feature(rustc_private)]
-
-extern crate libc;
 use std::thread;
 
-mod rustrt {
-    extern crate libc;
-
-    #[link(name = "rust_test_helpers", kind = "static")]
-    extern "C" {
-        pub fn rust_dbg_call(
-            cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t,
-            data: libc::uintptr_t,
-        ) -> libc::uintptr_t;
-    }
+#[link(name = "rust_test_helpers", kind = "static")]
+extern "C" {
+    pub fn rust_dbg_call(
+        cb: extern "C" fn(u64) -> u64,
+        data: u64,
+    ) -> u64;
 }
 
-extern "C" fn cb(data: libc::uintptr_t) -> libc::uintptr_t {
+extern "C" fn cb(data: u64) -> u64 {
     if data == 1 { data } else { count(data - 1) + count(data - 1) }
 }
 
-fn count(n: libc::uintptr_t) -> libc::uintptr_t {
+fn count(n: u64) -> u64 {
     unsafe {
         println!("n = {}", n);
-        rustrt::rust_dbg_call(cb, n)
+        rust_dbg_call(cb, n)
     }
 }
 
@@ -41,5 +33,5 @@ pub fn main() {
         println!("result = {}", result);
         assert_eq!(result, 2048);
     })
-    .join();
+    .join().unwrap();
 }
diff --git a/tests/ui/abi/extern/extern-crosscrate.rs b/tests/ui/abi/extern/extern-crosscrate.rs
index c283cbe3216..b467d992984 100644
--- a/tests/ui/abi/extern/extern-crosscrate.rs
+++ b/tests/ui/abi/extern/extern-crosscrate.rs
@@ -1,15 +1,12 @@
 //@ run-pass
 //@ aux-build:extern-crosscrate-source.rs
 
-#![feature(rustc_private)]
-
 extern crate externcallback;
-extern crate libc;
 
-fn fact(n: libc::uintptr_t) -> libc::uintptr_t {
+fn fact(n: u64) -> u64 {
     unsafe {
-        println!("n = {}", n);
-        externcallback::rustrt::rust_dbg_call(externcallback::cb, n)
+        println!("n = {:?}", n);
+        externcallback::rust_dbg_call(externcallback::cb, n)
     }
 }
 
diff --git a/tests/ui/abi/foreign/foreign-call-no-runtime.rs b/tests/ui/abi/foreign/foreign-call-no-runtime.rs
deleted file mode 100644
index fccd62b6100..00000000000
--- a/tests/ui/abi/foreign/foreign-call-no-runtime.rs
+++ /dev/null
@@ -1,60 +0,0 @@
-//@ run-pass
-//@ needs-threads
-
-#![feature(rustc_private)]
-
-extern crate libc;
-
-use std::mem;
-use std::thread;
-
-#[link(name = "rust_test_helpers", kind = "static")]
-extern "C" {
-    fn rust_dbg_call(cb: extern "C" fn(libc::uintptr_t), data: libc::uintptr_t) -> libc::uintptr_t;
-}
-
-pub fn main() {
-    unsafe {
-        thread::spawn(move || {
-            let i: isize = 100;
-            rust_dbg_call(callback_isize, mem::transmute(&i));
-        })
-        .join()
-        .unwrap();
-
-        thread::spawn(move || {
-            let i: i32 = 100;
-            rust_dbg_call(callback_i32, mem::transmute(&i));
-        })
-        .join()
-        .unwrap();
-
-        thread::spawn(move || {
-            let i: i64 = 100;
-            rust_dbg_call(callback_i64, mem::transmute(&i));
-        })
-        .join()
-        .unwrap();
-    }
-}
-
-extern "C" fn callback_isize(data: libc::uintptr_t) {
-    unsafe {
-        let data = data as *const isize;
-        assert_eq!(*data, 100);
-    }
-}
-
-extern "C" fn callback_i64(data: libc::uintptr_t) {
-    unsafe {
-        let data = data as *const i64;
-        assert_eq!(*data, 100);
-    }
-}
-
-extern "C" fn callback_i32(data: libc::uintptr_t) {
-    unsafe {
-        let data = data as *const i32;
-        assert_eq!(*data, 100);
-    }
-}
diff --git a/tests/ui/associated-consts/issue-105330.rs b/tests/ui/associated-consts/issue-105330.rs
index fb2169ab43f..959bb4fe7ac 100644
--- a/tests/ui/associated-consts/issue-105330.rs
+++ b/tests/ui/associated-consts/issue-105330.rs
@@ -11,7 +11,6 @@ impl TraitWAssocConst for impl Demo { //~ ERROR E0404
 fn foo<A: TraitWAssocConst<A=32>>() { //~ ERROR E0658
     foo::<Demo>()();
     //~^ ERROR is not satisfied
-    //~| ERROR type mismatch
     //~| ERROR expected function, found `()`
 }
 
@@ -19,6 +18,5 @@ fn main<A: TraitWAssocConst<A=32>>() {
     //~^ ERROR E0658
     //~| ERROR E0131
     foo::<Demo>();
-    //~^ ERROR type mismatch
-    //~| ERROR is not satisfied
+    //~^ ERROR is not satisfied
 }
diff --git a/tests/ui/associated-consts/issue-105330.stderr b/tests/ui/associated-consts/issue-105330.stderr
index bde3675b48c..72527193555 100644
--- a/tests/ui/associated-consts/issue-105330.stderr
+++ b/tests/ui/associated-consts/issue-105330.stderr
@@ -26,7 +26,7 @@ LL | fn foo<A: TraitWAssocConst<A=32>>() {
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: associated const equality is incomplete
-  --> $DIR/issue-105330.rs:18:29
+  --> $DIR/issue-105330.rs:17:29
    |
 LL | fn main<A: TraitWAssocConst<A=32>>() {
    |                             ^^^^
@@ -44,7 +44,7 @@ LL | impl TraitWAssocConst for impl Demo {
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
 
 error[E0131]: `main` function is not allowed to have generic parameters
-  --> $DIR/issue-105330.rs:18:8
+  --> $DIR/issue-105330.rs:17:8
    |
 LL | fn main<A: TraitWAssocConst<A=32>>() {
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `main` cannot have generic parameters
@@ -61,20 +61,6 @@ note: required by a bound in `foo`
 LL | fn foo<A: TraitWAssocConst<A=32>>() {
    |           ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo`
 
-error[E0271]: type mismatch resolving `<Demo as TraitWAssocConst>::A == 32`
-  --> $DIR/issue-105330.rs:12:11
-   |
-LL |     foo::<Demo>()();
-   |           ^^^^ expected `32`, found `<Demo as TraitWAssocConst>::A`
-   |
-   = note: expected constant `32`
-              found constant `<Demo as TraitWAssocConst>::A`
-note: required by a bound in `foo`
-  --> $DIR/issue-105330.rs:11:28
-   |
-LL | fn foo<A: TraitWAssocConst<A=32>>() {
-   |                            ^^^^ required by this bound in `foo`
-
 error[E0618]: expected function, found `()`
   --> $DIR/issue-105330.rs:12:5
    |
@@ -86,7 +72,7 @@ LL |     foo::<Demo>()();
    |     call expression requires function
 
 error[E0277]: the trait bound `Demo: TraitWAssocConst` is not satisfied
-  --> $DIR/issue-105330.rs:21:11
+  --> $DIR/issue-105330.rs:20:11
    |
 LL |     foo::<Demo>();
    |           ^^^^ the trait `TraitWAssocConst` is not implemented for `Demo`
@@ -97,21 +83,7 @@ note: required by a bound in `foo`
 LL | fn foo<A: TraitWAssocConst<A=32>>() {
    |           ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo`
 
-error[E0271]: type mismatch resolving `<Demo as TraitWAssocConst>::A == 32`
-  --> $DIR/issue-105330.rs:21:11
-   |
-LL |     foo::<Demo>();
-   |           ^^^^ expected `32`, found `<Demo as TraitWAssocConst>::A`
-   |
-   = note: expected constant `32`
-              found constant `<Demo as TraitWAssocConst>::A`
-note: required by a bound in `foo`
-  --> $DIR/issue-105330.rs:11:28
-   |
-LL | fn foo<A: TraitWAssocConst<A=32>>() {
-   |                            ^^^^ required by this bound in `foo`
-
-error: aborting due to 11 previous errors
+error: aborting due to 9 previous errors
 
-Some errors have detailed explanations: E0131, E0271, E0277, E0404, E0562, E0618, E0658.
+Some errors have detailed explanations: E0131, E0277, E0404, E0562, E0618, E0658.
 For more information about an error, try `rustc --explain E0131`.
diff --git a/tests/ui/async-await/async-closures/ambiguous-arg.rs b/tests/ui/async-await/async-closures/ambiguous-arg.rs
new file mode 100644
index 00000000000..d76a1cf953e
--- /dev/null
+++ b/tests/ui/async-await/async-closures/ambiguous-arg.rs
@@ -0,0 +1,15 @@
+//@ edition:2021
+
+// Regression test for #123901. We previously ICE'd as we silently
+// swallowed an in the `ExprUseVisitor`.
+
+#![feature(async_closure)]
+
+pub fn test(test: &u64, temp: &u64) {
+    async |check, a, b| {
+        //~^ ERROR type annotations needed
+        temp.abs_diff(12);
+    };
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/async-closures/ambiguous-arg.stderr b/tests/ui/async-await/async-closures/ambiguous-arg.stderr
new file mode 100644
index 00000000000..01f72e94ecc
--- /dev/null
+++ b/tests/ui/async-await/async-closures/ambiguous-arg.stderr
@@ -0,0 +1,13 @@
+error[E0282]: type annotations needed
+  --> $DIR/ambiguous-arg.rs:9:25
+   |
+LL |       async |check, a, b| {
+   |  _________________________^
+LL | |
+LL | |         temp.abs_diff(12);
+LL | |     };
+   | |_____^ cannot infer type
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/cast/ice-cast-type-with-error-124848.rs b/tests/ui/cast/ice-cast-type-with-error-124848.rs
new file mode 100644
index 00000000000..9b3732b02db
--- /dev/null
+++ b/tests/ui/cast/ice-cast-type-with-error-124848.rs
@@ -0,0 +1,18 @@
+// Regression test for ICE #124848
+// Tests that there is no ICE when a cast
+// involves a type with error
+
+use std::cell::Cell;
+
+struct MyType<'a>(Cell<Option<&'unpinned mut MyType<'a>>>, Pin);
+//~^ ERROR use of undeclared lifetime name `'unpinned`
+//~| ERROR cannot find type `Pin` in this scope
+
+fn main() {
+    let mut unpinned = MyType(Cell::new(None));
+    //~^ ERROR his struct takes 2 arguments but 1 argument was supplied
+    let bad_addr = &unpinned as *const Cell<Option<&'a mut MyType<'a>>> as usize;
+    //~^ ERROR use of undeclared lifetime name `'a`
+    //~| ERROR use of undeclared lifetime name `'a`
+    //~| ERROR casting `&MyType<'_>` as `*const Cell<Option<&mut MyType<'_>>>` is invalid
+}
diff --git a/tests/ui/cast/ice-cast-type-with-error-124848.stderr b/tests/ui/cast/ice-cast-type-with-error-124848.stderr
new file mode 100644
index 00000000000..2d86bf76d11
--- /dev/null
+++ b/tests/ui/cast/ice-cast-type-with-error-124848.stderr
@@ -0,0 +1,63 @@
+error[E0261]: use of undeclared lifetime name `'unpinned`
+  --> $DIR/ice-cast-type-with-error-124848.rs:7:32
+   |
+LL | struct MyType<'a>(Cell<Option<&'unpinned mut MyType<'a>>>, Pin);
+   |               -                ^^^^^^^^^ undeclared lifetime
+   |               |
+   |               help: consider introducing lifetime `'unpinned` here: `'unpinned,`
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/ice-cast-type-with-error-124848.rs:14:53
+   |
+LL | fn main() {
+   |        - help: consider introducing lifetime `'a` here: `<'a>`
+...
+LL |     let bad_addr = &unpinned as *const Cell<Option<&'a mut MyType<'a>>> as usize;
+   |                                                     ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/ice-cast-type-with-error-124848.rs:14:67
+   |
+LL | fn main() {
+   |        - help: consider introducing lifetime `'a` here: `<'a>`
+...
+LL |     let bad_addr = &unpinned as *const Cell<Option<&'a mut MyType<'a>>> as usize;
+   |                                                                   ^^ undeclared lifetime
+
+error[E0412]: cannot find type `Pin` in this scope
+  --> $DIR/ice-cast-type-with-error-124848.rs:7:60
+   |
+LL | struct MyType<'a>(Cell<Option<&'unpinned mut MyType<'a>>>, Pin);
+   |                                                            ^^^ not found in this scope
+   |
+help: consider importing this struct
+   |
+LL + use std::pin::Pin;
+   |
+
+error[E0061]: this struct takes 2 arguments but 1 argument was supplied
+  --> $DIR/ice-cast-type-with-error-124848.rs:12:24
+   |
+LL |     let mut unpinned = MyType(Cell::new(None));
+   |                        ^^^^^^----------------- an argument is missing
+   |
+note: tuple struct defined here
+  --> $DIR/ice-cast-type-with-error-124848.rs:7:8
+   |
+LL | struct MyType<'a>(Cell<Option<&'unpinned mut MyType<'a>>>, Pin);
+   |        ^^^^^^
+help: provide the argument
+   |
+LL |     let mut unpinned = MyType(Cell::new(None), /* value */);
+   |                              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0606]: casting `&MyType<'_>` as `*const Cell<Option<&mut MyType<'_>>>` is invalid
+  --> $DIR/ice-cast-type-with-error-124848.rs:14:20
+   |
+LL |     let bad_addr = &unpinned as *const Cell<Option<&'a mut MyType<'a>>> as usize;
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0061, E0261, E0412, E0606.
+For more information about an error, try `rustc --explain E0061`.
diff --git a/tests/ui/coercion/pin-dyn-dispatch-sound.rs b/tests/ui/coercion/pin-dyn-dispatch-sound.rs
new file mode 100644
index 00000000000..b9d43ebac8b
--- /dev/null
+++ b/tests/ui/coercion/pin-dyn-dispatch-sound.rs
@@ -0,0 +1,19 @@
+use std::marker::PhantomPinned;
+use std::pin::Pin;
+
+trait MyUnpinTrait {
+    fn into_pinned_type(self: Pin<&mut Self>) -> Pin<&mut PhantomPinned>;
+}
+impl MyUnpinTrait for PhantomPinned {
+    fn into_pinned_type(self: Pin<&mut Self>) -> Pin<&mut PhantomPinned> {
+        self
+    }
+}
+impl Unpin for dyn MyUnpinTrait {} //~ ERROR E0321
+
+// It would be unsound for this function to compile.
+fn pin_it(not_yet_pinned: &mut PhantomPinned) -> Pin<&mut PhantomPinned> {
+    Pin::new(not_yet_pinned as &mut dyn MyUnpinTrait).into_pinned_type()
+}
+
+fn main() {}
diff --git a/tests/ui/coercion/pin-dyn-dispatch-sound.stderr b/tests/ui/coercion/pin-dyn-dispatch-sound.stderr
new file mode 100644
index 00000000000..45860bfcfc7
--- /dev/null
+++ b/tests/ui/coercion/pin-dyn-dispatch-sound.stderr
@@ -0,0 +1,9 @@
+error[E0321]: cross-crate traits with a default impl, like `Unpin`, can only be implemented for a struct/enum type, not `(dyn MyUnpinTrait + 'static)`
+  --> $DIR/pin-dyn-dispatch-sound.rs:12:1
+   |
+LL | impl Unpin for dyn MyUnpinTrait {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0321`.
diff --git a/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr b/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr
index f8bed86ccf5..a26c617dc93 100644
--- a/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr
@@ -1,19 +1,33 @@
 error: implementation of `Trait` is not general enough
   --> $DIR/issue-59311.rs:17:5
    |
-LL |     v.t(|| {});
-   |     ^^^^^^^^^^ implementation of `Trait` is not general enough
+LL | / pub fn crash<V>(v: &V)
+LL | | where
+LL | |     for<'a> &'a V: Trait + 'static,
+   | |____________________-----__________- due to a where-clause on `crash`...
+   |                      |
+   |                      doesn't satisfy where-clause
+LL |   {
+LL |       v.t(|| {});
+   |       ^^^^^^^^^^
    |
-   = note: `Trait` would have to be implemented for the type `&'a V`
+   = note: ...`Trait` would have to be implemented for the type `&'a V`
    = note: ...but `Trait` is actually implemented for the type `&'0 V`, for some specific lifetime `'0`
 
 error: implementation of `Trait` is not general enough
   --> $DIR/issue-59311.rs:17:5
    |
-LL |     v.t(|| {});
-   |     ^^^^^^^^^^ implementation of `Trait` is not general enough
+LL | / pub fn crash<V>(v: &V)
+LL | | where
+LL | |     for<'a> &'a V: Trait + 'static,
+   | |____________________-----__________- due to a where-clause on `crash`...
+   |                      |
+   |                      doesn't satisfy where-clause
+LL |   {
+LL |       v.t(|| {});
+   |       ^^^^^^^^^^
    |
-   = note: `Trait` would have to be implemented for the type `&'a V`
+   = note: ...`Trait` would have to be implemented for the type `&'a V`
    = note: ...but `Trait` is actually implemented for the type `&'0 V`, for some specific lifetime `'0`
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
diff --git a/tests/ui/higher-ranked/trait-bounds/trivial-does-not-hold.rs b/tests/ui/higher-ranked/trait-bounds/trivial-does-not-hold.rs
new file mode 100644
index 00000000000..fa76686cc8b
--- /dev/null
+++ b/tests/ui/higher-ranked/trait-bounds/trivial-does-not-hold.rs
@@ -0,0 +1,11 @@
+// Minimized test from #59311.
+
+pub fn crash()
+where
+    for<'a> &'a (): 'static,
+{
+    || {};
+    //~^ ERROR higher-ranked lifetime error
+}
+
+fn main() {}
diff --git a/tests/ui/higher-ranked/trait-bounds/trivial-does-not-hold.stderr b/tests/ui/higher-ranked/trait-bounds/trivial-does-not-hold.stderr
new file mode 100644
index 00000000000..9e0d7e4b7be
--- /dev/null
+++ b/tests/ui/higher-ranked/trait-bounds/trivial-does-not-hold.stderr
@@ -0,0 +1,10 @@
+error: higher-ranked lifetime error
+  --> $DIR/trivial-does-not-hold.rs:7:5
+   |
+LL |     || {};
+   |     ^^^^^
+   |
+   = note: could not prove `for<'a> &'a (): 'b`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/impl-trait/precise-capturing/apit.stderr b/tests/ui/impl-trait/precise-capturing/apit.stderr
index 36bf80d9e2f..96548f5732f 100644
--- a/tests/ui/impl-trait/precise-capturing/apit.stderr
+++ b/tests/ui/impl-trait/precise-capturing/apit.stderr
@@ -11,7 +11,7 @@ error: `use<...>` precise capturing syntax not allowed on argument-position `imp
   --> $DIR/apit.rs:4:18
    |
 LL | fn hello(_: impl use<> Sized) {}
-   |                  ^^^
+   |                  ^^^^^
 
 error: aborting due to 1 previous error; 1 warning emitted
 
diff --git a/tests/ui/impl-trait/precise-capturing/overcaptures-2024.fixed b/tests/ui/impl-trait/precise-capturing/overcaptures-2024.fixed
new file mode 100644
index 00000000000..014ab23e4eb
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/overcaptures-2024.fixed
@@ -0,0 +1,29 @@
+//@ run-rustfix
+
+#![feature(precise_capturing)]
+#![allow(unused, incomplete_features)]
+#![deny(impl_trait_overcaptures)]
+
+fn named<'a>(x: &'a i32) -> impl use<> Sized { *x }
+//~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024
+
+fn implicit(x: &i32) -> impl use<> Sized { *x }
+//~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024
+
+struct W;
+impl W {
+    fn hello(&self, x: &i32) -> impl use<'_> Sized + '_ { self }
+    //~^ ERROR `impl Sized + '_` will capture more lifetimes than possibly intended in edition 2024
+}
+
+trait Higher<'a> {
+    type Output;
+}
+impl Higher<'_> for () {
+    type Output = ();
+}
+
+fn hrtb() -> impl for<'a> Higher<'a, Output = impl use<> Sized> {}
+//~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024
+
+fn main() {}
diff --git a/tests/ui/impl-trait/precise-capturing/overcaptures-2024.rs b/tests/ui/impl-trait/precise-capturing/overcaptures-2024.rs
new file mode 100644
index 00000000000..e4b7828d60f
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/overcaptures-2024.rs
@@ -0,0 +1,29 @@
+//@ run-rustfix
+
+#![feature(precise_capturing)]
+#![allow(unused, incomplete_features)]
+#![deny(impl_trait_overcaptures)]
+
+fn named<'a>(x: &'a i32) -> impl Sized { *x }
+//~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024
+
+fn implicit(x: &i32) -> impl Sized { *x }
+//~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024
+
+struct W;
+impl W {
+    fn hello(&self, x: &i32) -> impl Sized + '_ { self }
+    //~^ ERROR `impl Sized + '_` will capture more lifetimes than possibly intended in edition 2024
+}
+
+trait Higher<'a> {
+    type Output;
+}
+impl Higher<'_> for () {
+    type Output = ();
+}
+
+fn hrtb() -> impl for<'a> Higher<'a, Output = impl Sized> {}
+//~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024
+
+fn main() {}
diff --git a/tests/ui/impl-trait/precise-capturing/overcaptures-2024.stderr b/tests/ui/impl-trait/precise-capturing/overcaptures-2024.stderr
new file mode 100644
index 00000000000..16cb8b7e94b
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/overcaptures-2024.stderr
@@ -0,0 +1,75 @@
+error: `impl Sized` will capture more lifetimes than possibly intended in edition 2024
+  --> $DIR/overcaptures-2024.rs:7:29
+   |
+LL | fn named<'a>(x: &'a i32) -> impl Sized { *x }
+   |                             ^^^^^^^^^^
+   |
+note: specifically, this lifetime is in scope but not mentioned in the type's bounds
+  --> $DIR/overcaptures-2024.rs:7:10
+   |
+LL | fn named<'a>(x: &'a i32) -> impl Sized { *x }
+   |          ^^
+   = note: all lifetimes in scope will be captured by `impl Trait`s in edition 2024
+note: the lint level is defined here
+  --> $DIR/overcaptures-2024.rs:5:9
+   |
+LL | #![deny(impl_trait_overcaptures)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+help: use the precise capturing `use<...>` syntax to make the captures explicit
+   |
+LL | fn named<'a>(x: &'a i32) -> impl use<> Sized { *x }
+   |                                  +++++
+
+error: `impl Sized` will capture more lifetimes than possibly intended in edition 2024
+  --> $DIR/overcaptures-2024.rs:10:25
+   |
+LL | fn implicit(x: &i32) -> impl Sized { *x }
+   |                         ^^^^^^^^^^
+   |
+note: specifically, this lifetime is in scope but not mentioned in the type's bounds
+  --> $DIR/overcaptures-2024.rs:10:16
+   |
+LL | fn implicit(x: &i32) -> impl Sized { *x }
+   |                ^
+   = note: all lifetimes in scope will be captured by `impl Trait`s in edition 2024
+help: use the precise capturing `use<...>` syntax to make the captures explicit
+   |
+LL | fn implicit(x: &i32) -> impl use<> Sized { *x }
+   |                              +++++
+
+error: `impl Sized + '_` will capture more lifetimes than possibly intended in edition 2024
+  --> $DIR/overcaptures-2024.rs:15:33
+   |
+LL |     fn hello(&self, x: &i32) -> impl Sized + '_ { self }
+   |                                 ^^^^^^^^^^^^^^^
+   |
+note: specifically, this lifetime is in scope but not mentioned in the type's bounds
+  --> $DIR/overcaptures-2024.rs:15:24
+   |
+LL |     fn hello(&self, x: &i32) -> impl Sized + '_ { self }
+   |                        ^
+   = note: all lifetimes in scope will be captured by `impl Trait`s in edition 2024
+help: use the precise capturing `use<...>` syntax to make the captures explicit
+   |
+LL |     fn hello(&self, x: &i32) -> impl use<'_> Sized + '_ { self }
+   |                                      +++++++
+
+error: `impl Sized` will capture more lifetimes than possibly intended in edition 2024
+  --> $DIR/overcaptures-2024.rs:26:47
+   |
+LL | fn hrtb() -> impl for<'a> Higher<'a, Output = impl Sized> {}
+   |                                               ^^^^^^^^^^
+   |
+note: specifically, this lifetime is in scope but not mentioned in the type's bounds
+  --> $DIR/overcaptures-2024.rs:26:23
+   |
+LL | fn hrtb() -> impl for<'a> Higher<'a, Output = impl Sized> {}
+   |                       ^^
+   = note: all lifetimes in scope will be captured by `impl Trait`s in edition 2024
+help: use the precise capturing `use<...>` syntax to make the captures explicit
+   |
+LL | fn hrtb() -> impl for<'a> Higher<'a, Output = impl use<> Sized> {}
+   |                                                    +++++
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/impl-trait/precise-capturing/redundant.rs b/tests/ui/impl-trait/precise-capturing/redundant.rs
new file mode 100644
index 00000000000..108a4cb64aa
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/redundant.rs
@@ -0,0 +1,25 @@
+//@ compile-flags: -Zunstable-options --edition=2024
+//@ check-pass
+
+#![feature(precise_capturing)]
+//~^ WARN the feature `precise_capturing` is incomplete
+
+fn hello<'a>() -> impl use<'a> Sized {}
+//~^ WARN all possible in-scope parameters are already captured
+
+struct Inherent;
+impl Inherent {
+    fn inherent(&self) -> impl use<'_> Sized {}
+    //~^ WARN all possible in-scope parameters are already captured
+}
+
+trait Test<'a> {
+    fn in_trait() -> impl use<'a, Self> Sized;
+    //~^ WARN all possible in-scope parameters are already captured
+}
+impl<'a> Test<'a> for () {
+    fn in_trait() -> impl use<'a> Sized {}
+    //~^ WARN all possible in-scope parameters are already captured
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/precise-capturing/redundant.stderr b/tests/ui/impl-trait/precise-capturing/redundant.stderr
new file mode 100644
index 00000000000..325f04d3536
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/redundant.stderr
@@ -0,0 +1,45 @@
+warning: the feature `precise_capturing` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/redundant.rs:4:12
+   |
+LL | #![feature(precise_capturing)]
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #123432 <https://github.com/rust-lang/rust/issues/123432> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
+  --> $DIR/redundant.rs:7:19
+   |
+LL | fn hello<'a>() -> impl use<'a> Sized {}
+   |                   ^^^^^-------^^^^^^
+   |                        |
+   |                        help: remove the `use<...>` syntax
+   |
+   = note: `#[warn(impl_trait_redundant_captures)]` on by default
+
+warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
+  --> $DIR/redundant.rs:12:27
+   |
+LL |     fn inherent(&self) -> impl use<'_> Sized {}
+   |                           ^^^^^-------^^^^^^
+   |                                |
+   |                                help: remove the `use<...>` syntax
+
+warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
+  --> $DIR/redundant.rs:17:22
+   |
+LL |     fn in_trait() -> impl use<'a, Self> Sized;
+   |                      ^^^^^-------------^^^^^^
+   |                           |
+   |                           help: remove the `use<...>` syntax
+
+warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
+  --> $DIR/redundant.rs:21:22
+   |
+LL |     fn in_trait() -> impl use<'a> Sized {}
+   |                      ^^^^^-------^^^^^^
+   |                           |
+   |                           help: remove the `use<...>` syntax
+
+warning: 5 warnings emitted
+
diff --git a/tests/ui/lint/lint-unnecessary-parens.fixed b/tests/ui/lint/lint-unnecessary-parens.fixed
index 973bbd70f25..760897c5143 100644
--- a/tests/ui/lint/lint-unnecessary-parens.fixed
+++ b/tests/ui/lint/lint-unnecessary-parens.fixed
@@ -46,6 +46,28 @@ pub fn parens_with_keyword(e: &[()]) -> i32 {
 macro_rules! baz {
     ($($foo:expr),+) => {
         ($($foo),*)
+    };
+}
+
+macro_rules! unit {
+    () => {
+        ()
+    };
+}
+
+struct One;
+
+impl std::ops::Sub<One> for () {
+    type Output = i32;
+    fn sub(self, _: One) -> Self::Output {
+        -1
+    }
+}
+
+impl std::ops::Neg for One {
+    type Output = i32;
+    fn neg(self) -> Self::Output {
+        -1
     }
 }
 
@@ -94,4 +116,13 @@ fn main() {
 
     let _a = baz!(3, 4);
     let _b = baz!(3);
+
+    let _ = {
+        unit!() - One //~ ERROR unnecessary parentheses around block return value
+    } + {
+        unit![] - One //~ ERROR unnecessary parentheses around block return value
+    } + {
+        // FIXME: false positive. This parenthesis is required.
+        unit! {} - One //~ ERROR unnecessary parentheses around block return value
+    };
 }
diff --git a/tests/ui/lint/lint-unnecessary-parens.rs b/tests/ui/lint/lint-unnecessary-parens.rs
index 40cd61fcc2c..7cbaac8ae54 100644
--- a/tests/ui/lint/lint-unnecessary-parens.rs
+++ b/tests/ui/lint/lint-unnecessary-parens.rs
@@ -46,6 +46,28 @@ pub fn parens_with_keyword(e: &[()]) -> i32 {
 macro_rules! baz {
     ($($foo:expr),+) => {
         ($($foo),*)
+    };
+}
+
+macro_rules! unit {
+    () => {
+        ()
+    };
+}
+
+struct One;
+
+impl std::ops::Sub<One> for () {
+    type Output = i32;
+    fn sub(self, _: One) -> Self::Output {
+        -1
+    }
+}
+
+impl std::ops::Neg for One {
+    type Output = i32;
+    fn neg(self) -> Self::Output {
+        -1
     }
 }
 
@@ -94,4 +116,13 @@ fn main() {
 
     let _a = baz!(3, 4);
     let _b = baz!(3);
+
+    let _ = {
+        (unit!() - One) //~ ERROR unnecessary parentheses around block return value
+    } + {
+        (unit![] - One) //~ ERROR unnecessary parentheses around block return value
+    } + {
+        // FIXME: false positive. This parenthesis is required.
+        (unit! {} - One) //~ ERROR unnecessary parentheses around block return value
+    };
 }
diff --git a/tests/ui/lint/lint-unnecessary-parens.stderr b/tests/ui/lint/lint-unnecessary-parens.stderr
index ba7a78b8da1..755dd5fc309 100644
--- a/tests/ui/lint/lint-unnecessary-parens.stderr
+++ b/tests/ui/lint/lint-unnecessary-parens.stderr
@@ -124,7 +124,7 @@ LL +     return 1;
    |
 
 error: unnecessary parentheses around assigned value
-  --> $DIR/lint-unnecessary-parens.rs:52:31
+  --> $DIR/lint-unnecessary-parens.rs:74:31
    |
 LL | pub const CONST_ITEM: usize = (10);
    |                               ^  ^
@@ -136,7 +136,7 @@ LL + pub const CONST_ITEM: usize = 10;
    |
 
 error: unnecessary parentheses around assigned value
-  --> $DIR/lint-unnecessary-parens.rs:53:33
+  --> $DIR/lint-unnecessary-parens.rs:75:33
    |
 LL | pub static STATIC_ITEM: usize = (10);
    |                                 ^  ^
@@ -148,7 +148,7 @@ LL + pub static STATIC_ITEM: usize = 10;
    |
 
 error: unnecessary parentheses around function argument
-  --> $DIR/lint-unnecessary-parens.rs:57:9
+  --> $DIR/lint-unnecessary-parens.rs:79:9
    |
 LL |     bar((true));
    |         ^    ^
@@ -160,7 +160,7 @@ LL +     bar(true);
    |
 
 error: unnecessary parentheses around `if` condition
-  --> $DIR/lint-unnecessary-parens.rs:59:8
+  --> $DIR/lint-unnecessary-parens.rs:81:8
    |
 LL |     if (true) {}
    |        ^    ^
@@ -172,7 +172,7 @@ LL +     if true {}
    |
 
 error: unnecessary parentheses around `while` condition
-  --> $DIR/lint-unnecessary-parens.rs:60:11
+  --> $DIR/lint-unnecessary-parens.rs:82:11
    |
 LL |     while (true) {}
    |           ^    ^
@@ -184,7 +184,7 @@ LL +     while true {}
    |
 
 error: unnecessary parentheses around `match` scrutinee expression
-  --> $DIR/lint-unnecessary-parens.rs:61:11
+  --> $DIR/lint-unnecessary-parens.rs:83:11
    |
 LL |     match (true) {
    |           ^    ^
@@ -196,7 +196,7 @@ LL +     match true {
    |
 
 error: unnecessary parentheses around `let` scrutinee expression
-  --> $DIR/lint-unnecessary-parens.rs:64:16
+  --> $DIR/lint-unnecessary-parens.rs:86:16
    |
 LL |     if let 1 = (1) {}
    |                ^ ^
@@ -208,7 +208,7 @@ LL +     if let 1 = 1 {}
    |
 
 error: unnecessary parentheses around `let` scrutinee expression
-  --> $DIR/lint-unnecessary-parens.rs:65:19
+  --> $DIR/lint-unnecessary-parens.rs:87:19
    |
 LL |     while let 1 = (2) {}
    |                   ^ ^
@@ -220,7 +220,7 @@ LL +     while let 1 = 2 {}
    |
 
 error: unnecessary parentheses around method argument
-  --> $DIR/lint-unnecessary-parens.rs:81:24
+  --> $DIR/lint-unnecessary-parens.rs:103:24
    |
 LL |     X { y: false }.foo((true));
    |                        ^    ^
@@ -232,7 +232,7 @@ LL +     X { y: false }.foo(true);
    |
 
 error: unnecessary parentheses around assigned value
-  --> $DIR/lint-unnecessary-parens.rs:83:18
+  --> $DIR/lint-unnecessary-parens.rs:105:18
    |
 LL |     let mut _a = (0);
    |                  ^ ^
@@ -244,7 +244,7 @@ LL +     let mut _a = 0;
    |
 
 error: unnecessary parentheses around assigned value
-  --> $DIR/lint-unnecessary-parens.rs:84:10
+  --> $DIR/lint-unnecessary-parens.rs:106:10
    |
 LL |     _a = (0);
    |          ^ ^
@@ -256,7 +256,7 @@ LL +     _a = 0;
    |
 
 error: unnecessary parentheses around assigned value
-  --> $DIR/lint-unnecessary-parens.rs:85:11
+  --> $DIR/lint-unnecessary-parens.rs:107:11
    |
 LL |     _a += (1);
    |           ^ ^
@@ -268,7 +268,7 @@ LL +     _a += 1;
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/lint-unnecessary-parens.rs:87:8
+  --> $DIR/lint-unnecessary-parens.rs:109:8
    |
 LL |     let(mut _a) = 3;
    |        ^      ^
@@ -280,7 +280,7 @@ LL +     let mut _a = 3;
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/lint-unnecessary-parens.rs:88:9
+  --> $DIR/lint-unnecessary-parens.rs:110:9
    |
 LL |     let (mut _a) = 3;
    |         ^      ^
@@ -292,7 +292,7 @@ LL +     let mut _a = 3;
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/lint-unnecessary-parens.rs:89:8
+  --> $DIR/lint-unnecessary-parens.rs:111:8
    |
 LL |     let( mut _a) = 3;
    |        ^^      ^
@@ -304,7 +304,7 @@ LL +     let mut _a = 3;
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/lint-unnecessary-parens.rs:91:8
+  --> $DIR/lint-unnecessary-parens.rs:113:8
    |
 LL |     let(_a) = 3;
    |        ^  ^
@@ -316,7 +316,7 @@ LL +     let _a = 3;
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/lint-unnecessary-parens.rs:92:9
+  --> $DIR/lint-unnecessary-parens.rs:114:9
    |
 LL |     let (_a) = 3;
    |         ^  ^
@@ -328,7 +328,7 @@ LL +     let _a = 3;
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/lint-unnecessary-parens.rs:93:8
+  --> $DIR/lint-unnecessary-parens.rs:115:8
    |
 LL |     let( _a) = 3;
    |        ^^  ^
@@ -339,5 +339,41 @@ LL -     let( _a) = 3;
 LL +     let _a = 3;
    |
 
-error: aborting due to 28 previous errors
+error: unnecessary parentheses around block return value
+  --> $DIR/lint-unnecessary-parens.rs:121:9
+   |
+LL |         (unit!() - One)
+   |         ^             ^
+   |
+help: remove these parentheses
+   |
+LL -         (unit!() - One)
+LL +         unit!() - One
+   |
+
+error: unnecessary parentheses around block return value
+  --> $DIR/lint-unnecessary-parens.rs:123:9
+   |
+LL |         (unit![] - One)
+   |         ^             ^
+   |
+help: remove these parentheses
+   |
+LL -         (unit![] - One)
+LL +         unit![] - One
+   |
+
+error: unnecessary parentheses around block return value
+  --> $DIR/lint-unnecessary-parens.rs:126:9
+   |
+LL |         (unit! {} - One)
+   |         ^              ^
+   |
+help: remove these parentheses
+   |
+LL -         (unit! {} - One)
+LL +         unit! {} - One
+   |
+
+error: aborting due to 31 previous errors
 
diff --git a/tests/ui/lint/reference_casting.rs b/tests/ui/lint/reference_casting.rs
index 87a682249b0..87fa42f9477 100644
--- a/tests/ui/lint/reference_casting.rs
+++ b/tests/ui/lint/reference_casting.rs
@@ -261,6 +261,13 @@ unsafe fn bigger_layout() {
         let ptr = r as *mut i32 as *mut Vec3<i32>;
         unsafe { *ptr = Vec3(0, 0, 0) }
     }
+
+    unsafe fn deref(v: &mut Vec3<i32>) {
+        let r = &mut v.0;
+        let r = &mut *r;
+        let ptr = &mut *(r as *mut i32 as *mut Vec3<i32>);
+        unsafe { *ptr = Vec3(0, 0, 0) }
+    }
 }
 
 const RAW_PTR: *mut u8 = 1 as *mut u8;
diff --git a/tests/ui/macros/nonterminal-matching.stderr b/tests/ui/macros/nonterminal-matching.stderr
index 499f9a7637d..d19141145fa 100644
--- a/tests/ui/macros/nonterminal-matching.stderr
+++ b/tests/ui/macros/nonterminal-matching.stderr
@@ -1,8 +1,6 @@
 error: no rules expected the token `enum E {}`
   --> $DIR/nonterminal-matching.rs:19:10
    |
-LL | macro complex_nonterminal($nt_item: item) {
-   |                           --------------
 LL |     macro n(a $nt_item b) {
    |     --------------------- when calling this macro
 ...
diff --git a/tests/ui/macros/stringify.rs b/tests/ui/macros/stringify.rs
index 492bd2450b1..6b215ba525d 100644
--- a/tests/ui/macros/stringify.rs
+++ b/tests/ui/macros/stringify.rs
@@ -213,6 +213,21 @@ fn test_expr() {
         "match () { _ => ({ 1 }) - 1, }",
         "match () { _ => { 1 } - 1 }",
     );
+    c2_match_arm!(
+        [ m!() - 1 ],
+        "match () { _ => m!() - 1, }",
+        "match () { _ => m!() - 1 }",
+    );
+    c2_match_arm!(
+        [ m![] - 1 ],
+        "match () { _ => m![] - 1, }",
+        "match () { _ => m![] - 1 }",
+    );
+    c2_match_arm!(
+        [ m! {} - 1 ],
+        "match () { _ => m! {} - 1, }",
+        "match () { _ => m! {} - 1 }",
+    );
 
     // ExprKind::Closure
     c1!(expr, [ || {} ], "|| {}");
@@ -660,6 +675,11 @@ fn test_stmt() {
         "let (a, b): (u32, u32) = (1, 2);",
         "let (a, b): (u32, u32) = (1, 2)"
     );
+    c2!(stmt,
+        [ let _ = f() else { return; } ],
+        "let _ = f() else { return; };",
+        "let _ = f() else { return; }",
+    );
     macro_rules! c2_let_expr_minus_one {
         ([ $expr:expr ], $stmt_expected:expr, $tokens_expected:expr $(,)?) => {
             c2!(stmt, [ let _ = $expr - 1 ], $stmt_expected, $tokens_expected);
@@ -670,6 +690,16 @@ fn test_stmt() {
         "let _ = match void {} - 1;",
         "let _ = match void {} - 1",
     );
+    macro_rules! c2_let_expr_else_return {
+        ([ $expr:expr ], $stmt_expected:expr, $tokens_expected:expr $(,)?) => {
+            c2!(stmt, [ let _ = $expr else { return; } ], $stmt_expected, $tokens_expected);
+        };
+    }
+    c2_let_expr_else_return!(
+        [ f() ],
+        "let _ = f() else { return; };",
+        "let _ = f() else { return; }",
+    );
 
     // StmtKind::Item
     c1!(stmt, [ struct S; ], "struct S;");
@@ -720,6 +750,21 @@ fn test_stmt() {
         "(loop { break 1; }) - 1;",
         "loop { break 1; } - 1",
     );
+    c2_minus_one!(
+        [ m!() ],
+        "m!() - 1;",
+        "m!() - 1"
+    );
+    c2_minus_one!(
+        [ m![] ],
+        "m![] - 1;",
+        "m![] - 1"
+    );
+    c2_minus_one!(
+        [ m! {} ],
+        "(m! {}) - 1;",
+        "m! {} - 1"
+    );
 
     // StmtKind::Empty
     c1!(stmt, [ ; ], ";");
diff --git a/tests/ui/macros/trace_faulty_macros.stderr b/tests/ui/macros/trace_faulty_macros.stderr
index 69607600b55..665dcc7d091 100644
--- a/tests/ui/macros/trace_faulty_macros.stderr
+++ b/tests/ui/macros/trace_faulty_macros.stderr
@@ -73,14 +73,10 @@ error: expected expression, found pattern `1 + 1`
   --> $DIR/trace_faulty_macros.rs:49:37
    |
 LL |     (let $p:pat = $e:expr) => {test!(($p,$e))};
-   |                   -------                -- this is interpreted as expression, but it is expected to be pattern
-   |                   |
-   |                   this macro fragment matcher is expression
+   |                                          -- this is interpreted as expression, but it is expected to be pattern
 ...
 LL |     (($p:pat, $e:pat)) => {let $p = $e;};
-   |               ------                ^^ expected expression
-   |               |
-   |               this macro fragment matcher is pattern
+   |                                     ^^ expected expression
 ...
 LL |     test!(let x = 1+1);
    |     ------------------
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024.rs b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024.rs
index f1ac3e340e9..62e4f82a3ff 100644
--- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024.rs
+++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024.rs
@@ -53,6 +53,12 @@ pub fn main() {
     if let Some(&Some(Some(&x))) = &Some(Some(&mut Some(0))) {
         let _: u32 = x;
     }
+    if let Some(&Some(&x)) = Some(&Some(&mut 0)) {
+        let _: u32 = x;
+    }
+    if let Some(&Some(x)) = &mut Some(Some(0)) {
+        let _: u32 = x;
+    }
 
     let &mut x = &&mut 0;
     let _: &u32 = x;
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs
index ec091bb1746..96b4ff77ddb 100644
--- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs
+++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs
@@ -14,18 +14,20 @@ pub fn main() {
         let _: &mut u32 = x;
         //~^ ERROR: mismatched types
     }
-    if let Some(&Some(&_)) = Some(&Some(&mut 0)) {
-        //~^ ERROR: mismatched types
-    }
     if let Some(&Some(&mut _)) = &mut Some(&Some(0)) {
         //~^ ERROR: mismatched types
     }
     if let Some(&Some(Some((&mut _)))) = &Some(Some(&mut Some(0))) {
         //~^ ERROR: mismatched types
     }
+    if let Some(&mut Some(x)) = &Some(Some(0)) {
+        //~^ ERROR: mismatched types
+    }
+    if let Some(&mut Some(x)) = &Some(Some(0)) {
+        //~^ ERROR: mismatched types
+    }
 
-
-    let &mut _= &&0;
+    let &mut _ = &&0;
     //~^ ERROR: mismatched types
 
     let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&0;
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr
index be71ee606c7..e06a645fc0d 100644
--- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr
+++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr
@@ -34,17 +34,6 @@ LL |         let _: &mut u32 = x;
 error[E0308]: mismatched types
   --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:17:23
    |
-LL |     if let Some(&Some(&_)) = Some(&Some(&mut 0)) {
-   |                       ^^     ------------------- this expression has type `Option<&Option<&mut {integer}>>`
-   |                       |
-   |                       types differ in mutability
-   |
-   = note: expected mutable reference `&mut {integer}`
-                      found reference `&_`
-
-error[E0308]: mismatched types
-  --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:20:23
-   |
 LL |     if let Some(&Some(&mut _)) = &mut Some(&Some(0)) {
    |                       ^^^^^^     ------------------- this expression has type `&mut Option<&Option<{integer}>>`
    |                       |
@@ -54,7 +43,7 @@ LL |     if let Some(&Some(&mut _)) = &mut Some(&Some(0)) {
            found mutable reference `&mut _`
 
 error[E0308]: mismatched types
-  --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:23:29
+  --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:20:29
    |
 LL |     if let Some(&Some(Some((&mut _)))) = &Some(Some(&mut Some(0))) {
    |                             ^^^^^^       ------------------------- this expression has type `&Option<Option<&mut Option<{integer}>>>`
@@ -65,10 +54,32 @@ LL |     if let Some(&Some(Some((&mut _)))) = &Some(Some(&mut Some(0))) {
            found mutable reference `&mut _`
 
 error[E0308]: mismatched types
-  --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:28:9
+  --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:23:17
+   |
+LL |     if let Some(&mut Some(x)) = &Some(Some(0)) {
+   |                 ^^^^^^^^^^^^    -------------- this expression has type `&Option<Option<{integer}>>`
+   |                 |
+   |                 expected `Option<{integer}>`, found `&mut _`
+   |
+   = note:           expected enum `Option<{integer}>`
+           found mutable reference `&mut _`
+
+error[E0308]: mismatched types
+  --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:26:17
+   |
+LL |     if let Some(&mut Some(x)) = &Some(Some(0)) {
+   |                 ^^^^^^^^^^^^    -------------- this expression has type `&Option<Option<{integer}>>`
+   |                 |
+   |                 expected `Option<{integer}>`, found `&mut _`
+   |
+   = note:           expected enum `Option<{integer}>`
+           found mutable reference `&mut _`
+
+error[E0308]: mismatched types
+  --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:30:9
    |
-LL |     let &mut _= &&0;
-   |         ^^^^^^  --- this expression has type `&&{integer}`
+LL |     let &mut _ = &&0;
+   |         ^^^^^^   --- this expression has type `&&{integer}`
    |         |
    |         expected integer, found `&mut _`
    |
@@ -76,7 +87,7 @@ LL |     let &mut _= &&0;
            found mutable reference `&mut _`
 
 error[E0308]: mismatched types
-  --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:31:9
+  --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:33:9
    |
 LL |     let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&0;
    |         ^^^^^^   ----------------------------- this expression has type `&&&&&&&&&&&&&&&&&&&&&&&&&&&&{integer}`
@@ -86,6 +97,6 @@ LL |     let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&0;
    = note:           expected type `{integer}`
            found mutable reference `&mut _`
 
-error: aborting due to 8 previous errors
+error: aborting due to 9 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.rs b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.rs
index 36455488407..3cdf47c1dbf 100644
--- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.rs
+++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.rs
@@ -8,4 +8,7 @@ pub fn main() {
         //~^ ERROR: cannot move out of a shared reference [E0507]
         let _: &u32 = x;
     }
+
+    let &ref mut x = &0;
+    //~^ cannot borrow data in a `&` reference as mutable [E0596]
 }
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.stderr b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.stderr
index ccfb5c7a0c0..8b86fa65c4d 100644
--- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.stderr
+++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.stderr
@@ -12,6 +12,13 @@ help: consider borrowing the pattern binding
 LL |     if let Some(&Some(ref x)) = Some(&Some(&mut 0)) {
    |                       +++
 
-error: aborting due to 1 previous error
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/ref_pat_eat_one_layer_2024_fail2.rs:12:10
+   |
+LL |     let &ref mut x = &0;
+   |          ^^^^^^^^^ cannot borrow as mutable
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0507`.
+Some errors have detailed explanations: E0507, E0596.
+For more information about an error, try `rustc --explain E0507`.
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_ref_mut_inside_and.fixed b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_ref_mut_inside_and.fixed
new file mode 100644
index 00000000000..bc7a58a382d
--- /dev/null
+++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_ref_mut_inside_and.fixed
@@ -0,0 +1,30 @@
+//@ edition: 2024
+//@ compile-flags: -Zunstable-options
+//@ run-rustfix
+#![allow(incomplete_features)]
+#![feature(ref_pat_eat_one_layer_2024)]
+
+pub fn main() {
+    if let Some(&mut Some(ref mut x)) = &mut Some(Some(0)) {
+        //~^ ERROR: cannot borrow as mutable inside an `&` pattern
+        let _: &mut u8 = x;
+    }
+
+    if let &mut Some(Some(ref mut x)) = &mut Some(Some(0)) {
+        //~^ ERROR: cannot borrow as mutable inside an `&` pattern
+        let _: &mut u8 = x;
+    }
+
+    macro_rules! pat {
+        ($var:ident) => { ref mut $var };
+    }
+    let &mut pat!(x) = &mut 0;
+    //~^ ERROR: cannot borrow as mutable inside an `&` pattern
+    let _: &mut u8 = x;
+
+    let &mut (ref mut a, ref mut b) = &mut (true, false);
+    //~^ ERROR: cannot borrow as mutable inside an `&` pattern
+    //~| ERROR: cannot borrow as mutable inside an `&` pattern
+    let _: &mut bool = a;
+    let _: &mut bool = b;
+}
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_ref_mut_inside_and.rs b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_ref_mut_inside_and.rs
new file mode 100644
index 00000000000..c6d72b0a9d7
--- /dev/null
+++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_ref_mut_inside_and.rs
@@ -0,0 +1,30 @@
+//@ edition: 2024
+//@ compile-flags: -Zunstable-options
+//@ run-rustfix
+#![allow(incomplete_features)]
+#![feature(ref_pat_eat_one_layer_2024)]
+
+pub fn main() {
+    if let Some(&Some(ref mut x)) = &mut Some(Some(0)) {
+        //~^ ERROR: cannot borrow as mutable inside an `&` pattern
+        let _: &mut u8 = x;
+    }
+
+    if let &Some(Some(ref mut x)) = &mut Some(Some(0)) {
+        //~^ ERROR: cannot borrow as mutable inside an `&` pattern
+        let _: &mut u8 = x;
+    }
+
+    macro_rules! pat {
+        ($var:ident) => { ref mut $var };
+    }
+    let &pat!(x) = &mut 0;
+    //~^ ERROR: cannot borrow as mutable inside an `&` pattern
+    let _: &mut u8 = x;
+
+    let &(ref mut a, ref mut b) = &mut (true, false);
+    //~^ ERROR: cannot borrow as mutable inside an `&` pattern
+    //~| ERROR: cannot borrow as mutable inside an `&` pattern
+    let _: &mut bool = a;
+    let _: &mut bool = b;
+}
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_ref_mut_inside_and.stderr b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_ref_mut_inside_and.stderr
new file mode 100644
index 00000000000..964e9f36596
--- /dev/null
+++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_ref_mut_inside_and.stderr
@@ -0,0 +1,43 @@
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/ref_pat_eat_one_layer_2024_ref_mut_inside_and.rs:8:31
+   |
+LL |     if let Some(&Some(ref mut x)) = &mut Some(Some(0)) {
+   |                 -             ^
+   |                 |
+   |                 help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/ref_pat_eat_one_layer_2024_ref_mut_inside_and.rs:13:31
+   |
+LL |     if let &Some(Some(ref mut x)) = &mut Some(Some(0)) {
+   |            -                  ^
+   |            |
+   |            help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/ref_pat_eat_one_layer_2024_ref_mut_inside_and.rs:21:15
+   |
+LL |     let &pat!(x) = &mut 0;
+   |         -     ^
+   |         |
+   |         help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/ref_pat_eat_one_layer_2024_ref_mut_inside_and.rs:25:19
+   |
+LL |     let &(ref mut a, ref mut b) = &mut (true, false);
+   |         -         ^
+   |         |
+   |         help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/ref_pat_eat_one_layer_2024_ref_mut_inside_and.rs:25:30
+   |
+LL |     let &(ref mut a, ref mut b) = &mut (true, false);
+   |         -                    ^
+   |         |
+   |         help: replace this `&` with `&mut`: `&mut`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/tests/ui/match/ref_pat_everywhere-mutability-mismatch.rs b/tests/ui/match/ref_pat_everywhere-fail.rs
index 9dd7a7893ec..d1b1c04730d 100644
--- a/tests/ui/match/ref_pat_everywhere-mutability-mismatch.rs
+++ b/tests/ui/match/ref_pat_everywhere-fail.rs
@@ -5,11 +5,7 @@ pub fn main() {
         //~^ ERROR: mismatched types [E0308]
         let _: u32 = x;
     }
-    if let &Some(x) = &mut Some(0) {
-        //~^ ERROR: mismatched types [E0308]
-        let _: u32 = x;
-    }
-    if let Some(&x) = &mut Some(0) {
+    if let Some(&mut x) = Some(&0) {
         //~^ ERROR: mismatched types [E0308]
         let _: u32 = x;
     }
diff --git a/tests/ui/match/ref_pat_everywhere-fail.stderr b/tests/ui/match/ref_pat_everywhere-fail.stderr
new file mode 100644
index 00000000000..25a01129f4a
--- /dev/null
+++ b/tests/ui/match/ref_pat_everywhere-fail.stderr
@@ -0,0 +1,38 @@
+error[E0308]: mismatched types
+  --> $DIR/ref_pat_everywhere-fail.rs:4:17
+   |
+LL |     if let Some(&x) = Some(0) {
+   |                 ^^    ------- this expression has type `Option<{integer}>`
+   |                 |
+   |                 expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL |     if let Some(x) = Some(0) {
+   |                 ~
+
+error[E0308]: mismatched types
+  --> $DIR/ref_pat_everywhere-fail.rs:8:17
+   |
+LL |     if let Some(&mut x) = Some(&0) {
+   |                 ^^^^^^    -------- this expression has type `Option<&{integer}>`
+   |                 |
+   |                 types differ in mutability
+   |
+   = note:      expected reference `&{integer}`
+           found mutable reference `&mut _`
+note: to declare a mutable binding use: `mut x`
+  --> $DIR/ref_pat_everywhere-fail.rs:8:17
+   |
+LL |     if let Some(&mut x) = Some(&0) {
+   |                 ^^^^^^
+help: consider removing `&mut` from the pattern
+   |
+LL |     if let Some(x) = Some(&0) {
+   |                 ~
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/match/ref_pat_everywhere-mutability-mismatch.stderr b/tests/ui/match/ref_pat_everywhere-mutability-mismatch.stderr
deleted file mode 100644
index d512ea5f957..00000000000
--- a/tests/ui/match/ref_pat_everywhere-mutability-mismatch.stderr
+++ /dev/null
@@ -1,44 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/ref_pat_everywhere-mutability-mismatch.rs:4:17
-   |
-LL |     if let Some(&x) = Some(0) {
-   |                 ^^    ------- this expression has type `Option<{integer}>`
-   |                 |
-   |                 expected integer, found `&_`
-   |
-   = note:   expected type `{integer}`
-           found reference `&_`
-help: consider removing `&` from the pattern
-   |
-LL |     if let Some(x) = Some(0) {
-   |                 ~
-
-error[E0308]: mismatched types
-  --> $DIR/ref_pat_everywhere-mutability-mismatch.rs:8:12
-   |
-LL |     if let &Some(x) = &mut Some(0) {
-   |            ^^^^^^^^   ------------ this expression has type `&mut Option<{integer}>`
-   |            |
-   |            types differ in mutability
-   |
-   = note: expected mutable reference `&mut Option<{integer}>`
-                      found reference `&_`
-
-error[E0308]: mismatched types
-  --> $DIR/ref_pat_everywhere-mutability-mismatch.rs:12:17
-   |
-LL |     if let Some(&x) = &mut Some(0) {
-   |                 ^^    ------------ this expression has type `&mut Option<{integer}>`
-   |                 |
-   |                 expected integer, found `&_`
-   |
-   = note:   expected type `{integer}`
-           found reference `&_`
-help: consider removing `&` from the pattern
-   |
-LL |     if let Some(x) = &mut Some(0) {
-   |                 ~
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/match/ref_pat_everywhere.rs b/tests/ui/match/ref_pat_everywhere.rs
index b3daca48409..9a79c548475 100644
--- a/tests/ui/match/ref_pat_everywhere.rs
+++ b/tests/ui/match/ref_pat_everywhere.rs
@@ -15,4 +15,10 @@ pub fn main() {
     if let Some(Some(&x)) = &Some(&mut Some(0)) {
         let _: u32 = x;
     }
+    if let &Some(x) = &mut Some(0) {
+        let _: u32 = x;
+    }
+    if let Some(&x) = &mut Some(0) {
+        let _: u32 = x;
+    }
 }
diff --git a/tests/ui/parser/else-no-if.rs b/tests/ui/parser/else-no-if.rs
index f0b40ecde66..ad5262cd2cc 100644
--- a/tests/ui/parser/else-no-if.rs
+++ b/tests/ui/parser/else-no-if.rs
@@ -1,3 +1,7 @@
+macro_rules! falsy {
+    () => { false };
+}
+
 fn foo() {
     if true {
     } else false {
@@ -25,6 +29,32 @@ fn foo4() {
     {}
 }
 
+fn foo5() {
+    if true {
+    } else falsy!() {
+    //~^ ERROR expected `{`, found `falsy`
+    }
+}
+
+fn foo6() {
+    if true {
+    } else falsy!();
+    //~^ ERROR expected `{`, found `falsy`
+}
+
+fn foo7() {
+    if true {
+    } else falsy! {} {
+    //~^ ERROR expected `{`, found `falsy`
+    }
+}
+
+fn foo8() {
+    if true {
+    } else falsy! {};
+    //~^ ERROR expected `{`, found `falsy`
+}
+
 fn falsy() -> bool {
     false
 }
diff --git a/tests/ui/parser/else-no-if.stderr b/tests/ui/parser/else-no-if.stderr
index b9c1a75276c..2e3e8f6b50e 100644
--- a/tests/ui/parser/else-no-if.stderr
+++ b/tests/ui/parser/else-no-if.stderr
@@ -1,5 +1,5 @@
 error: expected `{`, found keyword `false`
-  --> $DIR/else-no-if.rs:3:12
+  --> $DIR/else-no-if.rs:7:12
    |
 LL |     } else false {
    |       ---- ^^^^^
@@ -12,7 +12,7 @@ LL |     } else if false {
    |            ++
 
 error: expected `{`, found `falsy`
-  --> $DIR/else-no-if.rs:10:12
+  --> $DIR/else-no-if.rs:14:12
    |
 LL |     } else falsy() {
    |       ---- ^^^^^
@@ -25,7 +25,7 @@ LL |     } else if falsy() {
    |            ++
 
 error: expected `{`, found `falsy`
-  --> $DIR/else-no-if.rs:17:12
+  --> $DIR/else-no-if.rs:21:12
    |
 LL |     } else falsy();
    |            ^^^^^ expected `{`
@@ -36,7 +36,7 @@ LL |     } else { falsy() };
    |            +         +
 
 error: expected `{`, found keyword `loop`
-  --> $DIR/else-no-if.rs:23:12
+  --> $DIR/else-no-if.rs:27:12
    |
 LL |     } else loop{}
    |            ^^^^ expected `{`
@@ -46,5 +46,51 @@ help: try placing this code inside a block
 LL |     } else { loop{} }
    |            +        +
 
-error: aborting due to 4 previous errors
+error: expected `{`, found `falsy`
+  --> $DIR/else-no-if.rs:34:12
+   |
+LL |     } else falsy!() {
+   |       ---- ^^^^^
+   |       |
+   |       expected an `if` or a block after this `else`
+   |
+help: add an `if` if this is the condition of a chained `else if` statement
+   |
+LL |     } else if falsy!() {
+   |            ++
+
+error: expected `{`, found `falsy`
+  --> $DIR/else-no-if.rs:41:12
+   |
+LL |     } else falsy!();
+   |            ^^^^^ expected `{`
+   |
+help: try placing this code inside a block
+   |
+LL |     } else { falsy!() };
+   |            +          +
+
+error: expected `{`, found `falsy`
+  --> $DIR/else-no-if.rs:47:12
+   |
+LL |     } else falsy! {} {
+   |            ^^^^^ expected `{`
+   |
+help: try placing this code inside a block
+   |
+LL |     } else { falsy! {} } {
+   |            +           +
+
+error: expected `{`, found `falsy`
+  --> $DIR/else-no-if.rs:54:12
+   |
+LL |     } else falsy! {};
+   |            ^^^^^ expected `{`
+   |
+help: try placing this code inside a block
+   |
+LL |     } else { falsy! {} };
+   |            +           +
+
+error: aborting due to 8 previous errors
 
diff --git a/tests/ui/parser/macro/statement-boundaries.rs b/tests/ui/parser/macro/statement-boundaries.rs
new file mode 100644
index 00000000000..67a6aa30f0c
--- /dev/null
+++ b/tests/ui/parser/macro/statement-boundaries.rs
@@ -0,0 +1,104 @@
+//@ run-pass
+//@ edition:2021
+
+// This is a test of several uses of rustc_ast::util::classify::expr_requires_semi_to_be_stmt
+// by the Rust parser, which relates to the insertion of statement boundaries
+// after certain kinds of expressions if they appear at the head of a statement.
+
+#![allow(unused_braces, unused_unsafe)]
+
+macro_rules! unit {
+    () => {
+        { () }
+    };
+}
+
+#[derive(Copy, Clone)]
+struct X;
+
+fn main() {
+    let x = X;
+
+    // There is a statement boundary before `|x| x`, so it's a closure.
+    let _: fn(X) -> X = { if true {} |x| x };
+    let _: fn(X) -> X = { if true {} else {} |x| x };
+    let _: fn(X) -> X = { match () { () => {} } |x| x };
+    let _: fn(X) -> X = { { () } |x| x };
+    let _: fn(X) -> X = { unsafe {} |x| x };
+    let _: fn(X) -> X = { while false {} |x| x };
+    let _: fn(X) -> X = { loop { break; } |x| x };
+    let _: fn(X) -> X = { for _ in 0..0 {} |x| x };
+    let _: fn(X) -> X = { const {} |x| x };
+    let _: fn(X) -> X = { unit! {} |x| x };
+
+    // No statement boundary, so `|x| x` is 2× BitOr operation.
+    () = { "" |x| x };
+    () = { ("") |x| x };
+    () = { [""] |x| x };
+    () = { unit!() |x| x };
+    () = { unit![] |x| x };
+
+    // All the same cases, but as a match arm.
+    () = match x {
+        // Statement boundary before `| X`, which becomes a new arm with leading vert.
+        X if false => if true {} | X if false => {}
+        X if false => if true {} else {} | X if false => {}
+        X if false => match () { () => {} } | X if false => {}
+        X if false => { () } | X if false => {}
+        X if false => unsafe {} | X if false => {}
+        X if false => while false {} | X if false => {}
+        X if false => loop { break; } | X if false => {}
+        X if false => for _ in 0..0 {} | X if false => {}
+        X if false => const {} | X if false => {}
+
+        // No statement boundary, so `| X` is BitOr.
+        X if false => "" | X,
+        X if false => ("") | X,
+        X if false => [""] | X,
+        X if false => unit! {} | X, // !! inconsistent with braced mac call in statement position
+        X if false => unit!() | X,
+        X if false => unit![] | X,
+
+        X => {}
+    };
+
+    // Test how the statement boundary logic interacts with macro metavariables /
+    // "invisible delimiters".
+    macro_rules! assert_statement_boundary {
+        ($expr:expr) => {
+            let _: fn(X) -> X = { $expr |x| x };
+
+            () = match X {
+                X if false => $expr | X if false => {}
+                X => {}
+            };
+        };
+    }
+    macro_rules! assert_no_statement_boundary {
+        ($expr:expr) => {
+            () = { $expr |x| x };
+
+            () = match x {
+                X if false => $expr | X,
+                X => {}
+            };
+        };
+    }
+    assert_statement_boundary!(if true {});
+    assert_no_statement_boundary!("");
+}
+
+impl std::ops::BitOr<X> for () {
+    type Output = ();
+    fn bitor(self, _: X) {}
+}
+
+impl std::ops::BitOr<X> for &str {
+    type Output = ();
+    fn bitor(self, _: X) {}
+}
+
+impl<T, const N: usize> std::ops::BitOr<X> for [T; N] {
+    type Output = ();
+    fn bitor(self, _: X) {}
+}
diff --git a/tests/ui/pattern/auxiliary/match_ergonomics_2024_macros.rs b/tests/ui/pattern/auxiliary/match_ergonomics_2024_macros.rs
new file mode 100644
index 00000000000..0b70e4404ab
--- /dev/null
+++ b/tests/ui/pattern/auxiliary/match_ergonomics_2024_macros.rs
@@ -0,0 +1,12 @@
+//@ edition: 2024
+//@ compile-flags: -Z unstable-options
+
+// This contains a binding in edition 2024, so if matched with a reference binding mode it will end
+// up with a `mut ref mut` binding mode. We use this to test the migration lint on patterns with
+// mixed editions.
+#[macro_export]
+macro_rules! mixed_edition_pat {
+    ($foo:ident) => {
+        Some(mut $foo)
+    };
+}
diff --git a/tests/ui/pattern/match_ergonomics_2024.fixed b/tests/ui/pattern/match_ergonomics_2024.fixed
new file mode 100644
index 00000000000..d8dbcb217c0
--- /dev/null
+++ b/tests/ui/pattern/match_ergonomics_2024.fixed
@@ -0,0 +1,57 @@
+//@ edition: 2021
+//@ run-rustfix
+//@ rustfix-only-machine-applicable
+//@ aux-build:match_ergonomics_2024_macros.rs
+#![feature(mut_preserve_binding_mode_2024, ref_pat_eat_one_layer_2024)]
+#![allow(incomplete_features, unused)]
+#![deny(rust_2024_incompatible_pat)]
+
+extern crate match_ergonomics_2024_macros;
+
+struct Foo(u8);
+
+fn main() {
+    let &Foo(mut a) = &Foo(0);
+    //~^ ERROR: the semantics of this pattern will change in edition 2024
+    a = 42;
+
+    let &mut Foo(mut a) = &mut Foo(0);
+    //~^ ERROR: the semantics of this pattern will change in edition 2024
+    a = 42;
+
+    if let &&&&&Some(&_) = &&&&&Some(&0u8) {}
+    //~^ ERROR: the semantics of this pattern will change in edition 2024
+
+    if let &&&&&Some(&mut _) = &&&&&Some(&mut 0u8) {}
+    //~^ ERROR: the semantics of this pattern will change in edition 2024
+
+    if let &&&&&mut Some(&_) = &&&&&mut Some(&0u8) {}
+    //~^ ERROR: the semantics of this pattern will change in edition 2024
+
+    if let &mut Some(&mut Some(&mut Some(_))) = &mut Some(&mut Some(&mut Some(0u8))) {}
+    //~^ ERROR: the semantics of this pattern will change in edition 2024
+
+    if let &mut Some(&mut Some(&mut Some(ref mut _a))) = &mut Some(&mut Some(&mut Some(0u8))) {}
+    //~^ ERROR: the semantics of this pattern will change in edition 2024
+
+    struct Struct {
+        a: u32,
+        b: u32,
+        c: u32,
+    }
+    let s = Struct { a: 0, b: 0, c: 0 };
+    let &Struct { ref a, mut b, ref c } = &s;
+    //~^ ERROR: the semantics of this pattern will change in edition 2024
+
+    #[warn(rust_2024_incompatible_pat)]
+    match &(Some(0), Some(0)) {
+        // The two patterns are the same syntactically, but because they're defined in different
+        // editions they don't mean the same thing.
+        (Some(mut _x), match_ergonomics_2024_macros::mixed_edition_pat!(_y)) => {
+            //~^ WARN: the semantics of this pattern will change in edition 2024
+            _x = 4;
+            _y = &7;
+        }
+        _ => {}
+    }
+}
diff --git a/tests/ui/pattern/match_ergonomics_2024.rs b/tests/ui/pattern/match_ergonomics_2024.rs
new file mode 100644
index 00000000000..38dc0c8bebb
--- /dev/null
+++ b/tests/ui/pattern/match_ergonomics_2024.rs
@@ -0,0 +1,57 @@
+//@ edition: 2021
+//@ run-rustfix
+//@ rustfix-only-machine-applicable
+//@ aux-build:match_ergonomics_2024_macros.rs
+#![feature(mut_preserve_binding_mode_2024, ref_pat_eat_one_layer_2024)]
+#![allow(incomplete_features, unused)]
+#![deny(rust_2024_incompatible_pat)]
+
+extern crate match_ergonomics_2024_macros;
+
+struct Foo(u8);
+
+fn main() {
+    let Foo(mut a) = &Foo(0);
+    //~^ ERROR: the semantics of this pattern will change in edition 2024
+    a = 42;
+
+    let Foo(mut a) = &mut Foo(0);
+    //~^ ERROR: the semantics of this pattern will change in edition 2024
+    a = 42;
+
+    if let Some(&_) = &&&&&Some(&0u8) {}
+    //~^ ERROR: the semantics of this pattern will change in edition 2024
+
+    if let Some(&mut _) = &&&&&Some(&mut 0u8) {}
+    //~^ ERROR: the semantics of this pattern will change in edition 2024
+
+    if let Some(&_) = &&&&&mut Some(&0u8) {}
+    //~^ ERROR: the semantics of this pattern will change in edition 2024
+
+    if let Some(&mut Some(Some(_))) = &mut Some(&mut Some(&mut Some(0u8))) {}
+    //~^ ERROR: the semantics of this pattern will change in edition 2024
+
+    if let Some(&mut Some(Some(_a))) = &mut Some(&mut Some(&mut Some(0u8))) {}
+    //~^ ERROR: the semantics of this pattern will change in edition 2024
+
+    struct Struct {
+        a: u32,
+        b: u32,
+        c: u32,
+    }
+    let s = Struct { a: 0, b: 0, c: 0 };
+    let Struct { a, mut b, c } = &s;
+    //~^ ERROR: the semantics of this pattern will change in edition 2024
+
+    #[warn(rust_2024_incompatible_pat)]
+    match &(Some(0), Some(0)) {
+        // The two patterns are the same syntactically, but because they're defined in different
+        // editions they don't mean the same thing.
+        (Some(mut _x), match_ergonomics_2024_macros::mixed_edition_pat!(_y)) => {
+            //~^ WARN: the semantics of this pattern will change in edition 2024
+            _x = 4;
+            _y = &7;
+        }
+        _ => {}
+    }
+}
diff --git a/tests/ui/pattern/match_ergonomics_2024.stderr b/tests/ui/pattern/match_ergonomics_2024.stderr
new file mode 100644
index 00000000000..11844434ad2
--- /dev/null
+++ b/tests/ui/pattern/match_ergonomics_2024.stderr
@@ -0,0 +1,97 @@
+error: the semantics of this pattern will change in edition 2024
+  --> $DIR/match_ergonomics_2024.rs:14:9
+   |
+LL |     let Foo(mut a) = &Foo(0);
+   |         -^^^^^^^^^
+   |         |
+   |         help: desugar the match ergonomics: `&`
+   |
+note: the lint level is defined here
+  --> $DIR/match_ergonomics_2024.rs:7:9
+   |
+LL | #![deny(rust_2024_incompatible_pat)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the semantics of this pattern will change in edition 2024
+  --> $DIR/match_ergonomics_2024.rs:18:9
+   |
+LL |     let Foo(mut a) = &mut Foo(0);
+   |         -^^^^^^^^^
+   |         |
+   |         help: desugar the match ergonomics: `&mut`
+
+error: the semantics of this pattern will change in edition 2024
+  --> $DIR/match_ergonomics_2024.rs:22:12
+   |
+LL |     if let Some(&_) = &&&&&Some(&0u8) {}
+   |            -^^^^^^^
+   |            |
+   |            help: desugar the match ergonomics: `&&&&&`
+
+error: the semantics of this pattern will change in edition 2024
+  --> $DIR/match_ergonomics_2024.rs:25:12
+   |
+LL |     if let Some(&mut _) = &&&&&Some(&mut 0u8) {}
+   |            -^^^^^^^^^^^
+   |            |
+   |            help: desugar the match ergonomics: `&&&&&`
+
+error: the semantics of this pattern will change in edition 2024
+  --> $DIR/match_ergonomics_2024.rs:28:12
+   |
+LL |     if let Some(&_) = &&&&&mut Some(&0u8) {}
+   |            -^^^^^^^
+   |            |
+   |            help: desugar the match ergonomics: `&&&&&mut`
+
+error: the semantics of this pattern will change in edition 2024
+  --> $DIR/match_ergonomics_2024.rs:31:12
+   |
+LL |     if let Some(&mut Some(Some(_))) = &mut Some(&mut Some(&mut Some(0u8))) {}
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: desugar the match ergonomics
+   |
+LL |     if let &mut Some(&mut Some(&mut Some(_))) = &mut Some(&mut Some(&mut Some(0u8))) {}
+   |            ++++                ++++
+
+error: the semantics of this pattern will change in edition 2024
+  --> $DIR/match_ergonomics_2024.rs:34:12
+   |
+LL |     if let Some(&mut Some(Some(_a))) = &mut Some(&mut Some(&mut Some(0u8))) {}
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: desugar the match ergonomics
+   |
+LL |     if let &mut Some(&mut Some(&mut Some(ref mut _a))) = &mut Some(&mut Some(&mut Some(0u8))) {}
+   |            ++++                ++++      +++++++
+
+error: the semantics of this pattern will change in edition 2024
+  --> $DIR/match_ergonomics_2024.rs:43:9
+   |
+LL |     let Struct { a, mut b, c } = &s;
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: desugar the match ergonomics
+   |
+LL |     let &Struct { ref a, mut b, ref c } = &s;
+   |         +         +++           +++
+
+warning: the semantics of this pattern will change in edition 2024
+  --> $DIR/match_ergonomics_2024.rs:50:9
+   |
+LL |         (Some(mut _x), match_ergonomics_2024_macros::mixed_edition_pat!(_y)) => {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/match_ergonomics_2024.rs:46:12
+   |
+LL |     #[warn(rust_2024_incompatible_pat)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: desugar the match ergonomics
+   |
+LL |         &(Some(mut _x), match_ergonomics_2024_macros::mixed_edition_pat!(ref _y)) => {
+   |         +                                                                +++
+
+error: aborting due to 8 previous errors; 1 warning emitted
+
diff --git a/tests/ui/pattern/mut_preserve_binding_mode_2024_lint.rs b/tests/ui/pattern/mut_preserve_binding_mode_2024_lint.rs
deleted file mode 100644
index 249f251d2cd..00000000000
--- a/tests/ui/pattern/mut_preserve_binding_mode_2024_lint.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-//@ edition: 2021
-#![feature(mut_preserve_binding_mode_2024)]
-#![allow(incomplete_features, unused)]
-#![forbid(dereferencing_mut_binding)]
-
-struct Foo(u8);
-
-fn main() {
-    let Foo(mut a) = &Foo(0);
-    //~^ ERROR: dereferencing `mut` binding
-    a = 42;
-
-    let Foo(mut a) = &mut Foo(0);
-    //~^ ERROR: dereferencing `mut` binding
-    a = 42;
-}
diff --git a/tests/ui/pattern/mut_preserve_binding_mode_2024_lint.stderr b/tests/ui/pattern/mut_preserve_binding_mode_2024_lint.stderr
deleted file mode 100644
index e8d11acd83e..00000000000
--- a/tests/ui/pattern/mut_preserve_binding_mode_2024_lint.stderr
+++ /dev/null
@@ -1,31 +0,0 @@
-error: dereferencing `mut` binding
-  --> $DIR/mut_preserve_binding_mode_2024_lint.rs:9:13
-   |
-LL |     let Foo(mut a) = &Foo(0);
-   |             ^^^^^ `mut` dereferences the type of this binding
-   |
-help: this will change in edition 2024
-  --> $DIR/mut_preserve_binding_mode_2024_lint.rs:9:13
-   |
-LL |     let Foo(mut a) = &Foo(0);
-   |             ^^^^^
-note: the lint level is defined here
-  --> $DIR/mut_preserve_binding_mode_2024_lint.rs:4:11
-   |
-LL | #![forbid(dereferencing_mut_binding)]
-   |           ^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: dereferencing `mut` binding
-  --> $DIR/mut_preserve_binding_mode_2024_lint.rs:13:13
-   |
-LL |     let Foo(mut a) = &mut Foo(0);
-   |             ^^^^^ `mut` dereferences the type of this binding
-   |
-help: this will change in edition 2024
-  --> $DIR/mut_preserve_binding_mode_2024_lint.rs:13:13
-   |
-LL |     let Foo(mut a) = &mut Foo(0);
-   |             ^^^^^
-
-error: aborting due to 2 previous errors
-
diff --git a/tests/ui/suggestions/recover-from-semicolon-trailing-item.stderr b/tests/ui/suggestions/recover-from-semicolon-trailing-item.stderr
index fee83eb5c18..e068fdb5aba 100644
--- a/tests/ui/suggestions/recover-from-semicolon-trailing-item.stderr
+++ b/tests/ui/suggestions/recover-from-semicolon-trailing-item.stderr
@@ -3,6 +3,8 @@ error: expected item, found `;`
    |
 LL | mod M {};
    |         ^ help: remove this semicolon
+   |
+   = help: module declarations are not followed by a semicolon
 
 error: expected item, found `;`
   --> $DIR/recover-from-semicolon-trailing-item.rs:4:12
@@ -17,6 +19,8 @@ error: expected item, found `;`
    |
 LL | fn foo(a: usize) {};
    |                    ^ help: remove this semicolon
+   |
+   = help: function declarations are not followed by a semicolon
 
 error[E0308]: mismatched types
   --> $DIR/recover-from-semicolon-trailing-item.rs:10:20
diff --git a/tests/ui/symbol-names/types.legacy.stderr b/tests/ui/symbol-names/types.legacy.stderr
index a4984d5629f..87c3acae0bd 100644
--- a/tests/ui/symbol-names/types.legacy.stderr
+++ b/tests/ui/symbol-names/types.legacy.stderr
@@ -1,470 +1,506 @@
 error: symbol-name(_ZN1a1b16Type$LT$bool$GT$17h[HASH]E)
-  --> $DIR/types.rs:13:5
+  --> $DIR/types.rs:18:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<bool>::h[HASH])
-  --> $DIR/types.rs:13:5
+  --> $DIR/types.rs:18:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<bool>)
-  --> $DIR/types.rs:13:5
+  --> $DIR/types.rs:18:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b16Type$LT$char$GT$17h[HASH]E)
-  --> $DIR/types.rs:19:5
+  --> $DIR/types.rs:27:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<char>::h[HASH])
-  --> $DIR/types.rs:19:5
+  --> $DIR/types.rs:27:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<char>)
-  --> $DIR/types.rs:19:5
+  --> $DIR/types.rs:27:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b14Type$LT$i8$GT$17h[HASH]E)
-  --> $DIR/types.rs:25:5
+  --> $DIR/types.rs:36:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<i8>::h[HASH])
-  --> $DIR/types.rs:25:5
+  --> $DIR/types.rs:36:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<i8>)
-  --> $DIR/types.rs:25:5
+  --> $DIR/types.rs:36:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b15Type$LT$i16$GT$17h[HASH]E)
-  --> $DIR/types.rs:31:5
+  --> $DIR/types.rs:45:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<i16>::h[HASH])
-  --> $DIR/types.rs:31:5
+  --> $DIR/types.rs:45:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<i16>)
-  --> $DIR/types.rs:31:5
+  --> $DIR/types.rs:45:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b15Type$LT$i32$GT$17h[HASH]E)
-  --> $DIR/types.rs:37:5
+  --> $DIR/types.rs:54:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<i32>::h[HASH])
-  --> $DIR/types.rs:37:5
+  --> $DIR/types.rs:54:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<i32>)
-  --> $DIR/types.rs:37:5
+  --> $DIR/types.rs:54:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b15Type$LT$i64$GT$17h[HASH]E)
-  --> $DIR/types.rs:43:5
+  --> $DIR/types.rs:63:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<i64>::h[HASH])
-  --> $DIR/types.rs:43:5
+  --> $DIR/types.rs:63:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<i64>)
-  --> $DIR/types.rs:43:5
+  --> $DIR/types.rs:63:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b14Type$LT$u8$GT$17h[HASH]E)
-  --> $DIR/types.rs:49:5
+  --> $DIR/types.rs:72:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<u8>::h[HASH])
-  --> $DIR/types.rs:49:5
+  --> $DIR/types.rs:72:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<u8>)
-  --> $DIR/types.rs:49:5
+  --> $DIR/types.rs:72:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b15Type$LT$u16$GT$17h[HASH]E)
-  --> $DIR/types.rs:55:5
+  --> $DIR/types.rs:81:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<u16>::h[HASH])
-  --> $DIR/types.rs:55:5
+  --> $DIR/types.rs:81:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<u16>)
-  --> $DIR/types.rs:55:5
+  --> $DIR/types.rs:81:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b15Type$LT$u32$GT$17h[HASH]E)
-  --> $DIR/types.rs:61:5
+  --> $DIR/types.rs:90:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<u32>::h[HASH])
-  --> $DIR/types.rs:61:5
+  --> $DIR/types.rs:90:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<u32>)
-  --> $DIR/types.rs:61:5
+  --> $DIR/types.rs:90:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b15Type$LT$u64$GT$17h[HASH]E)
-  --> $DIR/types.rs:67:5
+  --> $DIR/types.rs:99:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<u64>::h[HASH])
-  --> $DIR/types.rs:67:5
+  --> $DIR/types.rs:99:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<u64>)
-  --> $DIR/types.rs:67:5
+  --> $DIR/types.rs:99:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_ZN1a1b15Type$LT$f16$GT$17h[HASH]E)
+  --> $DIR/types.rs:108:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(a::b::Type<f16>::h[HASH])
+  --> $DIR/types.rs:108:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(a::b::Type<f16>)
+  --> $DIR/types.rs:108:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b15Type$LT$f32$GT$17h[HASH]E)
-  --> $DIR/types.rs:73:5
+  --> $DIR/types.rs:117:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<f32>::h[HASH])
-  --> $DIR/types.rs:73:5
+  --> $DIR/types.rs:117:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<f32>)
-  --> $DIR/types.rs:73:5
+  --> $DIR/types.rs:117:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b15Type$LT$f64$GT$17h[HASH]E)
-  --> $DIR/types.rs:79:5
+  --> $DIR/types.rs:126:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<f64>::h[HASH])
-  --> $DIR/types.rs:79:5
+  --> $DIR/types.rs:126:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<f64>)
-  --> $DIR/types.rs:79:5
+  --> $DIR/types.rs:126:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_ZN1a1b16Type$LT$f128$GT$17h[HASH]E)
+  --> $DIR/types.rs:135:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(a::b::Type<f128>::h[HASH])
+  --> $DIR/types.rs:135:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(a::b::Type<f128>)
+  --> $DIR/types.rs:135:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b15Type$LT$str$GT$17h[HASH]E)
-  --> $DIR/types.rs:85:5
+  --> $DIR/types.rs:144:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<str>::h[HASH])
-  --> $DIR/types.rs:85:5
+  --> $DIR/types.rs:144:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<str>)
-  --> $DIR/types.rs:85:5
+  --> $DIR/types.rs:144:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b17Type$LT$$u21$$GT$17h[HASH]E)
-  --> $DIR/types.rs:91:5
+  --> $DIR/types.rs:153:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<!>::h[HASH])
-  --> $DIR/types.rs:91:5
+  --> $DIR/types.rs:153:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<!>)
-  --> $DIR/types.rs:91:5
+  --> $DIR/types.rs:153:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b20Type$LT$$LP$$RP$$GT$17h[HASH]E)
-  --> $DIR/types.rs:97:5
+  --> $DIR/types.rs:162:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<()>::h[HASH])
-  --> $DIR/types.rs:97:5
+  --> $DIR/types.rs:162:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<()>)
-  --> $DIR/types.rs:97:5
+  --> $DIR/types.rs:162:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b25Type$LT$$LP$u8$C$$RP$$GT$17h[HASH]E)
-  --> $DIR/types.rs:103:5
+  --> $DIR/types.rs:171:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<(u8,)>::h[HASH])
-  --> $DIR/types.rs:103:5
+  --> $DIR/types.rs:171:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<(u8,)>)
-  --> $DIR/types.rs:103:5
+  --> $DIR/types.rs:171:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b28Type$LT$$LP$u8$C$u16$RP$$GT$17h[HASH]E)
-  --> $DIR/types.rs:109:5
+  --> $DIR/types.rs:180:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<(u8,u16)>::h[HASH])
-  --> $DIR/types.rs:109:5
+  --> $DIR/types.rs:180:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<(u8,u16)>)
-  --> $DIR/types.rs:109:5
+  --> $DIR/types.rs:180:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b34Type$LT$$LP$u8$C$u16$C$u32$RP$$GT$17h[HASH]E)
-  --> $DIR/types.rs:115:5
+  --> $DIR/types.rs:189:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<(u8,u16,u32)>::h[HASH])
-  --> $DIR/types.rs:115:5
+  --> $DIR/types.rs:189:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<(u8,u16,u32)>)
-  --> $DIR/types.rs:115:5
+  --> $DIR/types.rs:189:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b28Type$LT$$BP$const$u20$u8$GT$17h[HASH]E)
-  --> $DIR/types.rs:121:5
+  --> $DIR/types.rs:198:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<*const u8>::h[HASH])
-  --> $DIR/types.rs:121:5
+  --> $DIR/types.rs:198:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<*const u8>)
-  --> $DIR/types.rs:121:5
+  --> $DIR/types.rs:198:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b26Type$LT$$BP$mut$u20$u8$GT$17h[HASH]E)
-  --> $DIR/types.rs:127:5
+  --> $DIR/types.rs:207:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<*mut u8>::h[HASH])
-  --> $DIR/types.rs:127:5
+  --> $DIR/types.rs:207:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<*mut u8>)
-  --> $DIR/types.rs:127:5
+  --> $DIR/types.rs:207:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b19Type$LT$$RF$str$GT$17h[HASH]E)
-  --> $DIR/types.rs:133:5
+  --> $DIR/types.rs:216:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<&str>::h[HASH])
-  --> $DIR/types.rs:133:5
+  --> $DIR/types.rs:216:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<&str>)
-  --> $DIR/types.rs:133:5
+  --> $DIR/types.rs:216:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b27Type$LT$$RF$mut$u20$str$GT$17h[HASH]E)
-  --> $DIR/types.rs:139:5
+  --> $DIR/types.rs:225:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<&mut str>::h[HASH])
-  --> $DIR/types.rs:139:5
+  --> $DIR/types.rs:225:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<&mut str>)
-  --> $DIR/types.rs:139:5
+  --> $DIR/types.rs:225:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b35Type$LT$$u5b$u8$u3b$$u20$0$u5d$$GT$17h[HASH]E)
-  --> $DIR/types.rs:145:5
+  --> $DIR/types.rs:234:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<[u8; 0]>::h[HASH])
-  --> $DIR/types.rs:145:5
+  --> $DIR/types.rs:234:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<[u8; 0]>)
-  --> $DIR/types.rs:145:5
+  --> $DIR/types.rs:234:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b22Type$LT$fn$LP$$RP$$GT$17h[HASH]E)
-  --> $DIR/types.rs:151:5
+  --> $DIR/types.rs:243:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<fn()>::h[HASH])
-  --> $DIR/types.rs:151:5
+  --> $DIR/types.rs:243:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<fn()>)
-  --> $DIR/types.rs:151:5
+  --> $DIR/types.rs:243:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b60Type$LT$unsafe$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RP$$GT$17h[HASH]E)
-  --> $DIR/types.rs:157:5
+  --> $DIR/types.rs:252:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<unsafe extern "C" fn()>::h[HASH])
-  --> $DIR/types.rs:157:5
+  --> $DIR/types.rs:252:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<unsafe extern "C" fn()>)
-  --> $DIR/types.rs:157:5
+  --> $DIR/types.rs:252:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b34Type$LT$$u5b$T$u3b$$u20$N$u5d$$GT$17h[HASH]E)
-  --> $DIR/types.rs:163:5
+  --> $DIR/types.rs:261:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<[T; N]>::h[HASH])
-  --> $DIR/types.rs:163:5
+  --> $DIR/types.rs:261:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<[T; N]>)
-  --> $DIR/types.rs:163:5
+  --> $DIR/types.rs:261:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 78 previous errors
+error: aborting due to 84 previous errors
 
diff --git a/tests/ui/symbol-names/types.rs b/tests/ui/symbol-names/types.rs
index b121408c843..7ed19e0e5a8 100644
--- a/tests/ui/symbol-names/types.rs
+++ b/tests/ui/symbol-names/types.rs
@@ -1,169 +1,270 @@
 //@ build-fail
-//@ revisions: legacy verbose-legacy
-//@ compile-flags: --crate-name=a -C symbol-mangling-version=legacy -Z unstable-options
-//@[verbose-legacy]compile-flags: -Zverbose-internals
+//@ revisions: legacy verbose-legacy v0
+//@ compile-flags: --crate-name=a -Z unstable-options
+//@ [legacy] compile-flags: -Csymbol-mangling-version=legacy
+//@ [verbose-legacy] compile-flags: -Csymbol-mangling-version=legacy -Zverbose-internals
+//@ [v0] compile-flags: -Csymbol-mangling-version=v0
 //@ normalize-stderr-test: "h[[:xdigit:]]{16}" -> "h[HASH]"
+//@ [v0] normalize-stderr-test: "\[[[:xdigit:]]{16}\]" -> "[HASH]"
 
 #![feature(never_type)]
 #![feature(rustc_attrs)]
+#![feature(f128)]
+#![feature(f16)]
 
 pub fn b() {
     struct Type<T: ?Sized>(T);
 
     #[rustc_symbol_name]
-    //~^ ERROR symbol-name(_ZN1a1b16Type$LT$bool$GT$
-    //~| ERROR demangling(a::b::Type<bool>::
-    //~| ERROR demangling-alt(a::b::Type<bool>)
+    //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b16Type$LT$bool$GT$
+    //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<bool>::
+    //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<bool>)
+    //[v0]~^^^^ ERROR symbol-name(_RMNvCsCRATE_HASH_1a1bINtB<REF>_4TypebE)
+    //[v0]~| ERROR ::b::Type<bool>>)
+    //[v0]~| ERROR demangling-alt(<a::b::Type<bool>>)
     impl Type<bool> {}
 
     #[rustc_symbol_name]
-    //~^ ERROR symbol-name(_ZN1a1b16Type$LT$char$GT$
-    //~| ERROR demangling(a::b::Type<char>::
-    //~| ERROR demangling-alt(a::b::Type<char>)
+    //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b16Type$LT$char$GT$
+    //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<char>::
+    //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<char>)
+    //[v0]~^^^^ ERROR symbol-name(_RMs_NvCsCRATE_HASH_1a1bINtB<REF>_4TypecE)
+    //[v0]~| ERROR ::b::Type<char>>)
+    //[v0]~| ERROR demangling-alt(<a::b::Type<char>>)
     impl Type<char> {}
 
     #[rustc_symbol_name]
-    //~^ ERROR symbol-name(_ZN1a1b14Type$LT$i8$GT$
-    //~| ERROR demangling(a::b::Type<i8>::
-    //~| ERROR demangling-alt(a::b::Type<i8>)
+    //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b14Type$LT$i8$GT$
+    //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<i8>::
+    //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<i8>)
+    //[v0]~^^^^ ERROR symbol-name(_RMs0_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeaE)
+    //[v0]~| ERROR ::b::Type<i8>>)
+    //[v0]~| ERROR demangling-alt(<a::b::Type<i8>>)
     impl Type<i8> {}
 
     #[rustc_symbol_name]
-    //~^ ERROR symbol-name(_ZN1a1b15Type$LT$i16$GT$
-    //~| ERROR demangling(a::b::Type<i16>::
-    //~| ERROR demangling-alt(a::b::Type<i16>)
+    //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b15Type$LT$i16$GT$
+    //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<i16>::
+    //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<i16>)
+    //[v0]~^^^^ ERROR symbol-name(_RMs1_NvCsCRATE_HASH_1a1bINtB<REF>_4TypesE)
+    //[v0]~| ERROR ::b::Type<i16>>)
+    //[v0]~| ERROR demangling-alt(<a::b::Type<i16>>)
     impl Type<i16> {}
 
     #[rustc_symbol_name]
-    //~^ ERROR symbol-name(_ZN1a1b15Type$LT$i32$GT$
-    //~| ERROR demangling(a::b::Type<i32>::
-    //~| ERROR demangling-alt(a::b::Type<i32>)
+    //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b15Type$LT$i32$GT$
+    //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<i32>::
+    //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<i32>)
+    //[v0]~^^^^ ERROR symbol-name(_RMs2_NvCsCRATE_HASH_1a1bINtB<REF>_4TypelE)
+    //[v0]~| ERROR ::b::Type<i32>>)
+    //[v0]~| ERROR demangling-alt(<a::b::Type<i32>>)
     impl Type<i32> {}
 
     #[rustc_symbol_name]
-    //~^ ERROR symbol-name(_ZN1a1b15Type$LT$i64$GT$
-    //~| ERROR demangling(a::b::Type<i64>::
-    //~| ERROR demangling-alt(a::b::Type<i64>)
+    //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b15Type$LT$i64$GT$
+    //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<i64>::
+    //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<i64>)
+    //[v0]~^^^^ ERROR symbol-name(_RMs3_NvCsCRATE_HASH_1a1bINtB<REF>_4TypexE)
+    //[v0]~| ERROR ::b::Type<i64>>)
+    //[v0]~| ERROR demangling-alt(<a::b::Type<i64>>)
     impl Type<i64> {}
 
     #[rustc_symbol_name]
-    //~^ ERROR symbol-name(_ZN1a1b14Type$LT$u8$GT$
-    //~| ERROR demangling(a::b::Type<u8>::
-    //~| ERROR demangling-alt(a::b::Type<u8>)
+    //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b14Type$LT$u8$GT$
+    //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<u8>::
+    //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<u8>)
+    //[v0]~^^^^ ERROR symbol-name(_RMs4_NvCsCRATE_HASH_1a1bINtB<REF>_4TypehE)
+    //[v0]~| ERROR ::b::Type<u8>>)
+    //[v0]~| ERROR demangling-alt(<a::b::Type<u8>>)
     impl Type<u8> {}
 
     #[rustc_symbol_name]
-    //~^ ERROR symbol-name(_ZN1a1b15Type$LT$u16$GT$
-    //~| ERROR demangling(a::b::Type<u16>::
-    //~| ERROR demangling-alt(a::b::Type<u16>)
+    //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b15Type$LT$u16$GT$
+    //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<u16>::
+    //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<u16>)
+    //[v0]~^^^^ ERROR symbol-name(_RMs5_NvCsCRATE_HASH_1a1bINtB<REF>_4TypetE)
+    //[v0]~| ERROR ::b::Type<u16>>)
+    //[v0]~| ERROR demangling-alt(<a::b::Type<u16>>)
     impl Type<u16> {}
 
     #[rustc_symbol_name]
-    //~^ ERROR symbol-name(_ZN1a1b15Type$LT$u32$GT$
-    //~| ERROR demangling(a::b::Type<u32>::
-    //~| ERROR demangling-alt(a::b::Type<u32>)
+    //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b15Type$LT$u32$GT$
+    //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<u32>::
+    //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<u32>)
+    //[v0]~^^^^ ERROR symbol-name(_RMs6_NvCsCRATE_HASH_1a1bINtB<REF>_4TypemE)
+    //[v0]~| ERROR ::b::Type<u32>>)
+    //[v0]~| ERROR demangling-alt(<a::b::Type<u32>>)
     impl Type<u32> {}
 
     #[rustc_symbol_name]
-    //~^ ERROR symbol-name(_ZN1a1b15Type$LT$u64$GT$
-    //~| ERROR demangling(a::b::Type<u64>::
-    //~| ERROR demangling-alt(a::b::Type<u64>)
+    //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b15Type$LT$u64$GT$
+    //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<u64>::
+    //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<u64>)
+    //[v0]~^^^^ ERROR symbol-name(_RMs7_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeyE)
+    //[v0]~| ERROR ::b::Type<u64>>)
+    //[v0]~| ERROR demangling-alt(<a::b::Type<u64>>)
     impl Type<u64> {}
 
     #[rustc_symbol_name]
-    //~^ ERROR symbol-name(_ZN1a1b15Type$LT$f32$GT$
-    //~| ERROR demangling(a::b::Type<f32>::
-    //~| ERROR demangling-alt(a::b::Type<f32>)
+    //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b15Type$LT$f16$GT$
+    //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<f16>::
+    //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<f16>)
+    //[v0]~^^^^ ERROR symbol-name(_RMs8_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeC3f16E)
+    //[v0]~| ERROR ::b::Type<f16>>)
+    //[v0]~| ERROR demangling-alt(<a::b::Type<f16>>)
+    impl Type<f16> {}
+
+    #[rustc_symbol_name]
+    //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b15Type$LT$f32$GT$
+    //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<f32>::
+    //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<f32>)
+    //[v0]~^^^^ ERROR symbol-name(_RMs9_NvCsCRATE_HASH_1a1bINtB<REF>_4TypefE)
+    //[v0]~| ERROR ::b::Type<f32>>)
+    //[v0]~| ERROR demangling-alt(<a::b::Type<f32>>)
     impl Type<f32> {}
 
     #[rustc_symbol_name]
-    //~^ ERROR symbol-name(_ZN1a1b15Type$LT$f64$GT$
-    //~| ERROR demangling(a::b::Type<f64>::
-    //~| ERROR demangling-alt(a::b::Type<f64>)
+    //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b15Type$LT$f64$GT$
+    //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<f64>::
+    //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<f64>)
+    //[v0]~^^^^ ERROR symbol-name(_RMsa_NvCsCRATE_HASH_1a1bINtB<REF>_4TypedE)
+    //[v0]~| ERROR ::b::Type<f64>>)
+    //[v0]~| ERROR demangling-alt(<a::b::Type<f64>>)
     impl Type<f64> {}
 
     #[rustc_symbol_name]
-    //~^ ERROR symbol-name(_ZN1a1b15Type$LT$str$GT$
-    //~| ERROR demangling(a::b::Type<str>::
-    //~| ERROR demangling-alt(a::b::Type<str>)
+    //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b16Type$LT$f128$GT$
+    //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<f128>::
+    //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<f128>)
+    //[v0]~^^^^ ERROR symbol-name(_RMsb_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeC4f128E)
+    //[v0]~| ERROR ::b::Type<f128>>)
+    //[v0]~| ERROR demangling-alt(<a::b::Type<f128>>)
+    impl Type<f128> {}
+
+    #[rustc_symbol_name]
+    //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b15Type$LT$str$GT$
+    //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<str>::
+    //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<str>)
+    //[v0]~^^^^ ERROR symbol-name(_RMsc_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeeE)
+    //[v0]~| ERROR ::b::Type<str>>)
+    //[v0]~| ERROR demangling-alt(<a::b::Type<str>>)
     impl Type<str> {}
 
     #[rustc_symbol_name]
-    //~^ ERROR symbol-name(_ZN1a1b17Type$LT$$u21$$GT$
-    //~| ERROR demangling(a::b::Type<!>::
-    //~| ERROR demangling-alt(a::b::Type<!>)
+    //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b17Type$LT$$u21$$GT$
+    //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<!>::
+    //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<!>)
+    //[v0]~^^^^ ERROR symbol-name(_RMsd_NvCsCRATE_HASH_1a1bINtB<REF>_4TypezE)
+    //[v0]~| ERROR ::b::Type<!>>)
+    //[v0]~| ERROR demangling-alt(<a::b::Type<!>>)
     impl Type<!> {}
 
     #[rustc_symbol_name]
-    //~^ ERROR symbol-name(_ZN1a1b20Type$LT$$LP$$RP$$GT
-    //~| ERROR demangling(a::b::Type<()>::
-    //~| ERROR demangling-alt(a::b::Type<()>)
+    //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b20Type$LT$$LP$$RP$$GT$
+    //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<()>::
+    //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<()>)
+    //[v0]~^^^^ ERROR symbol-name(_RMse_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeuE)
+    //[v0]~| ERROR ::b::Type<()>>)
+    //[v0]~| ERROR demangling-alt(<a::b::Type<()>>)
     impl Type<()> {}
 
     #[rustc_symbol_name]
-    //~^ ERROR symbol-name(_ZN1a1b25Type$LT$$LP$u8$C$$RP$$GT$
-    //~| ERROR demangling(a::b::Type<(u8,)>::
-    //~| ERROR demangling-alt(a::b::Type<(u8,)>)
+    //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b25Type$LT$$LP$u8$C$$RP$$GT$
+    //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<(u8,)>::
+    //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<(u8,)>)
+    //[v0]~^^^^ ERROR symbol-name(_RMsf_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeThEE)
+    //[v0]~| ERROR ::b::Type<(u8,)>>)
+    //[v0]~| ERROR demangling-alt(<a::b::Type<(u8,)>>)
     impl Type<(u8,)> {}
 
     #[rustc_symbol_name]
-    //~^ ERROR symbol-name(_ZN1a1b28Type$LT$$LP$u8$C$u16$RP$$GT$
-    //~| ERROR demangling(a::b::Type<(u8,u16)>::
-    //~| ERROR demangling-alt(a::b::Type<(u8,u16)>)
-    impl Type<(u8,u16)> {}
+    //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b28Type$LT$$LP$u8$C$u16$RP$$GT$
+    //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<(u8,u16)>::
+    //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<(u8,u16)>)
+    //[v0]~^^^^ ERROR symbol-name(_RMsg_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeThtEE)
+    //[v0]~| ERROR ::b::Type<(u8, u16)>>)
+    //[v0]~| ERROR demangling-alt(<a::b::Type<(u8, u16)>>)
+    impl Type<(u8, u16)> {}
 
     #[rustc_symbol_name]
-    //~^ ERROR symbol-name(_ZN1a1b34Type$LT$$LP$u8$C$u16$C$u32$RP$$GT$
-    //~| ERROR demangling(a::b::Type<(u8,u16,u32)>::
-    //~| ERROR demangling-alt(a::b::Type<(u8,u16,u32)>)
-    impl Type<(u8,u16,u32)> {}
+    //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b34Type$LT$$LP$u8$C$u16$C$u32$RP$$GT$
+    //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<(u8,u16,u32)>::
+    //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<(u8,u16,u32)>)
+    //[v0]~^^^^ ERROR symbol-name(_RMsh_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeThtmEE)
+    //[v0]~| ERROR ::b::Type<(u8, u16, u32)>>)
+    //[v0]~| ERROR demangling-alt(<a::b::Type<(u8, u16, u32)>>)
+    impl Type<(u8, u16, u32)> {}
 
     #[rustc_symbol_name]
-    //~^ ERROR symbol-name(_ZN1a1b28Type$LT$$BP$const$u20$u8$GT$
-    //~| ERROR demangling(a::b::Type<*const u8>::
-    //~| ERROR demangling-alt(a::b::Type<*const u8>)
+    //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b28Type$LT$$BP$const$u20$u8$GT$
+    //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<*const u8>::
+    //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<*const u8>)
+    //[v0]~^^^^ ERROR symbol-name(_RMsi_NvCsCRATE_HASH_1a1bINtB<REF>_4TypePhE)
+    //[v0]~| ERROR ::b::Type<*const u8>>)
+    //[v0]~| ERROR demangling-alt(<a::b::Type<*const u8>>)
     impl Type<*const u8> {}
 
     #[rustc_symbol_name]
-    //~^ ERROR symbol-name(_ZN1a1b26Type$LT$$BP$mut$u20$u8$GT$
-    //~| ERROR demangling(a::b::Type<*mut u8>::
-    //~| ERROR demangling-alt(a::b::Type<*mut u8>)
+    //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b26Type$LT$$BP$mut$u20$u8$GT$
+    //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<*mut u8>::
+    //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<*mut u8>)
+    //[v0]~^^^^ ERROR symbol-name(_RMsj_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeOhE)
+    //[v0]~| ERROR ::b::Type<*mut u8>>)
+    //[v0]~| ERROR demangling-alt(<a::b::Type<*mut u8>>)
     impl Type<*mut u8> {}
 
     #[rustc_symbol_name]
-    //~^ ERROR symbol-name(_ZN1a1b19Type$LT$$RF$str$GT$
-    //~| ERROR demangling(a::b::Type<&str>::
-    //~| ERROR demangling-alt(a::b::Type<&str>)
+    //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b19Type$LT$$RF$str$GT$
+    //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<&str>::
+    //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<&str>)
+    //[v0]~^^^^ ERROR symbol-name(_RMsk_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeReE)
+    //[v0]~| ERROR ::b::Type<&str>>)
+    //[v0]~| ERROR demangling-alt(<a::b::Type<&str>>)
     impl Type<&str> {}
 
     #[rustc_symbol_name]
-    //~^ ERROR symbol-name(_ZN1a1b27Type$LT$$RF$mut$u20$str$GT$
-    //~| ERROR demangling(a::b::Type<&mut str>::
-    //~| ERROR demangling-alt(a::b::Type<&mut str>)
+    //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b27Type$LT$$RF$mut$u20$str$GT$
+    //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<&mut str>::
+    //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<&mut str>)
+    //[v0]~^^^^ ERROR symbol-name(_RMsl_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeQeE)
+    //[v0]~| ERROR ::b::Type<&mut str>>)
+    //[v0]~| ERROR demangling-alt(<a::b::Type<&mut str>>)
     impl Type<&mut str> {}
 
     #[rustc_symbol_name]
-    //~^ ERROR symbol-name(_ZN1a1b35Type$LT$$u5b$u8$u3b$$u20$0$u5d$$GT$
-    //~| ERROR demangling(a::b::Type<[u8; 0]>::
-    //~| ERROR demangling-alt(a::b::Type<[u8; 0]>)
+    //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b35Type$LT$$u5b$u8$u3b$$u20$0$u5d$$GT$
+    //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<[u8; 0]>::
+    //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<[u8; 0]>)
+    //[v0]~^^^^ ERROR symbol-name(_RMsm_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeAhj0_E)
+    //[v0]~| ERROR ::b::Type<[u8; 0usize]>>)
+    //[v0]~| ERROR demangling-alt(<a::b::Type<[u8; 0]>>)
     impl Type<[u8; 0]> {}
 
     #[rustc_symbol_name]
-    //~^ ERROR symbol-name(_ZN1a1b22Type$LT$fn$LP$$RP$$GT$
-    //~| ERROR demangling(a::b::Type<fn()>::
-    //~| ERROR demangling-alt(a::b::Type<fn()>)
+    //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b22Type$LT$fn$LP$$RP$$GT$
+    //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<fn()>::
+    //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<fn()>)
+    //[v0]~^^^^ ERROR symbol-name(_RMsn_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeFEuE)
+    //[v0]~| ERROR ::b::Type<fn()>>)
+    //[v0]~| ERROR demangling-alt(<a::b::Type<fn()>>)
     impl Type<fn()> {}
 
     #[rustc_symbol_name]
-    //~^ ERROR symbol-name(_ZN1a1b60Type$LT$unsafe$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RP$$GT$
-    //~| ERROR demangling(a::b::Type<unsafe extern "C" fn()>::
-    //~| ERROR demangling-alt(a::b::Type<unsafe extern "C" fn()>)
+    //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b60Type$LT$unsafe$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RP$$GT$
+    //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<unsafe extern "C" fn()>::
+    //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<unsafe extern "C" fn()>)
+    //[v0]~^^^^ ERROR symbol-name(_RMso_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeFUKCEuE)
+    //[v0]~| ERROR ::b::Type<unsafe extern "C" fn()>>)
+    //[v0]~| ERROR demangling-alt(<a::b::Type<unsafe extern "C" fn()>>)
     impl Type<unsafe extern "C" fn()> {}
 
     #[rustc_symbol_name]
-    //~^ ERROR symbol-name(_ZN1a1b34Type$LT$$u5b$T$u3b$$u20$N$u5d$$GT$
-    //~| ERROR demangling(a::b::Type<[T; N]>::
-    //~| ERROR demangling-alt(a::b::Type<[T; N]>)
+    //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b34Type$LT$$u5b$T$u3b$$u20$N$u5d$$GT$
+    //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<[T; N]>::
+    //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<[T; N]>)
+    //[v0]~^^^^ ERROR symbol-name(_RMsp_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeAppEB<REF>_)
+    //[v0]~| ERROR ::b::Type<[_; _]>>)
+    //[v0]~| ERROR demangling-alt(<a::b::Type<[_; _]>>)
     impl<const N: usize, T> Type<[T; N]> {}
 }
 
diff --git a/tests/ui/symbol-names/types.v0.stderr b/tests/ui/symbol-names/types.v0.stderr
new file mode 100644
index 00000000000..58680e00202
--- /dev/null
+++ b/tests/ui/symbol-names/types.v0.stderr
@@ -0,0 +1,506 @@
+error: symbol-name(_RMNvCsCRATE_HASH_1a1bINtB<REF>_4TypebE)
+  --> $DIR/types.rs:18:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<a[HASH]::b::Type<bool>>)
+  --> $DIR/types.rs:18:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<a::b::Type<bool>>)
+  --> $DIR/types.rs:18:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMs_NvCsCRATE_HASH_1a1bINtB<REF>_4TypecE)
+  --> $DIR/types.rs:27:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<a[HASH]::b::Type<char>>)
+  --> $DIR/types.rs:27:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<a::b::Type<char>>)
+  --> $DIR/types.rs:27:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMs0_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeaE)
+  --> $DIR/types.rs:36:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<a[HASH]::b::Type<i8>>)
+  --> $DIR/types.rs:36:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<a::b::Type<i8>>)
+  --> $DIR/types.rs:36:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMs1_NvCsCRATE_HASH_1a1bINtB<REF>_4TypesE)
+  --> $DIR/types.rs:45:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<a[HASH]::b::Type<i16>>)
+  --> $DIR/types.rs:45:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<a::b::Type<i16>>)
+  --> $DIR/types.rs:45:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMs2_NvCsCRATE_HASH_1a1bINtB<REF>_4TypelE)
+  --> $DIR/types.rs:54:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<a[HASH]::b::Type<i32>>)
+  --> $DIR/types.rs:54:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<a::b::Type<i32>>)
+  --> $DIR/types.rs:54:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMs3_NvCsCRATE_HASH_1a1bINtB<REF>_4TypexE)
+  --> $DIR/types.rs:63:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<a[HASH]::b::Type<i64>>)
+  --> $DIR/types.rs:63:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<a::b::Type<i64>>)
+  --> $DIR/types.rs:63:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMs4_NvCsCRATE_HASH_1a1bINtB<REF>_4TypehE)
+  --> $DIR/types.rs:72:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<a[HASH]::b::Type<u8>>)
+  --> $DIR/types.rs:72:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<a::b::Type<u8>>)
+  --> $DIR/types.rs:72:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMs5_NvCsCRATE_HASH_1a1bINtB<REF>_4TypetE)
+  --> $DIR/types.rs:81:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<a[HASH]::b::Type<u16>>)
+  --> $DIR/types.rs:81:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<a::b::Type<u16>>)
+  --> $DIR/types.rs:81:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMs6_NvCsCRATE_HASH_1a1bINtB<REF>_4TypemE)
+  --> $DIR/types.rs:90:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<a[HASH]::b::Type<u32>>)
+  --> $DIR/types.rs:90:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<a::b::Type<u32>>)
+  --> $DIR/types.rs:90:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMs7_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeyE)
+  --> $DIR/types.rs:99:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<a[HASH]::b::Type<u64>>)
+  --> $DIR/types.rs:99:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<a::b::Type<u64>>)
+  --> $DIR/types.rs:99:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMs8_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeC3f16E)
+  --> $DIR/types.rs:108:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<a[HASH]::b::Type<f16>>)
+  --> $DIR/types.rs:108:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<a::b::Type<f16>>)
+  --> $DIR/types.rs:108:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMs9_NvCsCRATE_HASH_1a1bINtB<REF>_4TypefE)
+  --> $DIR/types.rs:117:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<a[HASH]::b::Type<f32>>)
+  --> $DIR/types.rs:117:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<a::b::Type<f32>>)
+  --> $DIR/types.rs:117:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMsa_NvCsCRATE_HASH_1a1bINtB<REF>_4TypedE)
+  --> $DIR/types.rs:126:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<a[HASH]::b::Type<f64>>)
+  --> $DIR/types.rs:126:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<a::b::Type<f64>>)
+  --> $DIR/types.rs:126:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMsb_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeC4f128E)
+  --> $DIR/types.rs:135:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<a[HASH]::b::Type<f128>>)
+  --> $DIR/types.rs:135:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<a::b::Type<f128>>)
+  --> $DIR/types.rs:135:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMsc_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeeE)
+  --> $DIR/types.rs:144:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<a[HASH]::b::Type<str>>)
+  --> $DIR/types.rs:144:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<a::b::Type<str>>)
+  --> $DIR/types.rs:144:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMsd_NvCsCRATE_HASH_1a1bINtB<REF>_4TypezE)
+  --> $DIR/types.rs:153:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<a[HASH]::b::Type<!>>)
+  --> $DIR/types.rs:153:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<a::b::Type<!>>)
+  --> $DIR/types.rs:153:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMse_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeuE)
+  --> $DIR/types.rs:162:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<a[HASH]::b::Type<()>>)
+  --> $DIR/types.rs:162:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<a::b::Type<()>>)
+  --> $DIR/types.rs:162:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMsf_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeThEE)
+  --> $DIR/types.rs:171:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<a[HASH]::b::Type<(u8,)>>)
+  --> $DIR/types.rs:171:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<a::b::Type<(u8,)>>)
+  --> $DIR/types.rs:171:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMsg_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeThtEE)
+  --> $DIR/types.rs:180:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<a[HASH]::b::Type<(u8, u16)>>)
+  --> $DIR/types.rs:180:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<a::b::Type<(u8, u16)>>)
+  --> $DIR/types.rs:180:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMsh_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeThtmEE)
+  --> $DIR/types.rs:189:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<a[HASH]::b::Type<(u8, u16, u32)>>)
+  --> $DIR/types.rs:189:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<a::b::Type<(u8, u16, u32)>>)
+  --> $DIR/types.rs:189:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMsi_NvCsCRATE_HASH_1a1bINtB<REF>_4TypePhE)
+  --> $DIR/types.rs:198:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<a[HASH]::b::Type<*const u8>>)
+  --> $DIR/types.rs:198:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<a::b::Type<*const u8>>)
+  --> $DIR/types.rs:198:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMsj_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeOhE)
+  --> $DIR/types.rs:207:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<a[HASH]::b::Type<*mut u8>>)
+  --> $DIR/types.rs:207:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<a::b::Type<*mut u8>>)
+  --> $DIR/types.rs:207:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMsk_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeReE)
+  --> $DIR/types.rs:216:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<a[HASH]::b::Type<&str>>)
+  --> $DIR/types.rs:216:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<a::b::Type<&str>>)
+  --> $DIR/types.rs:216:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMsl_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeQeE)
+  --> $DIR/types.rs:225:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<a[HASH]::b::Type<&mut str>>)
+  --> $DIR/types.rs:225:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<a::b::Type<&mut str>>)
+  --> $DIR/types.rs:225:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMsm_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeAhj0_E)
+  --> $DIR/types.rs:234:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<a[HASH]::b::Type<[u8; 0usize]>>)
+  --> $DIR/types.rs:234:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<a::b::Type<[u8; 0]>>)
+  --> $DIR/types.rs:234:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMsn_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeFEuE)
+  --> $DIR/types.rs:243:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<a[HASH]::b::Type<fn()>>)
+  --> $DIR/types.rs:243:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<a::b::Type<fn()>>)
+  --> $DIR/types.rs:243:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMso_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeFUKCEuE)
+  --> $DIR/types.rs:252:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<a[HASH]::b::Type<unsafe extern "C" fn()>>)
+  --> $DIR/types.rs:252:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<a::b::Type<unsafe extern "C" fn()>>)
+  --> $DIR/types.rs:252:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMsp_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeAppEB<REF>_)
+  --> $DIR/types.rs:261:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<a[HASH]::b::Type<[_; _]>>)
+  --> $DIR/types.rs:261:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<a::b::Type<[_; _]>>)
+  --> $DIR/types.rs:261:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 84 previous errors
+
diff --git a/tests/ui/symbol-names/types.verbose-legacy.stderr b/tests/ui/symbol-names/types.verbose-legacy.stderr
index a4984d5629f..87c3acae0bd 100644
--- a/tests/ui/symbol-names/types.verbose-legacy.stderr
+++ b/tests/ui/symbol-names/types.verbose-legacy.stderr
@@ -1,470 +1,506 @@
 error: symbol-name(_ZN1a1b16Type$LT$bool$GT$17h[HASH]E)
-  --> $DIR/types.rs:13:5
+  --> $DIR/types.rs:18:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<bool>::h[HASH])
-  --> $DIR/types.rs:13:5
+  --> $DIR/types.rs:18:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<bool>)
-  --> $DIR/types.rs:13:5
+  --> $DIR/types.rs:18:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b16Type$LT$char$GT$17h[HASH]E)
-  --> $DIR/types.rs:19:5
+  --> $DIR/types.rs:27:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<char>::h[HASH])
-  --> $DIR/types.rs:19:5
+  --> $DIR/types.rs:27:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<char>)
-  --> $DIR/types.rs:19:5
+  --> $DIR/types.rs:27:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b14Type$LT$i8$GT$17h[HASH]E)
-  --> $DIR/types.rs:25:5
+  --> $DIR/types.rs:36:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<i8>::h[HASH])
-  --> $DIR/types.rs:25:5
+  --> $DIR/types.rs:36:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<i8>)
-  --> $DIR/types.rs:25:5
+  --> $DIR/types.rs:36:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b15Type$LT$i16$GT$17h[HASH]E)
-  --> $DIR/types.rs:31:5
+  --> $DIR/types.rs:45:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<i16>::h[HASH])
-  --> $DIR/types.rs:31:5
+  --> $DIR/types.rs:45:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<i16>)
-  --> $DIR/types.rs:31:5
+  --> $DIR/types.rs:45:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b15Type$LT$i32$GT$17h[HASH]E)
-  --> $DIR/types.rs:37:5
+  --> $DIR/types.rs:54:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<i32>::h[HASH])
-  --> $DIR/types.rs:37:5
+  --> $DIR/types.rs:54:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<i32>)
-  --> $DIR/types.rs:37:5
+  --> $DIR/types.rs:54:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b15Type$LT$i64$GT$17h[HASH]E)
-  --> $DIR/types.rs:43:5
+  --> $DIR/types.rs:63:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<i64>::h[HASH])
-  --> $DIR/types.rs:43:5
+  --> $DIR/types.rs:63:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<i64>)
-  --> $DIR/types.rs:43:5
+  --> $DIR/types.rs:63:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b14Type$LT$u8$GT$17h[HASH]E)
-  --> $DIR/types.rs:49:5
+  --> $DIR/types.rs:72:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<u8>::h[HASH])
-  --> $DIR/types.rs:49:5
+  --> $DIR/types.rs:72:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<u8>)
-  --> $DIR/types.rs:49:5
+  --> $DIR/types.rs:72:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b15Type$LT$u16$GT$17h[HASH]E)
-  --> $DIR/types.rs:55:5
+  --> $DIR/types.rs:81:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<u16>::h[HASH])
-  --> $DIR/types.rs:55:5
+  --> $DIR/types.rs:81:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<u16>)
-  --> $DIR/types.rs:55:5
+  --> $DIR/types.rs:81:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b15Type$LT$u32$GT$17h[HASH]E)
-  --> $DIR/types.rs:61:5
+  --> $DIR/types.rs:90:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<u32>::h[HASH])
-  --> $DIR/types.rs:61:5
+  --> $DIR/types.rs:90:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<u32>)
-  --> $DIR/types.rs:61:5
+  --> $DIR/types.rs:90:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b15Type$LT$u64$GT$17h[HASH]E)
-  --> $DIR/types.rs:67:5
+  --> $DIR/types.rs:99:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<u64>::h[HASH])
-  --> $DIR/types.rs:67:5
+  --> $DIR/types.rs:99:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<u64>)
-  --> $DIR/types.rs:67:5
+  --> $DIR/types.rs:99:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_ZN1a1b15Type$LT$f16$GT$17h[HASH]E)
+  --> $DIR/types.rs:108:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(a::b::Type<f16>::h[HASH])
+  --> $DIR/types.rs:108:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(a::b::Type<f16>)
+  --> $DIR/types.rs:108:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b15Type$LT$f32$GT$17h[HASH]E)
-  --> $DIR/types.rs:73:5
+  --> $DIR/types.rs:117:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<f32>::h[HASH])
-  --> $DIR/types.rs:73:5
+  --> $DIR/types.rs:117:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<f32>)
-  --> $DIR/types.rs:73:5
+  --> $DIR/types.rs:117:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b15Type$LT$f64$GT$17h[HASH]E)
-  --> $DIR/types.rs:79:5
+  --> $DIR/types.rs:126:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<f64>::h[HASH])
-  --> $DIR/types.rs:79:5
+  --> $DIR/types.rs:126:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<f64>)
-  --> $DIR/types.rs:79:5
+  --> $DIR/types.rs:126:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_ZN1a1b16Type$LT$f128$GT$17h[HASH]E)
+  --> $DIR/types.rs:135:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(a::b::Type<f128>::h[HASH])
+  --> $DIR/types.rs:135:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(a::b::Type<f128>)
+  --> $DIR/types.rs:135:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b15Type$LT$str$GT$17h[HASH]E)
-  --> $DIR/types.rs:85:5
+  --> $DIR/types.rs:144:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<str>::h[HASH])
-  --> $DIR/types.rs:85:5
+  --> $DIR/types.rs:144:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<str>)
-  --> $DIR/types.rs:85:5
+  --> $DIR/types.rs:144:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b17Type$LT$$u21$$GT$17h[HASH]E)
-  --> $DIR/types.rs:91:5
+  --> $DIR/types.rs:153:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<!>::h[HASH])
-  --> $DIR/types.rs:91:5
+  --> $DIR/types.rs:153:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<!>)
-  --> $DIR/types.rs:91:5
+  --> $DIR/types.rs:153:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b20Type$LT$$LP$$RP$$GT$17h[HASH]E)
-  --> $DIR/types.rs:97:5
+  --> $DIR/types.rs:162:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<()>::h[HASH])
-  --> $DIR/types.rs:97:5
+  --> $DIR/types.rs:162:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<()>)
-  --> $DIR/types.rs:97:5
+  --> $DIR/types.rs:162:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b25Type$LT$$LP$u8$C$$RP$$GT$17h[HASH]E)
-  --> $DIR/types.rs:103:5
+  --> $DIR/types.rs:171:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<(u8,)>::h[HASH])
-  --> $DIR/types.rs:103:5
+  --> $DIR/types.rs:171:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<(u8,)>)
-  --> $DIR/types.rs:103:5
+  --> $DIR/types.rs:171:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b28Type$LT$$LP$u8$C$u16$RP$$GT$17h[HASH]E)
-  --> $DIR/types.rs:109:5
+  --> $DIR/types.rs:180:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<(u8,u16)>::h[HASH])
-  --> $DIR/types.rs:109:5
+  --> $DIR/types.rs:180:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<(u8,u16)>)
-  --> $DIR/types.rs:109:5
+  --> $DIR/types.rs:180:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b34Type$LT$$LP$u8$C$u16$C$u32$RP$$GT$17h[HASH]E)
-  --> $DIR/types.rs:115:5
+  --> $DIR/types.rs:189:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<(u8,u16,u32)>::h[HASH])
-  --> $DIR/types.rs:115:5
+  --> $DIR/types.rs:189:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<(u8,u16,u32)>)
-  --> $DIR/types.rs:115:5
+  --> $DIR/types.rs:189:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b28Type$LT$$BP$const$u20$u8$GT$17h[HASH]E)
-  --> $DIR/types.rs:121:5
+  --> $DIR/types.rs:198:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<*const u8>::h[HASH])
-  --> $DIR/types.rs:121:5
+  --> $DIR/types.rs:198:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<*const u8>)
-  --> $DIR/types.rs:121:5
+  --> $DIR/types.rs:198:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b26Type$LT$$BP$mut$u20$u8$GT$17h[HASH]E)
-  --> $DIR/types.rs:127:5
+  --> $DIR/types.rs:207:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<*mut u8>::h[HASH])
-  --> $DIR/types.rs:127:5
+  --> $DIR/types.rs:207:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<*mut u8>)
-  --> $DIR/types.rs:127:5
+  --> $DIR/types.rs:207:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b19Type$LT$$RF$str$GT$17h[HASH]E)
-  --> $DIR/types.rs:133:5
+  --> $DIR/types.rs:216:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<&str>::h[HASH])
-  --> $DIR/types.rs:133:5
+  --> $DIR/types.rs:216:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<&str>)
-  --> $DIR/types.rs:133:5
+  --> $DIR/types.rs:216:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b27Type$LT$$RF$mut$u20$str$GT$17h[HASH]E)
-  --> $DIR/types.rs:139:5
+  --> $DIR/types.rs:225:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<&mut str>::h[HASH])
-  --> $DIR/types.rs:139:5
+  --> $DIR/types.rs:225:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<&mut str>)
-  --> $DIR/types.rs:139:5
+  --> $DIR/types.rs:225:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b35Type$LT$$u5b$u8$u3b$$u20$0$u5d$$GT$17h[HASH]E)
-  --> $DIR/types.rs:145:5
+  --> $DIR/types.rs:234:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<[u8; 0]>::h[HASH])
-  --> $DIR/types.rs:145:5
+  --> $DIR/types.rs:234:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<[u8; 0]>)
-  --> $DIR/types.rs:145:5
+  --> $DIR/types.rs:234:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b22Type$LT$fn$LP$$RP$$GT$17h[HASH]E)
-  --> $DIR/types.rs:151:5
+  --> $DIR/types.rs:243:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<fn()>::h[HASH])
-  --> $DIR/types.rs:151:5
+  --> $DIR/types.rs:243:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<fn()>)
-  --> $DIR/types.rs:151:5
+  --> $DIR/types.rs:243:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b60Type$LT$unsafe$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RP$$GT$17h[HASH]E)
-  --> $DIR/types.rs:157:5
+  --> $DIR/types.rs:252:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<unsafe extern "C" fn()>::h[HASH])
-  --> $DIR/types.rs:157:5
+  --> $DIR/types.rs:252:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<unsafe extern "C" fn()>)
-  --> $DIR/types.rs:157:5
+  --> $DIR/types.rs:252:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN1a1b34Type$LT$$u5b$T$u3b$$u20$N$u5d$$GT$17h[HASH]E)
-  --> $DIR/types.rs:163:5
+  --> $DIR/types.rs:261:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(a::b::Type<[T; N]>::h[HASH])
-  --> $DIR/types.rs:163:5
+  --> $DIR/types.rs:261:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(a::b::Type<[T; N]>)
-  --> $DIR/types.rs:163:5
+  --> $DIR/types.rs:261:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 78 previous errors
+error: aborting due to 84 previous errors
 
diff --git a/tests/ui/traits/next-solver/typeck/normalize-in-upvar-collection.rs b/tests/ui/traits/next-solver/typeck/normalize-in-upvar-collection.rs
new file mode 100644
index 00000000000..6567f275240
--- /dev/null
+++ b/tests/ui/traits/next-solver/typeck/normalize-in-upvar-collection.rs
@@ -0,0 +1,19 @@
+//@ compile-flags: -Znext-solver
+//@ check-pass
+
+// Fixes a regression in icu_provider_adaptors where we weren't normalizing the
+// return type of a function type before performing a `Ty::builtin_deref` call,
+// leading to an ICE.
+
+struct Struct {
+    field: i32,
+}
+
+fn hello(f: impl Fn() -> &'static Box<[i32]>, f2: impl Fn() -> &'static Struct) {
+    let cl = || {
+        let x = &f()[0];
+        let y = &f2().field;
+    };
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/static-lifetime-through-closure-issue-122775.rs b/tests/ui/type-alias-impl-trait/static-lifetime-through-closure-issue-122775.rs
new file mode 100644
index 00000000000..1bb0acf9b75
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/static-lifetime-through-closure-issue-122775.rs
@@ -0,0 +1,17 @@
+//@ check-pass
+
+#![feature(type_alias_impl_trait)]
+
+fn spawn<T, F>(future: F) -> impl Sized
+where
+    F: FnOnce() -> T,
+{
+    future
+}
+
+fn spawn_task(sender: &'static ()) -> impl Sized {
+    type Tait = impl Sized + 'static;
+    spawn::<Tait, _>(move || sender)
+}
+
+fn main() {}
diff --git a/tests/ui/unpretty/pretty-let-else.rs b/tests/ui/unpretty/let-else-hir.rs
index 9c231189659..9c231189659 100644
--- a/tests/ui/unpretty/pretty-let-else.rs
+++ b/tests/ui/unpretty/let-else-hir.rs
diff --git a/tests/ui/unpretty/pretty-let-else.stdout b/tests/ui/unpretty/let-else-hir.stdout
index ed55f293876..ed55f293876 100644
--- a/tests/ui/unpretty/pretty-let-else.stdout
+++ b/tests/ui/unpretty/let-else-hir.stdout
diff --git a/tests/ui/unpretty/let-else.rs b/tests/ui/unpretty/let-else.rs
new file mode 100644
index 00000000000..4db6eca99b1
--- /dev/null
+++ b/tests/ui/unpretty/let-else.rs
@@ -0,0 +1,11 @@
+//@ compile-flags: -Zunpretty=expanded
+//@ check-pass
+
+macro_rules! expr {
+    ($e:expr) => { $e };
+}
+
+fn main() {
+    let _ = expr!(1 + 1) else { return; };
+    let _ = expr!(loop {}) else { return; };
+}
diff --git a/tests/ui/unpretty/let-else.stdout b/tests/ui/unpretty/let-else.stdout
new file mode 100644
index 00000000000..4bc4d9e085f
--- /dev/null
+++ b/tests/ui/unpretty/let-else.stdout
@@ -0,0 +1,15 @@
+#![feature(prelude_import)]
+#![no_std]
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+#[macro_use]
+extern crate std;
+//@ compile-flags: -Zunpretty=expanded
+//@ check-pass
+
+macro_rules! expr { ($e:expr) => { $e }; }
+
+fn main() {
+    let _ = 1 + 1 else { return; };
+    let _ = (loop {}) else { return; };
+}
diff --git a/tests/ui/write-fmt-errors.rs b/tests/ui/write-fmt-errors.rs
index f194e25b556..1dafb9a784b 100644
--- a/tests/ui/write-fmt-errors.rs
+++ b/tests/ui/write-fmt-errors.rs
@@ -1,9 +1,11 @@
 //@ run-pass
+//@ needs-unwind
 
 #![feature(io_error_uncategorized)]
 
 use std::fmt;
 use std::io::{self, Error, Write, sink};
+use std::panic::catch_unwind;
 
 struct ErrorDisplay;
 
@@ -15,7 +17,6 @@ impl fmt::Display for ErrorDisplay {
 
 struct ErrorWriter;
 
-const FORMAT_ERROR: io::ErrorKind = io::ErrorKind::Uncategorized;
 const WRITER_ERROR: io::ErrorKind = io::ErrorKind::NotConnected;
 
 impl Write for ErrorWriter {
@@ -27,22 +28,28 @@ impl Write for ErrorWriter {
 }
 
 fn main() {
-    // Test that the error from the formatter is propagated.
-    let res = write!(sink(), "{} {} {}", 1, ErrorDisplay, "bar");
-    assert!(res.is_err(), "formatter error did not propagate");
-    assert_eq!(res.unwrap_err().kind(), FORMAT_ERROR);
-
     // Test that an underlying error is propagated
     let res = write!(ErrorWriter, "abc");
     assert!(res.is_err(), "writer error did not propagate");
 
-    // Writer error
+    // Test that the error from the formatter is detected.
+    let res = catch_unwind(|| write!(sink(), "{} {} {}", 1, ErrorDisplay, "bar"));
+    let err = res.expect_err("formatter error did not lead to panic").downcast::<&str>().unwrap();
+    assert!(
+        err.contains("formatting trait implementation returned an error"),
+        "unexpected panic: {}", err
+    );
+
+    // Writer error when there's some string before the first `{}`
     let res = write!(ErrorWriter, "abc {}", ErrorDisplay);
     assert!(res.is_err(), "writer error did not propagate");
     assert_eq!(res.unwrap_err().kind(), WRITER_ERROR);
 
-    // Formatter error
-    let res = write!(ErrorWriter, "{} abc", ErrorDisplay);
-    assert!(res.is_err(), "formatter error did not propagate");
-    assert_eq!(res.unwrap_err().kind(), FORMAT_ERROR);
+    // Formatter error when the `{}` comes first
+    let res = catch_unwind(|| write!(ErrorWriter, "{} abc", ErrorDisplay));
+    let err = res.expect_err("formatter error did not lead to panic").downcast::<&str>().unwrap();
+    assert!(
+        err.contains("formatting trait implementation returned an error"),
+        "unexpected panic: {}", err
+    );
 }
diff --git a/triagebot.toml b/triagebot.toml
index dd6a03faaaf..ddab6701786 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -310,7 +310,7 @@ trigger_files = [
     "configure",
     "Cargo.toml",
     "config.example.toml",
-    "src/stage0.json",
+    "src/stage0",
     "src/tools/compiletest",
     "src/tools/tidy",
     "src/tools/rustdoc-gui-test",
@@ -370,7 +370,7 @@ trigger_files = [
 [autolabel."T-release"]
 trigger_files = [
     "RELEASES.md",
-    "src/stage0.json",
+    "src/stage0",
     "src/version"
 ]
 
@@ -419,7 +419,7 @@ message_on_add = """\
 - Priority?
 - Regression?
 - Notify people/groups?
-- Needs `I-nominated`?
+- Needs `I-{team}-nominated`?
 """
 message_on_remove = "Issue #{number}'s prioritization request has been removed."
 message_on_close = "Issue #{number} has been closed while requested for prioritization."
@@ -933,11 +933,13 @@ arena = [
 mir = [
     "@davidtwco",
     "@oli-obk",
-    "@matthewjasper"
+    "@matthewjasper",
+    "@saethlin",
 ]
 mir-opt = [
     "@oli-obk",
     "@wesleywiser",
+    "@saethlin",
 ]
 types = [
     "@compiler-errors",
@@ -1003,6 +1005,7 @@ project-exploit-mitigations = [
 "/compiler/rustc_lexer" =                                ["compiler", "lexer"]
 "/compiler/rustc_llvm" =                                 ["@cuviper"]
 "/compiler/rustc_codegen_llvm/src/debuginfo" =           ["compiler", "debuginfo"]
+"/compiler/rustc_codegen_ssa" =                          ["compiler", "@saethlin"]
 "/compiler/rustc_middle/src/mir" =                       ["compiler", "mir"]
 "/compiler/rustc_middle/src/traits" =                    ["compiler", "types"]
 "/compiler/rustc_middle/src/ty" =                        ["compiler", "types"]
@@ -1046,7 +1049,7 @@ project-exploit-mitigations = [
 "/src/librustdoc" =                                      ["rustdoc"]
 "/src/llvm-project" =                                    ["@cuviper"]
 "/src/rustdoc-json-types" =                              ["rustdoc"]
-"/src/stage0.json" =                                     ["bootstrap"]
+"/src/stage0" =                                          ["bootstrap"]
 "/tests/run-make" =                                      ["@jieyouxu"]
 "/tests/ui" =                                            ["compiler"]
 "/src/tools/cargo" =                                     ["@ehuss"]