about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-01-21 13:13:03 +0000
committerbors <bors@rust-lang.org>2024-01-21 13:13:03 +0000
commit70e720bc685e21bbae276445fedf7d89613ecb0d (patch)
treebea46b5cbfb4f8baa9e4b0e34be77eb9600be0da /compiler
parent0c8e1e6f444d28742aff75f8789df69007ca589a (diff)
parent7092c660077d185df375eaf07d649be2b49018d0 (diff)
downloadrust-70e720bc685e21bbae276445fedf7d89613ecb0d.tar.gz
rust-70e720bc685e21bbae276445fedf7d89613ecb0d.zip
Auto merge of #3270 - rust-lang:rustup-2024-01-21, r=RalfJung
Automatic Rustup
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_abi/src/lib.rs9
-rw-r--r--compiler/rustc_ast/src/ast.rs14
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs2
-rw-r--r--compiler/rustc_ast/src/util/classify.rs10
-rw-r--r--compiler/rustc_ast/src/util/literal.rs12
-rw-r--r--compiler/rustc_ast/src/visit.rs2
-rw-r--r--compiler/rustc_ast_lowering/messages.ftl4
-rw-r--r--compiler/rustc_ast_lowering/src/errors.rs8
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs39
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs370
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs6
-rw-r--r--compiler/rustc_ast_lowering/src/pat.rs1
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs5
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs105
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs17
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs25
-rw-r--r--compiler/rustc_borrowck/src/lib.rs2
-rw-r--r--compiler/rustc_borrowck/src/nll.rs5
-rw-r--r--compiler/rustc_borrowck/src/polonius/loan_invalidations.rs2
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs20
-rw-r--r--compiler/rustc_borrowck/src/region_infer/values.rs189
-rw-r--r--compiler/rustc_borrowck/src/type_check/free_region_relations.rs25
-rw-r--r--compiler/rustc_borrowck/src/type_check/input_output.rs13
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs8
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/mod.rs5
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/trace.rs9
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs54
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs6
-rw-r--r--compiler/rustc_builtin_macros/src/lib.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/test.rs21
-rw-r--r--compiler/rustc_codegen_cranelift/Cargo.lock6
-rw-r--r--compiler/rustc_codegen_cranelift/Cargo.toml2
-rw-r--r--compiler/rustc_codegen_cranelift/src/abi/mod.rs13
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs86
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs22
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs24
-rw-r--r--compiler/rustc_codegen_llvm/Cargo.toml2
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs8
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs21
-rw-r--r--compiler/rustc_const_eval/src/const_eval/eval_queries.rs38
-rw-r--r--compiler/rustc_const_eval/src/interpret/memory.rs31
-rw-r--r--compiler/rustc_const_eval/src/interpret/terminator.rs8
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs4
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs2
-rw-r--r--compiler/rustc_data_structures/Cargo.toml2
-rw-r--r--compiler/rustc_data_structures/src/binary_search_util/mod.rs25
-rw-r--r--compiler/rustc_data_structures/src/hashes.rs12
-rw-r--r--compiler/rustc_data_structures/src/marker.rs1
-rw-r--r--compiler/rustc_data_structures/src/stable_hasher.rs14
-rw-r--r--compiler/rustc_data_structures/src/sync.rs56
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs4
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0708.md6
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0795.md4
-rw-r--r--compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs12
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs45
-rw-r--r--compiler/rustc_errors/src/diagnostic_builder.rs17
-rw-r--r--compiler/rustc_errors/src/emitter.rs17
-rw-r--r--compiler/rustc_errors/src/json.rs37
-rw-r--r--compiler/rustc_errors/src/lib.rs37
-rw-r--r--compiler/rustc_expand/messages.ftl3
-rw-r--r--compiler/rustc_expand/src/base.rs62
-rw-r--r--compiler/rustc_expand/src/errors.rs7
-rw-r--r--compiler/rustc_expand/src/mbe/macro_rules.rs1
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs2
-rw-r--r--compiler/rustc_feature/src/unstable.rs4
-rw-r--r--compiler/rustc_hir/src/hir.rs13
-rw-r--r--compiler/rustc_hir/src/intravisit.rs2
-rw-r--r--compiler/rustc_hir/src/lang_items.rs27
-rw-r--r--compiler/rustc_hir/src/stable_hash_impls.rs7
-rw-r--r--compiler/rustc_hir_analysis/Cargo.toml1
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/bounds.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/generics.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/lint.rs32
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs63
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/object_safety.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/region.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs66
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs79
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs48
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs14
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs39
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check.rs46
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs134
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs36
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/test.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/structured_errors.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/variance/mod.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/variance/test.rs13
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs5
-rw-r--r--compiler/rustc_hir_typeck/Cargo.toml1
-rw-r--r--compiler/rustc_hir_typeck/src/autoderef.rs9
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs82
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs235
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs33
-rw-r--r--compiler/rustc_hir_typeck/src/expr_use_visitor.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs12
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs11
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs15
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs28
-rw-r--r--compiler/rustc_hir_typeck/src/mem_categorization.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/method/confirm.rs14
-rw-r--r--compiler/rustc_hir_typeck/src/method/mod.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs36
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs12
-rw-r--r--compiler/rustc_incremental/src/assert_dep_graph.rs8
-rw-r--r--compiler/rustc_incremental/src/persist/dirty_clean.rs3
-rw-r--r--compiler/rustc_index_macros/src/lib.rs6
-rw-r--r--compiler/rustc_index_macros/src/newtype.rs11
-rw-r--r--compiler/rustc_infer/src/infer/at.rs1
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs16
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs37
-rw-r--r--compiler/rustc_infer/src/infer/freshen.rs10
-rw-r--r--compiler/rustc_infer/src/infer/fudge.rs11
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs37
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs7
-rw-r--r--compiler/rustc_infer/src/infer/relate/combine.rs26
-rw-r--r--compiler/rustc_infer/src/infer/relate/generalize.rs15
-rw-r--r--compiler/rustc_infer/src/infer/resolve.rs90
-rw-r--r--compiler/rustc_infer/src/traits/mod.rs21
-rw-r--r--compiler/rustc_infer/src/traits/structural_impls.rs15
-rw-r--r--compiler/rustc_interface/Cargo.toml2
-rw-r--r--compiler/rustc_interface/src/interface.rs4
-rw-r--r--compiler/rustc_interface/src/lib.rs3
-rw-r--r--compiler/rustc_interface/src/tests.rs9
-rw-r--r--compiler/rustc_interface/src/util.rs12
-rw-r--r--compiler/rustc_lexer/src/unescape.rs17
-rw-r--r--compiler/rustc_lint/src/context/diagnostics.rs11
-rw-r--r--compiler/rustc_lint/src/unused.rs2
-rw-r--r--compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs2
-rw-r--r--compiler/rustc_metadata/Cargo.toml2
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs1
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs4
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs4
-rw-r--r--compiler/rustc_middle/Cargo.toml2
-rw-r--r--compiler/rustc_middle/src/arena.rs1
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs58
-rw-r--r--compiler/rustc_middle/src/hir/mod.rs35
-rw-r--r--compiler/rustc_middle/src/infer/unify_key.rs29
-rw-r--r--compiler/rustc_middle/src/lint.rs7
-rw-r--r--compiler/rustc_middle/src/mir/interpret/queries.rs4
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs12
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs64
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs5
-rw-r--r--compiler/rustc_middle/src/mir/tcx.rs12
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs2
-rw-r--r--compiler/rustc_middle/src/query/erase.rs13
-rw-r--r--compiler/rustc_middle/src/query/keys.rs3
-rw-r--r--compiler/rustc_middle/src/query/mod.rs35
-rw-r--r--compiler/rustc_middle/src/query/plumbing.rs12
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs4
-rw-r--r--compiler/rustc_middle/src/traits/query.rs2
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs3
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs59
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs25
-rw-r--r--compiler/rustc_middle/src/ty/trait_def.rs18
-rw-r--r--compiler/rustc_middle/src/ty/util.rs14
-rw-r--r--compiler/rustc_middle/src/util/find_self_call.rs9
-rw-r--r--compiler/rustc_mir_build/Cargo.toml1
-rw-r--r--compiler/rustc_mir_build/messages.ftl5
-rw-r--r--compiler/rustc_mir_build/src/build/custom/parse/instruction.rs5
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs10
-rw-r--r--compiler/rustc_mir_build/src/build/expr/into.rs6
-rw-r--r--compiler/rustc_mir_build/src/build/matches/test.rs10
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs5
-rw-r--r--compiler/rustc_mir_build/src/build/scope.rs5
-rw-r--r--compiler/rustc_mir_build/src/errors.rs10
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs3
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/mod.rs56
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs21
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/elaborate_drops.rs7
-rw-r--r--compiler/rustc_mir_dataflow/src/lib.rs1
-rw-r--r--compiler/rustc_mir_dataflow/src/move_paths/builder.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/points.rs156
-rw-r--r--compiler/rustc_mir_dataflow/src/rustc_peek.rs2
-rw-r--r--compiler/rustc_mir_transform/src/coroutine.rs6
-rw-r--r--compiler/rustc_mir_transform/src/coverage/graph.rs244
-rw-r--r--compiler/rustc_mir_transform/src/dead_store_elimination.rs18
-rw-r--r--compiler/rustc_mir_transform/src/deduce_param_attrs.rs2
-rw-r--r--compiler/rustc_mir_transform/src/dest_prop.rs83
-rw-r--r--compiler/rustc_mir_transform/src/errors.rs2
-rw-r--r--compiler/rustc_mir_transform/src/function_item_references.rs9
-rw-r--r--compiler/rustc_mir_transform/src/gvn.rs254
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs17
-rw-r--r--compiler/rustc_mir_transform/src/instsimplify.rs4
-rw-r--r--compiler/rustc_mir_transform/src/jump_threading.rs262
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs22
-rw-r--r--compiler/rustc_mir_transform/src/lint.rs2
-rw-r--r--compiler/rustc_mir_transform/src/lower_intrinsics.rs24
-rw-r--r--compiler/rustc_mir_transform/src/lower_slice_len.rs2
-rw-r--r--compiler/rustc_mir_transform/src/promote_consts.rs7
-rw-r--r--compiler/rustc_mir_transform/src/shim.rs5
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs108
-rw-r--r--compiler/rustc_monomorphize/src/partitioning.rs4
-rw-r--r--compiler/rustc_parse/messages.ftl7
-rw-r--r--compiler/rustc_parse/src/errors.rs61
-rw-r--r--compiler/rustc_parse/src/lexer/unescape_error_reporting.rs3
-rw-r--r--compiler/rustc_parse/src/parser/attr.rs28
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs30
-rw-r--r--compiler/rustc_parse/src/parser/stmt.rs15
-rw-r--r--compiler/rustc_passes/src/dead.rs23
-rw-r--r--compiler/rustc_passes/src/entry.rs4
-rw-r--r--compiler/rustc_passes/src/hir_stats.rs6
-rw-r--r--compiler/rustc_pattern_analysis/Cargo.toml7
-rw-r--r--compiler/rustc_pattern_analysis/src/constructor.rs34
-rw-r--r--compiler/rustc_pattern_analysis/src/lib.rs90
-rw-r--r--compiler/rustc_pattern_analysis/src/lints.rs38
-rw-r--r--compiler/rustc_pattern_analysis/src/pat.rs14
-rw-r--r--compiler/rustc_pattern_analysis/src/rustc.rs61
-rw-r--r--compiler/rustc_pattern_analysis/src/usefulness.rs142
-rw-r--r--compiler/rustc_query_impl/Cargo.toml2
-rw-r--r--compiler/rustc_query_system/src/dep_graph/graph.rs2
-rw-r--r--compiler/rustc_query_system/src/dep_graph/serialized.rs1
-rw-r--r--compiler/rustc_query_system/src/ich/hcx.rs35
-rw-r--r--compiler/rustc_query_system/src/ich/impls_hir.rs22
-rw-r--r--compiler/rustc_query_system/src/ich/impls_syntax.rs2
-rw-r--r--compiler/rustc_query_system/src/ich/mod.rs1
-rw-r--r--compiler/rustc_query_system/src/query/caches.rs79
-rw-r--r--compiler/rustc_query_system/src/query/mod.rs10
-rw-r--r--compiler/rustc_query_system/src/query/plumbing.rs5
-rw-r--r--compiler/rustc_resolve/messages.ftl4
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs3
-rw-r--r--compiler/rustc_resolve/src/errors.rs9
-rw-r--r--compiler/rustc_resolve/src/late.rs132
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs9
-rw-r--r--compiler/rustc_resolve/src/lib.rs4
-rw-r--r--compiler/rustc_serialize/src/lib.rs1
-rw-r--r--compiler/rustc_session/messages.ftl2
-rw-r--r--compiler/rustc_session/src/config.rs52
-rw-r--r--compiler/rustc_session/src/errors.rs15
-rw-r--r--compiler/rustc_session/src/options.rs21
-rw-r--r--compiler/rustc_session/src/parse.rs5
-rw-r--r--compiler/rustc_session/src/session.rs22
-rw-r--r--compiler/rustc_smir/src/rustc_internal/mod.rs122
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/mir.rs2
-rw-r--r--compiler/rustc_span/src/hygiene.rs23
-rw-r--r--compiler/rustc_span/src/source_map.rs6
-rw-r--r--compiler/rustc_span/src/symbol.rs3
-rw-r--r--compiler/rustc_target/src/spec/base/freebsd.rs1
-rw-r--r--compiler/rustc_target/src/spec/targets/asmjs_unknown_emscripten.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/i386_apple_ios.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_linux_android.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs2
-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.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs4
-rw-r--r--compiler/rustc_trait_selection/src/infer.rs91
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill.rs145
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs45
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs48
-rw-r--r--compiler/rustc_trait_selection/src/traits/misc.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/outlives_bounds.rs210
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs54
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs94
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs17
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs10
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/mod.rs26
-rw-r--r--compiler/rustc_traits/src/codegen.rs2
-rw-r--r--compiler/rustc_traits/src/implied_outlives_bounds.rs18
-rw-r--r--compiler/rustc_traits/src/normalize_projection_ty.rs2
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs6
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs4
-rw-r--r--compiler/rustc_type_ir/src/lib.rs6
-rw-r--r--compiler/stable_mir/src/ty.rs4
328 files changed, 4216 insertions, 2960 deletions
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index ea194e10def..c45a4a410f9 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -49,7 +49,14 @@ bitflags! {
                                  | ReprFlags::IS_LINEAR.bits();
     }
 }
-rustc_data_structures::external_bitflags_debug! { ReprFlags }
+
+// This is the same as `rustc_data_structures::external_bitflags_debug` but without the
+// `rustc_data_structures` to make it build on stable.
+impl std::fmt::Debug for ReprFlags {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        bitflags::parser::to_writer(self, f)
+    }
+}
 
 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
 #[cfg_attr(feature = "nightly", derive(Encodable_Generic, Decodable_Generic, HashStable_Generic))]
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 21077c312bd..7f5213431f7 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -625,7 +625,8 @@ impl Pat {
             | PatKind::Range(..)
             | PatKind::Ident(..)
             | PatKind::Path(..)
-            | PatKind::MacCall(_) => {}
+            | PatKind::MacCall(_)
+            | PatKind::Err(_) => {}
         }
     }
 
@@ -809,6 +810,9 @@ pub enum PatKind {
 
     /// A macro pattern; pre-expansion.
     MacCall(P<MacCall>),
+
+    /// Placeholder for a pattern that wasn't syntactically well formed in some way.
+    Err(ErrorGuaranteed),
 }
 
 /// Whether the `..` is present in a struct fields pattern.
@@ -3300,9 +3304,13 @@ mod size_asserts {
     static_assert_size!(Impl, 136);
     static_assert_size!(Item, 136);
     static_assert_size!(ItemKind, 64);
-    static_assert_size!(LitKind, 24);
+    // This can be removed after i128:128 is in the bootstrap compiler's target.
+    #[cfg(not(bootstrap))]
+    static_assert_size!(LitKind, 32);
     static_assert_size!(Local, 72);
-    static_assert_size!(MetaItemLit, 40);
+    // This can be removed after i128:128 is in the bootstrap compiler's target.
+    #[cfg(not(bootstrap))]
+    static_assert_size!(MetaItemLit, 48);
     static_assert_size!(Param, 40);
     static_assert_size!(Pat, 72);
     static_assert_size!(Path, 24);
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 450555d0cb5..90677151d25 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -1267,7 +1267,7 @@ pub fn noop_visit_pat<T: MutVisitor>(pat: &mut P<Pat>, vis: &mut T) {
     let Pat { id, kind, span, tokens } = pat.deref_mut();
     vis.visit_id(id);
     match kind {
-        PatKind::Wild | PatKind::Rest | PatKind::Never => {}
+        PatKind::Wild | PatKind::Rest | PatKind::Never | PatKind::Err(_) => {}
         PatKind::Ident(_binding_mode, ident, sub) => {
             vis.visit_ident(ident);
             visit_opt(sub, |sub| vis.visit_pat(sub));
diff --git a/compiler/rustc_ast/src/util/classify.rs b/compiler/rustc_ast/src/util/classify.rs
index 65036bcdc36..098b8f2d6d0 100644
--- a/compiler/rustc_ast/src/util/classify.rs
+++ b/compiler/rustc_ast/src/util/classify.rs
@@ -2,7 +2,7 @@
 
 // Predicates on exprs and stmts that the pretty-printer and parser use
 
-use crate::ast;
+use crate::{ast, token::Delimiter};
 
 /// Does this expression require a semicolon to be treated
 /// as a statement? The negation of this: 'can this expression
@@ -59,8 +59,12 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
             | While(..)
             | ConstBlock(_) => break Some(expr),
 
-            // FIXME: These can end in `}`, but changing these would break stable code.
-            InlineAsm(_) | OffsetOf(_, _) | MacCall(_) | IncludedBytes(_) | FormatArgs(_) => {
+            MacCall(mac) => {
+                break (mac.args.delim == Delimiter::Brace).then_some(expr);
+            }
+
+            InlineAsm(_) | OffsetOf(_, _) | IncludedBytes(_) | FormatArgs(_) => {
+                // These should have been denied pre-expansion.
                 break None;
             }
 
diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs
index 92b9adf1db7..fbae4964588 100644
--- a/compiler/rustc_ast/src/util/literal.rs
+++ b/compiler/rustc_ast/src/util/literal.rs
@@ -8,7 +8,6 @@ use rustc_lexer::unescape::{
 };
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::Span;
-use std::ops::Range;
 use std::{ascii, fmt, str};
 
 // Escapes a string, represented as a symbol. Reuses the original symbol,
@@ -39,7 +38,6 @@ pub enum LitError {
     InvalidFloatSuffix,
     NonDecimalFloat(u32),
     IntTooLarge(u32),
-    NulInCStr(Range<usize>),
 }
 
 impl LitKind {
@@ -156,10 +154,7 @@ impl LitKind {
                 let s = symbol.as_str();
                 let mut buf = Vec::with_capacity(s.len());
                 let mut error = Ok(());
-                unescape_c_string(s, Mode::CStr, &mut |span, c| match c {
-                    Ok(CStrUnit::Byte(0) | CStrUnit::Char('\0')) => {
-                        error = Err(LitError::NulInCStr(span));
-                    }
+                unescape_c_string(s, Mode::CStr, &mut |_span, c| match c {
                     Ok(CStrUnit::Byte(b)) => buf.push(b),
                     Ok(CStrUnit::Char(c)) => {
                         buf.extend_from_slice(c.encode_utf8(&mut [0; 4]).as_bytes())
@@ -179,10 +174,7 @@ impl LitKind {
                 // can convert the symbol directly to a `Lrc<u8>` on success.
                 let s = symbol.as_str();
                 let mut error = Ok(());
-                unescape_c_string(s, Mode::RawCStr, &mut |span, c| match c {
-                    Ok(CStrUnit::Byte(0) | CStrUnit::Char('\0')) => {
-                        error = Err(LitError::NulInCStr(span));
-                    }
+                unescape_c_string(s, Mode::RawCStr, &mut |_, c| match c {
                     Ok(_) => {}
                     Err(err) => {
                         if err.is_fatal() {
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 3617df931e2..89f50d3a0a7 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -568,7 +568,7 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) {
             walk_list!(visitor, visit_expr, lower_bound);
             walk_list!(visitor, visit_expr, upper_bound);
         }
-        PatKind::Wild | PatKind::Rest | PatKind::Never => {}
+        PatKind::Wild | PatKind::Rest | PatKind::Never | PatKind::Err(_) => {}
         PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => {
             walk_list!(visitor, visit_pat, elems);
         }
diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl
index e7177402db1..8615016cda5 100644
--- a/compiler/rustc_ast_lowering/messages.ftl
+++ b/compiler/rustc_ast_lowering/messages.ftl
@@ -14,10 +14,6 @@ ast_lowering_assoc_ty_parentheses =
 ast_lowering_async_coroutines_not_supported =
     `async` coroutines are not yet supported
 
-ast_lowering_async_non_move_closure_not_supported =
-    `async` non-`move` closures with parameters are not currently supported
-    .help = consider using `let` statements to manually capture variables by reference before entering an `async move` closure
-
 ast_lowering_att_syntax_only_x86 =
     the `att_syntax` option is only supported on x86
 
diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs
index 2811fe104cd..4843d36372d 100644
--- a/compiler/rustc_ast_lowering/src/errors.rs
+++ b/compiler/rustc_ast_lowering/src/errors.rs
@@ -146,14 +146,6 @@ pub struct ClosureCannotBeStatic {
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[help]
-#[diag(ast_lowering_async_non_move_closure_not_supported, code = "E0708")]
-pub struct AsyncNonMoveClosureNotSupported {
-    #[primary_span]
-    pub fn_decl_span: Span,
-}
-
-#[derive(Diagnostic, Clone, Copy)]
 #[diag(ast_lowering_functional_record_update_destructuring_assignment)]
 pub struct FunctionalRecordUpdateDestructuringAssignment {
     #[primary_span]
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index e0b1a10c82e..0920de48eb8 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -1,6 +1,6 @@
 use super::errors::{
-    AsyncCoroutinesNotSupported, AsyncNonMoveClosureNotSupported, AwaitOnlyInAsyncFnAndBlocks,
-    BaseExpressionDoubleDot, ClosureCannotBeStatic, CoroutineTooManyParameters,
+    AsyncCoroutinesNotSupported, AwaitOnlyInAsyncFnAndBlocks, BaseExpressionDoubleDot,
+    ClosureCannotBeStatic, CoroutineTooManyParameters,
     FunctionalRecordUpdateDestructuringAssignment, InclusiveRangeWithNoEnd, MatchArmWithNoBody,
     NeverPatternWithBody, NeverPatternWithGuard, NotSupportedForLifetimeBinderAsyncClosure,
     UnderscoreExprLhsAssign,
@@ -13,7 +13,6 @@ use rustc_ast::*;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
-use rustc_middle::span_bug;
 use rustc_session::errors::report_lit_error;
 use rustc_span::source_map::{respan, Spanned};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -1028,28 +1027,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
         fn_decl_span: Span,
         fn_arg_span: Span,
     ) -> hir::ExprKind<'hir> {
-        let CoroutineKind::Async { closure_id: inner_closure_id, .. } = coroutine_kind else {
-            span_bug!(fn_decl_span, "`async gen` and `gen` closures are not supported, yet");
-        };
-
         if let &ClosureBinder::For { span, .. } = binder {
             self.dcx().emit_err(NotSupportedForLifetimeBinderAsyncClosure { span });
         }
 
         let (binder_clause, generic_params) = self.lower_closure_binder(binder);
 
-        let outer_decl =
-            FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) };
-
         let body = self.with_new_scopes(fn_decl_span, |this| {
-            // FIXME(cramertj): allow `async` non-`move` closures with arguments.
-            if capture_clause == CaptureBy::Ref && !decl.inputs.is_empty() {
-                this.dcx().emit_err(AsyncNonMoveClosureNotSupported { fn_decl_span });
-            }
-
             // Transform `async |x: u8| -> X { ... }` into
             // `|x: u8| || -> X { ... }`.
-            let body_id = this.lower_fn_body(&outer_decl, |this| {
+            let body_id = this.lower_body(|this| {
                 let async_ret_ty = if let FnRetTy::Ty(ty) = &decl.output {
                     let itctx = ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock);
                     Some(hir::FnRetTy::Return(this.lower_ty(ty, &itctx)))
@@ -1057,22 +1044,26 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     None
                 };
 
-                let async_body = this.make_desugared_coroutine_expr(
-                    capture_clause,
-                    inner_closure_id,
-                    async_ret_ty,
+                let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(
+                    decl,
+                    |this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)),
                     body.span,
-                    hir::CoroutineDesugaring::Async,
+                    coroutine_kind,
                     hir::CoroutineSource::Closure,
-                    |this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)),
+                    async_ret_ty,
                 );
-                let hir_id = this.lower_node_id(inner_closure_id);
+
+                let hir_id = this.lower_node_id(coroutine_kind.closure_id());
                 this.maybe_forward_track_caller(body.span, closure_hir_id, hir_id);
-                hir::Expr { hir_id, kind: async_body, span: this.lower_span(body.span) }
+
+                (parameters, expr)
             });
             body_id
         });
 
+        let outer_decl =
+            FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) };
+
         let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params);
         // We need to lower the declaration outside the new scope, because we
         // have to conserve the state of being inside a loop condition for the
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index a3ff02f5f69..dd3f7289a60 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -1082,194 +1082,224 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let (Some(coroutine_kind), Some(body)) = (coroutine_kind, body) else {
             return self.lower_fn_body_block(span, decl, body);
         };
-        let closure_id = coroutine_kind.closure_id();
-
         self.lower_body(|this| {
-            let mut parameters: Vec<hir::Param<'_>> = Vec::new();
-            let mut statements: Vec<hir::Stmt<'_>> = Vec::new();
-
-            // Async function parameters are lowered into the closure body so that they are
-            // captured and so that the drop order matches the equivalent non-async functions.
-            //
-            // from:
-            //
-            //     async fn foo(<pattern>: <ty>, <pattern>: <ty>, <pattern>: <ty>) {
-            //         <body>
-            //     }
-            //
-            // into:
-            //
-            //     fn foo(__arg0: <ty>, __arg1: <ty>, __arg2: <ty>) {
-            //       async move {
-            //         let __arg2 = __arg2;
-            //         let <pattern> = __arg2;
-            //         let __arg1 = __arg1;
-            //         let <pattern> = __arg1;
-            //         let __arg0 = __arg0;
-            //         let <pattern> = __arg0;
-            //         drop-temps { <body> } // see comments later in fn for details
-            //       }
-            //     }
-            //
-            // If `<pattern>` is a simple ident, then it is lowered to a single
-            // `let <pattern> = <pattern>;` statement as an optimization.
-            //
-            // Note that the body is embedded in `drop-temps`; an
-            // equivalent desugaring would be `return { <body>
-            // };`. The key point is that we wish to drop all the
-            // let-bound variables and temporaries created in the body
-            // (and its tail expression!) before we drop the
-            // parameters (c.f. rust-lang/rust#64512).
-            for (index, parameter) in decl.inputs.iter().enumerate() {
-                let parameter = this.lower_param(parameter);
-                let span = parameter.pat.span;
-
-                // Check if this is a binding pattern, if so, we can optimize and avoid adding a
-                // `let <pat> = __argN;` statement. In this case, we do not rename the parameter.
-                let (ident, is_simple_parameter) = match parameter.pat.kind {
-                    hir::PatKind::Binding(hir::BindingAnnotation(ByRef::No, _), _, ident, _) => {
-                        (ident, true)
-                    }
-                    // For `ref mut` or wildcard arguments, we can't reuse the binding, but
-                    // we can keep the same name for the parameter.
-                    // This lets rustdoc render it correctly in documentation.
-                    hir::PatKind::Binding(_, _, ident, _) => (ident, false),
-                    hir::PatKind::Wild => {
-                        (Ident::with_dummy_span(rustc_span::symbol::kw::Underscore), false)
-                    }
-                    _ => {
-                        // Replace the ident for bindings that aren't simple.
-                        let name = format!("__arg{index}");
-                        let ident = Ident::from_str(&name);
-
-                        (ident, false)
-                    }
-                };
-
-                let desugared_span = this.mark_span_with_reason(DesugaringKind::Async, span, None);
-
-                // Construct a parameter representing `__argN: <ty>` to replace the parameter of the
-                // async function.
-                //
-                // If this is the simple case, this parameter will end up being the same as the
-                // original parameter, but with a different pattern id.
-                let stmt_attrs = this.attrs.get(&parameter.hir_id.local_id).copied();
-                let (new_parameter_pat, new_parameter_id) = this.pat_ident(desugared_span, ident);
-                let new_parameter = hir::Param {
-                    hir_id: parameter.hir_id,
-                    pat: new_parameter_pat,
-                    ty_span: this.lower_span(parameter.ty_span),
-                    span: this.lower_span(parameter.span),
-                };
+            let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(
+                decl,
+                |this| this.lower_block_expr(body),
+                body.span,
+                coroutine_kind,
+                hir::CoroutineSource::Fn,
+                None,
+            );
 
-                if is_simple_parameter {
-                    // If this is the simple case, then we only insert one statement that is
-                    // `let <pat> = <pat>;`. We re-use the original argument's pattern so that
-                    // `HirId`s are densely assigned.
-                    let expr = this.expr_ident(desugared_span, ident, new_parameter_id);
-                    let stmt = this.stmt_let_pat(
-                        stmt_attrs,
-                        desugared_span,
-                        Some(expr),
-                        parameter.pat,
-                        hir::LocalSource::AsyncFn,
-                    );
-                    statements.push(stmt);
-                } else {
-                    // If this is not the simple case, then we construct two statements:
-                    //
-                    // ```
-                    // let __argN = __argN;
-                    // let <pat> = __argN;
-                    // ```
-                    //
-                    // The first statement moves the parameter into the closure and thus ensures
-                    // that the drop order is correct.
-                    //
-                    // The second statement creates the bindings that the user wrote.
-
-                    // Construct the `let mut __argN = __argN;` statement. It must be a mut binding
-                    // because the user may have specified a `ref mut` binding in the next
-                    // statement.
-                    let (move_pat, move_id) = this.pat_ident_binding_mode(
-                        desugared_span,
-                        ident,
-                        hir::BindingAnnotation::MUT,
-                    );
-                    let move_expr = this.expr_ident(desugared_span, ident, new_parameter_id);
-                    let move_stmt = this.stmt_let_pat(
-                        None,
-                        desugared_span,
-                        Some(move_expr),
-                        move_pat,
-                        hir::LocalSource::AsyncFn,
-                    );
+            // FIXME(async_fn_track_caller): Can this be moved above?
+            let hir_id = this.lower_node_id(coroutine_kind.closure_id());
+            this.maybe_forward_track_caller(body.span, fn_id, hir_id);
 
-                    // Construct the `let <pat> = __argN;` statement. We re-use the original
-                    // parameter's pattern so that `HirId`s are densely assigned.
-                    let pattern_expr = this.expr_ident(desugared_span, ident, move_id);
-                    let pattern_stmt = this.stmt_let_pat(
-                        stmt_attrs,
-                        desugared_span,
-                        Some(pattern_expr),
-                        parameter.pat,
-                        hir::LocalSource::AsyncFn,
-                    );
+            (parameters, expr)
+        })
+    }
 
-                    statements.push(move_stmt);
-                    statements.push(pattern_stmt);
-                };
+    /// Lowers a desugared coroutine body after moving all of the arguments
+    /// into the body. This is to make sure that the future actually owns the
+    /// arguments that are passed to the function, and to ensure things like
+    /// drop order are stable.
+    pub fn lower_coroutine_body_with_moved_arguments(
+        &mut self,
+        decl: &FnDecl,
+        lower_body: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::Expr<'hir>,
+        body_span: Span,
+        coroutine_kind: CoroutineKind,
+        coroutine_source: hir::CoroutineSource,
+        return_type_hint: Option<hir::FnRetTy<'hir>>,
+    ) -> (&'hir [hir::Param<'hir>], hir::Expr<'hir>) {
+        let mut parameters: Vec<hir::Param<'_>> = Vec::new();
+        let mut statements: Vec<hir::Stmt<'_>> = Vec::new();
+
+        // Async function parameters are lowered into the closure body so that they are
+        // captured and so that the drop order matches the equivalent non-async functions.
+        //
+        // from:
+        //
+        //     async fn foo(<pattern>: <ty>, <pattern>: <ty>, <pattern>: <ty>) {
+        //         <body>
+        //     }
+        //
+        // into:
+        //
+        //     fn foo(__arg0: <ty>, __arg1: <ty>, __arg2: <ty>) {
+        //       async move {
+        //         let __arg2 = __arg2;
+        //         let <pattern> = __arg2;
+        //         let __arg1 = __arg1;
+        //         let <pattern> = __arg1;
+        //         let __arg0 = __arg0;
+        //         let <pattern> = __arg0;
+        //         drop-temps { <body> } // see comments later in fn for details
+        //       }
+        //     }
+        //
+        // If `<pattern>` is a simple ident, then it is lowered to a single
+        // `let <pattern> = <pattern>;` statement as an optimization.
+        //
+        // Note that the body is embedded in `drop-temps`; an
+        // equivalent desugaring would be `return { <body>
+        // };`. The key point is that we wish to drop all the
+        // let-bound variables and temporaries created in the body
+        // (and its tail expression!) before we drop the
+        // parameters (c.f. rust-lang/rust#64512).
+        for (index, parameter) in decl.inputs.iter().enumerate() {
+            let parameter = self.lower_param(parameter);
+            let span = parameter.pat.span;
+
+            // Check if this is a binding pattern, if so, we can optimize and avoid adding a
+            // `let <pat> = __argN;` statement. In this case, we do not rename the parameter.
+            let (ident, is_simple_parameter) = match parameter.pat.kind {
+                hir::PatKind::Binding(hir::BindingAnnotation(ByRef::No, _), _, ident, _) => {
+                    (ident, true)
+                }
+                // For `ref mut` or wildcard arguments, we can't reuse the binding, but
+                // we can keep the same name for the parameter.
+                // This lets rustdoc render it correctly in documentation.
+                hir::PatKind::Binding(_, _, ident, _) => (ident, false),
+                hir::PatKind::Wild => {
+                    (Ident::with_dummy_span(rustc_span::symbol::kw::Underscore), false)
+                }
+                _ => {
+                    // Replace the ident for bindings that aren't simple.
+                    let name = format!("__arg{index}");
+                    let ident = Ident::from_str(&name);
 
-                parameters.push(new_parameter);
-            }
+                    (ident, false)
+                }
+            };
 
-            let mkbody = |this: &mut LoweringContext<'_, 'hir>| {
-                // Create a block from the user's function body:
-                let user_body = this.lower_block_expr(body);
+            let desugared_span = self.mark_span_with_reason(DesugaringKind::Async, span, None);
 
-                // Transform into `drop-temps { <user-body> }`, an expression:
-                let desugared_span =
-                    this.mark_span_with_reason(DesugaringKind::Async, user_body.span, None);
-                let user_body = this.expr_drop_temps(desugared_span, this.arena.alloc(user_body));
+            // Construct a parameter representing `__argN: <ty>` to replace the parameter of the
+            // async function.
+            //
+            // If this is the simple case, this parameter will end up being the same as the
+            // original parameter, but with a different pattern id.
+            let stmt_attrs = self.attrs.get(&parameter.hir_id.local_id).copied();
+            let (new_parameter_pat, new_parameter_id) = self.pat_ident(desugared_span, ident);
+            let new_parameter = hir::Param {
+                hir_id: parameter.hir_id,
+                pat: new_parameter_pat,
+                ty_span: self.lower_span(parameter.ty_span),
+                span: self.lower_span(parameter.span),
+            };
 
-                // As noted above, create the final block like
+            if is_simple_parameter {
+                // If this is the simple case, then we only insert one statement that is
+                // `let <pat> = <pat>;`. We re-use the original argument's pattern so that
+                // `HirId`s are densely assigned.
+                let expr = self.expr_ident(desugared_span, ident, new_parameter_id);
+                let stmt = self.stmt_let_pat(
+                    stmt_attrs,
+                    desugared_span,
+                    Some(expr),
+                    parameter.pat,
+                    hir::LocalSource::AsyncFn,
+                );
+                statements.push(stmt);
+            } else {
+                // If this is not the simple case, then we construct two statements:
                 //
                 // ```
-                // {
-                //   let $param_pattern = $raw_param;
-                //   ...
-                //   drop-temps { <user-body> }
-                // }
+                // let __argN = __argN;
+                // let <pat> = __argN;
                 // ```
-                let body = this.block_all(
+                //
+                // The first statement moves the parameter into the closure and thus ensures
+                // that the drop order is correct.
+                //
+                // The second statement creates the bindings that the user wrote.
+
+                // Construct the `let mut __argN = __argN;` statement. It must be a mut binding
+                // because the user may have specified a `ref mut` binding in the next
+                // statement.
+                let (move_pat, move_id) =
+                    self.pat_ident_binding_mode(desugared_span, ident, hir::BindingAnnotation::MUT);
+                let move_expr = self.expr_ident(desugared_span, ident, new_parameter_id);
+                let move_stmt = self.stmt_let_pat(
+                    None,
                     desugared_span,
-                    this.arena.alloc_from_iter(statements),
-                    Some(user_body),
+                    Some(move_expr),
+                    move_pat,
+                    hir::LocalSource::AsyncFn,
                 );
 
-                this.expr_block(body)
-            };
-            let desugaring_kind = match coroutine_kind {
-                CoroutineKind::Async { .. } => hir::CoroutineDesugaring::Async,
-                CoroutineKind::Gen { .. } => hir::CoroutineDesugaring::Gen,
-                CoroutineKind::AsyncGen { .. } => hir::CoroutineDesugaring::AsyncGen,
+                // Construct the `let <pat> = __argN;` statement. We re-use the original
+                // parameter's pattern so that `HirId`s are densely assigned.
+                let pattern_expr = self.expr_ident(desugared_span, ident, move_id);
+                let pattern_stmt = self.stmt_let_pat(
+                    stmt_attrs,
+                    desugared_span,
+                    Some(pattern_expr),
+                    parameter.pat,
+                    hir::LocalSource::AsyncFn,
+                );
+
+                statements.push(move_stmt);
+                statements.push(pattern_stmt);
             };
-            let coroutine_expr = this.make_desugared_coroutine_expr(
-                CaptureBy::Value { move_kw: rustc_span::DUMMY_SP },
-                closure_id,
-                None,
-                body.span,
-                desugaring_kind,
-                hir::CoroutineSource::Fn,
-                mkbody,
+
+            parameters.push(new_parameter);
+        }
+
+        let mkbody = |this: &mut LoweringContext<'_, 'hir>| {
+            // Create a block from the user's function body:
+            let user_body = lower_body(this);
+
+            // Transform into `drop-temps { <user-body> }`, an expression:
+            let desugared_span =
+                this.mark_span_with_reason(DesugaringKind::Async, user_body.span, None);
+            let user_body = this.expr_drop_temps(desugared_span, this.arena.alloc(user_body));
+
+            // As noted above, create the final block like
+            //
+            // ```
+            // {
+            //   let $param_pattern = $raw_param;
+            //   ...
+            //   drop-temps { <user-body> }
+            // }
+            // ```
+            let body = this.block_all(
+                desugared_span,
+                this.arena.alloc_from_iter(statements),
+                Some(user_body),
             );
 
-            let hir_id = this.lower_node_id(closure_id);
-            this.maybe_forward_track_caller(body.span, fn_id, hir_id);
-            let expr = hir::Expr { hir_id, kind: coroutine_expr, span: this.lower_span(body.span) };
+            this.expr_block(body)
+        };
+        let desugaring_kind = match coroutine_kind {
+            CoroutineKind::Async { .. } => hir::CoroutineDesugaring::Async,
+            CoroutineKind::Gen { .. } => hir::CoroutineDesugaring::Gen,
+            CoroutineKind::AsyncGen { .. } => hir::CoroutineDesugaring::AsyncGen,
+        };
+        let closure_id = coroutine_kind.closure_id();
+        let coroutine_expr = self.make_desugared_coroutine_expr(
+            // FIXME(async_closures): This should only move locals,
+            // and not upvars. Capturing closure upvars by ref doesn't
+            // work right now anyways, so whatever.
+            CaptureBy::Value { move_kw: rustc_span::DUMMY_SP },
+            closure_id,
+            return_type_hint,
+            body_span,
+            desugaring_kind,
+            coroutine_source,
+            mkbody,
+        );
 
-            (this.arena.alloc_from_iter(parameters), expr)
-        })
+        let expr = hir::Expr {
+            hir_id: self.lower_node_id(closure_id),
+            kind: coroutine_expr,
+            span: self.lower_span(body_span),
+        };
+
+        (self.arena.alloc_from_iter(parameters), expr)
     }
 
     fn lower_method_sig(
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 5387880b6e6..057fe65d0af 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -662,9 +662,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let (opt_hash_including_bodies, attrs_hash) = if self.tcx.needs_crate_hash() {
             self.tcx.with_stable_hashing_context(|mut hcx| {
                 let mut stable_hasher = StableHasher::new();
-                hcx.with_hir_bodies(node.def_id(), &bodies, |hcx| {
-                    node.hash_stable(hcx, &mut stable_hasher)
-                });
+                node.hash_stable(&mut hcx, &mut stable_hasher);
+                // Bodies are stored out of line, so we need to pull them explicitly in the hash.
+                bodies.hash_stable(&mut hcx, &mut stable_hasher);
                 let h1 = stable_hasher.finish();
 
                 let mut stable_hasher = StableHasher::new();
diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs
index 1c405fac7e4..0af141ff99a 100644
--- a/compiler/rustc_ast_lowering/src/pat.rs
+++ b/compiler/rustc_ast_lowering/src/pat.rs
@@ -109,6 +109,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     // return inner to be processed in next loop
                     PatKind::Paren(inner) => pattern = inner,
                     PatKind::MacCall(_) => panic!("{:?} shouldn't exist here", pattern.span),
+                    PatKind::Err(guar) => break hir::PatKind::Err(*guar),
                 }
             };
 
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index f4b424259de..c2fd4558fd7 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -1519,6 +1519,11 @@ impl<'a> State<'a> {
                 self.pclose();
             }
             PatKind::MacCall(m) => self.print_mac(m),
+            PatKind::Err(_) => {
+                self.popen();
+                self.word("/*ERROR*/");
+                self.pclose();
+            }
         }
         self.ann.post(self, AnnNode::Pat(pat))
     }
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index b4a73574aa2..da67862a48d 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -26,6 +26,7 @@ use rustc_span::hygiene::DesugaringKind;
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::{BytePos, Span, Symbol};
 use rustc_trait_selection::infer::InferCtxtExt;
+use rustc_trait_selection::traits::error_reporting::FindExprBySpan;
 use rustc_trait_selection::traits::ObligationCtxt;
 use std::iter;
 
@@ -1257,7 +1258,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     return None;
                 };
                 debug!("checking call args for uses of inner_param: {:?}", args);
-                args.contains(&Operand::Move(inner_param)).then_some((loc, term))
+                args.iter()
+                    .map(|a| &a.node)
+                    .any(|a| a == &Operand::Move(inner_param))
+                    .then_some((loc, term))
             })
         else {
             debug!("no uses of inner_param found as a by-move call arg");
@@ -1301,14 +1305,96 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         place: Place<'tcx>,
         borrowed_place: Place<'tcx>,
     ) {
-        if let ([ProjectionElem::Index(_)], [ProjectionElem::Index(_)]) =
-            (&place.projection[..], &borrowed_place.projection[..])
+        let tcx = self.infcx.tcx;
+        let hir = tcx.hir();
+
+        if let ([ProjectionElem::Index(index1)], [ProjectionElem::Index(index2)])
+        | (
+            [ProjectionElem::Deref, ProjectionElem::Index(index1)],
+            [ProjectionElem::Deref, ProjectionElem::Index(index2)],
+        ) = (&place.projection[..], &borrowed_place.projection[..])
         {
-            err.help(
-                "consider using `.split_at_mut(position)` or similar method to obtain \
-                     two mutable non-overlapping sub-slices",
-            )
-            .help("consider using `.swap(index_1, index_2)` to swap elements at the specified indices");
+            let mut note_default_suggestion = || {
+                err.help(
+                    "consider using `.split_at_mut(position)` or similar method to obtain \
+                         two mutable non-overlapping sub-slices",
+                )
+                .help("consider using `.swap(index_1, index_2)` to swap elements at the specified indices");
+            };
+
+            let Some(body_id) = tcx.hir_node(self.mir_hir_id()).body_id() else {
+                note_default_suggestion();
+                return;
+            };
+
+            let mut expr_finder =
+                FindExprBySpan::new(self.body.local_decls[*index1].source_info.span);
+            expr_finder.visit_expr(hir.body(body_id).value);
+            let Some(index1) = expr_finder.result else {
+                note_default_suggestion();
+                return;
+            };
+
+            expr_finder = FindExprBySpan::new(self.body.local_decls[*index2].source_info.span);
+            expr_finder.visit_expr(hir.body(body_id).value);
+            let Some(index2) = expr_finder.result else {
+                note_default_suggestion();
+                return;
+            };
+
+            let sm = tcx.sess.source_map();
+
+            let Ok(index1_str) = sm.span_to_snippet(index1.span) else {
+                note_default_suggestion();
+                return;
+            };
+
+            let Ok(index2_str) = sm.span_to_snippet(index2.span) else {
+                note_default_suggestion();
+                return;
+            };
+
+            let Some(object) = hir.parent_id_iter(index1.hir_id).find_map(|id| {
+                if let hir::Node::Expr(expr) = tcx.hir_node(id)
+                    && let hir::ExprKind::Index(obj, ..) = expr.kind
+                {
+                    Some(obj)
+                } else {
+                    None
+                }
+            }) else {
+                note_default_suggestion();
+                return;
+            };
+
+            let Ok(obj_str) = sm.span_to_snippet(object.span) else {
+                note_default_suggestion();
+                return;
+            };
+
+            let Some(swap_call) = hir.parent_id_iter(object.hir_id).find_map(|id| {
+                if let hir::Node::Expr(call) = tcx.hir_node(id)
+                    && let hir::ExprKind::Call(callee, ..) = call.kind
+                    && let hir::ExprKind::Path(qpath) = callee.kind
+                    && let hir::QPath::Resolved(None, res) = qpath
+                    && let hir::def::Res::Def(_, did) = res.res
+                    && tcx.is_diagnostic_item(sym::mem_swap, did)
+                {
+                    Some(call)
+                } else {
+                    None
+                }
+            }) else {
+                note_default_suggestion();
+                return;
+            };
+
+            err.span_suggestion(
+                swap_call.span,
+                "use `.swap()` to swap elements at the specified indices instead",
+                format!("{obj_str}.swap({index1_str}, {index2_str})"),
+                Applicability::MachineApplicable,
+            );
         }
     }
 
@@ -3242,7 +3328,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         assigned_to, args
                     );
                     for operand in args {
-                        let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) = operand
+                        let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) =
+                            &operand.node
                         else {
                             continue;
                         };
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index 6606be2f9f4..4f66468a865 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -691,7 +691,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         );
                         // Check if one of the arguments to this function is the target place.
                         let found_target = args.iter().any(|arg| {
-                            if let Operand::Move(place) = arg {
+                            if let Operand::Move(place) = arg.node {
                                 if let Some(potential) = place.as_local() {
                                     potential == target
                                 } else {
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index b31325485db..b35d4e16ecc 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -23,6 +23,7 @@ use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
 use rustc_middle::util::{call_kind, CallDesugaringKind};
 use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult};
 use rustc_span::def_id::LocalDefId;
+use rustc_span::source_map::Spanned;
 use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP};
 use rustc_target::abi::{FieldIdx, VariantIdx};
 use rustc_trait_selection::infer::InferCtxtExt;
@@ -111,9 +112,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 debug!("add_moved_or_invoked_closure_note: id={:?}", id);
                 if Some(self.infcx.tcx.parent(id)) == self.infcx.tcx.lang_items().fn_once_trait() {
                     let closure = match args.first() {
-                        Some(Operand::Copy(place) | Operand::Move(place))
-                            if target == place.local_or_deref_local() =>
-                        {
+                        Some(Spanned {
+                            node: Operand::Copy(place) | Operand::Move(place), ..
+                        }) if target == place.local_or_deref_local() => {
                             place.local_or_deref_local().unwrap()
                         }
                         _ => return false,
@@ -1178,9 +1179,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                             } else {
                                 vec![(move_span.shrink_to_hi(), ".clone()".to_string())]
                             };
-                            if let Some(errors) =
-                                self.infcx.could_impl_trait(clone_trait, ty, self.param_env)
-                                && !has_sugg
+                            if let Some(errors) = self.infcx.type_implements_trait_shallow(
+                                clone_trait,
+                                ty,
+                                self.param_env,
+                            ) && !has_sugg
                             {
                                 let msg = match &errors[..] {
                                     [] => "you can `clone` the value and consume it, but this \
@@ -1213,7 +1216,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                                     Applicability::MaybeIncorrect,
                                 );
                                 for error in errors {
-                                    if let FulfillmentErrorCode::CodeSelectionError(
+                                    if let FulfillmentErrorCode::SelectionError(
                                         SelectionError::Unimplemented,
                                     ) = error.code
                                         && let ty::PredicateKind::Clause(ty::ClauseKind::Trait(
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 3b3d440df97..0a6b758efa5 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -1217,19 +1217,22 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     {
                         match self
                             .infcx
-                            .could_impl_trait(clone_trait, ty.peel_refs(), self.param_env)
+                            .type_implements_trait_shallow(
+                                clone_trait,
+                                ty.peel_refs(),
+                                self.param_env,
+                            )
                             .as_deref()
                         {
                             Some([]) => {
-                                // The type implements Clone.
-                                err.span_help(
-                                    expr.span,
-                                    format!(
-                                        "you can `clone` the `{}` value and consume it, but this \
-                                         might not be your desired behavior",
-                                        ty.peel_refs(),
-                                    ),
-                                );
+                                // FIXME: This error message isn't useful, since we're just
+                                // vaguely suggesting to clone a value that already
+                                // implements `Clone`.
+                                //
+                                // A correct suggestion here would take into account the fact
+                                // that inference may be affected by missing types on bindings,
+                                // etc., to improve "tests/ui/borrowck/issue-91206.stderr", for
+                                // example.
                             }
                             None => {
                                 if let hir::ExprKind::MethodCall(segment, _rcvr, [], span) =
@@ -1288,7 +1291,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                                 }
                                 // The type doesn't implement Clone because of unmet obligations.
                                 for error in errors {
-                                    if let traits::FulfillmentErrorCode::CodeSelectionError(
+                                    if let traits::FulfillmentErrorCode::SelectionError(
                                         traits::SelectionError::Unimplemented,
                                     ) = error.code
                                         && let ty::PredicateKind::Clause(ty::ClauseKind::Trait(
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 0457b4e6ddc..b304fb5589f 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -703,7 +703,7 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro
             } => {
                 self.consume_operand(loc, (func, span), flow_state);
                 for arg in args {
-                    self.consume_operand(loc, (arg, span), flow_state);
+                    self.consume_operand(loc, (&arg.node, arg.span), flow_state);
                 }
                 self.mutate_place(loc, (*destination, span), Deep, flow_state);
             }
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index 5b764495922..cc8208e9dc3 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -12,6 +12,7 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self, OpaqueHiddenType, TyCtxt};
 use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
 use rustc_mir_dataflow::move_paths::MoveData;
+use rustc_mir_dataflow::points::DenseLocationMap;
 use rustc_mir_dataflow::ResultsCursor;
 use rustc_span::symbol::sym;
 use std::env;
@@ -27,7 +28,7 @@ use crate::{
     facts::{AllFacts, AllFactsExt, RustcFacts},
     location::LocationTable,
     polonius,
-    region_infer::{values::RegionValueElements, RegionInferenceContext},
+    region_infer::RegionInferenceContext,
     renumber,
     type_check::{self, MirTypeckRegionConstraints, MirTypeckResults},
     universal_regions::UniversalRegions,
@@ -98,7 +99,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
 
     let universal_regions = Rc::new(universal_regions);
 
-    let elements = &Rc::new(RegionValueElements::new(body));
+    let elements = &Rc::new(DenseLocationMap::new(body));
 
     // Run the MIR type-checker.
     let MirTypeckResults { constraints, universal_region_relations, opaque_type_values } =
diff --git a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs
index 232bd741825..5c9056272cc 100644
--- a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs
+++ b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs
@@ -120,7 +120,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'cx, 'tcx> {
             } => {
                 self.consume_operand(location, func);
                 for arg in args {
-                    self.consume_operand(location, arg);
+                    self.consume_operand(location, &arg.node);
                 }
                 self.mutate_place(location, *destination, Deep);
             }
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 948221e9407..89b203f80a4 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -18,7 +18,8 @@ use rustc_middle::mir::{
 };
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::traits::ObligationCauseCode;
-use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
+use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable};
+use rustc_mir_dataflow::points::DenseLocationMap;
 use rustc_span::Span;
 
 use crate::constraints::graph::{self, NormalConstraintGraph, RegionGraph};
@@ -30,8 +31,7 @@ use crate::{
     nll::PoloniusOutput,
     region_infer::reverse_sccs::ReverseSccGraph,
     region_infer::values::{
-        LivenessValues, PlaceholderIndices, RegionElement, RegionValueElements, RegionValues,
-        ToElementIndex,
+        LivenessValues, PlaceholderIndices, RegionElement, RegionValues, ToElementIndex,
     },
     type_check::{free_region_relations::UniversalRegionRelations, Locations},
     universal_regions::UniversalRegions,
@@ -330,7 +330,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         universe_causes: FxIndexMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
         type_tests: Vec<TypeTest<'tcx>>,
         liveness_constraints: LivenessValues,
-        elements: &Rc<RegionValueElements>,
+        elements: &Rc<DenseLocationMap>,
     ) -> Self {
         debug!("universal_regions: {:#?}", universal_regions);
         debug!("outlives constraints: {:#?}", outlives_constraints);
@@ -1145,6 +1145,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         }
 
         let ty = ty.fold_with(&mut OpaqueFolder { tcx });
+        let mut failed = false;
 
         let ty = tcx.fold_regions(ty, |r, _depth| {
             let r_vid = self.to_region_vid(r);
@@ -1160,15 +1161,18 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 .filter(|&u_r| !self.universal_regions.is_local_free_region(u_r))
                 .find(|&u_r| self.eval_equal(u_r, r_vid))
                 .map(|u_r| ty::Region::new_var(tcx, u_r))
-                // In the case of a failure, use `ReErased`. We will eventually
-                // return `None` in this case.
-                .unwrap_or(tcx.lifetimes.re_erased)
+                // In case we could not find a named region to map to,
+                // we will return `None` below.
+                .unwrap_or_else(|| {
+                    failed = true;
+                    r
+                })
         });
 
         debug!("try_promote_type_test_subject: folded ty = {:?}", ty);
 
         // This will be true if we failed to promote some region.
-        if ty.has_erased_regions() {
+        if failed {
             return None;
         }
 
diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs
index dc3ee849d00..e147f62011d 100644
--- a/compiler/rustc_borrowck/src/region_infer/values.rs
+++ b/compiler/rustc_borrowck/src/region_infer/values.rs
@@ -1,101 +1,18 @@
 #![deny(rustc::untranslatable_diagnostic)]
 #![deny(rustc::diagnostic_outside_of_impl)]
+use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_index::bit_set::SparseBitMatrix;
 use rustc_index::interval::IntervalSet;
 use rustc_index::interval::SparseIntervalMatrix;
 use rustc_index::Idx;
-use rustc_index::IndexVec;
-use rustc_middle::mir::{BasicBlock, Body, Location};
+use rustc_middle::mir::{BasicBlock, Location};
 use rustc_middle::ty::{self, RegionVid};
+use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex};
 use std::fmt::Debug;
 use std::rc::Rc;
 
-use crate::dataflow::BorrowIndex;
-
-/// Maps between a `Location` and a `PointIndex` (and vice versa).
-pub(crate) struct RegionValueElements {
-    /// For each basic block, how many points are contained within?
-    statements_before_block: IndexVec<BasicBlock, usize>,
-
-    /// Map backward from each point to the basic block that it
-    /// belongs to.
-    basic_blocks: IndexVec<PointIndex, BasicBlock>,
-
-    num_points: usize,
-}
-
-impl RegionValueElements {
-    pub(crate) fn new(body: &Body<'_>) -> Self {
-        let mut num_points = 0;
-        let statements_before_block: IndexVec<BasicBlock, usize> = body
-            .basic_blocks
-            .iter()
-            .map(|block_data| {
-                let v = num_points;
-                num_points += block_data.statements.len() + 1;
-                v
-            })
-            .collect();
-        debug!("RegionValueElements: statements_before_block={:#?}", statements_before_block);
-        debug!("RegionValueElements: num_points={:#?}", num_points);
-
-        let mut basic_blocks = IndexVec::with_capacity(num_points);
-        for (bb, bb_data) in body.basic_blocks.iter_enumerated() {
-            basic_blocks.extend((0..=bb_data.statements.len()).map(|_| bb));
-        }
-
-        Self { statements_before_block, basic_blocks, num_points }
-    }
-
-    /// Total number of point indices
-    pub(crate) fn num_points(&self) -> usize {
-        self.num_points
-    }
-
-    /// Converts a `Location` into a `PointIndex`. O(1).
-    pub(crate) fn point_from_location(&self, location: Location) -> PointIndex {
-        let Location { block, statement_index } = location;
-        let start_index = self.statements_before_block[block];
-        PointIndex::new(start_index + statement_index)
-    }
-
-    /// Converts a `Location` into a `PointIndex`. O(1).
-    pub(crate) fn entry_point(&self, block: BasicBlock) -> PointIndex {
-        let start_index = self.statements_before_block[block];
-        PointIndex::new(start_index)
-    }
-
-    /// Return the PointIndex for the block start of this index.
-    pub(crate) fn to_block_start(&self, index: PointIndex) -> PointIndex {
-        PointIndex::new(self.statements_before_block[self.basic_blocks[index]])
-    }
-
-    /// Converts a `PointIndex` back to a location. O(1).
-    pub(crate) fn to_location(&self, index: PointIndex) -> Location {
-        assert!(index.index() < self.num_points);
-        let block = self.basic_blocks[index];
-        let start_index = self.statements_before_block[block];
-        let statement_index = index.index() - start_index;
-        Location { block, statement_index }
-    }
-
-    /// Sometimes we get point-indices back from bitsets that may be
-    /// out of range (because they round up to the nearest 2^N number
-    /// of bits). Use this function to filter such points out if you
-    /// like.
-    pub(crate) fn point_in_range(&self, index: PointIndex) -> bool {
-        index.index() < self.num_points
-    }
-}
-
-rustc_index::newtype_index! {
-    /// A single integer representing a `Location` in the MIR control-flow
-    /// graph. Constructed efficiently from `RegionValueElements`.
-    #[orderable]
-    #[debug_format = "PointIndex({})"]
-    pub struct PointIndex {}
-}
+use crate::BorrowIndex;
 
 rustc_index::newtype_index! {
     /// A single integer representing a `ty::Placeholder`.
@@ -123,10 +40,17 @@ pub(crate) enum RegionElement {
 /// an interval matrix storing liveness ranges for each region-vid.
 pub(crate) struct LivenessValues {
     /// The map from locations to points.
-    elements: Rc<RegionValueElements>,
+    elements: Rc<DenseLocationMap>,
+
+    /// Which regions are live. This is exclusive with the fine-grained tracking in `points`, and
+    /// currently only used for validating promoteds (which don't care about more precise tracking).
+    live_regions: Option<FxHashSet<RegionVid>>,
 
     /// For each region: the points where it is live.
-    points: SparseIntervalMatrix<RegionVid, PointIndex>,
+    ///
+    /// This is not initialized for promoteds, because we don't care *where* within a promoted a
+    /// region is live, only that it is.
+    points: Option<SparseIntervalMatrix<RegionVid, PointIndex>>,
 
     /// When using `-Zpolonius=next`, for each point: the loans flowing into the live regions at
     /// that point.
@@ -155,24 +79,52 @@ impl LiveLoans {
 
 impl LivenessValues {
     /// Create an empty map of regions to locations where they're live.
-    pub(crate) fn new(elements: Rc<RegionValueElements>) -> Self {
+    pub(crate) fn with_specific_points(elements: Rc<DenseLocationMap>) -> Self {
         LivenessValues {
-            points: SparseIntervalMatrix::new(elements.num_points),
+            live_regions: None,
+            points: Some(SparseIntervalMatrix::new(elements.num_points())),
+            elements,
+            loans: None,
+        }
+    }
+
+    /// Create an empty map of regions to locations where they're live.
+    ///
+    /// Unlike `with_specific_points`, does not track exact locations where something is live, only
+    /// which regions are live.
+    pub(crate) fn without_specific_points(elements: Rc<DenseLocationMap>) -> Self {
+        LivenessValues {
+            live_regions: Some(Default::default()),
+            points: None,
             elements,
             loans: None,
         }
     }
 
     /// Iterate through each region that has a value in this set.
-    pub(crate) fn regions(&self) -> impl Iterator<Item = RegionVid> {
-        self.points.rows()
+    pub(crate) fn regions(&self) -> impl Iterator<Item = RegionVid> + '_ {
+        self.points.as_ref().expect("use with_specific_points").rows()
+    }
+
+    /// Iterate through each region that has a value in this set.
+    // We are passing query instability implications to the caller.
+    #[rustc_lint_query_instability]
+    #[allow(rustc::potential_query_instability)]
+    pub(crate) fn live_regions_unordered(&self) -> impl Iterator<Item = RegionVid> + '_ {
+        self.live_regions.as_ref().unwrap().iter().copied()
     }
 
     /// Records `region` as being live at the given `location`.
     pub(crate) fn add_location(&mut self, region: RegionVid, location: Location) {
-        debug!("LivenessValues::add_location(region={:?}, location={:?})", region, location);
         let point = self.elements.point_from_location(location);
-        self.points.insert(region, point);
+        debug!("LivenessValues::add_location(region={:?}, location={:?})", region, location);
+        if let Some(points) = &mut self.points {
+            points.insert(region, point);
+        } else {
+            if self.elements.point_in_range(point) {
+                self.live_regions.as_mut().unwrap().insert(region);
+            }
+        }
 
         // When available, record the loans flowing into this region as live at the given point.
         if let Some(loans) = self.loans.as_mut() {
@@ -185,7 +137,13 @@ impl LivenessValues {
     /// Records `region` as being live at all the given `points`.
     pub(crate) fn add_points(&mut self, region: RegionVid, points: &IntervalSet<PointIndex>) {
         debug!("LivenessValues::add_points(region={:?}, points={:?})", region, points);
-        self.points.union_row(region, points);
+        if let Some(this) = &mut self.points {
+            this.union_row(region, points);
+        } else {
+            if points.iter().any(|point| self.elements.point_in_range(point)) {
+                self.live_regions.as_mut().unwrap().insert(region);
+            }
+        }
 
         // When available, record the loans flowing into this region as live at the given points.
         if let Some(loans) = self.loans.as_mut() {
@@ -201,23 +159,33 @@ impl LivenessValues {
 
     /// Records `region` as being live at all the control-flow points.
     pub(crate) fn add_all_points(&mut self, region: RegionVid) {
-        self.points.insert_all_into_row(region);
+        if let Some(points) = &mut self.points {
+            points.insert_all_into_row(region);
+        } else {
+            self.live_regions.as_mut().unwrap().insert(region);
+        }
     }
 
     /// Returns whether `region` is marked live at the given `location`.
     pub(crate) fn is_live_at(&self, region: RegionVid, location: Location) -> bool {
         let point = self.elements.point_from_location(location);
-        self.points.row(region).is_some_and(|r| r.contains(point))
-    }
-
-    /// Returns whether `region` is marked live at any location.
-    pub(crate) fn is_live_anywhere(&self, region: RegionVid) -> bool {
-        self.live_points(region).next().is_some()
+        if let Some(points) = &self.points {
+            points.row(region).is_some_and(|r| r.contains(point))
+        } else {
+            unreachable!(
+                "Should be using LivenessValues::with_specific_points to ask whether live at a location"
+            )
+        }
     }
 
     /// Returns an iterator of all the points where `region` is live.
     fn live_points(&self, region: RegionVid) -> impl Iterator<Item = PointIndex> + '_ {
-        self.points
+        let Some(points) = &self.points else {
+            unreachable!(
+                "Should be using LivenessValues::with_specific_points to ask whether live at a location"
+            )
+        };
+        points
             .row(region)
             .into_iter()
             .flat_map(|set| set.iter())
@@ -298,7 +266,7 @@ impl PlaceholderIndices {
 /// it would also contain various points from within the function.
 #[derive(Clone)]
 pub(crate) struct RegionValues<N: Idx> {
-    elements: Rc<RegionValueElements>,
+    elements: Rc<DenseLocationMap>,
     placeholder_indices: Rc<PlaceholderIndices>,
     points: SparseIntervalMatrix<N, PointIndex>,
     free_regions: SparseBitMatrix<N, RegionVid>,
@@ -313,14 +281,14 @@ impl<N: Idx> RegionValues<N> {
     /// Each of the regions in num_region_variables will be initialized with an
     /// empty set of points and no causal information.
     pub(crate) fn new(
-        elements: &Rc<RegionValueElements>,
+        elements: &Rc<DenseLocationMap>,
         num_universal_regions: usize,
         placeholder_indices: &Rc<PlaceholderIndices>,
     ) -> Self {
         let num_placeholders = placeholder_indices.len();
         Self {
             elements: elements.clone(),
-            points: SparseIntervalMatrix::new(elements.num_points),
+            points: SparseIntervalMatrix::new(elements.num_points()),
             placeholder_indices: placeholder_indices.clone(),
             free_regions: SparseBitMatrix::new(num_universal_regions),
             placeholders: SparseBitMatrix::new(num_placeholders),
@@ -372,7 +340,10 @@ impl<N: Idx> RegionValues<N> {
     /// elements for the region `from` from `values` and add them to
     /// the region `to` in `self`.
     pub(crate) fn merge_liveness(&mut self, to: N, from: RegionVid, values: &LivenessValues) {
-        if let Some(set) = values.points.row(from) {
+        let Some(value_points) = &values.points else {
+            panic!("LivenessValues must track specific points for use in merge_liveness");
+        };
+        if let Some(set) = value_points.row(from) {
             self.points.union_row(to, set);
         }
     }
@@ -486,7 +457,7 @@ impl ToElementIndex for ty::PlaceholderRegion {
 
 /// For debugging purposes, returns a pretty-printed string of the given points.
 pub(crate) fn pretty_print_points(
-    elements: &RegionValueElements,
+    elements: &DenseLocationMap,
     points: impl IntoIterator<Item = PointIndex>,
 ) -> String {
     pretty_print_region_elements(
diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
index 4a76d877af0..011b5b760c2 100644
--- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
+++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
@@ -1,5 +1,6 @@
 use rustc_data_structures::frozen::Frozen;
 use rustc_data_structures::transitive_relation::{TransitiveRelation, TransitiveRelationBuilder};
+use rustc_hir::def::DefKind;
 use rustc_infer::infer::canonical::QueryRegionConstraints;
 use rustc_infer::infer::outlives;
 use rustc_infer::infer::outlives::env::RegionBoundPairs;
@@ -195,7 +196,9 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
 
     #[instrument(level = "debug", skip(self))]
     pub(crate) fn create(mut self) -> CreateResult<'tcx> {
-        let span = self.infcx.tcx.def_span(self.universal_regions.defining_ty.def_id());
+        let tcx = self.infcx.tcx;
+        let defining_ty_def_id = self.universal_regions.defining_ty.def_id().expect_local();
+        let span = tcx.def_span(defining_ty_def_id);
 
         // Insert the facts we know from the predicates. Why? Why not.
         let param_env = self.param_env;
@@ -275,6 +278,26 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
             normalized_inputs_and_output.push(norm_ty);
         }
 
+        // Add implied bounds from impl header.
+        if matches!(tcx.def_kind(defining_ty_def_id), DefKind::AssocFn | DefKind::AssocConst) {
+            for &(ty, _) in tcx.assumed_wf_types(tcx.local_parent(defining_ty_def_id)) {
+                let Ok(TypeOpOutput { output: norm_ty, constraints: c, .. }) = self
+                    .param_env
+                    .and(type_op::normalize::Normalize::new(ty))
+                    .fully_perform(self.infcx, span)
+                else {
+                    tcx.dcx().span_delayed_bug(span, format!("failed to normalize {ty:?}"));
+                    continue;
+                };
+                constraints.extend(c);
+
+                // We currently add implied bounds from the normalized ty only.
+                // This is more conservative and matches wfcheck behavior.
+                let c = self.add_implied_bounds(norm_ty);
+                constraints.extend(c);
+            }
+        }
+
         for c in constraints {
             self.push_region_constraints(c, span);
         }
diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs
index 61b6bef3b87..59518f68ab1 100644
--- a/compiler/rustc_borrowck/src/type_check/input_output.rs
+++ b/compiler/rustc_borrowck/src/type_check/input_output.rs
@@ -7,6 +7,7 @@
 //! `RETURN_PLACE` the MIR arguments) are always fully normalized (and
 //! contain revealed `impl Trait` values).
 
+use itertools::Itertools;
 use rustc_infer::infer::BoundRegionConversionTime;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, Ty};
@@ -39,9 +40,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             user_provided_sig,
         );
 
-        for (&user_ty, arg_decl) in user_provided_sig.inputs().iter().zip(
-            // In MIR, closure args begin with an implicit `self`. Skip it!
-            body.args_iter().skip(1).map(|local| &body.local_decls[local]),
+        let is_coroutine_with_implicit_resume_ty = self.tcx().is_coroutine(mir_def_id.to_def_id())
+            && user_provided_sig.inputs().is_empty();
+
+        for (&user_ty, arg_decl) in user_provided_sig.inputs().iter().zip_eq(
+            // In MIR, closure args begin with an implicit `self`.
+            // Also, coroutines have a resume type which may be implicitly `()`.
+            body.args_iter()
+                .skip(1 + if is_coroutine_with_implicit_resume_ty { 1 } else { 0 })
+                .map(|local| &body.local_decls[local]),
         ) {
             self.ascribe_user_type_skip_wf(
                 arg_decl.ty,
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs
index 7433c94a0bc..da5456692ab 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs
@@ -2,9 +2,9 @@ use rustc_data_structures::vec_linked_list as vll;
 use rustc_index::IndexVec;
 use rustc_middle::mir::visit::{PlaceContext, Visitor};
 use rustc_middle::mir::{Body, Local, Location};
+use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex};
 
 use crate::def_use::{self, DefUse};
-use crate::region_infer::values::{PointIndex, RegionValueElements};
 
 /// A map that cross references each local with the locations where it
 /// is defined (assigned), used, or dropped. Used during liveness
@@ -60,7 +60,7 @@ impl vll::LinkElem for Appearance {
 impl LocalUseMap {
     pub(crate) fn build(
         live_locals: &[Local],
-        elements: &RegionValueElements,
+        elements: &DenseLocationMap,
         body: &Body<'_>,
     ) -> Self {
         let nones = IndexVec::from_elem(None, &body.local_decls);
@@ -103,7 +103,7 @@ impl LocalUseMap {
 
 struct LocalUseMapBuild<'me> {
     local_use_map: &'me mut LocalUseMap,
-    elements: &'me RegionValueElements,
+    elements: &'me DenseLocationMap,
 
     // Vector used in `visit_local` to signal which `Local`s do we need
     // def/use/drop information on, constructed from `live_locals` (that
@@ -144,7 +144,7 @@ impl LocalUseMapBuild<'_> {
     }
 
     fn insert(
-        elements: &RegionValueElements,
+        elements: &DenseLocationMap,
         first_appearance: &mut Option<AppearanceIndex>,
         appearances: &mut IndexVec<AppearanceIndex, Appearance>,
         location: Location,
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
index e137bc1be0a..51ae7d14e43 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
@@ -6,6 +6,7 @@ use rustc_middle::ty::visit::TypeVisitable;
 use rustc_middle::ty::{GenericArgsRef, Region, RegionVid, Ty, TyCtxt};
 use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
 use rustc_mir_dataflow::move_paths::MoveData;
+use rustc_mir_dataflow::points::DenseLocationMap;
 use rustc_mir_dataflow::ResultsCursor;
 use std::rc::Rc;
 
@@ -13,7 +14,7 @@ use crate::{
     constraints::OutlivesConstraintSet,
     facts::{AllFacts, AllFactsExt},
     location::LocationTable,
-    region_infer::values::{LivenessValues, RegionValueElements},
+    region_infer::values::LivenessValues,
     universal_regions::UniversalRegions,
 };
 
@@ -34,7 +35,7 @@ mod trace;
 pub(super) fn generate<'mir, 'tcx>(
     typeck: &mut TypeChecker<'_, 'tcx>,
     body: &Body<'tcx>,
-    elements: &Rc<RegionValueElements>,
+    elements: &Rc<DenseLocationMap>,
     flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>,
     move_data: &MoveData<'tcx>,
     location_table: &LocationTable,
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
index c718d57bec3..eec128b5f1d 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
@@ -7,6 +7,7 @@ use rustc_infer::infer::outlives::for_liveness;
 use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, Local, Location};
 use rustc_middle::traits::query::DropckOutlivesResult;
 use rustc_middle::ty::{Ty, TyCtxt, TypeVisitable, TypeVisitableExt};
+use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex};
 use rustc_span::DUMMY_SP;
 use rustc_trait_selection::traits::query::type_op::outlives::DropckOutlives;
 use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
@@ -17,7 +18,7 @@ use rustc_mir_dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex};
 use rustc_mir_dataflow::ResultsCursor;
 
 use crate::{
-    region_infer::values::{self, LiveLoans, PointIndex, RegionValueElements},
+    region_infer::values::{self, LiveLoans},
     type_check::liveness::local_use_map::LocalUseMap,
     type_check::liveness::polonius,
     type_check::NormalizeLocation,
@@ -41,7 +42,7 @@ use crate::{
 pub(super) fn trace<'mir, 'tcx>(
     typeck: &mut TypeChecker<'_, 'tcx>,
     body: &Body<'tcx>,
-    elements: &Rc<RegionValueElements>,
+    elements: &Rc<DenseLocationMap>,
     flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>,
     move_data: &MoveData<'tcx>,
     relevant_live_locals: Vec<Local>,
@@ -105,7 +106,7 @@ struct LivenessContext<'me, 'typeck, 'flow, 'tcx> {
     typeck: &'me mut TypeChecker<'typeck, 'tcx>,
 
     /// Defines the `PointIndex` mapping
-    elements: &'me RegionValueElements,
+    elements: &'me DenseLocationMap,
 
     /// MIR we are analyzing.
     body: &'me Body<'tcx>,
@@ -570,7 +571,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
     }
 
     fn make_all_regions_live(
-        elements: &RegionValueElements,
+        elements: &DenseLocationMap,
         typeck: &mut TypeChecker<'_, 'tcx>,
         value: impl TypeVisitable<TyCtxt<'tcx>>,
         live_at: &IntervalSet<PointIndex>,
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 9c0f53ddb86..cf28e62177f 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -35,7 +35,9 @@ use rustc_middle::ty::{
     OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, UserType, UserTypeAnnotationIndex,
 };
 use rustc_middle::ty::{GenericArgsRef, UserArgs};
+use rustc_mir_dataflow::points::DenseLocationMap;
 use rustc_span::def_id::CRATE_DEF_ID;
+use rustc_span::source_map::Spanned;
 use rustc_span::symbol::sym;
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
@@ -58,9 +60,7 @@ use crate::{
     location::LocationTable,
     member_constraints::MemberConstraintSet,
     path_utils,
-    region_infer::values::{
-        LivenessValues, PlaceholderIndex, PlaceholderIndices, RegionValueElements,
-    },
+    region_infer::values::{LivenessValues, PlaceholderIndex, PlaceholderIndices},
     region_infer::TypeTest,
     type_check::free_region_relations::{CreateResult, UniversalRegionRelations},
     universal_regions::{DefiningTy, UniversalRegions},
@@ -133,7 +133,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
     all_facts: &mut Option<AllFacts>,
     flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>,
     move_data: &MoveData<'tcx>,
-    elements: &Rc<RegionValueElements>,
+    elements: &Rc<DenseLocationMap>,
     upvars: &[&ty::CapturedPlace<'tcx>],
     use_polonius: bool,
 ) -> MirTypeckResults<'tcx> {
@@ -141,7 +141,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
     let mut constraints = MirTypeckRegionConstraints {
         placeholder_indices: PlaceholderIndices::default(),
         placeholder_index_to_region: IndexVec::default(),
-        liveness_constraints: LivenessValues::new(elements.clone()),
+        liveness_constraints: LivenessValues::with_specific_points(elements.clone()),
         outlives_constraints: OutlivesConstraintSet::default(),
         member_constraints: MemberConstraintSet::default(),
         type_tests: Vec::default(),
@@ -406,6 +406,16 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
                     instantiated_predicates,
                     locations,
                 );
+
+                assert!(!matches!(
+                    tcx.impl_of_method(def_id).map(|imp| tcx.def_kind(imp)),
+                    Some(DefKind::Impl { of_trait: true })
+                ));
+                self.cx.prove_predicates(
+                    args.types().map(|ty| ty::ClauseKind::WellFormed(ty.into())),
+                    locations,
+                    ConstraintCategory::Boring,
+                );
             }
         }
     }
@@ -545,7 +555,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
         let all_facts = &mut None;
         let mut constraints = Default::default();
         let mut liveness_constraints =
-            LivenessValues::new(Rc::new(RegionValueElements::new(promoted_body)));
+            LivenessValues::without_specific_points(Rc::new(DenseLocationMap::new(promoted_body)));
         // Don't try to add borrow_region facts for the promoted MIR
 
         let mut swap_constraints = |this: &mut Self| {
@@ -584,17 +594,19 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
             }
             self.cx.borrowck_context.constraints.outlives_constraints.push(constraint)
         }
-        for region in liveness_constraints.regions() {
-            // If the region is live at at least one location in the promoted MIR,
-            // then add a liveness constraint to the main MIR for this region
-            // at the location provided as an argument to this method
-            if liveness_constraints.is_live_anywhere(region) {
-                self.cx
-                    .borrowck_context
-                    .constraints
-                    .liveness_constraints
-                    .add_location(region, location);
-            }
+        // If the region is live at at least one location in the promoted MIR,
+        // then add a liveness constraint to the main MIR for this region
+        // at the location provided as an argument to this method
+        //
+        // add_location doesn't care about ordering so not a problem for the live regions to be
+        // unordered.
+        #[allow(rustc::potential_query_instability)]
+        for region in liveness_constraints.live_regions_unordered() {
+            self.cx
+                .borrowck_context
+                .constraints
+                .liveness_constraints
+                .add_location(region, location);
         }
     }
 
@@ -1359,7 +1371,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             TerminatorKind::Call { func, args, destination, call_source, target, .. } => {
                 self.check_operand(func, term_location);
                 for arg in args {
-                    self.check_operand(arg, term_location);
+                    self.check_operand(&arg.node, term_location);
                 }
 
                 let func_ty = func.ty(body, tcx);
@@ -1580,7 +1592,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         term: &Terminator<'tcx>,
         func: &Operand<'tcx>,
         sig: &ty::FnSig<'tcx>,
-        args: &[Operand<'tcx>],
+        args: &[Spanned<Operand<'tcx>>],
         term_location: Location,
         call_source: CallSource,
     ) {
@@ -1593,7 +1605,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             if self.tcx().is_intrinsic(def_id) {
                 match self.tcx().item_name(def_id) {
                     sym::simd_shuffle => {
-                        if !matches!(args[2], Operand::Constant(_)) {
+                        if !matches!(args[2], Spanned { node: Operand::Constant(_), .. }) {
                             self.tcx()
                                 .dcx()
                                 .emit_err(SimdShuffleLastConst { span: term.source_info.span });
@@ -1606,7 +1618,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         debug!(?func_ty);
 
         for (n, (fn_arg, op_arg)) in iter::zip(sig.inputs(), args).enumerate() {
-            let op_arg_ty = op_arg.ty(body, self.tcx());
+            let op_arg_ty = op_arg.node.ty(body, self.tcx());
 
             let op_arg_ty = self.normalize(op_arg_ty, term_location);
             let category = if call_source.from_hir_call() {
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index addb41ff5fc..ae8a135f090 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -668,7 +668,11 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
                     kind: ty::BrEnv,
                 };
                 let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br);
-                let closure_ty = tcx.closure_env_ty(def_id, args, env_region).unwrap();
+                let closure_ty = tcx.closure_env_ty(
+                    Ty::new_closure(tcx, def_id, args),
+                    args.as_closure().kind(),
+                    env_region,
+                );
 
                 // The "inputs" of the closure in the
                 // signature appear as a tuple. The MIR side
diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index f60b73fbe9b..3e9b06a5b05 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -6,6 +6,7 @@
 #![doc(rust_logo)]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(array_windows)]
+#![feature(assert_matches)]
 #![feature(box_patterns)]
 #![feature(decl_macro)]
 #![feature(if_let_guard)]
diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs
index 4d44e340ae1..0631f796894 100644
--- a/compiler/rustc_builtin_macros/src/test.rs
+++ b/compiler/rustc_builtin_macros/src/test.rs
@@ -9,6 +9,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder, Level};
 use rustc_expand::base::*;
 use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::{ErrorGuaranteed, FileNameDisplayPreference, Span};
+use std::assert_matches::assert_matches;
 use std::iter;
 use thin_vec::{thin_vec, ThinVec};
 
@@ -182,6 +183,16 @@ pub fn expand_test_or_bench(
     // creates $name: $expr
     let field = |name, expr| cx.field_imm(sp, Ident::from_str_and_span(name, sp), expr);
 
+    // Adds `#[coverage(off)]` to a closure, so it won't be instrumented in
+    // `-Cinstrument-coverage` builds.
+    // This requires `#[allow_internal_unstable(coverage_attribute)]` on the
+    // corresponding macro declaration in `core::macros`.
+    let coverage_off = |mut expr: P<ast::Expr>| {
+        assert_matches!(expr.kind, ast::ExprKind::Closure(_));
+        expr.attrs.push(cx.attr_nested_word(sym::coverage, sym::off, sp));
+        expr
+    };
+
     let test_fn = if is_bench {
         // A simple ident for a lambda
         let b = Ident::from_str_and_span("b", attr_sp);
@@ -190,8 +201,9 @@ pub fn expand_test_or_bench(
             sp,
             cx.expr_path(test_path("StaticBenchFn")),
             thin_vec![
+                // #[coverage(off)]
                 // |b| self::test::assert_test_result(
-                cx.lambda1(
+                coverage_off(cx.lambda1(
                     sp,
                     cx.expr_call(
                         sp,
@@ -206,7 +218,7 @@ pub fn expand_test_or_bench(
                         ],
                     ),
                     b,
-                ), // )
+                )), // )
             ],
         )
     } else {
@@ -214,8 +226,9 @@ pub fn expand_test_or_bench(
             sp,
             cx.expr_path(test_path("StaticTestFn")),
             thin_vec![
+                // #[coverage(off)]
                 // || {
-                cx.lambda0(
+                coverage_off(cx.lambda0(
                     sp,
                     // test::assert_test_result(
                     cx.expr_call(
@@ -230,7 +243,7 @@ pub fn expand_test_or_bench(
                             ), // )
                         ],
                     ), // }
-                ), // )
+                )), // )
             ],
         )
     };
diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock
index 74e7afee7bc..6d6a1200f50 100644
--- a/compiler/rustc_codegen_cranelift/Cargo.lock
+++ b/compiler/rustc_codegen_cranelift/Cargo.lock
@@ -246,12 +246,12 @@ checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b"
 
 [[package]]
 name = "libloading"
-version = "0.7.4"
+version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
+checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161"
 dependencies = [
  "cfg-if",
- "winapi",
+ "windows-sys",
 ]
 
 [[package]]
diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml
index fdac789423c..c57e964168f 100644
--- a/compiler/rustc_codegen_cranelift/Cargo.toml
+++ b/compiler/rustc_codegen_cranelift/Cargo.toml
@@ -19,7 +19,7 @@ gimli = { version = "0.28", default-features = false, features = ["write"]}
 object = { version = "0.32", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
 
 indexmap = "2.0.0"
-libloading = { version = "0.7.3", optional = true }
+libloading = { version = "0.8.0", optional = true }
 smallvec = "1.8.1"
 
 [patch.crates-io]
diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
index 795c8daec6a..abd70dd4458 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
@@ -11,6 +11,7 @@ use cranelift_module::ModuleError;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::ty::layout::FnAbiOf;
 use rustc_session::Session;
+use rustc_span::source_map::Spanned;
 use rustc_target::abi::call::{Conv, FnAbi};
 use rustc_target::spec::abi::Abi;
 
@@ -360,7 +361,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
     fx: &mut FunctionCx<'_, '_, 'tcx>,
     source_info: mir::SourceInfo,
     func: &Operand<'tcx>,
-    args: &[Operand<'tcx>],
+    args: &[Spanned<Operand<'tcx>>],
     destination: Place<'tcx>,
     target: Option<BasicBlock>,
 ) {
@@ -415,7 +416,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
 
     let extra_args = &args[fn_sig.inputs().skip_binder().len()..];
     let extra_args = fx.tcx.mk_type_list_from_iter(
-        extra_args.iter().map(|op_arg| fx.monomorphize(op_arg.ty(fx.mir, fx.tcx))),
+        extra_args.iter().map(|op_arg| fx.monomorphize(op_arg.node.ty(fx.mir, fx.tcx))),
     );
     let fn_abi = if let Some(instance) = instance {
         RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(instance, extra_args)
@@ -440,10 +441,10 @@ pub(crate) fn codegen_terminator_call<'tcx>(
     // Unpack arguments tuple for closures
     let mut args = if fn_sig.abi() == Abi::RustCall {
         let (self_arg, pack_arg) = match args {
-            [pack_arg] => (None, codegen_call_argument_operand(fx, pack_arg)),
+            [pack_arg] => (None, codegen_call_argument_operand(fx, &pack_arg.node)),
             [self_arg, pack_arg] => (
-                Some(codegen_call_argument_operand(fx, self_arg)),
-                codegen_call_argument_operand(fx, pack_arg),
+                Some(codegen_call_argument_operand(fx, &self_arg.node)),
+                codegen_call_argument_operand(fx, &pack_arg.node),
             ),
             _ => panic!("rust-call abi requires one or two arguments"),
         };
@@ -463,7 +464,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
         }
         args
     } else {
-        args.iter().map(|arg| codegen_call_argument_operand(fx, arg)).collect::<Vec<_>>()
+        args.iter().map(|arg| codegen_call_argument_operand(fx, &arg.node)).collect::<Vec<_>>()
     };
 
     // Pass the caller location for `#[track_caller]`.
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
index a38a728c926..1345c4614e2 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
@@ -7,7 +7,7 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
     fx: &mut FunctionCx<'_, '_, 'tcx>,
     intrinsic: &str,
     generic_args: GenericArgsRef<'tcx>,
-    args: &[mir::Operand<'tcx>],
+    args: &[Spanned<mir::Operand<'tcx>>],
     ret: CPlace<'tcx>,
     target: Option<BasicBlock>,
     span: Span,
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs
index c8f9c3997a6..f6f3b85d3ef 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs
@@ -7,7 +7,7 @@ pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>(
     fx: &mut FunctionCx<'_, '_, 'tcx>,
     intrinsic: &str,
     _args: GenericArgsRef<'tcx>,
-    args: &[mir::Operand<'tcx>],
+    args: &[Spanned<mir::Operand<'tcx>>],
     ret: CPlace<'tcx>,
     target: Option<BasicBlock>,
 ) {
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
index 81114cbf40d..994dc66835c 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
@@ -11,7 +11,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
     fx: &mut FunctionCx<'_, '_, 'tcx>,
     intrinsic: &str,
     _args: GenericArgsRef<'tcx>,
-    args: &[mir::Operand<'tcx>],
+    args: &[Spanned<mir::Operand<'tcx>>],
     ret: CPlace<'tcx>,
     target: Option<BasicBlock>,
     span: Span,
@@ -175,9 +175,9 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
                 [x, y, kind] => (x, y, kind),
                 _ => bug!("wrong number of args for intrinsic {intrinsic}"),
             };
-            let x = codegen_operand(fx, x);
-            let y = codegen_operand(fx, y);
-            let kind = match kind {
+            let x = codegen_operand(fx, &x.node);
+            let y = codegen_operand(fx, &y.node);
+            let kind = match &kind.node {
                 Operand::Constant(const_) => crate::constant::eval_mir_constant(fx, const_).0,
                 Operand::Copy(_) | Operand::Move(_) => unreachable!("{kind:?}"),
             };
@@ -287,8 +287,8 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
                 [a, b] => (a, b),
                 _ => bug!("wrong number of args for intrinsic {intrinsic}"),
             };
-            let a = codegen_operand(fx, a);
-            let b = codegen_operand(fx, b);
+            let a = codegen_operand(fx, &a.node);
+            let b = codegen_operand(fx, &b.node);
 
             // Based on the pseudocode at https://github.com/rust-lang/stdarch/blob/1cfbca8b38fd9b4282b2f054f61c6ca69fc7ce29/crates/core_arch/src/x86/avx2.rs#L2319-L2332
             let zero = fx.bcx.ins().iconst(types::I8, 0);
@@ -325,9 +325,9 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
                 [a, b, imm8] => (a, b, imm8),
                 _ => bug!("wrong number of args for intrinsic {intrinsic}"),
             };
-            let a = codegen_operand(fx, a);
-            let b = codegen_operand(fx, b);
-            let imm8 = codegen_operand(fx, imm8).load_scalar(fx);
+            let a = codegen_operand(fx, &a.node);
+            let b = codegen_operand(fx, &b.node);
+            let imm8 = codegen_operand(fx, &imm8.node).load_scalar(fx);
 
             let a_low = a.value_typed_lane(fx, fx.tcx.types.u128, 0).load_scalar(fx);
             let a_high = a.value_typed_lane(fx, fx.tcx.types.u128, 1).load_scalar(fx);
@@ -956,14 +956,14 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
             let b = b.load_scalar(fx);
             let lb = lb.load_scalar(fx);
 
-            let imm8 = if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[4])
-            {
-                imm8
-            } else {
-                fx.tcx
-                    .dcx()
-                    .span_fatal(span, "Index argument for `_mm_cmpestri` is not a constant");
-            };
+            let imm8 =
+                if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[4].node) {
+                    imm8
+                } else {
+                    fx.tcx
+                        .dcx()
+                        .span_fatal(span, "Index argument for `_mm_cmpestri` is not a constant");
+                };
 
             let imm8 = imm8.try_to_u8().unwrap_or_else(|_| panic!("kind not scalar: {:?}", imm8));
 
@@ -1009,14 +1009,14 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
             let b = b.load_scalar(fx);
             let lb = lb.load_scalar(fx);
 
-            let imm8 = if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[4])
-            {
-                imm8
-            } else {
-                fx.tcx
-                    .dcx()
-                    .span_fatal(span, "Index argument for `_mm_cmpestrm` is not a constant");
-            };
+            let imm8 =
+                if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[4].node) {
+                    imm8
+                } else {
+                    fx.tcx
+                        .dcx()
+                        .span_fatal(span, "Index argument for `_mm_cmpestrm` is not a constant");
+                };
 
             let imm8 = imm8.try_to_u8().unwrap_or_else(|_| panic!("kind not scalar: {:?}", imm8));
 
@@ -1056,15 +1056,15 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
             let a = a.load_scalar(fx);
             let b = b.load_scalar(fx);
 
-            let imm8 = if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[2])
-            {
-                imm8
-            } else {
-                fx.tcx.dcx().span_fatal(
-                    span,
-                    "Index argument for `_mm_clmulepi64_si128` is not a constant",
-                );
-            };
+            let imm8 =
+                if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[2].node) {
+                    imm8
+                } else {
+                    fx.tcx.dcx().span_fatal(
+                        span,
+                        "Index argument for `_mm_clmulepi64_si128` is not a constant",
+                    );
+                };
 
             let imm8 = imm8.try_to_u8().unwrap_or_else(|_| panic!("kind not scalar: {:?}", imm8));
 
@@ -1093,15 +1093,15 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
 
             let a = a.load_scalar(fx);
 
-            let imm8 = if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[1])
-            {
-                imm8
-            } else {
-                fx.tcx.dcx().span_fatal(
-                    span,
-                    "Index argument for `_mm_aeskeygenassist_si128` is not a constant",
-                );
-            };
+            let imm8 =
+                if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[1].node) {
+                    imm8
+                } else {
+                    fx.tcx.dcx().span_fatal(
+                        span,
+                        "Index argument for `_mm_aeskeygenassist_si128` is not a constant",
+                    );
+                };
 
             let imm8 = imm8.try_to_u8().unwrap_or_else(|_| panic!("kind not scalar: {:?}", imm8));
 
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index 15249402a63..a27853fa0a8 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -5,7 +5,7 @@ macro_rules! intrinsic_args {
     ($fx:expr, $args:expr => ($($arg:tt),*); $intrinsic:expr) => {
         #[allow(unused_parens)]
         let ($($arg),*) = if let [$($arg),*] = $args {
-            ($(codegen_operand($fx, $arg)),*)
+            ($(codegen_operand($fx, &($arg).node)),*)
         } else {
             $crate::intrinsics::bug_on_incorrect_arg_count($intrinsic);
         };
@@ -22,6 +22,7 @@ use rustc_middle::ty;
 use rustc_middle::ty::layout::{HasParamEnv, ValidityRequirement};
 use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
 use rustc_middle::ty::GenericArgsRef;
+use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Symbol};
 
 pub(crate) use self::llvm::codegen_llvm_intrinsic_call;
@@ -263,7 +264,7 @@ fn bool_to_zero_or_max_uint<'tcx>(
 pub(crate) fn codegen_intrinsic_call<'tcx>(
     fx: &mut FunctionCx<'_, '_, 'tcx>,
     instance: Instance<'tcx>,
-    args: &[mir::Operand<'tcx>],
+    args: &[Spanned<mir::Operand<'tcx>>],
     destination: CPlace<'tcx>,
     target: Option<BasicBlock>,
     source_info: mir::SourceInfo,
@@ -301,7 +302,7 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
 fn codegen_float_intrinsic_call<'tcx>(
     fx: &mut FunctionCx<'_, '_, 'tcx>,
     intrinsic: Symbol,
-    args: &[mir::Operand<'tcx>],
+    args: &[Spanned<mir::Operand<'tcx>>],
     ret: CPlace<'tcx>,
 ) -> bool {
     let (name, arg_count, ty, clif_ty) = match intrinsic {
@@ -353,18 +354,21 @@ fn codegen_float_intrinsic_call<'tcx>(
     let (a, b, c);
     let args = match args {
         [x] => {
-            a = [codegen_operand(fx, x).load_scalar(fx)];
+            a = [codegen_operand(fx, &x.node).load_scalar(fx)];
             &a as &[_]
         }
         [x, y] => {
-            b = [codegen_operand(fx, x).load_scalar(fx), codegen_operand(fx, y).load_scalar(fx)];
+            b = [
+                codegen_operand(fx, &x.node).load_scalar(fx),
+                codegen_operand(fx, &y.node).load_scalar(fx),
+            ];
             &b
         }
         [x, y, z] => {
             c = [
-                codegen_operand(fx, x).load_scalar(fx),
-                codegen_operand(fx, y).load_scalar(fx),
-                codegen_operand(fx, z).load_scalar(fx),
+                codegen_operand(fx, &x.node).load_scalar(fx),
+                codegen_operand(fx, &y.node).load_scalar(fx),
+                codegen_operand(fx, &z.node).load_scalar(fx),
             ];
             &c
         }
@@ -422,7 +426,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
     instance: Instance<'tcx>,
     intrinsic: Symbol,
     generic_args: GenericArgsRef<'tcx>,
-    args: &[mir::Operand<'tcx>],
+    args: &[Spanned<mir::Operand<'tcx>>],
     ret: CPlace<'tcx>,
     destination: Option<BasicBlock>,
     source_info: mir::SourceInfo,
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
index 78ea7c2dbfc..d56d17892d5 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
@@ -21,7 +21,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
     fx: &mut FunctionCx<'_, '_, 'tcx>,
     intrinsic: Symbol,
     generic_args: GenericArgsRef<'tcx>,
-    args: &[mir::Operand<'tcx>],
+    args: &[Spanned<mir::Operand<'tcx>>],
     ret: CPlace<'tcx>,
     target: BasicBlock,
     span: Span,
@@ -121,8 +121,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
             let [x, y] = args else {
                 bug!("wrong number of args for intrinsic {intrinsic}");
             };
-            let x = codegen_operand(fx, x);
-            let y = codegen_operand(fx, y);
+            let x = codegen_operand(fx, &x.node);
+            let y = codegen_operand(fx, &y.node);
 
             if !x.layout().ty.is_simd() {
                 report_simd_type_validation_error(fx, intrinsic, span, x.layout().ty);
@@ -172,8 +172,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
                     bug!("wrong number of args for intrinsic {intrinsic}");
                 }
             };
-            let x = codegen_operand(fx, x);
-            let y = codegen_operand(fx, y);
+            let x = codegen_operand(fx, &x.node);
+            let y = codegen_operand(fx, &y.node);
 
             if !x.layout().ty.is_simd() {
                 report_simd_type_validation_error(fx, intrinsic, span, x.layout().ty);
@@ -182,7 +182,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
 
             // Make sure this is actually an array, since typeck only checks the length-suffixed
             // version of this intrinsic.
-            let idx_ty = fx.monomorphize(idx.ty(fx.mir, fx.tcx));
+            let idx_ty = fx.monomorphize(idx.node.ty(fx.mir, fx.tcx));
             let n: u16 = match idx_ty.kind() {
                 ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => len
                     .try_eval_target_usize(fx.tcx, ty::ParamEnv::reveal_all())
@@ -215,7 +215,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
 
             let indexes = {
                 use rustc_middle::mir::interpret::*;
-                let idx_const = match idx {
+                let idx_const = match &idx.node {
                     Operand::Constant(const_) => crate::constant::eval_mir_constant(fx, const_).0,
                     Operand::Copy(_) | Operand::Move(_) => unreachable!("{idx:?}"),
                 };
@@ -269,12 +269,12 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
                     bug!("wrong number of args for intrinsic {intrinsic}");
                 }
             };
-            let base = codegen_operand(fx, base);
-            let val = codegen_operand(fx, val);
+            let base = codegen_operand(fx, &base.node);
+            let val = codegen_operand(fx, &val.node);
 
             // FIXME validate
             let idx_const = if let Some(idx_const) =
-                crate::constant::mir_operand_get_const_val(fx, idx)
+                crate::constant::mir_operand_get_const_val(fx, &idx.node)
             {
                 idx_const
             } else {
@@ -304,7 +304,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
                     bug!("wrong number of args for intrinsic {intrinsic}");
                 }
             };
-            let v = codegen_operand(fx, v);
+            let v = codegen_operand(fx, &v.node);
 
             if !v.layout().ty.is_simd() {
                 report_simd_type_validation_error(fx, intrinsic, span, v.layout().ty);
@@ -312,7 +312,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
             }
 
             let idx_const = if let Some(idx_const) =
-                crate::constant::mir_operand_get_const_val(fx, idx)
+                crate::constant::mir_operand_get_const_val(fx, &idx.node)
             {
                 idx_const
             } else {
diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml
index c12142e302d..3948a49ee2a 100644
--- a/compiler/rustc_codegen_llvm/Cargo.toml
+++ b/compiler/rustc_codegen_llvm/Cargo.toml
@@ -11,7 +11,7 @@ test = false
 bitflags = "2.4.1"
 itertools = "0.11"
 libc = "0.2"
-measureme = "10.0.0"
+measureme = "11"
 object = { version = "0.32.0", default-features = false, features = ["std", "read"] }
 rustc-demangle = "0.1.21"
 rustc_ast = { path = "../rustc_ast" }
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 1d1b6e6148d..f3b2caf9b80 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -145,6 +145,14 @@ pub unsafe fn create_module<'ll>(
                 .replace("-Fi64", "");
         }
     }
+    if llvm_version < (18, 0, 0) {
+        if sess.target.arch == "x86" || sess.target.arch == "x86_64" {
+            // LLVM 18 adjusts i128 to be 128-bit aligned on x86 variants.
+            // Earlier LLVMs leave this as default alignment, so remove it.
+            // See https://reviews.llvm.org/D86310
+            target_data_layout = target_data_layout.replace("-i128:128", "");
+        }
+    }
 
     // Ensure the data-layout values hardcoded remain the defaults.
     if sess.target.is_builtin {
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index af1c6594446..5d497d4a188 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -14,7 +14,7 @@ use rustc_data_structures::memmap::Mmap;
 use rustc_data_structures::profiling::{SelfProfilerRef, VerboseTimingGuard};
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::emitter::Emitter;
-use rustc_errors::{translation::Translate, DiagCtxt, DiagnosticId, FatalError, Level};
+use rustc_errors::{translation::Translate, DiagCtxt, FatalError, Level};
 use rustc_errors::{DiagnosticBuilder, DiagnosticMessage, Style};
 use rustc_fs_util::link_or_copy;
 use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
@@ -1000,7 +1000,7 @@ type DiagnosticArgName<'source> = Cow<'source, str>;
 struct Diagnostic {
     msgs: Vec<(DiagnosticMessage, Style)>,
     args: FxHashMap<DiagnosticArgName<'static>, rustc_errors::DiagnosticArgValue<'static>>,
-    code: Option<DiagnosticId>,
+    code: Option<String>,
     lvl: Level,
 }
 
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index a1662f25e14..e35b4029b45 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -17,7 +17,7 @@ use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
 use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
 use rustc_middle::ty::{self, Instance, Ty};
 use rustc_session::config::OptLevel;
-use rustc_span::{sym, Span, Symbol};
+use rustc_span::{source_map::Spanned, sym, Span, Symbol};
 use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode, Reg};
 use rustc_target::abi::{self, HasDataLayout, WrappingRange};
 use rustc_target::spec::abi::Abi;
@@ -742,7 +742,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         bx: &mut Bx,
         terminator: &mir::Terminator<'tcx>,
         func: &mir::Operand<'tcx>,
-        args: &[mir::Operand<'tcx>],
+        args: &[Spanned<mir::Operand<'tcx>>],
         destination: mir::Place<'tcx>,
         target: Option<mir::BasicBlock>,
         unwind: mir::UnwindAction,
@@ -793,7 +793,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
         let extra_args = &args[sig.inputs().skip_binder().len()..];
         let extra_args = bx.tcx().mk_type_list_from_iter(extra_args.iter().map(|op_arg| {
-            let op_ty = op_arg.ty(self.mir, bx.tcx());
+            let op_ty = op_arg.node.ty(self.mir, bx.tcx());
             self.monomorphize(op_ty)
         }));
 
@@ -863,7 +863,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         // checked by const-qualification, which also
                         // promotes any complex rvalues to constants.
                         if i == 2 && intrinsic == sym::simd_shuffle {
-                            if let mir::Operand::Constant(constant) = arg {
+                            if let mir::Operand::Constant(constant) = &arg.node {
                                 let (llval, ty) = self.simd_shuffle_indices(bx, constant);
                                 return OperandRef {
                                     val: Immediate(llval),
@@ -874,7 +874,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                             }
                         }
 
-                        self.codegen_operand(bx, arg)
+                        self.codegen_operand(bx, &arg.node)
                     })
                     .collect();
 
@@ -910,7 +910,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
         let mut copied_constant_arguments = vec![];
         'make_args: for (i, arg) in first_args.iter().enumerate() {
-            let mut op = self.codegen_operand(bx, arg);
+            let mut op = self.codegen_operand(bx, &arg.node);
 
             if let (0, Some(ty::InstanceDef::Virtual(_, idx))) = (i, def) {
                 match op.val {
@@ -988,7 +988,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
             // The callee needs to own the argument memory if we pass it
             // by-ref, so make a local copy of non-immediate constants.
-            match (arg, op.val) {
+            match (&arg.node, op.val) {
                 (&mir::Operand::Copy(_), Ref(_, None, _))
                 | (&mir::Operand::Constant(_), Ref(_, None, _)) => {
                     let tmp = PlaceRef::alloca(bx, op.layout);
@@ -1003,7 +1003,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             self.codegen_argument(bx, op, &mut llargs, &fn_abi.args[i]);
         }
         let num_untupled = untuple.map(|tup| {
-            self.codegen_arguments_untupled(bx, tup, &mut llargs, &fn_abi.args[first_args.len()..])
+            self.codegen_arguments_untupled(
+                bx,
+                &tup.node,
+                &mut llargs,
+                &fn_abi.args[first_args.len()..],
+            )
         });
 
         let needs_location =
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 9d22df50d4f..4236117d75b 100644
--- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -225,17 +225,10 @@ pub fn eval_to_const_value_raw_provider<'tcx>(
     tcx: TyCtxt<'tcx>,
     key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
 ) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> {
-    // see comment in eval_to_allocation_raw_provider for what we're doing here
-    if key.param_env.reveal() == Reveal::All {
-        let mut key = key;
-        key.param_env = key.param_env.with_user_facing();
-        match tcx.eval_to_const_value_raw(key) {
-            // try again with reveal all as requested
-            Err(ErrorHandled::TooGeneric(_)) => {}
-            // deduplicate calls
-            other => return other,
-        }
-    }
+    // Const eval always happens in Reveal::All mode in order to be able to use the hidden types of
+    // opaque types. This is needed for trivial things like `size_of`, but also for using associated
+    // types that are not specified in the opaque type.
+    assert_eq!(key.param_env.reveal(), Reveal::All);
 
     // We call `const_eval` for zero arg intrinsics, too, in order to cache their value.
     // Catch such calls and evaluate them instead of trying to load a constant's MIR.
@@ -265,24 +258,11 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
     tcx: TyCtxt<'tcx>,
     key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
 ) -> ::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> {
-    // Because the constant is computed twice (once per value of `Reveal`), we are at risk of
-    // reporting the same error twice here. To resolve this, we check whether we can evaluate the
-    // constant in the more restrictive `Reveal::UserFacing`, which most likely already was
-    // computed. For a large percentage of constants that will already have succeeded. Only
-    // associated constants of generic functions will fail due to not enough monomorphization
-    // information being available.
-
-    // In case we fail in the `UserFacing` variant, we just do the real computation.
-    if key.param_env.reveal() == Reveal::All {
-        let mut key = key;
-        key.param_env = key.param_env.with_user_facing();
-        match tcx.eval_to_allocation_raw(key) {
-            // try again with reveal all as requested
-            Err(ErrorHandled::TooGeneric(_)) => {}
-            // deduplicate calls
-            other => return other,
-        }
-    }
+    // Const eval always happens in Reveal::All mode in order to be able to use the hidden types of
+    // opaque types. This is needed for trivial things like `size_of`, but also for using associated
+    // types that are not specified in the opaque type.
+
+    assert_eq!(key.param_env.reveal(), Reveal::All);
     if cfg!(debug_assertions) {
         // Make sure we format the instance even if we do not print it.
         // This serves as a regression test against an ICE on printing.
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index 7ff970661d6..3afd14eb574 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -1209,21 +1209,28 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                         throw_ub_custom!(fluent::const_eval_copy_nonoverlapping_overlapping);
                     }
                 }
+            }
 
-                for i in 0..num_copies {
-                    ptr::copy(
-                        src_bytes,
-                        dest_bytes.add((size * i).bytes_usize()), // `Size` multiplication
-                        size.bytes_usize(),
-                    );
+            let size_in_bytes = size.bytes_usize();
+            // For particularly large arrays (where this is perf-sensitive) it's common that
+            // we're writing a single byte repeatedly. So, optimize that case to a memset.
+            if size_in_bytes == 1 && num_copies >= 1 {
+                // SAFETY: `src_bytes` would be read from anyway by copies below (num_copies >= 1).
+                // Since size_in_bytes = 1, then the `init.no_bytes_init()` check above guarantees
+                // that this read at type `u8` is OK -- it must be an initialized byte.
+                let value = *src_bytes;
+                dest_bytes.write_bytes(value, (size * num_copies).bytes_usize());
+            } else if src_alloc_id == dest_alloc_id {
+                let mut dest_ptr = dest_bytes;
+                for _ in 0..num_copies {
+                    ptr::copy(src_bytes, dest_ptr, size_in_bytes);
+                    dest_ptr = dest_ptr.add(size_in_bytes);
                 }
             } else {
-                for i in 0..num_copies {
-                    ptr::copy_nonoverlapping(
-                        src_bytes,
-                        dest_bytes.add((size * i).bytes_usize()), // `Size` multiplication
-                        size.bytes_usize(),
-                    );
+                let mut dest_ptr = dest_bytes;
+                for _ in 0..num_copies {
+                    ptr::copy_nonoverlapping(src_bytes, dest_ptr, size_in_bytes);
+                    dest_ptr = dest_ptr.add(size_in_bytes);
                 }
             }
         }
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index 2358caffc9b..7b993279f18 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -9,7 +9,7 @@ use rustc_middle::{
         AdtDef, Instance, Ty,
     },
 };
-use rustc_span::sym;
+use rustc_span::{source_map::Spanned, sym};
 use rustc_target::abi::{self, FieldIdx};
 use rustc_target::abi::{
     call::{ArgAbi, FnAbi, PassMode},
@@ -242,13 +242,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     /// Evaluate the arguments of a function call
     pub(super) fn eval_fn_call_arguments(
         &self,
-        ops: &[mir::Operand<'tcx>],
+        ops: &[Spanned<mir::Operand<'tcx>>],
     ) -> InterpResult<'tcx, Vec<FnArg<'tcx, M::Provenance>>> {
         ops.iter()
             .map(|op| {
-                Ok(match op {
+                Ok(match &op.node {
                     mir::Operand::Move(place) => FnArg::InPlace(self.eval_place(*place)?),
-                    _ => FnArg::Copy(self.eval_operand(op, None)?),
+                    _ => FnArg::Copy(self.eval_operand(&op.node, None)?),
                 })
             })
             .collect()
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 ae9595d7e64..89c65d92325 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -804,7 +804,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
 
                 // const-eval of the `begin_panic` fn assumes the argument is `&str`
                 if Some(callee) == tcx.lang_items().begin_panic_fn() {
-                    match args[0].ty(&self.ccx.body.local_decls, tcx).kind() {
+                    match args[0].node.ty(&self.ccx.body.local_decls, tcx).kind() {
                         ty::Ref(_, ty, _) if ty.is_str() => return,
                         _ => self.check_op(ops::PanicNonStr),
                     }
@@ -812,7 +812,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
 
                 // const-eval of `#[rustc_const_panic_str]` functions assumes the argument is `&&str`
                 if tcx.has_attr(callee, sym::rustc_const_panic_str) {
-                    match args[0].ty(&self.ccx.body.local_decls, tcx).kind() {
+                    match args[0].node.ty(&self.ccx.body.local_decls, tcx).kind() {
                         ty::Ref(_, ty, _) if matches!(ty.kind(), ty::Ref(_, ty, _) if ty.is_str()) =>
                         {
                             return;
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index 0b73691204d..9c2f336e912 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -402,7 +402,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
                     );
                 }
                 for arg in args {
-                    if let Operand::Move(place) = arg {
+                    if let Operand::Move(place) = &arg.node {
                         if is_within_packed(self.tcx, &self.body.local_decls, *place).is_some() {
                             // This is bad! The callee will expect the memory to be aligned.
                             self.fail(
diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml
index 23949deaade..9d598c32e6f 100644
--- a/compiler/rustc_data_structures/Cargo.toml
+++ b/compiler/rustc_data_structures/Cargo.toml
@@ -13,7 +13,7 @@ indexmap = { version = "2.0.0" }
 itertools = "0.11"
 jobserver_crate = { version = "0.1.27", package = "jobserver" }
 libc = "0.2"
-measureme = "10.0.0"
+measureme = "11"
 rustc-hash = "1.1.0"
 rustc-rayon = { version = "0.5.0", optional = true }
 rustc-rayon-core = { version = "0.5.0", optional = true }
diff --git a/compiler/rustc_data_structures/src/binary_search_util/mod.rs b/compiler/rustc_data_structures/src/binary_search_util/mod.rs
index bc8a6b9eac0..1c6e227cec4 100644
--- a/compiler/rustc_data_structures/src/binary_search_util/mod.rs
+++ b/compiler/rustc_data_structures/src/binary_search_util/mod.rs
@@ -18,27 +18,10 @@ where
         return &[];
     };
 
-    // Now search forward to find the *last* one.
-    let mut end = start;
-    let mut previous = start;
-    let mut step = 1;
-    loop {
-        end = end.saturating_add(step).min(size);
-        if end == size || key_fn(&data[end]) != *key {
-            break;
-        }
-        previous = end;
-        step *= 2;
-    }
-    step = end - previous;
-    while step > 1 {
-        let half = step / 2;
-        let mid = end - half;
-        if key_fn(&data[mid]) != *key {
-            end = mid;
-        }
-        step -= half;
-    }
+    // Find the first entry with key > `key`. Skip `start` entries since
+    // key_fn(&data[start]) == *key
+    let offset = start + 1;
+    let end = data[offset..].partition_point(|x| key_fn(x) <= *key) + offset;
 
     &data[start..end]
 }
diff --git a/compiler/rustc_data_structures/src/hashes.rs b/compiler/rustc_data_structures/src/hashes.rs
index 291ee5bbe26..1564eeb4bae 100644
--- a/compiler/rustc_data_structures/src/hashes.rs
+++ b/compiler/rustc_data_structures/src/hashes.rs
@@ -75,11 +75,21 @@ impl fmt::LowerHex for Hash64 {
     }
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)]
 pub struct Hash128 {
     inner: u128,
 }
 
+// We expect Hash128 to be well mixed. So there's no point in hashing both parts.
+//
+// This also allows using Hash128-containing types in UnHash-based hashmaps, which would otherwise
+// debug_assert! that we're hashing more than a single u64.
+impl std::hash::Hash for Hash128 {
+    fn hash<H: std::hash::Hasher>(&self, h: &mut H) {
+        h.write_u64(self.truncate().as_u64());
+    }
+}
+
 impl Hash128 {
     #[inline]
     pub fn truncate(self) -> Hash64 {
diff --git a/compiler/rustc_data_structures/src/marker.rs b/compiler/rustc_data_structures/src/marker.rs
index 266e54604a6..a9ccfbed411 100644
--- a/compiler/rustc_data_structures/src/marker.rs
+++ b/compiler/rustc_data_structures/src/marker.rs
@@ -177,7 +177,6 @@ cfg_match! {
             [Vec<T, A> where T: DynSync, A: std::alloc::Allocator + DynSync]
             [Box<T, A> where T: ?Sized + DynSync, A: std::alloc::Allocator + DynSync]
             [crate::sync::RwLock<T> where T: DynSend + DynSync]
-            [crate::sync::OneThread<T> where T]
             [crate::sync::WorkerLocal<T> where T: DynSend]
             [crate::intern::Interned<'a, T> where 'a, T: DynSync]
             [crate::tagged_ptr::CopyTaggedPtr<P, T, CP> where P: Sync + crate::tagged_ptr::Pointer, T: Sync + crate::tagged_ptr::Tag, const CP: bool]
diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs
index afe26f80de8..52304c72a2f 100644
--- a/compiler/rustc_data_structures/src/stable_hasher.rs
+++ b/compiler/rustc_data_structures/src/stable_hasher.rs
@@ -314,7 +314,19 @@ impl_stable_traits_for_trivial_type!(char);
 impl_stable_traits_for_trivial_type!(());
 
 impl_stable_traits_for_trivial_type!(Hash64);
-impl_stable_traits_for_trivial_type!(Hash128);
+
+// We need a custom impl as the default hash function will only hash half the bits. For stable
+// hashing we want to hash the full 128-bit hash.
+impl<CTX> HashStable<CTX> for Hash128 {
+    #[inline]
+    fn hash_stable(&self, _: &mut CTX, hasher: &mut StableHasher) {
+        self.as_u128().hash(hasher);
+    }
+}
+
+unsafe impl StableOrd for Hash128 {
+    const CAN_USE_UNSTABLE_SORT: bool = true;
+}
 
 impl<CTX> HashStable<CTX> for ! {
     fn hash_stable(&self, _ctx: &mut CTX, _hasher: &mut StableHasher) {
diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs
index 48edfba8da0..adcb6ceaebf 100644
--- a/compiler/rustc_data_structures/src/sync.rs
+++ b/compiler/rustc_data_structures/src/sync.rs
@@ -43,7 +43,6 @@
 pub use crate::marker::*;
 use std::collections::HashMap;
 use std::hash::{BuildHasher, Hash};
-use std::ops::{Deref, DerefMut};
 
 mod lock;
 pub use lock::{Lock, LockGuard, Mode};
@@ -309,8 +308,6 @@ cfg_match! {
 
         use parking_lot::RwLock as InnerRwLock;
 
-        use std::thread;
-
         /// This makes locks panic if they are already held.
         /// It is only useful when you are running in a single thread
         const ERROR_CHECKING: bool = false;
@@ -445,56 +442,3 @@ impl<T: Clone> Clone for RwLock<T> {
         RwLock::new(self.borrow().clone())
     }
 }
-
-/// A type which only allows its inner value to be used in one thread.
-/// It will panic if it is used on multiple threads.
-#[derive(Debug)]
-pub struct OneThread<T> {
-    #[cfg(parallel_compiler)]
-    thread: thread::ThreadId,
-    inner: T,
-}
-
-#[cfg(parallel_compiler)]
-unsafe impl<T> std::marker::Sync for OneThread<T> {}
-#[cfg(parallel_compiler)]
-unsafe impl<T> std::marker::Send for OneThread<T> {}
-
-impl<T> OneThread<T> {
-    #[inline(always)]
-    fn check(&self) {
-        #[cfg(parallel_compiler)]
-        assert_eq!(thread::current().id(), self.thread);
-    }
-
-    #[inline(always)]
-    pub fn new(inner: T) -> Self {
-        OneThread {
-            #[cfg(parallel_compiler)]
-            thread: thread::current().id(),
-            inner,
-        }
-    }
-
-    #[inline(always)]
-    pub fn into_inner(value: Self) -> T {
-        value.check();
-        value.inner
-    }
-}
-
-impl<T> Deref for OneThread<T> {
-    type Target = T;
-
-    fn deref(&self) -> &T {
-        self.check();
-        &self.inner
-    }
-}
-
-impl<T> DerefMut for OneThread<T> {
-    fn deref_mut(&mut self) -> &mut T {
-        self.check();
-        &mut self.inner
-    }
-}
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 2e4baf26176..11dcf4108d4 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -35,7 +35,7 @@ use rustc_lint::unerased_lint_store;
 use rustc_metadata::creader::MetadataLoader;
 use rustc_metadata::locator;
 use rustc_session::config::{nightly_options, CG_OPTIONS, Z_OPTIONS};
-use rustc_session::config::{ErrorOutputType, Input, OutFileName, OutputType, TrimmedDefPaths};
+use rustc_session::config::{ErrorOutputType, Input, OutFileName, OutputType};
 use rustc_session::getopts::{self, Matches};
 use rustc_session::lint::{Lint, LintId};
 use rustc_session::{config, EarlyDiagCtxt, Session};
@@ -204,7 +204,7 @@ impl Callbacks for TimePassesCallbacks {
         //
         self.time_passes = (config.opts.prints.is_empty() && config.opts.unstable_opts.time_passes)
             .then(|| config.opts.unstable_opts.time_passes_format);
-        config.opts.trimmed_def_paths = TrimmedDefPaths::GoodPath;
+        config.opts.trimmed_def_paths = true;
     }
 }
 
diff --git a/compiler/rustc_error_codes/src/error_codes/E0708.md b/compiler/rustc_error_codes/src/error_codes/E0708.md
index 9287fc803d1..61a853ac446 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0708.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0708.md
@@ -1,12 +1,14 @@
+#### Note: this error code is no longer emitted by the compiler.
+
 `async` non-`move` closures with parameters are currently not supported.
 
 Erroneous code example:
 
-```compile_fail,edition2018,E0708
+```edition2018
 #![feature(async_closure)]
 
 fn main() {
-    let add_one = async |num: u8| { // error!
+    let add_one = async |num: u8| {
         num + 1
     };
 }
diff --git a/compiler/rustc_error_codes/src/error_codes/E0795.md b/compiler/rustc_error_codes/src/error_codes/E0795.md
index 20f51441c29..ad77d72c913 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0795.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0795.md
@@ -3,7 +3,7 @@ Invalid argument for the `offset_of!` macro.
 Erroneous code example:
 
 ```compile_fail,E0795
-#![feature(offset_of, offset_of_enum)]
+#![feature(offset_of_enum, offset_of_nested)]
 
 let x = std::mem::offset_of!(Option<u8>, Some);
 ```
@@ -16,7 +16,7 @@ The offset of the contained `u8` in the `Option<u8>` can be found by specifying
 the field name `0`:
 
 ```
-#![feature(offset_of, offset_of_enum)]
+#![feature(offset_of_enum, offset_of_nested)]
 
 let x: usize = std::mem::offset_of!(Option<u8>, Some.0);
 ```
diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
index 648c9118400..f0699a56f98 100644
--- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
+++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
@@ -9,8 +9,8 @@ use crate::emitter::FileWithAnnotatedLines;
 use crate::snippet::Line;
 use crate::translation::{to_fluent_args, Translate};
 use crate::{
-    CodeSuggestion, Diagnostic, DiagnosticId, DiagnosticMessage, Emitter, FluentBundle,
-    LazyFallbackBundle, Level, MultiSpan, Style, SubDiagnostic,
+    CodeSuggestion, Diagnostic, DiagnosticMessage, Emitter, FluentBundle, LazyFallbackBundle,
+    Level, MultiSpan, Style, SubDiagnostic,
 };
 use annotate_snippets::{Annotation, AnnotationType, Renderer, Slice, Snippet, SourceAnnotation};
 use rustc_data_structures::sync::Lrc;
@@ -127,7 +127,7 @@ impl AnnotateSnippetEmitter {
         level: &Level,
         messages: &[(DiagnosticMessage, Style)],
         args: &FluentArgs<'_>,
-        code: &Option<DiagnosticId>,
+        code: &Option<String>,
         msp: &MultiSpan,
         _children: &[SubDiagnostic],
         _suggestions: &[CodeSuggestion],
@@ -181,11 +181,7 @@ impl AnnotateSnippetEmitter {
             let snippet = Snippet {
                 title: Some(Annotation {
                     label: Some(&message),
-                    id: code.as_ref().map(|c| match c {
-                        DiagnosticId::Error(val) | DiagnosticId::Lint { name: val, .. } => {
-                            val.as_str()
-                        }
-                    }),
+                    id: code.as_deref(),
                     annotation_type: annotation_type_for_level(*level),
                 }),
                 footer: vec![],
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index 786aced5b4f..4934bc2450c 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -104,7 +104,7 @@ pub struct Diagnostic {
     pub(crate) level: Level,
 
     pub messages: Vec<(DiagnosticMessage, Style)>,
-    pub code: Option<DiagnosticId>,
+    pub code: Option<String>,
     pub span: MultiSpan,
     pub children: Vec<SubDiagnostic>,
     pub suggestions: Result<Vec<CodeSuggestion>, SuggestionsDisabled>,
@@ -115,9 +115,9 @@ pub struct Diagnostic {
     /// `span` if there is one. Otherwise, it is `DUMMY_SP`.
     pub sort_span: Span,
 
-    /// If diagnostic is from Lint, custom hash function ignores notes
-    /// otherwise hash is based on the all the fields
-    pub is_lint: bool,
+    /// If diagnostic is from Lint, custom hash function ignores children.
+    /// Otherwise hash is based on the all the fields.
+    pub is_lint: Option<IsLint>,
 
     /// With `-Ztrack_diagnostics` enabled,
     /// we print where in rustc this error was emitted.
@@ -146,13 +146,11 @@ impl fmt::Display for DiagnosticLocation {
 }
 
 #[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
-pub enum DiagnosticId {
-    Error(String),
-    Lint {
-        name: String,
-        /// Indicates whether this lint should show up in cargo's future breakage report.
-        has_future_breakage: bool,
-    },
+pub struct IsLint {
+    /// The lint name.
+    pub(crate) name: String,
+    /// Indicates whether this lint should show up in cargo's future breakage report.
+    has_future_breakage: bool,
 }
 
 /// A "sub"-diagnostic attached to a parent diagnostic.
@@ -231,7 +229,7 @@ impl Diagnostic {
             suggestions: Ok(vec![]),
             args: Default::default(),
             sort_span: DUMMY_SP,
-            is_lint: false,
+            is_lint: None,
             emitted_at: DiagnosticLocation::caller(),
         }
     }
@@ -288,16 +286,13 @@ impl Diagnostic {
 
     /// Indicates whether this diagnostic should show up in cargo's future breakage report.
     pub(crate) fn has_future_breakage(&self) -> bool {
-        match self.code {
-            Some(DiagnosticId::Lint { has_future_breakage, .. }) => has_future_breakage,
-            _ => false,
-        }
+        matches!(self.is_lint, Some(IsLint { has_future_breakage: true, .. }))
     }
 
     pub(crate) fn is_force_warn(&self) -> bool {
         match self.level {
             Level::ForceWarning(_) => {
-                assert!(self.is_lint);
+                assert!(self.is_lint.is_some());
                 true
             }
             _ => false,
@@ -893,12 +888,12 @@ impl Diagnostic {
         self
     }
 
-    pub fn is_lint(&mut self) -> &mut Self {
-        self.is_lint = true;
+    pub fn is_lint(&mut self, name: String, has_future_breakage: bool) -> &mut Self {
+        self.is_lint = Some(IsLint { name, has_future_breakage });
         self
     }
 
-    pub fn code(&mut self, s: DiagnosticId) -> &mut Self {
+    pub fn code(&mut self, s: String) -> &mut Self {
         self.code = Some(s);
         self
     }
@@ -908,8 +903,8 @@ impl Diagnostic {
         self
     }
 
-    pub fn get_code(&self) -> Option<DiagnosticId> {
-        self.code.clone()
+    pub fn get_code(&self) -> Option<&str> {
+        self.code.as_deref()
     }
 
     pub fn primary_message(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self {
@@ -995,7 +990,8 @@ impl Diagnostic {
         &Level,
         &[(DiagnosticMessage, Style)],
         Vec<(&Cow<'static, str>, &DiagnosticArgValue<'static>)>,
-        &Option<DiagnosticId>,
+        &Option<String>,
+        &Option<IsLint>,
         &MultiSpan,
         &Result<Vec<CodeSuggestion>, SuggestionsDisabled>,
         Option<&[SubDiagnostic]>,
@@ -1005,9 +1001,10 @@ impl Diagnostic {
             &self.messages,
             self.args().collect(),
             &self.code,
+            &self.is_lint,
             &self.span,
             &self.suggestions,
-            (if self.is_lint { None } else { Some(&self.children) }),
+            (if self.is_lint.is_some() { None } else { Some(&self.children) }),
         )
     }
 }
diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs
index bd7c58d904e..87e2d295c7f 100644
--- a/compiler/rustc_errors/src/diagnostic_builder.rs
+++ b/compiler/rustc_errors/src/diagnostic_builder.rs
@@ -1,8 +1,8 @@
 use crate::diagnostic::IntoDiagnosticArg;
 use crate::{DiagCtxt, Level, MultiSpan, StashKey};
 use crate::{
-    Diagnostic, DiagnosticId, DiagnosticMessage, DiagnosticStyledString, ErrorGuaranteed,
-    ExplicitBug, SubdiagnosticMessage,
+    Diagnostic, DiagnosticMessage, DiagnosticStyledString, ErrorGuaranteed, ExplicitBug,
+    SubdiagnosticMessage,
 };
 use rustc_lint_defs::Applicability;
 use rustc_span::source_map::Spanned;
@@ -395,8 +395,11 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
     forward!((span, with_span)(
         sp: impl Into<MultiSpan>,
     ));
+    forward!((is_lint, with_is_lint)(
+        name: String, has_future_breakage: bool,
+    ));
     forward!((code, with_code)(
-        s: DiagnosticId,
+        s: String,
     ));
     forward!((arg, with_arg)(
         name: impl Into<Cow<'static, str>>, arg: impl IntoDiagnosticArg,
@@ -437,15 +440,11 @@ impl<G: EmissionGuarantee> Drop for DiagnosticBuilder<'_, G> {
 #[macro_export]
 macro_rules! struct_span_code_err {
     ($dcx:expr, $span:expr, $code:ident, $($message:tt)*) => ({
-        $dcx.struct_span_err(
-            $span,
-            format!($($message)*),
-        )
-        .with_code($crate::error_code!($code))
+        $dcx.struct_span_err($span, format!($($message)*)).with_code($crate::error_code!($code))
     })
 }
 
 #[macro_export]
 macro_rules! error_code {
-    ($code:ident) => {{ $crate::DiagnosticId::Error(stringify!($code).to_owned()) }};
+    ($code:ident) => {{ stringify!($code).to_owned() }};
 }
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 987832e6937..23efdaea0eb 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -16,9 +16,9 @@ use crate::snippet::{
 use crate::styled_buffer::StyledBuffer;
 use crate::translation::{to_fluent_args, Translate};
 use crate::{
-    diagnostic::DiagnosticLocation, CodeSuggestion, DiagCtxt, Diagnostic, DiagnosticId,
-    DiagnosticMessage, FluentBundle, LazyFallbackBundle, Level, MultiSpan, SubDiagnostic,
-    SubstitutionHighlight, SuggestionStyle, TerminalUrl,
+    diagnostic::DiagnosticLocation, CodeSuggestion, DiagCtxt, Diagnostic, DiagnosticMessage,
+    FluentBundle, LazyFallbackBundle, Level, MultiSpan, SubDiagnostic, SubstitutionHighlight,
+    SuggestionStyle, TerminalUrl,
 };
 use rustc_lint_defs::pluralize;
 
@@ -1309,7 +1309,7 @@ impl HumanEmitter {
         msp: &MultiSpan,
         msgs: &[(DiagnosticMessage, Style)],
         args: &FluentArgs<'_>,
-        code: &Option<DiagnosticId>,
+        code: &Option<String>,
         level: &Level,
         max_line_num_len: usize,
         is_secondary: bool,
@@ -1336,14 +1336,13 @@ impl HumanEmitter {
                 buffer.append(0, level.to_str(), Style::Level(*level));
                 label_width += level.to_str().len();
             }
-            // only render error codes, not lint codes
-            if let Some(DiagnosticId::Error(ref code)) = *code {
+            if let Some(code) = code {
                 buffer.append(0, "[", Style::Level(*level));
                 let code = if let TerminalUrl::Yes = self.terminal_url {
                     let path = "https://doc.rust-lang.org/error_codes";
-                    format!("\x1b]8;;{path}/{code}.html\x07{code}\x1b]8;;\x07")
+                    Cow::Owned(format!("\x1b]8;;{path}/{code}.html\x07{code}\x1b]8;;\x07"))
                 } else {
-                    code.clone()
+                    Cow::Borrowed(code)
                 };
                 buffer.append(0, &code, Style::Level(*level));
                 buffer.append(0, "]", Style::Level(*level));
@@ -2077,7 +2076,7 @@ impl HumanEmitter {
         level: &Level,
         messages: &[(DiagnosticMessage, Style)],
         args: &FluentArgs<'_>,
-        code: &Option<DiagnosticId>,
+        code: &Option<String>,
         span: &MultiSpan,
         children: &[SubDiagnostic],
         suggestions: &[CodeSuggestion],
diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs
index 87bf9c23456..51b064f4c61 100644
--- a/compiler/rustc_errors/src/json.rs
+++ b/compiler/rustc_errors/src/json.rs
@@ -15,10 +15,9 @@ use termcolor::{ColorSpec, WriteColor};
 use crate::emitter::{should_show_source_code, Emitter, HumanReadableErrorType};
 use crate::registry::Registry;
 use crate::translation::{to_fluent_args, Translate};
-use crate::DiagnosticId;
 use crate::{
-    CodeSuggestion, FluentBundle, LazyFallbackBundle, MultiSpan, SpanLabel, SubDiagnostic,
-    TerminalUrl,
+    diagnostic::IsLint, CodeSuggestion, FluentBundle, LazyFallbackBundle, MultiSpan, SpanLabel,
+    SubDiagnostic, TerminalUrl,
 };
 use rustc_lint_defs::Applicability;
 
@@ -301,7 +300,8 @@ struct DiagnosticSpanMacroExpansion {
 
 #[derive(Serialize)]
 struct DiagnosticCode {
-    /// The code itself.
+    /// The error code (e.g. "E1234"), if the diagnostic has one. Or the lint
+    /// name, if it's a lint without an error code.
     code: String,
     /// An explanation for the code.
     explanation: Option<&'static str>,
@@ -399,9 +399,21 @@ impl Diagnostic {
         let output = String::from_utf8(output).unwrap();
 
         let translated_message = je.translate_messages(&diag.messages, &args);
+
+        let code = if let Some(code) = &diag.code {
+            Some(DiagnosticCode {
+                code: code.to_string(),
+                explanation: je.registry.as_ref().unwrap().try_find_description(&code).ok(),
+            })
+        } else if let Some(IsLint { name, .. }) = &diag.is_lint {
+            Some(DiagnosticCode { code: name.to_string(), explanation: None })
+        } else {
+            None
+        };
+
         Diagnostic {
             message: translated_message.to_string(),
-            code: DiagnosticCode::map_opt_string(diag.code.clone(), je),
+            code,
             level: diag.level.to_str(),
             spans: DiagnosticSpan::from_multispan(&diag.span, &args, je),
             children: diag
@@ -592,18 +604,3 @@ impl DiagnosticSpanLine {
             .unwrap_or_else(|_| vec![])
     }
 }
-
-impl DiagnosticCode {
-    fn map_opt_string(s: Option<DiagnosticId>, je: &JsonEmitter) -> Option<DiagnosticCode> {
-        s.map(|s| {
-            let s = match s {
-                DiagnosticId::Error(s) => s,
-                DiagnosticId::Lint { name, .. } => name,
-            };
-            let je_result =
-                je.registry.as_ref().map(|registry| registry.try_find_description(&s)).unwrap();
-
-            DiagnosticCode { code: s, explanation: je_result.ok() }
-        })
-    }
-}
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 63391a0faa6..141547b537d 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -30,7 +30,7 @@ extern crate tracing;
 extern crate self as rustc_errors;
 
 pub use diagnostic::{
-    AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgValue, DiagnosticId,
+    AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgValue,
     DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic,
 };
 pub use diagnostic_builder::{
@@ -442,13 +442,13 @@ struct DiagCtxtInner {
     /// This is used for the `good_path_delayed_bugs` check.
     suppressed_expected_diag: bool,
 
-    /// This set contains the `DiagnosticId` of all emitted diagnostics to avoid
+    /// This set contains the code of all emitted diagnostics to avoid
     /// emitting the same diagnostic with extended help (`--teach`) twice, which
     /// would be unnecessary repetition.
-    taught_diagnostics: FxHashSet<DiagnosticId>,
+    taught_diagnostics: FxHashSet<String>,
 
     /// Used to suggest rustc --explain `<error code>`
-    emitted_diagnostic_codes: FxIndexSet<DiagnosticId>,
+    emitted_diagnostic_codes: FxIndexSet<String>,
 
     /// This set contains a hash of every diagnostic that has been emitted by
     /// this `DiagCtxt`. These hashes is used to avoid emitting the same error
@@ -676,7 +676,7 @@ impl DiagCtxt {
         let key = (span.with_parent(None), key);
 
         if diag.is_error() {
-            if diag.is_lint {
+            if diag.is_lint.is_some() {
                 inner.lint_err_count += 1;
             } else {
                 inner.err_count += 1;
@@ -695,7 +695,7 @@ impl DiagCtxt {
         let key = (span.with_parent(None), key);
         let diag = inner.stashed_diagnostics.remove(&key)?;
         if diag.is_error() {
-            if diag.is_lint {
+            if diag.is_lint.is_some() {
                 inner.lint_err_count -= 1;
             } else {
                 inner.err_count -= 1;
@@ -715,9 +715,7 @@ impl DiagCtxt {
 
     /// Construct a builder at the `Warning` level at the given `span` and with the `msg`.
     ///
-    /// Attempting to `.emit()` the builder will only emit if either:
-    /// * `can_emit_warnings` is `true`
-    /// * `is_force_warn` was set in `DiagnosticId::Lint`
+    /// An `emit` call on the builder will only emit if `can_emit_warnings` is `true`.
     #[rustc_lint_diagnostics]
     #[track_caller]
     pub fn struct_span_warn(
@@ -730,9 +728,7 @@ impl DiagCtxt {
 
     /// Construct a builder at the `Warning` level with the `msg`.
     ///
-    /// Attempting to `.emit()` the builder will only emit if either:
-    /// * `can_emit_warnings` is `true`
-    /// * `is_force_warn` was set in `DiagnosticId::Lint`
+    /// An `emit` call on the builder will only emit if `can_emit_warnings` is `true`.
     #[rustc_lint_diagnostics]
     #[track_caller]
     pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
@@ -1011,11 +1007,12 @@ impl DiagCtxt {
             let mut error_codes = inner
                 .emitted_diagnostic_codes
                 .iter()
-                .filter_map(|x| match &x {
-                    DiagnosticId::Error(s) if registry.try_find_description(s).is_ok() => {
-                        Some(s.clone())
+                .filter_map(|code| {
+                    if registry.try_find_description(code).is_ok().clone() {
+                        Some(code.clone())
+                    } else {
+                        None
                     }
-                    _ => None,
                 })
                 .collect::<Vec<_>>();
             if !error_codes.is_empty() {
@@ -1058,8 +1055,8 @@ impl DiagCtxt {
     ///
     /// Used to suppress emitting the same error multiple times with extended explanation when
     /// calling `-Zteach`.
-    pub fn must_teach(&self, code: &DiagnosticId) -> bool {
-        self.inner.borrow_mut().taught_diagnostics.insert(code.clone())
+    pub fn must_teach(&self, code: &str) -> bool {
+        self.inner.borrow_mut().taught_diagnostics.insert(code.to_string())
     }
 
     pub fn force_print_diagnostic(&self, db: Diagnostic) {
@@ -1231,7 +1228,7 @@ impl DiagCtxtInner {
         for diag in diags {
             // Decrement the count tracking the stash; emitting will increment it.
             if diag.is_error() {
-                if diag.is_lint {
+                if diag.is_lint.is_some() {
                     self.lint_err_count -= 1;
                 } else {
                     self.err_count -= 1;
@@ -1363,7 +1360,7 @@ impl DiagCtxtInner {
                 self.has_printed = true;
             }
             if diagnostic.is_error() {
-                if diagnostic.is_lint {
+                if diagnostic.is_lint.is_some() {
                     self.lint_err_count += 1;
                 } else {
                     self.err_count += 1;
diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl
index 475dd348e7b..3e3b4814300 100644
--- a/compiler/rustc_expand/messages.ftl
+++ b/compiler/rustc_expand/messages.ftl
@@ -16,6 +16,9 @@ expand_attributes_wrong_form =
 expand_cannot_be_name_of_macro =
     `{$trait_ident}` cannot be a name of {$macro_type} macro
 
+expand_collapse_debuginfo_illegal =
+    illegal value for attribute #[collapse_debuginfo(no|external|yes)]
+
 expand_count_repetition_misplaced =
     `count` can not be placed inside the inner-most repetition
 
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 0a1c4430397..29b70f33a6c 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -1,5 +1,6 @@
 #![deny(rustc::untranslatable_diagnostic)]
 
+use crate::base::ast::NestedMetaItem;
 use crate::errors;
 use crate::expand::{self, AstFragment, Invocation};
 use crate::module::DirOwnership;
@@ -19,6 +20,7 @@ use rustc_feature::Features;
 use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT;
 use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiagnostics, RegisteredTools};
 use rustc_parse::{parser, MACRO_ARGUMENTS};
+use rustc_session::config::CollapseMacroDebuginfo;
 use rustc_session::errors::report_lit_error;
 use rustc_session::{parse::ParseSess, Limit, Session};
 use rustc_span::def_id::{CrateNum, DefId, LocalDefId};
@@ -664,8 +666,8 @@ pub enum SyntaxExtensionKind {
     /// A token-based attribute macro.
     Attr(
         /// An expander with signature (TokenStream, TokenStream) -> TokenStream.
-        /// The first TokenSteam is the attribute itself, the second is the annotated item.
-        /// The produced TokenSteam replaces the input TokenSteam.
+        /// The first TokenStream is the attribute itself, the second is the annotated item.
+        /// The produced TokenStream replaces the input TokenStream.
         Box<dyn AttrProcMacro + sync::DynSync + sync::DynSend>,
     ),
 
@@ -685,7 +687,7 @@ pub enum SyntaxExtensionKind {
     /// A token-based derive macro.
     Derive(
         /// An expander with signature TokenStream -> TokenStream.
-        /// The produced TokenSteam is appended to the input TokenSteam.
+        /// The produced TokenStream is appended to the input TokenStream.
         ///
         /// FIXME: The text above describes how this should work. Currently it
         /// is handled identically to `LegacyDerive`. It should be migrated to
@@ -761,6 +763,55 @@ impl SyntaxExtension {
         }
     }
 
+    fn collapse_debuginfo_by_name(sess: &Session, attr: &Attribute) -> CollapseMacroDebuginfo {
+        use crate::errors::CollapseMacroDebuginfoIllegal;
+        // #[collapse_debuginfo] without enum value (#[collapse_debuginfo(no/external/yes)])
+        // considered as `yes`
+        attr.meta_item_list().map_or(CollapseMacroDebuginfo::Yes, |l| {
+            let [NestedMetaItem::MetaItem(item)] = &l[..] else {
+                sess.dcx().emit_err(CollapseMacroDebuginfoIllegal { span: attr.span });
+                return CollapseMacroDebuginfo::Unspecified;
+            };
+            if !item.is_word() {
+                sess.dcx().emit_err(CollapseMacroDebuginfoIllegal { span: item.span });
+                CollapseMacroDebuginfo::Unspecified
+            } else {
+                match item.name_or_empty() {
+                    sym::no => CollapseMacroDebuginfo::No,
+                    sym::external => CollapseMacroDebuginfo::External,
+                    sym::yes => CollapseMacroDebuginfo::Yes,
+                    _ => {
+                        sess.dcx().emit_err(CollapseMacroDebuginfoIllegal { span: item.span });
+                        CollapseMacroDebuginfo::Unspecified
+                    }
+                }
+            }
+        })
+    }
+
+    /// if-ext - if macro from different crate (related to callsite code)
+    /// | cmd \ attr    | no  | (unspecified) | external | yes |
+    /// | no            | no  | no            | no       | no  |
+    /// | (unspecified) | no  | no            | if-ext   | yes |
+    /// | external      | no  | if-ext        | if-ext   | yes |
+    /// | yes           | yes | yes           | yes      | yes |
+    fn get_collapse_debuginfo(sess: &Session, attrs: &[ast::Attribute], is_local: bool) -> bool {
+        let collapse_debuginfo_attr = attr::find_by_name(attrs, sym::collapse_debuginfo)
+            .map(|v| Self::collapse_debuginfo_by_name(sess, v))
+            .unwrap_or(CollapseMacroDebuginfo::Unspecified);
+        let flag = sess.opts.unstable_opts.collapse_macro_debuginfo;
+        let attr = collapse_debuginfo_attr;
+        let ext = !is_local;
+        #[rustfmt::skip]
+        let collapse_table = [
+            [false, false, false, false],
+            [false, false, ext,   true],
+            [false, ext,   ext,   true],
+            [true,  true,  true,  true],
+        ];
+        collapse_table[flag as usize][attr as usize]
+    }
+
     /// Constructs a syntax extension with the given properties
     /// and other properties converted from attributes.
     pub fn new(
@@ -772,6 +823,7 @@ impl SyntaxExtension {
         edition: Edition,
         name: Symbol,
         attrs: &[ast::Attribute],
+        is_local: bool,
     ) -> SyntaxExtension {
         let allow_internal_unstable =
             attr::allow_internal_unstable(sess, attrs).collect::<Vec<Symbol>>();
@@ -780,8 +832,8 @@ impl SyntaxExtension {
         let local_inner_macros = attr::find_by_name(attrs, sym::macro_export)
             .and_then(|macro_export| macro_export.meta_item_list())
             .is_some_and(|l| attr::list_contains_name(&l, sym::local_inner_macros));
-        let collapse_debuginfo = attr::contains_name(attrs, sym::collapse_debuginfo);
-        tracing::debug!(?local_inner_macros, ?collapse_debuginfo, ?allow_internal_unsafe);
+        let collapse_debuginfo = Self::get_collapse_debuginfo(sess, attrs, is_local);
+        tracing::debug!(?name, ?local_inner_macros, ?collapse_debuginfo, ?allow_internal_unsafe);
 
         let (builtin_name, helper_attrs) = attr::find_by_name(attrs, sym::rustc_builtin_macro)
             .map(|attr| {
diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs
index 2b43fae6852..4a1c00f0104 100644
--- a/compiler/rustc_expand/src/errors.rs
+++ b/compiler/rustc_expand/src/errors.rs
@@ -59,6 +59,13 @@ pub(crate) struct ResolveRelativePath {
 }
 
 #[derive(Diagnostic)]
+#[diag(expand_collapse_debuginfo_illegal)]
+pub(crate) struct CollapseMacroDebuginfoIllegal {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
 #[diag(expand_macro_const_stability)]
 pub(crate) struct MacroConstStability {
     #[primary_span]
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index 363b52aef8a..1a39708ed8e 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -367,6 +367,7 @@ pub fn compile_declarative_macro(
             edition,
             def.ident.name,
             &def.attrs,
+            def.id != DUMMY_NODE_ID,
         )
     };
     let dummy_syn_ext = || (mk_syn_ext(Box::new(macro_rules_dummy_expander)), Vec::new());
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 4442b67df6e..68b6f69854d 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -469,7 +469,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
 
     // `#[collapse_debuginfo]`
     gated!(
-        collapse_debuginfo, Normal, template!(Word), WarnFollowing,
+        collapse_debuginfo, Normal, template!(Word, List: "no|external|yes"), ErrorFollowing,
         experimental!(collapse_debuginfo)
     ),
 
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 2f2b551e6ec..371b651f5e8 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -549,7 +549,9 @@ declare_features! (
     /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden.
     (unstable, object_safe_for_dispatch, "1.40.0", Some(43561)),
     /// Allows using enums in offset_of!
-    (unstable, offset_of_enum, "1.75.0", Some(106655)),
+    (unstable, offset_of_enum, "1.75.0", Some(120141)),
+    /// Allows using multiple nested field accesses in offset_of!
+    (unstable, offset_of_nested, "CURRENT_RUSTC_VERSION", Some(120140)),
     /// Allows using `#[optimize(X)]`.
     (unstable, optimize_attribute, "1.34.0", Some(54882)),
     /// Allows macro attributes on expressions, statements and non-inline modules.
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 6b347f7035a..23881cfd7df 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -248,7 +248,7 @@ pub struct InferArg {
 }
 
 impl InferArg {
-    pub fn to_ty(&self) -> Ty<'_> {
+    pub fn to_ty(&self) -> Ty<'static> {
         Ty { kind: TyKind::Infer, span: self.span, hir_id: self.hir_id }
     }
 }
@@ -841,7 +841,7 @@ pub struct OwnerNodes<'tcx> {
 }
 
 impl<'tcx> OwnerNodes<'tcx> {
-    fn node(&self) -> OwnerNode<'tcx> {
+    pub fn node(&self) -> OwnerNode<'tcx> {
         use rustc_index::Idx;
         let node = self.nodes[ItemLocalId::new(0)].as_ref().unwrap().node;
         let node = node.as_owner().unwrap(); // Indexing must ensure it is an OwnerNode.
@@ -1015,7 +1015,7 @@ impl<'hir> Pat<'hir> {
 
         use PatKind::*;
         match self.kind {
-            Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Path(_) => true,
+            Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Path(_) | Err(_) => true,
             Box(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_short_(it),
             Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_short_(it)),
             TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().all(|p| p.walk_short_(it)),
@@ -1042,7 +1042,7 @@ impl<'hir> Pat<'hir> {
 
         use PatKind::*;
         match self.kind {
-            Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Path(_) => {}
+            Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Path(_) | Err(_) => {}
             Box(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_(it),
             Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk_(it)),
             TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().for_each(|p| p.walk_(it)),
@@ -1205,6 +1205,9 @@ pub enum PatKind<'hir> {
     /// PatKind::Slice([Binding(a), Binding(b)], Some(Wild), [Binding(c), Binding(d)])
     /// ```
     Slice(&'hir [Pat<'hir>], Option<&'hir Pat<'hir>>, &'hir [Pat<'hir>]),
+
+    /// A placeholder for a pattern that wasn't well formed in some way.
+    Err(ErrorGuaranteed),
 }
 
 /// A statement.
@@ -1302,7 +1305,7 @@ pub enum UnsafeSource {
     UserProvided,
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
 pub struct BodyId {
     pub hir_id: HirId,
 }
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index adc09025809..116de6fb04d 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -655,7 +655,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) {
             walk_list!(visitor, visit_expr, lower_bound);
             walk_list!(visitor, visit_expr, upper_bound);
         }
-        PatKind::Never | PatKind::Wild => (),
+        PatKind::Never | PatKind::Wild | PatKind::Err(_) => (),
         PatKind::Slice(prepatterns, ref slice_pattern, postpatterns) => {
             walk_list!(visitor, visit_pat, prepatterns);
             walk_list!(visitor, visit_pat, slice_pattern);
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 3f3b57ba94f..1cc1f11b3c8 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -374,3 +374,30 @@ pub static OPERATORS: &'static [LangItem] = &[
     LangItem::PartialEq,
     LangItem::PartialOrd,
 ];
+
+pub static BINARY_OPERATORS: &'static [LangItem] = &[
+    LangItem::Add,
+    LangItem::Sub,
+    LangItem::Mul,
+    LangItem::Div,
+    LangItem::Rem,
+    LangItem::BitXor,
+    LangItem::BitAnd,
+    LangItem::BitOr,
+    LangItem::Shl,
+    LangItem::Shr,
+    LangItem::AddAssign,
+    LangItem::SubAssign,
+    LangItem::MulAssign,
+    LangItem::DivAssign,
+    LangItem::RemAssign,
+    LangItem::BitXorAssign,
+    LangItem::BitAndAssign,
+    LangItem::BitOrAssign,
+    LangItem::ShlAssign,
+    LangItem::ShrAssign,
+    LangItem::Index,
+    LangItem::IndexMut,
+    LangItem::PartialEq,
+    LangItem::PartialOrd,
+];
diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs
index 97fa710b354..baa1635f731 100644
--- a/compiler/rustc_hir/src/stable_hash_impls.rs
+++ b/compiler/rustc_hir/src/stable_hash_impls.rs
@@ -12,7 +12,6 @@ use rustc_span::def_id::DefPathHash;
 pub trait HashStableContext:
     rustc_ast::HashStableContext + rustc_target::HashStableContext
 {
-    fn hash_body_id(&mut self, _: BodyId, hasher: &mut StableHasher);
 }
 
 impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for HirId {
@@ -80,12 +79,6 @@ impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for ForeignItemId
     }
 }
 
-impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for BodyId {
-    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
-        hcx.hash_body_id(*self, hasher)
-    }
-}
-
 // The following implementations of HashStable for `ItemId`, `TraitItemId`, and
 // `ImplItemId` deserve special attention. Normally we do not hash `NodeId`s within
 // the HIR, since they just signify a HIR nodes own path. But `ItemId` et al
diff --git a/compiler/rustc_hir_analysis/Cargo.toml b/compiler/rustc_hir_analysis/Cargo.toml
index b5ebc1fab76..648b569a217 100644
--- a/compiler/rustc_hir_analysis/Cargo.toml
+++ b/compiler/rustc_hir_analysis/Cargo.toml
@@ -9,6 +9,7 @@ doctest = false
 
 [dependencies]
 # tidy-alphabetical-start
+itertools = "0.11"
 rustc_arena = { path = "../rustc_arena" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_attr = { path = "../rustc_attr" }
diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs
index 2ad96a24891..401efff9242 100644
--- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs
@@ -108,14 +108,16 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
     /// `param_ty` and `ast_bounds`. See `instantiate_poly_trait_ref`
     /// for more details.
     #[instrument(level = "debug", skip(self, ast_bounds, bounds))]
-    pub(crate) fn add_bounds<'hir, I: Iterator<Item = &'hir hir::GenericBound<'hir>>>(
+    pub(crate) fn add_bounds<'hir, I: Iterator<Item = &'hir hir::GenericBound<'tcx>>>(
         &self,
         param_ty: Ty<'tcx>,
         ast_bounds: I,
         bounds: &mut Bounds<'tcx>,
         bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
         only_self_bounds: OnlySelfBounds,
-    ) {
+    ) where
+        'tcx: 'hir,
+    {
         for ast_bound in ast_bounds {
             match ast_bound {
                 hir::GenericBound::Trait(poly_trait_ref, modifier) => {
@@ -179,7 +181,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
     pub(crate) fn compute_bounds(
         &self,
         param_ty: Ty<'tcx>,
-        ast_bounds: &[hir::GenericBound<'_>],
+        ast_bounds: &[hir::GenericBound<'tcx>],
         filter: PredicateFilter,
     ) -> Bounds<'tcx> {
         let mut bounds = Bounds::default();
diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs
index e2cd4d5f21c..f9628d1d6f3 100644
--- a/compiler/rustc_hir_analysis/src/astconv/generics.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs
@@ -168,7 +168,7 @@ fn generic_arg_mismatch_err(
 ///   instantiate a `GenericArg`.
 /// - `inferred_kind`: if no parameter was provided, and inference is enabled, then
 ///   creates a suitable inference variable.
-pub fn create_args_for_parent_generic_args<'tcx, 'a>(
+pub fn create_args_for_parent_generic_args<'tcx: 'a, 'a>(
     tcx: TyCtxt<'tcx>,
     def_id: DefId,
     parent_args: &[ty::GenericArg<'tcx>],
diff --git a/compiler/rustc_hir_analysis/src/astconv/lint.rs b/compiler/rustc_hir_analysis/src/astconv/lint.rs
index 3761d529517..b5f42e98127 100644
--- a/compiler/rustc_hir_analysis/src/astconv/lint.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/lint.rs
@@ -78,14 +78,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     fn maybe_lint_impl_trait(&self, self_ty: &hir::Ty<'_>, diag: &mut Diagnostic) -> bool {
         let tcx = self.tcx();
         let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id;
-        let (hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, generics, _), .. })
-        | hir::Node::TraitItem(hir::TraitItem {
-            kind: hir::TraitItemKind::Fn(sig, _),
-            generics,
-            ..
-        })) = tcx.hir_node_by_def_id(parent_id)
-        else {
-            return false;
+        let (sig, generics, owner) = match tcx.hir_node_by_def_id(parent_id) {
+            hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, generics, _), .. }) => {
+                (sig, generics, None)
+            }
+            hir::Node::TraitItem(hir::TraitItem {
+                kind: hir::TraitItemKind::Fn(sig, _),
+                generics,
+                owner_id,
+                ..
+            }) => (sig, generics, Some(tcx.parent(owner_id.to_def_id()))),
+            _ => return false,
         };
         let Ok(trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else {
             return false;
@@ -94,6 +97,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         let is_object_safe = match self_ty.kind {
             hir::TyKind::TraitObject(objects, ..) => {
                 objects.iter().all(|o| match o.trait_ref.path.res {
+                    Res::Def(DefKind::Trait, id) if Some(id) == owner => {
+                        // When we're dealing with a recursive trait, we don't want to downgrade
+                        // the error, so we consider them to be object safe always. (#119652)
+                        true
+                    }
                     Res::Def(DefKind::Trait, id) => tcx.check_is_object_safe(id),
                     _ => false,
                 })
@@ -122,7 +130,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     ],
                     Applicability::MachineApplicable,
                 );
-            } else {
+            } else if diag.is_error() {
                 // We'll emit the object safety error already, with a structured suggestion.
                 diag.downgrade_to_delayed_bug();
             }
@@ -148,8 +156,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             }
             if !is_object_safe {
                 diag.note(format!("`{trait_name}` it is not object safe, so it can't be `dyn`"));
-                // We'll emit the object safety error already, with a structured suggestion.
-                diag.downgrade_to_delayed_bug();
+                if diag.is_error() {
+                    // We'll emit the object safety error already, with a structured suggestion.
+                    diag.downgrade_to_delayed_bug();
+                }
             } else {
                 let sugg = if let hir::TyKind::TraitObject([_, _, ..], _, _) = self_ty.kind {
                     // There are more than one trait bound, we need surrounding parentheses.
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 9f4f1413650..00f0d6e7c22 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -122,7 +122,7 @@ pub trait AstConv<'tcx> {
         &self,
         span: Span,
         item_def_id: DefId,
-        item_segment: &hir::PathSegment<'_>,
+        item_segment: &hir::PathSegment<'tcx>,
         poly_trait_ref: ty::PolyTraitRef<'tcx>,
     ) -> Ty<'tcx>;
 
@@ -156,14 +156,14 @@ struct ConvertedBinding<'a, 'tcx> {
     hir_id: hir::HirId,
     item_name: Ident,
     kind: ConvertedBindingKind<'a, 'tcx>,
-    gen_args: &'a GenericArgs<'a>,
+    gen_args: &'tcx GenericArgs<'tcx>,
     span: Span,
 }
 
 #[derive(Debug)]
 enum ConvertedBindingKind<'a, 'tcx> {
     Equality(Spanned<ty::Term<'tcx>>),
-    Constraint(&'a [hir::GenericBound<'a>]),
+    Constraint(&'a [hir::GenericBound<'tcx>]),
 }
 
 /// New-typed boolean indicating whether explicit late-bound lifetimes
@@ -215,12 +215,12 @@ pub struct GenericArgCountResult {
 }
 
 pub trait CreateSubstsForGenericArgsCtxt<'a, 'tcx> {
-    fn args_for_def_id(&mut self, def_id: DefId) -> (Option<&'a GenericArgs<'a>>, bool);
+    fn args_for_def_id(&mut self, def_id: DefId) -> (Option<&'a GenericArgs<'tcx>>, bool);
 
     fn provided_kind(
         &mut self,
         param: &ty::GenericParamDef,
-        arg: &GenericArg<'_>,
+        arg: &GenericArg<'tcx>,
     ) -> ty::GenericArg<'tcx>;
 
     fn inferred_kind(
@@ -294,7 +294,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         &self,
         span: Span,
         def_id: DefId,
-        item_segment: &hir::PathSegment<'_>,
+        item_segment: &hir::PathSegment<'tcx>,
     ) -> GenericArgsRef<'tcx> {
         let (args, _) = self.create_args_for_ast_path(
             span,
@@ -351,7 +351,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         def_id: DefId,
         parent_args: &[ty::GenericArg<'tcx>],
         seg: &hir::PathSegment<'_>,
-        generic_args: &'a hir::GenericArgs<'_>,
+        generic_args: &'a hir::GenericArgs<'tcx>,
         infer_args: bool,
         self_ty: Option<Ty<'tcx>>,
         constness: ty::BoundConstness,
@@ -406,14 +406,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         struct SubstsForAstPathCtxt<'a, 'tcx> {
             astconv: &'a (dyn AstConv<'tcx> + 'a),
             def_id: DefId,
-            generic_args: &'a GenericArgs<'a>,
+            generic_args: &'a GenericArgs<'tcx>,
             span: Span,
             inferred_params: Vec<Span>,
             infer_args: bool,
         }
 
         impl<'a, 'tcx> CreateSubstsForGenericArgsCtxt<'a, 'tcx> for SubstsForAstPathCtxt<'a, 'tcx> {
-            fn args_for_def_id(&mut self, did: DefId) -> (Option<&'a GenericArgs<'a>>, bool) {
+            fn args_for_def_id(&mut self, did: DefId) -> (Option<&'a GenericArgs<'tcx>>, bool) {
                 if did == self.def_id {
                     (Some(self.generic_args), self.infer_args)
                 } else {
@@ -425,11 +425,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             fn provided_kind(
                 &mut self,
                 param: &ty::GenericParamDef,
-                arg: &GenericArg<'_>,
+                arg: &GenericArg<'tcx>,
             ) -> ty::GenericArg<'tcx> {
                 let tcx = self.astconv.tcx();
 
-                let mut handle_ty_args = |has_default, ty: &hir::Ty<'_>| {
+                let mut handle_ty_args = |has_default, ty: &hir::Ty<'tcx>| {
                     if has_default {
                         tcx.check_optional_stability(
                             param.def_id,
@@ -592,7 +592,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
     fn create_assoc_bindings_for_generic_args<'a>(
         &self,
-        generic_args: &'a hir::GenericArgs<'_>,
+        generic_args: &'a hir::GenericArgs<'tcx>,
     ) -> Vec<ConvertedBinding<'a, 'tcx>> {
         // Convert associated-type bindings or constraints into a separate vector.
         // Example: Given this:
@@ -640,7 +640,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         &self,
         span: Span,
         item_def_id: DefId,
-        item_segment: &hir::PathSegment<'_>,
+        item_segment: &hir::PathSegment<'tcx>,
         parent_args: GenericArgsRef<'tcx>,
     ) -> GenericArgsRef<'tcx> {
         debug!(
@@ -673,7 +673,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     /// are disallowed. Otherwise, they are pushed onto the vector given.
     pub fn instantiate_mono_trait_ref(
         &self,
-        trait_ref: &hir::TraitRef<'_>,
+        trait_ref: &hir::TraitRef<'tcx>,
         self_ty: Ty<'tcx>,
     ) -> ty::TraitRef<'tcx> {
         self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1.iter(), |_| {});
@@ -710,7 +710,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     #[instrument(level = "debug", skip(self, span, constness, bounds, speculative))]
     pub(crate) fn instantiate_poly_trait_ref(
         &self,
-        trait_ref: &hir::TraitRef<'_>,
+        trait_ref: &hir::TraitRef<'tcx>,
         span: Span,
         constness: ty::BoundConstness,
         polarity: ty::ImplPolarity,
@@ -788,7 +788,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         span: Span,
         trait_def_id: DefId,
         self_ty: Ty<'tcx>,
-        trait_segment: &hir::PathSegment<'_>,
+        trait_segment: &hir::PathSegment<'tcx>,
         is_impl: bool,
         // FIXME(effects) move all host param things in astconv to hir lowering
         constness: ty::BoundConstness,
@@ -813,7 +813,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         span: Span,
         trait_def_id: DefId,
         self_ty: Ty<'tcx>,
-        trait_segment: &'a hir::PathSegment<'a>,
+        trait_segment: &'a hir::PathSegment<'tcx>,
         is_impl: bool,
         constness: ty::BoundConstness,
     ) -> (GenericArgsRef<'tcx>, GenericArgCountResult) {
@@ -847,7 +847,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         &self,
         span: Span,
         did: DefId,
-        item_segment: &hir::PathSegment<'_>,
+        item_segment: &hir::PathSegment<'tcx>,
     ) -> Ty<'tcx> {
         let tcx = self.tcx();
         let args = self.ast_path_args_for_ty(span, did, item_segment);
@@ -1153,7 +1153,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         span: Span,
         qself_ty: Ty<'tcx>,
         qself: &hir::Ty<'_>,
-        assoc_segment: &hir::PathSegment<'_>,
+        assoc_segment: &hir::PathSegment<'tcx>,
         permit_variants: bool,
     ) -> Result<(Ty<'tcx>, DefKind, DefId), ErrorGuaranteed> {
         let tcx = self.tcx();
@@ -1428,7 +1428,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     fn lookup_inherent_assoc_ty(
         &self,
         name: Ident,
-        segment: &hir::PathSegment<'_>,
+        segment: &hir::PathSegment<'tcx>,
         adt_did: DefId,
         self_ty: Ty<'tcx>,
         block: hir::HirId,
@@ -1446,7 +1446,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         }
 
         let candidates: Vec<_> = tcx
-            .inherent_impls(adt_did)
+            .inherent_impls(adt_did)?
             .iter()
             .filter_map(|&impl_| Some((impl_, self.lookup_assoc_ty_unchecked(name, block, impl_)?)))
             .collect();
@@ -1702,8 +1702,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         span: Span,
         opt_self_ty: Option<Ty<'tcx>>,
         item_def_id: DefId,
-        trait_segment: &hir::PathSegment<'_>,
-        item_segment: &hir::PathSegment<'_>,
+        trait_segment: &hir::PathSegment<'tcx>,
+        item_segment: &hir::PathSegment<'tcx>,
         constness: ty::BoundConstness,
     ) -> Ty<'tcx> {
         let tcx = self.tcx();
@@ -2021,7 +2021,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     pub fn res_to_ty(
         &self,
         opt_self_ty: Option<Ty<'tcx>>,
-        path: &hir::Path<'_>,
+        path: &hir::Path<'tcx>,
         hir_id: hir::HirId,
         permit_variants: bool,
     ) -> Ty<'tcx> {
@@ -2311,13 +2311,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
     /// Parses the programmer's textual representation of a type into our
     /// internal notion of a type.
-    pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
+    pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
         self.ast_ty_to_ty_inner(ast_ty, false, false)
     }
 
     /// Parses the programmer's textual representation of a type into our
     /// internal notion of a type. This is meant to be used within a path.
-    pub fn ast_ty_to_ty_in_path(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
+    pub fn ast_ty_to_ty_in_path(&self, ast_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
         self.ast_ty_to_ty_inner(ast_ty, false, true)
     }
 
@@ -2432,7 +2432,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     /// Turns a `hir::Ty` into a `Ty`. For diagnostics' purposes we keep track of whether trait
     /// objects are borrowed like `&dyn Trait` to avoid emitting redundant errors.
     #[instrument(level = "debug", skip(self), ret)]
-    fn ast_ty_to_ty_inner(&self, ast_ty: &hir::Ty<'_>, borrowed: bool, in_path: bool) -> Ty<'tcx> {
+    fn ast_ty_to_ty_inner(
+        &self,
+        ast_ty: &hir::Ty<'tcx>,
+        borrowed: bool,
+        in_path: bool,
+    ) -> Ty<'tcx> {
         let tcx = self.tcx();
 
         let result_ty = match &ast_ty.kind {
@@ -2609,7 +2614,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         }
     }
 
-    pub fn ty_of_arg(&self, ty: &hir::Ty<'_>, expected_ty: Option<Ty<'tcx>>) -> Ty<'tcx> {
+    pub fn ty_of_arg(&self, ty: &hir::Ty<'tcx>, expected_ty: Option<Ty<'tcx>>) -> Ty<'tcx> {
         match ty.kind {
             hir::TyKind::Infer if expected_ty.is_some() => {
                 self.record_ty(ty.hir_id, expected_ty.unwrap(), ty.span);
@@ -2625,7 +2630,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         hir_id: hir::HirId,
         unsafety: hir::Unsafety,
         abi: abi::Abi,
-        decl: &hir::FnDecl<'_>,
+        decl: &hir::FnDecl<'tcx>,
         generics: Option<&hir::Generics<'_>>,
         hir_ty: Option<&hir::Ty<'_>>,
     ) -> ty::PolyFnSig<'tcx> {
diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
index f77f250cd28..8967b51749c 100644
--- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
@@ -22,7 +22,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         &self,
         span: Span,
         hir_id: hir::HirId,
-        hir_trait_bounds: &[hir::PolyTraitRef<'_>],
+        hir_trait_bounds: &[hir::PolyTraitRef<'tcx>],
         lifetime: &hir::Lifetime,
         borrowed: bool,
         representation: DynKind,
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 77914802bf7..03e2b0e0022 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -368,7 +368,7 @@ fn check_opaque_meets_bounds<'tcx>(
         // Can have different predicates to their defining use
         hir::OpaqueTyOrigin::TyAlias { .. } => {
             let wf_tys = ocx.assumed_wf_types_and_report_errors(param_env, def_id)?;
-            let implied_bounds = infcx.implied_bounds_tys(param_env, def_id, wf_tys);
+            let implied_bounds = infcx.implied_bounds_tys(param_env, def_id, &wf_tys);
             let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
             ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env)?;
         }
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 469e7a6a13c..5b264f6f034 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -2,7 +2,7 @@ use super::potentially_plural_count;
 use crate::errors::LifetimesOrBoundsMismatchOnTrait;
 use hir::def_id::{DefId, DefIdMap, LocalDefId};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
-use rustc_errors::{pluralize, struct_span_code_err, Applicability, DiagnosticId, ErrorGuaranteed};
+use rustc_errors::{pluralize, struct_span_code_err, Applicability, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit;
@@ -378,7 +378,7 @@ fn compare_method_predicate_entailment<'tcx>(
     // lifetime parameters.
     let outlives_env = OutlivesEnvironment::with_bounds(
         param_env,
-        infcx.implied_bounds_tys(param_env, impl_m_def_id, wf_tys),
+        infcx.implied_bounds_tys(param_env, impl_m_def_id, &wf_tys),
     );
     let errors = infcx.resolve_regions(&outlives_env);
     if !errors.is_empty() {
@@ -702,7 +702,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
     // lifetime parameters.
     let outlives_env = OutlivesEnvironment::with_bounds(
         param_env,
-        infcx.implied_bounds_tys(param_env, impl_m_def_id, wf_tys),
+        infcx.implied_bounds_tys(param_env, impl_m_def_id, &wf_tys),
     );
     ocx.resolve_regions_and_report_errors(impl_m_def_id, &outlives_env)?;
 
@@ -1382,7 +1382,7 @@ fn compare_number_of_generics<'tcx>(
                     kind = kind,
                 ),
             );
-            err.code(DiagnosticId::Error("E0049".into()));
+            err.code("E0049".into());
 
             let msg =
                 format!("expected {trait_count} {kind} parameter{}", pluralize!(trait_count),);
@@ -2070,7 +2070,7 @@ pub(super) fn check_type_bounds<'tcx>(
 
     // Finally, resolve all regions. This catches wily misuses of
     // lifetime parameters.
-    let implied_bounds = infcx.implied_bounds_tys(param_env, impl_ty_def_id, assumed_wf_types);
+    let implied_bounds = infcx.implied_bounds_tys(param_env, impl_ty_def_id, &assumed_wf_types);
     let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
     ocx.resolve_regions_and_report_errors(impl_ty_def_id, &outlives_env)
 }
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 f7fc0c81b95..0d8de0cabd1 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
@@ -158,7 +158,7 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
     }
     let outlives_env = OutlivesEnvironment::with_bounds(
         param_env,
-        infcx.implied_bounds_tys(param_env, impl_m.def_id.expect_local(), implied_wf_types),
+        infcx.implied_bounds_tys(param_env, impl_m.def_id.expect_local(), &implied_wf_types),
     );
     let errors = infcx.resolve_regions(&outlives_env);
     if !errors.is_empty() {
diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs
index 5d5a4789734..1c0a1a69513 100644
--- a/compiler/rustc_hir_analysis/src/check/region.rs
+++ b/compiler/rustc_hir_analysis/src/check/region.rs
@@ -681,7 +681,8 @@ fn resolve_local<'tcx>(
             | PatKind::Never
             | PatKind::Path(_)
             | PatKind::Lit(_)
-            | PatKind::Range(_, _, _) => false,
+            | PatKind::Range(_, _, _)
+            | PatKind::Err(_) => false,
         }
     }
 
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 4772bae58c4..3b9837ff7c2 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -15,6 +15,7 @@ use rustc_infer::infer::outlives::obligations::TypeOutlives;
 use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
 use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::query::Providers;
+use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::trait_def::TraitSpecializationKind;
 use rustc_middle::ty::{
     self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
@@ -112,8 +113,6 @@ where
 
     let assumed_wf_types = wfcx.ocx.assumed_wf_types_and_report_errors(param_env, body_def_id)?;
 
-    let implied_bounds = infcx.implied_bounds_tys(param_env, body_def_id, assumed_wf_types);
-
     let errors = wfcx.select_all_or_error();
     if !errors.is_empty() {
         let err = infcx.err_ctxt().report_fulfillment_errors(errors);
@@ -128,10 +127,65 @@ where
         }
     }
 
+    debug!(?assumed_wf_types);
+
+    let infcx_compat = infcx.fork();
+
+    // We specifically want to call the non-compat version of `implied_bounds_tys`; we do this always.
+    let implied_bounds =
+        infcx.implied_bounds_tys_compat(param_env, body_def_id, &assumed_wf_types, false);
     let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
 
-    wfcx.ocx.resolve_regions_and_report_errors(body_def_id, &outlives_env)?;
-    infcx.tainted_by_errors().error_reported()
+    let errors = infcx.resolve_regions(&outlives_env);
+    if errors.is_empty() {
+        return Ok(());
+    }
+
+    let is_bevy = 'is_bevy: {
+        // We don't want to emit this for dependents of Bevy, for now.
+        // See #119956
+        let is_bevy_paramset = |def: ty::AdtDef<'_>| {
+            let adt_did = with_no_trimmed_paths!(infcx.tcx.def_path_str(def.0.did));
+            adt_did.contains("ParamSet")
+        };
+        for ty in assumed_wf_types.iter() {
+            match ty.kind() {
+                ty::Adt(def, _) => {
+                    if is_bevy_paramset(*def) {
+                        break 'is_bevy true;
+                    }
+                }
+                ty::Ref(_, ty, _) => match ty.kind() {
+                    ty::Adt(def, _) => {
+                        if is_bevy_paramset(*def) {
+                            break 'is_bevy true;
+                        }
+                    }
+                    _ => {}
+                },
+                _ => {}
+            }
+        }
+        false
+    };
+
+    // If we have set `no_implied_bounds_compat`, then do not attempt compatibility.
+    // We could also just always enter if `is_bevy`, and call `implied_bounds_tys`,
+    // but that does result in slightly more work when this option is set and
+    // just obscures what we mean here anyways. Let's just be explicit.
+    if is_bevy && !infcx.tcx.sess.opts.unstable_opts.no_implied_bounds_compat {
+        let implied_bounds =
+            infcx_compat.implied_bounds_tys_compat(param_env, body_def_id, &assumed_wf_types, true);
+        let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
+        let errors_compat = infcx_compat.resolve_regions(&outlives_env);
+        if errors_compat.is_empty() {
+            Ok(())
+        } else {
+            Err(infcx_compat.err_ctxt().report_region_errors(body_def_id, &errors_compat))
+        }
+    } else {
+        Err(infcx.err_ctxt().report_region_errors(body_def_id, &errors))
+    }
 }
 
 fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) -> Result<(), ErrorGuaranteed> {
@@ -723,7 +777,7 @@ fn resolve_regions_with_wf_tys<'tcx>(
     let infcx = tcx.infer_ctxt().build();
     let outlives_environment = OutlivesEnvironment::with_bounds(
         param_env,
-        infcx.implied_bounds_tys(param_env, id, wf_tys.clone()),
+        infcx.implied_bounds_tys(param_env, id, wf_tys),
     );
     let region_bound_pairs = outlives_environment.region_bound_pairs();
 
@@ -1736,7 +1790,7 @@ fn receiver_is_implemented<'tcx>(
 fn check_variances_for_type_defn<'tcx>(
     tcx: TyCtxt<'tcx>,
     item: &hir::Item<'tcx>,
-    hir_generics: &hir::Generics<'_>,
+    hir_generics: &hir::Generics<'tcx>,
 ) {
     let identity_args = ty::GenericArgs::identity_for_item(tcx, item.owner_id);
 
diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
index 3162004a634..abef365c3ca 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
@@ -13,32 +13,41 @@ use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::ty::fast_reject::{simplify_type, SimplifiedType, TreatParams};
 use rustc_middle::ty::{self, CrateInherentImpls, Ty, TyCtxt};
 use rustc_span::symbol::sym;
+use rustc_span::ErrorGuaranteed;
 
 use crate::errors;
 
 /// On-demand query: yields a map containing all types mapped to their inherent impls.
-pub fn crate_inherent_impls(tcx: TyCtxt<'_>, (): ()) -> CrateInherentImpls {
+pub fn crate_inherent_impls(
+    tcx: TyCtxt<'_>,
+    (): (),
+) -> Result<&'_ CrateInherentImpls, ErrorGuaranteed> {
     let mut collect = InherentCollect { tcx, impls_map: Default::default() };
+    let mut res = Ok(());
     for id in tcx.hir().items() {
-        collect.check_item(id);
+        res = res.and(collect.check_item(id));
     }
-    collect.impls_map
+    res?;
+    Ok(tcx.arena.alloc(collect.impls_map))
 }
 
-pub fn crate_incoherent_impls(tcx: TyCtxt<'_>, simp: SimplifiedType) -> &[DefId] {
-    let crate_map = tcx.crate_inherent_impls(());
-    tcx.arena.alloc_from_iter(
+pub fn crate_incoherent_impls(
+    tcx: TyCtxt<'_>,
+    simp: SimplifiedType,
+) -> Result<&[DefId], ErrorGuaranteed> {
+    let crate_map = tcx.crate_inherent_impls(())?;
+    Ok(tcx.arena.alloc_from_iter(
         crate_map.incoherent_impls.get(&simp).unwrap_or(&Vec::new()).iter().map(|d| d.to_def_id()),
-    )
+    ))
 }
 
 /// On-demand query: yields a vector of the inherent impls for a specific type.
-pub fn inherent_impls(tcx: TyCtxt<'_>, ty_def_id: LocalDefId) -> &[DefId] {
-    let crate_map = tcx.crate_inherent_impls(());
-    match crate_map.inherent_impls.get(&ty_def_id) {
+pub fn inherent_impls(tcx: TyCtxt<'_>, ty_def_id: LocalDefId) -> Result<&[DefId], ErrorGuaranteed> {
+    let crate_map = tcx.crate_inherent_impls(())?;
+    Ok(match crate_map.inherent_impls.get(&ty_def_id) {
         Some(v) => &v[..],
         None => &[],
-    }
+    })
 }
 
 struct InherentCollect<'tcx> {
@@ -47,14 +56,19 @@ struct InherentCollect<'tcx> {
 }
 
 impl<'tcx> InherentCollect<'tcx> {
-    fn check_def_id(&mut self, impl_def_id: LocalDefId, self_ty: Ty<'tcx>, ty_def_id: DefId) {
+    fn check_def_id(
+        &mut self,
+        impl_def_id: LocalDefId,
+        self_ty: Ty<'tcx>,
+        ty_def_id: DefId,
+    ) -> Result<(), ErrorGuaranteed> {
         if let Some(ty_def_id) = ty_def_id.as_local() {
             // Add the implementation to the mapping from implementation to base
             // type def ID, if there is a base type for this implementation and
             // the implementation does not have any associated traits.
             let vec = self.impls_map.inherent_impls.entry(ty_def_id).or_default();
             vec.push(impl_def_id.to_def_id());
-            return;
+            return Ok(());
         }
 
         if self.tcx.features().rustc_attrs {
@@ -62,18 +76,16 @@ impl<'tcx> InherentCollect<'tcx> {
 
             if !self.tcx.has_attr(ty_def_id, sym::rustc_has_incoherent_inherent_impls) {
                 let impl_span = self.tcx.def_span(impl_def_id);
-                self.tcx.dcx().emit_err(errors::InherentTyOutside { span: impl_span });
-                return;
+                return Err(self.tcx.dcx().emit_err(errors::InherentTyOutside { span: impl_span }));
             }
 
             for &impl_item in items {
                 if !self.tcx.has_attr(impl_item, sym::rustc_allow_incoherent_impl) {
                     let impl_span = self.tcx.def_span(impl_def_id);
-                    self.tcx.dcx().emit_err(errors::InherentTyOutsideRelevant {
+                    return Err(self.tcx.dcx().emit_err(errors::InherentTyOutsideRelevant {
                         span: impl_span,
                         help_span: self.tcx.def_span(impl_item),
-                    });
-                    return;
+                    }));
                 }
             }
 
@@ -82,24 +94,28 @@ impl<'tcx> InherentCollect<'tcx> {
             } else {
                 bug!("unexpected self type: {:?}", self_ty);
             }
+            Ok(())
         } else {
             let impl_span = self.tcx.def_span(impl_def_id);
-            self.tcx.dcx().emit_err(errors::InherentTyOutsideNew { span: impl_span });
+            Err(self.tcx.dcx().emit_err(errors::InherentTyOutsideNew { span: impl_span }))
         }
     }
 
-    fn check_primitive_impl(&mut self, impl_def_id: LocalDefId, ty: Ty<'tcx>) {
+    fn check_primitive_impl(
+        &mut self,
+        impl_def_id: LocalDefId,
+        ty: Ty<'tcx>,
+    ) -> Result<(), ErrorGuaranteed> {
         let items = self.tcx.associated_item_def_ids(impl_def_id);
         if !self.tcx.hir().rustc_coherence_is_core() {
             if self.tcx.features().rustc_attrs {
                 for &impl_item in items {
                     if !self.tcx.has_attr(impl_item, sym::rustc_allow_incoherent_impl) {
                         let span = self.tcx.def_span(impl_def_id);
-                        self.tcx.dcx().emit_err(errors::InherentTyOutsidePrimitive {
+                        return Err(self.tcx.dcx().emit_err(errors::InherentTyOutsidePrimitive {
                             span,
                             help_span: self.tcx.def_span(impl_item),
-                        });
-                        return;
+                        }));
                     }
                 }
             } else {
@@ -108,8 +124,7 @@ impl<'tcx> InherentCollect<'tcx> {
                 if let ty::Ref(_, subty, _) = ty.kind() {
                     note = Some(errors::InherentPrimitiveTyNote { subty: *subty });
                 }
-                self.tcx.dcx().emit_err(errors::InherentPrimitiveTy { span, note });
-                return;
+                return Err(self.tcx.dcx().emit_err(errors::InherentPrimitiveTy { span, note }));
             }
         }
 
@@ -118,11 +133,12 @@ impl<'tcx> InherentCollect<'tcx> {
         } else {
             bug!("unexpected primitive type: {:?}", ty);
         }
+        Ok(())
     }
 
-    fn check_item(&mut self, id: hir::ItemId) {
+    fn check_item(&mut self, id: hir::ItemId) -> Result<(), ErrorGuaranteed> {
         if !matches!(self.tcx.def_kind(id.owner_id), DefKind::Impl { of_trait: false }) {
-            return;
+            return Ok(());
         }
 
         let id = id.owner_id.def_id;
@@ -132,10 +148,10 @@ impl<'tcx> InherentCollect<'tcx> {
             ty::Adt(def, _) => self.check_def_id(id, self_ty, def.did()),
             ty::Foreign(did) => self.check_def_id(id, self_ty, did),
             ty::Dynamic(data, ..) if data.principal_def_id().is_some() => {
-                self.check_def_id(id, self_ty, data.principal_def_id().unwrap());
+                self.check_def_id(id, self_ty, data.principal_def_id().unwrap())
             }
             ty::Dynamic(..) => {
-                self.tcx.dcx().emit_err(errors::InherentDyn { span: item_span });
+                Err(self.tcx.dcx().emit_err(errors::InherentDyn { span: item_span }))
             }
             ty::Bool
             | ty::Char
@@ -151,7 +167,7 @@ impl<'tcx> InherentCollect<'tcx> {
             | ty::FnPtr(_)
             | ty::Tuple(..) => self.check_primitive_impl(id, self_ty),
             ty::Alias(..) | ty::Param(_) => {
-                self.tcx.dcx().emit_err(errors::InherentNominal { span: item_span });
+                Err(self.tcx.dcx().emit_err(errors::InherentNominal { span: item_span }))
             }
             ty::FnDef(..)
             | ty::Closure(..)
@@ -162,7 +178,8 @@ impl<'tcx> InherentCollect<'tcx> {
             | ty::Infer(_) => {
                 bug!("unexpected impl self type of impl: {:?} {:?}", id, self_ty);
             }
-            ty::Error(_) => {}
+            // We could bail out here, but that will silence other useful errors.
+            ty::Error(_) => Ok(()),
         }
     }
 }
diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
index 4c3455c7240..63ea0272014 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
@@ -6,16 +6,18 @@ use rustc_hir::def_id::DefId;
 use rustc_index::IndexVec;
 use rustc_middle::traits::specialization_graph::OverlapMode;
 use rustc_middle::ty::{self, TyCtxt};
-use rustc_span::Symbol;
+use rustc_span::{ErrorGuaranteed, Symbol};
 use rustc_trait_selection::traits::{self, SkipLeakCheck};
 use smallvec::SmallVec;
 use std::collections::hash_map::Entry;
 
-pub fn crate_inherent_impls_overlap_check(tcx: TyCtxt<'_>, (): ()) {
+pub fn crate_inherent_impls_overlap_check(tcx: TyCtxt<'_>, (): ()) -> Result<(), ErrorGuaranteed> {
     let mut inherent_overlap_checker = InherentOverlapChecker { tcx };
+    let mut res = Ok(());
     for id in tcx.hir().items() {
-        inherent_overlap_checker.check_item(id);
+        res = res.and(inherent_overlap_checker.check_item(id));
     }
+    res
 }
 
 struct InherentOverlapChecker<'tcx> {
@@ -58,10 +60,11 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
                 == item2.ident(self.tcx).normalize_to_macros_2_0()
     }
 
-    fn check_for_duplicate_items_in_impl(&self, impl_: DefId) {
+    fn check_for_duplicate_items_in_impl(&self, impl_: DefId) -> Result<(), ErrorGuaranteed> {
         let impl_items = self.tcx.associated_items(impl_);
 
         let mut seen_items = FxHashMap::default();
+        let mut res = Ok(());
         for impl_item in impl_items.in_definition_order() {
             let span = self.tcx.def_span(impl_item.def_id);
             let ident = impl_item.ident(self.tcx);
@@ -70,7 +73,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
             match seen_items.entry(norm_ident) {
                 Entry::Occupied(entry) => {
                     let former = entry.get();
-                    struct_span_code_err!(
+                    res = Err(struct_span_code_err!(
                         self.tcx.dcx(),
                         span,
                         E0592,
@@ -79,13 +82,14 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
                     )
                     .with_span_label(span, format!("duplicate definitions for `{ident}`"))
                     .with_span_label(*former, format!("other definition for `{ident}`"))
-                    .emit();
+                    .emit());
                 }
                 Entry::Vacant(entry) => {
                     entry.insert(span);
                 }
             }
         }
+        res
     }
 
     fn check_for_common_items_in_impls(
@@ -93,10 +97,11 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
         impl1: DefId,
         impl2: DefId,
         overlap: traits::OverlapResult<'_>,
-    ) {
+    ) -> Result<(), ErrorGuaranteed> {
         let impl_items1 = self.tcx.associated_items(impl1);
         let impl_items2 = self.tcx.associated_items(impl2);
 
+        let mut res = Ok(());
         for &item1 in impl_items1.in_definition_order() {
             let collision = impl_items2
                 .filter_by_name_unhygienic(item1.name)
@@ -128,9 +133,10 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
                     traits::add_placeholder_note(&mut err);
                 }
 
-                err.emit();
+                res = Err(err.emit());
             }
         }
+        res
     }
 
     fn check_for_overlapping_inherent_impls(
@@ -138,7 +144,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
         overlap_mode: OverlapMode,
         impl1_def_id: DefId,
         impl2_def_id: DefId,
-    ) {
+    ) -> Result<(), ErrorGuaranteed> {
         let maybe_overlap = traits::overlapping_impls(
             self.tcx,
             impl1_def_id,
@@ -150,17 +156,19 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
         );
 
         if let Some(overlap) = maybe_overlap {
-            self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id, overlap);
+            self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id, overlap)
+        } else {
+            Ok(())
         }
     }
 
-    fn check_item(&mut self, id: hir::ItemId) {
+    fn check_item(&mut self, id: hir::ItemId) -> Result<(), ErrorGuaranteed> {
         let def_kind = self.tcx.def_kind(id.owner_id);
         if !matches!(def_kind, DefKind::Enum | DefKind::Struct | DefKind::Trait | DefKind::Union) {
-            return;
+            return Ok(());
         }
 
-        let impls = self.tcx.inherent_impls(id.owner_id);
+        let impls = self.tcx.inherent_impls(id.owner_id)?;
 
         let overlap_mode = OverlapMode::get(self.tcx, id.owner_id.to_def_id());
 
@@ -173,17 +181,18 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
         // otherwise switch to an allocating algorithm with
         // faster asymptotic runtime.
         const ALLOCATING_ALGO_THRESHOLD: usize = 500;
+        let mut res = Ok(());
         if impls.len() < ALLOCATING_ALGO_THRESHOLD {
             for (i, &(&impl1_def_id, impl_items1)) in impls_items.iter().enumerate() {
-                self.check_for_duplicate_items_in_impl(impl1_def_id);
+                res = res.and(self.check_for_duplicate_items_in_impl(impl1_def_id));
 
                 for &(&impl2_def_id, impl_items2) in &impls_items[(i + 1)..] {
                     if self.impls_have_common_items(impl_items1, impl_items2) {
-                        self.check_for_overlapping_inherent_impls(
+                        res = res.and(self.check_for_overlapping_inherent_impls(
                             overlap_mode,
                             impl1_def_id,
                             impl2_def_id,
-                        );
+                        ));
                     }
                 }
             }
@@ -315,20 +324,21 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
                 impl_blocks.sort_unstable();
                 for (i, &impl1_items_idx) in impl_blocks.iter().enumerate() {
                     let &(&impl1_def_id, impl_items1) = &impls_items[impl1_items_idx];
-                    self.check_for_duplicate_items_in_impl(impl1_def_id);
+                    res = res.and(self.check_for_duplicate_items_in_impl(impl1_def_id));
 
                     for &impl2_items_idx in impl_blocks[(i + 1)..].iter() {
                         let &(&impl2_def_id, impl_items2) = &impls_items[impl2_items_idx];
                         if self.impls_have_common_items(impl_items1, impl_items2) {
-                            self.check_for_overlapping_inherent_impls(
+                            res = res.and(self.check_for_overlapping_inherent_impls(
                                 overlap_mode,
                                 impl1_def_id,
                                 impl2_def_id,
-                            );
+                            ));
                         }
                     }
                 }
             }
         }
+        res
     }
 }
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index e557f36037b..d8ce2307995 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -348,7 +348,7 @@ impl<'tcx> ItemCtxt<'tcx> {
         ItemCtxt { tcx, item_def_id, tainted_by_errors: Cell::new(None) }
     }
 
-    pub fn to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
+    pub fn to_ty(&self, ast_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
         self.astconv().ast_ty_to_ty(ast_ty)
     }
 
@@ -412,7 +412,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
         &self,
         span: Span,
         item_def_id: DefId,
-        item_segment: &hir::PathSegment<'_>,
+        item_segment: &hir::PathSegment<'tcx>,
         poly_trait_ref: ty::PolyTraitRef<'tcx>,
     ) -> Ty<'tcx> {
         if let Some(trait_ref) = poly_trait_ref.no_bound_vars() {
@@ -1148,7 +1148,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<ty::PolyFnSig<
 
 fn infer_return_ty_for_fn_sig<'tcx>(
     tcx: TyCtxt<'tcx>,
-    sig: &hir::FnSig<'_>,
+    sig: &hir::FnSig<'tcx>,
     generics: &hir::Generics<'_>,
     def_id: LocalDefId,
     icx: &ItemCtxt<'tcx>,
@@ -1352,14 +1352,14 @@ fn impl_trait_ref(
                 let last_arg = args.args.len() - 1;
                 assert!(matches!(args.args[last_arg], hir::GenericArg::Const(anon_const) if anon_const.is_desugared_from_effects));
                 args.args = &args.args[..args.args.len() - 1];
-                path_segments[last_segment].args = Some(&args);
+                path_segments[last_segment].args = Some(tcx.hir_arena.alloc(args));
                 let path = hir::Path {
                     span: ast_trait_ref.path.span,
                     res: ast_trait_ref.path.res,
-                    segments: &path_segments,
+                    segments: tcx.hir_arena.alloc_slice(&path_segments),
                 };
-                let trait_ref = hir::TraitRef { path: &path, hir_ref_id: ast_trait_ref.hir_ref_id };
-                icx.astconv().instantiate_mono_trait_ref(&trait_ref, selfty)
+                let trait_ref = tcx.hir_arena.alloc(hir::TraitRef { path: tcx.hir_arena.alloc(path), hir_ref_id: ast_trait_ref.hir_ref_id });
+                icx.astconv().instantiate_mono_trait_ref(trait_ref, selfty)
             } else {
                 icx.astconv().instantiate_mono_trait_ref(ast_trait_ref, selfty)
             }
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 1f7ca48234a..85093bc12b3 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
@@ -5,20 +5,22 @@ use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{self as hir, def, Expr, ImplItem, Item, Node, TraitItem};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
-use rustc_span::{sym, DUMMY_SP};
+use rustc_span::{sym, ErrorGuaranteed, DUMMY_SP};
 
 use crate::errors::{TaitForwardCompat, TypeOf, UnconstrainedOpaqueType};
 
-pub fn test_opaque_hidden_types(tcx: TyCtxt<'_>) {
+pub fn test_opaque_hidden_types(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
+    let mut res = Ok(());
     if tcx.has_attr(CRATE_DEF_ID, sym::rustc_hidden_type_of_opaques) {
         for id in tcx.hir().items() {
             if matches!(tcx.def_kind(id.owner_id), DefKind::OpaqueTy) {
                 let type_of = tcx.type_of(id.owner_id).instantiate_identity();
 
-                tcx.dcx().emit_err(TypeOf { span: tcx.def_span(id.owner_id), type_of });
+                res = Err(tcx.dcx().emit_err(TypeOf { span: tcx.def_span(id.owner_id), type_of }));
             }
         }
     }
+    res
 }
 
 /// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions
@@ -135,18 +137,25 @@ impl TaitConstraintLocator<'_> {
             return;
         }
 
-        if let Some(hir_sig) = self.tcx.hir_node_by_def_id(item_def_id).fn_decl() {
-            if hir_sig.output.get_infer_ret_ty().is_some() {
-                let guar = self.tcx.dcx().span_delayed_bug(
-                    hir_sig.output.span(),
-                    "inferring return types and opaque types do not mix well",
-                );
-                self.found = Some(ty::OpaqueHiddenType {
-                    span: DUMMY_SP,
-                    ty: Ty::new_error(self.tcx, guar),
-                });
-                return;
-            }
+        // Function items with `_` in their return type already emit an error, skip any
+        // "non-defining use" errors for them.
+        // Note that we use `Node::fn_sig` instead of `Node::fn_decl` here, because the former
+        // excludes closures, which are allowed to have `_` in their return type.
+        let hir_node = self.tcx.hir_node_by_def_id(item_def_id);
+        debug_assert!(
+            !matches!(hir_node, Node::ForeignItem(..)),
+            "foreign items cannot constrain opaque types",
+        );
+        if let Some(hir_sig) = hir_node.fn_sig()
+            && hir_sig.decl.output.get_infer_ret_ty().is_some()
+        {
+            let guar = self.tcx.dcx().span_delayed_bug(
+                hir_sig.decl.output.span(),
+                "inferring return types and opaque types do not mix well",
+            );
+            self.found =
+                Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: Ty::new_error(self.tcx, guar) });
+            return;
         }
 
         // Calling `mir_borrowck` can lead to cycle errors through
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
index 3f9b1f384d7..2fe08ead72b 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
@@ -17,7 +17,7 @@ use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{LocalDefId, LocalModDefId};
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
-use rustc_span::{Span, Symbol};
+use rustc_span::{ErrorGuaranteed, Span, Symbol};
 
 mod min_specialization;
 
@@ -51,24 +51,29 @@ mod min_specialization;
 /// impl<'a> Trait<Foo> for Bar { type X = &'a i32; }
 /// //   ^ 'a is unused and appears in assoc type, error
 /// ```
-fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
+fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) -> Result<(), ErrorGuaranteed> {
     let min_specialization = tcx.features().min_specialization;
     let module = tcx.hir_module_items(module_def_id);
+    let mut res = Ok(());
     for id in module.items() {
         if matches!(tcx.def_kind(id.owner_id), DefKind::Impl { .. }) {
-            enforce_impl_params_are_constrained(tcx, id.owner_id.def_id);
+            res = res.and(enforce_impl_params_are_constrained(tcx, id.owner_id.def_id));
             if min_specialization {
-                check_min_specialization(tcx, id.owner_id.def_id);
+                res = res.and(check_min_specialization(tcx, id.owner_id.def_id));
             }
         }
     }
+    res
 }
 
 pub fn provide(providers: &mut Providers) {
     *providers = Providers { check_mod_impl_wf, ..*providers };
 }
 
-fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) {
+fn enforce_impl_params_are_constrained(
+    tcx: TyCtxt<'_>,
+    impl_def_id: LocalDefId,
+) -> Result<(), ErrorGuaranteed> {
     // Every lifetime used in an associated type must be constrained.
     let impl_self_ty = tcx.type_of(impl_def_id).instantiate_identity();
     if impl_self_ty.references_error() {
@@ -80,7 +85,10 @@ fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId)
                 "potentially unconstrained type parameters weren't evaluated: {impl_self_ty:?}",
             ),
         );
-        return;
+        // This is super fishy, but our current `rustc_hir_analysis::check_crate` pipeline depends on
+        // `type_of` having been called much earlier, and thus this value being read from cache.
+        // Compilation must continue in order for other important diagnostics to keep showing up.
+        return Ok(());
     }
     let impl_generics = tcx.generics_of(impl_def_id);
     let impl_predicates = tcx.predicates_of(impl_def_id);
@@ -113,13 +121,19 @@ fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId)
         })
         .collect();
 
+    let mut res = Ok(());
     for param in &impl_generics.params {
         match param.kind {
             // Disallow ANY unconstrained type parameters.
             ty::GenericParamDefKind::Type { .. } => {
                 let param_ty = ty::ParamTy::for_def(param);
                 if !input_parameters.contains(&cgp::Parameter::from(param_ty)) {
-                    report_unused_parameter(tcx, tcx.def_span(param.def_id), "type", param_ty.name);
+                    res = Err(report_unused_parameter(
+                        tcx,
+                        tcx.def_span(param.def_id),
+                        "type",
+                        param_ty.name,
+                    ));
                 }
             }
             ty::GenericParamDefKind::Lifetime => {
@@ -127,27 +141,28 @@ fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId)
                 if lifetimes_in_associated_types.contains(&param_lt) && // (*)
                     !input_parameters.contains(&param_lt)
                 {
-                    report_unused_parameter(
+                    res = Err(report_unused_parameter(
                         tcx,
                         tcx.def_span(param.def_id),
                         "lifetime",
                         param.name,
-                    );
+                    ));
                 }
             }
             ty::GenericParamDefKind::Const { .. } => {
                 let param_ct = ty::ParamConst::for_def(param);
                 if !input_parameters.contains(&cgp::Parameter::from(param_ct)) {
-                    report_unused_parameter(
+                    res = Err(report_unused_parameter(
                         tcx,
                         tcx.def_span(param.def_id),
                         "const",
                         param_ct.name,
-                    );
+                    ));
                 }
             }
         }
     }
+    res
 
     // (*) This is a horrible concession to reality. I think it'd be
     // better to just ban unconstrained lifetimes outright, but in
@@ -169,7 +184,12 @@ fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId)
     // used elsewhere are not projected back out.
 }
 
-fn report_unused_parameter(tcx: TyCtxt<'_>, span: Span, kind: &str, name: Symbol) {
+fn report_unused_parameter(
+    tcx: TyCtxt<'_>,
+    span: Span,
+    kind: &str,
+    name: Symbol,
+) -> ErrorGuaranteed {
     let mut err = struct_span_code_err!(
         tcx.dcx(),
         span,
@@ -188,5 +208,5 @@ fn report_unused_parameter(tcx: TyCtxt<'_>, span: Span, kind: &str, name: Symbol
             "proving the result of expressions other than the parameter are unique is not supported",
         );
     }
-    err.emit();
+    err.emit()
 }
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 93dd2342a4d..1b6a39d8162 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
@@ -82,10 +82,14 @@ use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
 use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
 use rustc_trait_selection::traits::{self, translate_args_with_cause, wf, ObligationCtxt};
 
-pub(super) fn check_min_specialization(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) {
+pub(super) fn check_min_specialization(
+    tcx: TyCtxt<'_>,
+    impl_def_id: LocalDefId,
+) -> Result<(), ErrorGuaranteed> {
     if let Some(node) = parent_specialization_node(tcx, impl_def_id) {
-        check_always_applicable(tcx, impl_def_id, node);
+        check_always_applicable(tcx, impl_def_id, node)?;
     }
+    Ok(())
 }
 
 fn parent_specialization_node(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId) -> Option<Node> {
@@ -109,42 +113,58 @@ fn parent_specialization_node(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId) -> Opti
 
 /// Check that `impl1` is a sound specialization
 #[instrument(level = "debug", skip(tcx))]
-fn check_always_applicable(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node: Node) {
+fn check_always_applicable(
+    tcx: TyCtxt<'_>,
+    impl1_def_id: LocalDefId,
+    impl2_node: Node,
+) -> Result<(), ErrorGuaranteed> {
     let span = tcx.def_span(impl1_def_id);
-    check_has_items(tcx, impl1_def_id, impl2_node, span);
-
-    if let Ok((impl1_args, impl2_args)) = get_impl_args(tcx, impl1_def_id, impl2_node) {
-        let impl2_def_id = impl2_node.def_id();
-        debug!(?impl2_def_id, ?impl2_args);
-
-        let parent_args = if impl2_node.is_from_trait() {
-            impl2_args.to_vec()
-        } else {
-            unconstrained_parent_impl_args(tcx, impl2_def_id, impl2_args)
-        };
-
-        check_constness(tcx, impl1_def_id, impl2_node, span);
-        check_static_lifetimes(tcx, &parent_args, span);
-        check_duplicate_params(tcx, impl1_args, &parent_args, span);
-        check_predicates(tcx, impl1_def_id, impl1_args, impl2_node, impl2_args, span);
-    }
+    let mut res = check_has_items(tcx, impl1_def_id, impl2_node, span);
+
+    let (impl1_args, impl2_args) = get_impl_args(tcx, impl1_def_id, impl2_node)?;
+    let impl2_def_id = impl2_node.def_id();
+    debug!(?impl2_def_id, ?impl2_args);
+
+    let parent_args = if impl2_node.is_from_trait() {
+        impl2_args.to_vec()
+    } else {
+        unconstrained_parent_impl_args(tcx, impl2_def_id, impl2_args)
+    };
+
+    res = res.and(check_constness(tcx, impl1_def_id, impl2_node, span));
+    res = res.and(check_static_lifetimes(tcx, &parent_args, span));
+    res = res.and(check_duplicate_params(tcx, impl1_args, &parent_args, span));
+    res = res.and(check_predicates(tcx, impl1_def_id, impl1_args, impl2_node, impl2_args, span));
+
+    res
 }
 
-fn check_has_items(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node: Node, span: Span) {
+fn check_has_items(
+    tcx: TyCtxt<'_>,
+    impl1_def_id: LocalDefId,
+    impl2_node: Node,
+    span: Span,
+) -> Result<(), ErrorGuaranteed> {
     if let Node::Impl(impl2_id) = impl2_node
         && tcx.associated_item_def_ids(impl1_def_id).is_empty()
     {
         let base_impl_span = tcx.def_span(impl2_id);
-        tcx.dcx().emit_err(errors::EmptySpecialization { span, base_impl_span });
+        return Err(tcx.dcx().emit_err(errors::EmptySpecialization { span, base_impl_span }));
     }
+    Ok(())
 }
 
 /// Check that the specializing impl `impl1` is at least as const as the base
 /// impl `impl2`
-fn check_constness(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node: Node, span: Span) {
+fn check_constness(
+    tcx: TyCtxt<'_>,
+    impl1_def_id: LocalDefId,
+    impl2_node: Node,
+    span: Span,
+) -> Result<(), ErrorGuaranteed> {
     if impl2_node.is_from_trait() {
         // This isn't a specialization
-        return;
+        return Ok(());
     }
 
     let impl1_constness = tcx.constness(impl1_def_id.to_def_id());
@@ -152,9 +172,10 @@ fn check_constness(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node: Node,
 
     if let hir::Constness::Const = impl2_constness {
         if let hir::Constness::NotConst = impl1_constness {
-            tcx.dcx().emit_err(errors::ConstSpecialize { span });
+            return Err(tcx.dcx().emit_err(errors::ConstSpecialize { span }));
         }
     }
+    Ok(())
 }
 
 /// Given a specializing impl `impl1`, and the base impl `impl2`, returns two
@@ -202,7 +223,7 @@ fn get_impl_args(
         return Err(guar);
     }
 
-    let implied_bounds = infcx.implied_bounds_tys(param_env, impl1_def_id, assumed_wf_types);
+    let implied_bounds = infcx.implied_bounds_tys(param_env, impl1_def_id, &assumed_wf_types);
     let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
     let _ = ocx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env);
     let Ok(impl2_args) = infcx.fully_resolve(impl2_args) else {
@@ -290,15 +311,17 @@ fn check_duplicate_params<'tcx>(
     impl1_args: GenericArgsRef<'tcx>,
     parent_args: &Vec<GenericArg<'tcx>>,
     span: Span,
-) {
+) -> Result<(), ErrorGuaranteed> {
     let mut base_params = cgp::parameters_for(parent_args, true);
     base_params.sort_by_key(|param| param.0);
     if let (_, [duplicate, ..]) = base_params.partition_dedup() {
         let param = impl1_args[duplicate.0 as usize];
-        tcx.dcx()
+        return Err(tcx
+            .dcx()
             .struct_span_err(span, format!("specializing impl repeats parameter `{param}`"))
-            .emit();
+            .emit());
     }
+    Ok(())
 }
 
 /// Check that `'static` lifetimes are not introduced by the specializing impl.
@@ -313,10 +336,11 @@ fn check_static_lifetimes<'tcx>(
     tcx: TyCtxt<'tcx>,
     parent_args: &Vec<GenericArg<'tcx>>,
     span: Span,
-) {
+) -> Result<(), ErrorGuaranteed> {
     if tcx.any_free_region_meets(parent_args, |r| r.is_static()) {
-        tcx.dcx().emit_err(errors::StaticSpecialize { span });
+        return Err(tcx.dcx().emit_err(errors::StaticSpecialize { span }));
     }
+    Ok(())
 }
 
 /// Check whether predicates on the specializing impl (`impl1`) are allowed.
@@ -337,7 +361,7 @@ fn check_predicates<'tcx>(
     impl2_node: Node,
     impl2_args: GenericArgsRef<'tcx>,
     span: Span,
-) {
+) -> Result<(), ErrorGuaranteed> {
     let impl1_predicates: Vec<_> = traits::elaborate(
         tcx,
         tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_args).into_iter(),
@@ -399,14 +423,16 @@ fn check_predicates<'tcx>(
     }
     impl2_predicates.extend(traits::elaborate(tcx, always_applicable_traits));
 
+    let mut res = Ok(());
     for (clause, span) in impl1_predicates {
         if !impl2_predicates
             .iter()
             .any(|pred2| trait_predicates_eq(tcx, clause.as_predicate(), *pred2, span))
         {
-            check_specialization_on(tcx, clause, span)
+            res = res.and(check_specialization_on(tcx, clause, span))
         }
     }
+    res
 }
 
 /// Checks if some predicate on the specializing impl (`predicate1`) is the same
@@ -443,19 +469,26 @@ fn trait_predicates_eq<'tcx>(
 }
 
 #[instrument(level = "debug", skip(tcx))]
-fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, clause: ty::Clause<'tcx>, span: Span) {
+fn check_specialization_on<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    clause: ty::Clause<'tcx>,
+    span: Span,
+) -> Result<(), ErrorGuaranteed> {
     match clause.kind().skip_binder() {
         // Global predicates are either always true or always false, so we
         // are fine to specialize on.
-        _ if clause.is_global() => (),
+        _ if clause.is_global() => Ok(()),
         // We allow specializing on explicitly marked traits with no associated
         // items.
         ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => {
-            if !matches!(
+            if matches!(
                 trait_specialization_kind(tcx, clause),
                 Some(TraitSpecializationKind::Marker)
             ) {
-                tcx.dcx()
+                Ok(())
+            } else {
+                Err(tcx
+                    .dcx()
                     .struct_span_err(
                         span,
                         format!(
@@ -463,17 +496,16 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, clause: ty::Clause<'tcx>, sp
                             tcx.def_path_str(trait_ref.def_id),
                         ),
                     )
-                    .emit();
+                    .emit())
             }
         }
-        ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => {
-            tcx.dcx()
-                .struct_span_err(
-                    span,
-                    format!("cannot specialize on associated type `{projection_ty} == {term}`",),
-                )
-                .emit();
-        }
+        ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => Err(tcx
+            .dcx()
+            .struct_span_err(
+                span,
+                format!("cannot specialize on associated type `{projection_ty} == {term}`",),
+            )
+            .emit()),
         ty::ClauseKind::ConstArgHasType(..) => {
             // FIXME(min_specialization), FIXME(const_generics):
             // It probably isn't right to allow _every_ `ConstArgHasType` but I am somewhat unsure
@@ -483,12 +515,12 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, clause: ty::Clause<'tcx>, sp
             // While we do not support constructs like `<T, const N: T>` there is probably no risk of
             // soundness bugs, but when we support generic const parameter types this will need to be
             // revisited.
+            Ok(())
         }
-        _ => {
-            tcx.dcx()
-                .struct_span_err(span, format!("cannot specialize on predicate `{clause}`"))
-                .emit();
-        }
+        _ => Err(tcx
+            .dcx()
+            .struct_span_err(span, format!("cannot specialize on predicate `{clause}`"))
+            .emit()),
     }
 }
 
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index f5abb7261c0..0a3a71ba1a2 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -166,33 +166,29 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
         tcx.hir().for_each_module(|module| tcx.ensure().collect_mod_item_types(module))
     });
 
-    // FIXME(matthewjasper) We shouldn't need to use `track_errors` anywhere in this function
-    // or the compiler in general.
     if tcx.features().rustc_attrs {
-        tcx.sess.track_errors(|| {
-            tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx));
-        })?;
+        tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx))?;
     }
 
-    tcx.sess.track_errors(|| {
-        tcx.sess.time("coherence_checking", || {
-            // Check impls constrain their parameters
-            tcx.hir().for_each_module(|module| tcx.ensure().check_mod_impl_wf(module));
+    tcx.sess.time("coherence_checking", || {
+        // Check impls constrain their parameters
+        let res =
+            tcx.hir().try_par_for_each_module(|module| tcx.ensure().check_mod_impl_wf(module));
 
+        // FIXME(matthewjasper) We shouldn't need to use `track_errors` anywhere in this function
+        // or the compiler in general.
+        res.and(tcx.sess.track_errors(|| {
             for &trait_def_id in tcx.all_local_trait_impls(()).keys() {
                 tcx.ensure().coherent_trait(trait_def_id);
             }
-
-            // these queries are executed for side-effects (error reporting):
-            tcx.ensure().crate_inherent_impls(());
-            tcx.ensure().crate_inherent_impls_overlap_check(());
-        });
+        }))
+        // these queries are executed for side-effects (error reporting):
+        .and(tcx.ensure().crate_inherent_impls(()))
+        .and(tcx.ensure().crate_inherent_impls_overlap_check(()))
     })?;
 
     if tcx.features().rustc_attrs {
-        tcx.sess.track_errors(|| {
-            tcx.sess.time("variance_testing", || variance::test::test_variance(tcx));
-        })?;
+        tcx.sess.time("variance_testing", || variance::test::test_variance(tcx))?;
     }
 
     tcx.sess.time("wf_checking", || {
@@ -200,7 +196,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
     })?;
 
     if tcx.features().rustc_attrs {
-        tcx.sess.track_errors(|| collect::test_opaque_hidden_types(tcx))?;
+        collect::test_opaque_hidden_types(tcx)?;
     }
 
     // Freeze definitions as we don't add new ones at this point. This improves performance by
@@ -225,7 +221,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
 
 /// A quasi-deprecated helper used in rustdoc and clippy to get
 /// the type from a HIR node.
-pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> {
+pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
     // In case there are any projections, etc., find the "environment"
     // def-ID that will be used to determine the traits/predicates in
     // scope. This is derived from the enclosing item-like thing.
@@ -236,7 +232,7 @@ pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> {
 
 pub fn hir_trait_to_predicates<'tcx>(
     tcx: TyCtxt<'tcx>,
-    hir_trait: &hir::TraitRef<'_>,
+    hir_trait: &hir::TraitRef<'tcx>,
     self_ty: Ty<'tcx>,
 ) -> Bounds<'tcx> {
     // In case there are any projections, etc., find the "environment"
diff --git a/compiler/rustc_hir_analysis/src/outlives/test.rs b/compiler/rustc_hir_analysis/src/outlives/test.rs
index dea3f1a9930..60cd8c39fa0 100644
--- a/compiler/rustc_hir_analysis/src/outlives/test.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/test.rs
@@ -1,7 +1,8 @@
 use rustc_middle::ty::{self, TyCtxt};
-use rustc_span::symbol::sym;
+use rustc_span::{symbol::sym, ErrorGuaranteed};
 
-pub fn test_inferred_outlives(tcx: TyCtxt<'_>) {
+pub fn test_inferred_outlives(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
+    let mut res = Ok(());
     for id in tcx.hir().items() {
         // For unit testing: check for a special "rustc_outlives"
         // attribute and report an error with various results if found.
@@ -22,7 +23,8 @@ pub fn test_inferred_outlives(tcx: TyCtxt<'_>) {
             for p in pred {
                 err.note(p);
             }
-            err.emit();
+            res = Err(err.emit());
         }
     }
+    res
 }
diff --git a/compiler/rustc_hir_analysis/src/structured_errors.rs b/compiler/rustc_hir_analysis/src/structured_errors.rs
index 04d04304e70..b061d637138 100644
--- a/compiler/rustc_hir_analysis/src/structured_errors.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors.rs
@@ -6,13 +6,13 @@ pub use self::{
     missing_cast_for_variadic_arg::*, sized_unsized_cast::*, wrong_number_of_generic_args::*,
 };
 
-use rustc_errors::{DiagnosticBuilder, DiagnosticId};
+use rustc_errors::DiagnosticBuilder;
 use rustc_session::Session;
 
 pub trait StructuredDiagnostic<'tcx> {
     fn session(&self) -> &Session;
 
-    fn code(&self) -> DiagnosticId;
+    fn code(&self) -> String;
 
     fn diagnostic(&self) -> DiagnosticBuilder<'tcx> {
         let err = self.diagnostic_common();
diff --git a/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs b/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs
index 634904e3271..6f4435db411 100644
--- a/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs
@@ -1,5 +1,5 @@
 use crate::{errors, structured_errors::StructuredDiagnostic};
-use rustc_errors::{DiagnosticBuilder, DiagnosticId};
+use rustc_errors::DiagnosticBuilder;
 use rustc_middle::ty::{Ty, TypeVisitableExt};
 use rustc_session::Session;
 use rustc_span::Span;
@@ -16,7 +16,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for MissingCastForVariadicArg<'tcx, '_> {
         self.sess
     }
 
-    fn code(&self) -> DiagnosticId {
+    fn code(&self) -> String {
         rustc_errors::error_code!(E0617)
     }
 
diff --git a/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs b/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs
index c68d74969a5..19cac4a38aa 100644
--- a/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs
@@ -1,5 +1,5 @@
 use crate::{errors, structured_errors::StructuredDiagnostic};
-use rustc_errors::{DiagnosticBuilder, DiagnosticId};
+use rustc_errors::DiagnosticBuilder;
 use rustc_middle::ty::{Ty, TypeVisitableExt};
 use rustc_session::Session;
 use rustc_span::Span;
@@ -16,7 +16,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for SizedUnsizedCast<'tcx> {
         self.sess
     }
 
-    fn code(&self) -> DiagnosticId {
+    fn code(&self) -> String {
         rustc_errors::error_code!(E0607)
     }
 
diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
index 6657e3fd872..ba81e7f1f81 100644
--- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
@@ -1,7 +1,5 @@
 use crate::structured_errors::StructuredDiagnostic;
-use rustc_errors::{
-    pluralize, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId, MultiSpan,
-};
+use rustc_errors::{pluralize, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan};
 use rustc_hir as hir;
 use rustc_middle::ty::{self as ty, AssocItems, AssocKind, TyCtxt};
 use rustc_session::Session;
@@ -1107,7 +1105,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for WrongNumberOfGenericArgs<'_, 'tcx> {
         self.tcx.sess
     }
 
-    fn code(&self) -> DiagnosticId {
+    fn code(&self) -> String {
         rustc_errors::error_code!(E0107)
     }
 
diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index 410706110c9..7d145ea1f23 100644
--- a/compiler/rustc_hir_analysis/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
@@ -3,6 +3,7 @@
 //!
 //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/variance.html
 
+use itertools::Itertools;
 use rustc_arena::DroplessArena;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
@@ -91,7 +92,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
         fn visit_opaque(&mut self, def_id: DefId, args: GenericArgsRef<'tcx>) -> ControlFlow<!> {
             if def_id != self.root_def_id && self.tcx.is_descendant_of(def_id, self.root_def_id) {
                 let child_variances = self.tcx.variances_of(def_id);
-                for (a, v) in args.iter().zip(child_variances) {
+                for (a, v) in args.iter().zip_eq(child_variances) {
                     if *v != ty::Bivariant {
                         a.visit_with(self)?;
                     }
diff --git a/compiler/rustc_hir_analysis/src/variance/test.rs b/compiler/rustc_hir_analysis/src/variance/test.rs
index 5264d5aa26f..c211e1af046 100644
--- a/compiler/rustc_hir_analysis/src/variance/test.rs
+++ b/compiler/rustc_hir_analysis/src/variance/test.rs
@@ -2,19 +2,21 @@ use rustc_hir::def::DefKind;
 use rustc_hir::def_id::CRATE_DEF_ID;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::sym;
+use rustc_span::ErrorGuaranteed;
 
 use crate::errors;
 
-pub fn test_variance(tcx: TyCtxt<'_>) {
+pub fn test_variance(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
+    let mut res = Ok(());
     if tcx.has_attr(CRATE_DEF_ID, sym::rustc_variance_of_opaques) {
         for id in tcx.hir().items() {
             if matches!(tcx.def_kind(id.owner_id), DefKind::OpaqueTy) {
                 let variances_of = tcx.variances_of(id.owner_id);
 
-                tcx.dcx().emit_err(errors::VariancesOf {
+                res = Err(tcx.dcx().emit_err(errors::VariancesOf {
                     span: tcx.def_span(id.owner_id),
                     variances_of: format!("{variances_of:?}"),
-                });
+                }));
             }
         }
     }
@@ -25,10 +27,11 @@ pub fn test_variance(tcx: TyCtxt<'_>) {
         if tcx.has_attr(id.owner_id, sym::rustc_variance) {
             let variances_of = tcx.variances_of(id.owner_id);
 
-            tcx.dcx().emit_err(errors::VariancesOf {
+            res = Err(tcx.dcx().emit_err(errors::VariancesOf {
                 span: tcx.def_span(id.owner_id),
                 variances_of: format!("{variances_of:?}"),
-            });
+            }));
         }
     }
+    res
 }
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index d36e0892d19..e76303bc6df 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -1838,6 +1838,11 @@ impl<'a> State<'a> {
                 self.commasep(Inconsistent, after, |s, p| s.print_pat(p));
                 self.word("]");
             }
+            PatKind::Err(_) => {
+                self.popen();
+                self.word("/*ERROR*/");
+                self.pclose();
+            }
         }
         self.ann.post(self, AnnNode::Pat(pat))
     }
diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml
index b0c60304424..975f9375642 100644
--- a/compiler/rustc_hir_typeck/Cargo.toml
+++ b/compiler/rustc_hir_typeck/Cargo.toml
@@ -5,6 +5,7 @@ edition = "2021"
 
 [dependencies]
 # tidy-alphabetical-start
+itertools = "0.11"
 rustc_ast = { path = "../rustc_ast" }
 rustc_attr = { path = "../rustc_attr" }
 rustc_data_structures = { path = "../rustc_data_structures" }
diff --git a/compiler/rustc_hir_typeck/src/autoderef.rs b/compiler/rustc_hir_typeck/src/autoderef.rs
index 7873257c4e3..2bb7caea3c4 100644
--- a/compiler/rustc_hir_typeck/src/autoderef.rs
+++ b/compiler/rustc_hir_typeck/src/autoderef.rs
@@ -2,6 +2,7 @@
 use super::method::MethodCallee;
 use super::{FnCtxt, PlaceOp};
 
+use itertools::Itertools;
 use rustc_hir_analysis::autoderef::{Autoderef, AutoderefKind};
 use rustc_infer::infer::InferOk;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
@@ -32,8 +33,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         autoderef: &Autoderef<'a, 'tcx>,
     ) -> InferOk<'tcx, Vec<Adjustment<'tcx>>> {
-        let mut obligations = vec![];
         let steps = autoderef.steps();
+        if steps.is_empty() {
+            return InferOk { obligations: vec![], value: vec![] };
+        }
+
+        let mut obligations = vec![];
         let targets =
             steps.iter().skip(1).map(|&(ty, _)| ty).chain(iter::once(autoderef.final_ty(false)));
         let steps: Vec<_> = steps
@@ -54,7 +59,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     None
                 }
             })
-            .zip(targets)
+            .zip_eq(targets)
             .map(|(autoderef, target)| Adjustment { kind: Adjust::Deref(autoderef), target })
             .collect();
 
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index 1a4e03d50ca..d486f069989 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -293,49 +293,59 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         callee_node: &hir::ExprKind<'_>,
         callee_span: Span,
     ) {
+        let hir::ExprKind::Block(..) = callee_node else {
+            // Only calls on blocks suggested here.
+            return;
+        };
+
         let hir = self.tcx.hir();
-        let parent_hir_id = hir.parent_id(hir_id);
-        let parent_node = self.tcx.hir_node(parent_hir_id);
-        if let (
-            hir::Node::Expr(hir::Expr {
-                kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, kind, .. }),
+        let fn_decl_span = if let hir::Node::Expr(hir::Expr {
+            kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }),
+            ..
+        }) = hir.get_parent(hir_id)
+        {
+            fn_decl_span
+        } else if let Some((
+            _,
+            hir::Node::Expr(&hir::Expr {
+                hir_id: parent_hir_id,
+                kind:
+                    hir::ExprKind::Closure(&hir::Closure {
+                        kind:
+                            hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
+                                hir::CoroutineDesugaring::Async,
+                                hir::CoroutineSource::Closure,
+                            )),
+                        ..
+                    }),
                 ..
             }),
-            hir::ExprKind::Block(..),
-        ) = (parent_node, callee_node)
+        )) = hir.parent_iter(hir_id).nth(3)
         {
-            let fn_decl_span = if matches!(
-                kind,
-                hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
-                    hir::CoroutineDesugaring::Async,
-                    hir::CoroutineSource::Closure
-                ),)
-            ) {
-                // Actually need to unwrap one more layer of HIR to get to
-                // the _real_ closure...
-                let async_closure = hir.parent_id(parent_hir_id);
-                if let hir::Node::Expr(hir::Expr {
-                    kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }),
-                    ..
-                }) = self.tcx.hir_node(async_closure)
-                {
-                    fn_decl_span
-                } else {
-                    return;
-                }
-            } else {
+            // Actually need to unwrap one more layer of HIR to get to
+            // the _real_ closure...
+            let async_closure = hir.parent_id(parent_hir_id);
+            if let hir::Node::Expr(hir::Expr {
+                kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }),
+                ..
+            }) = self.tcx.hir_node(async_closure)
+            {
                 fn_decl_span
-            };
+            } else {
+                return;
+            }
+        } else {
+            return;
+        };
 
-            let start = fn_decl_span.shrink_to_lo();
-            let end = callee_span.shrink_to_hi();
-            err.multipart_suggestion(
-                "if you meant to create this closure and immediately call it, surround the \
+        let start = fn_decl_span.shrink_to_lo();
+        let end = callee_span.shrink_to_hi();
+        err.multipart_suggestion(
+            "if you meant to create this closure and immediately call it, surround the \
                 closure with parentheses",
-                vec![(start, "(".to_string()), (end, ")".to_string())],
-                Applicability::MaybeIncorrect,
-            );
-        }
+            vec![(start, "(".to_string()), (end, ")".to_string())],
+            Applicability::MaybeIncorrect,
+        );
     }
 
     /// Give appropriate suggestion when encountering `[("a", 0) ("b", 1)]`, where the
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index b6b33299315..f51cc97b45d 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -14,7 +14,7 @@ use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
 use rustc_middle::ty::GenericArgs;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor};
 use rustc_span::def_id::LocalDefId;
-use rustc_span::{sym, Span};
+use rustc_span::Span;
 use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::traits;
 use rustc_trait_selection::traits::error_reporting::ArgKind;
@@ -49,7 +49,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expr_span: Span,
         expected: Expectation<'tcx>,
     ) -> Ty<'tcx> {
-        trace!("decl = {:#?}", closure.fn_decl);
+        let tcx = self.tcx;
+        let body = tcx.hir().body(closure.body);
+        let expr_def_id = closure.def_id;
 
         // It's always helpful for inference if we know the kind of
         // closure sooner rather than later, so first examine the expected
@@ -61,35 +63,63 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             None => (None, None),
         };
 
-        self.check_closure(closure, expr_span, expected_kind, expected_sig)
-    }
-
-    #[instrument(skip(self, closure), level = "debug", ret)]
-    fn check_closure(
-        &self,
-        closure: &hir::Closure<'tcx>,
-        expr_span: Span,
-        opt_kind: Option<ty::ClosureKind>,
-        expected_sig: Option<ExpectedSig<'tcx>>,
-    ) -> Ty<'tcx> {
-        let tcx = self.tcx;
-        let body = tcx.hir().body(closure.body);
-
-        trace!("decl = {:#?}", closure.fn_decl);
-        let expr_def_id = closure.def_id;
-        debug!(?expr_def_id);
-
         let ClosureSignatures { bound_sig, liberated_sig } =
             self.sig_of_closure(expr_def_id, closure.fn_decl, closure.kind, expected_sig);
 
         debug!(?bound_sig, ?liberated_sig);
 
+        let parent_args =
+            GenericArgs::identity_for_item(tcx, tcx.typeck_root_def_id(expr_def_id.to_def_id()));
+
+        let tupled_upvars_ty = self.next_ty_var(TypeVariableOrigin {
+            kind: TypeVariableOriginKind::ClosureSynthetic,
+            span: expr_span,
+        });
+
         // FIXME: We could probably actually just unify this further --
         // instead of having a `FnSig` and a `Option<CoroutineTypes>`,
         // we can have a `ClosureSignature { Coroutine { .. }, Closure { .. } }`,
         // similar to how `ty::GenSig` is a distinct data structure.
-        let coroutine_types = match closure.kind {
-            hir::ClosureKind::Closure => None,
+        let (closure_ty, coroutine_types) = match closure.kind {
+            hir::ClosureKind::Closure => {
+                // Tuple up the arguments and insert the resulting function type into
+                // the `closures` table.
+                let sig = bound_sig.map_bound(|sig| {
+                    tcx.mk_fn_sig(
+                        [Ty::new_tup(tcx, sig.inputs())],
+                        sig.output(),
+                        sig.c_variadic,
+                        sig.unsafety,
+                        sig.abi,
+                    )
+                });
+
+                debug!(?sig, ?expected_kind);
+
+                let closure_kind_ty = match expected_kind {
+                    Some(kind) => Ty::from_closure_kind(tcx, kind),
+
+                    // Create a type variable (for now) to represent the closure kind.
+                    // It will be unified during the upvar inference phase (`upvar.rs`)
+                    None => self.next_ty_var(TypeVariableOrigin {
+                        // FIXME(eddyb) distinguish closure kind inference variables from the rest.
+                        kind: TypeVariableOriginKind::ClosureSynthetic,
+                        span: expr_span,
+                    }),
+                };
+
+                let closure_args = ty::ClosureArgs::new(
+                    tcx,
+                    ty::ClosureArgsParts {
+                        parent_args,
+                        closure_kind_ty,
+                        closure_sig_as_fn_ptr_ty: Ty::new_fn_ptr(tcx, sig),
+                        tupled_upvars_ty,
+                    },
+                );
+
+                (Ty::new_closure(tcx, expr_def_id.to_def_id(), closure_args.args), None)
+            }
             hir::ClosureKind::Coroutine(kind) => {
                 let yield_ty = match kind {
                     hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)
@@ -135,80 +165,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // Resume type defaults to `()` if the coroutine has no argument.
                 let resume_ty = liberated_sig.inputs().get(0).copied().unwrap_or(tcx.types.unit);
 
-                Some(CoroutineTypes { resume_ty, yield_ty })
-            }
-        };
-
-        let mut fcx = FnCtxt::new(self, self.param_env, closure.def_id);
-        check_fn(
-            &mut fcx,
-            liberated_sig,
-            coroutine_types,
-            closure.fn_decl,
-            expr_def_id,
-            body,
-            // Closure "rust-call" ABI doesn't support unsized params
-            false,
-        );
-
-        let parent_args =
-            GenericArgs::identity_for_item(tcx, tcx.typeck_root_def_id(expr_def_id.to_def_id()));
-
-        let tupled_upvars_ty = self.next_root_ty_var(TypeVariableOrigin {
-            kind: TypeVariableOriginKind::ClosureSynthetic,
-            span: expr_span,
-        });
-
-        match closure.kind {
-            hir::ClosureKind::Closure => {
-                assert_eq!(coroutine_types, None);
-                // Tuple up the arguments and insert the resulting function type into
-                // the `closures` table.
-                let sig = bound_sig.map_bound(|sig| {
-                    tcx.mk_fn_sig(
-                        [Ty::new_tup(tcx, sig.inputs())],
-                        sig.output(),
-                        sig.c_variadic,
-                        sig.unsafety,
-                        sig.abi,
-                    )
-                });
-
-                debug!(?sig, ?opt_kind);
-
-                let closure_kind_ty = match opt_kind {
-                    Some(kind) => Ty::from_closure_kind(tcx, kind),
-
-                    // Create a type variable (for now) to represent the closure kind.
-                    // It will be unified during the upvar inference phase (`upvar.rs`)
-                    None => self.next_root_ty_var(TypeVariableOrigin {
-                        // FIXME(eddyb) distinguish closure kind inference variables from the rest.
-                        kind: TypeVariableOriginKind::ClosureSynthetic,
-                        span: expr_span,
-                    }),
-                };
-
-                let closure_args = ty::ClosureArgs::new(
-                    tcx,
-                    ty::ClosureArgsParts {
-                        parent_args,
-                        closure_kind_ty,
-                        closure_sig_as_fn_ptr_ty: Ty::new_fn_ptr(tcx, sig),
-                        tupled_upvars_ty,
-                    },
-                );
-
-                Ty::new_closure(tcx, expr_def_id.to_def_id(), closure_args.args)
-            }
-            hir::ClosureKind::Coroutine(_) => {
-                let Some(CoroutineTypes { resume_ty, yield_ty }) = coroutine_types else {
-                    bug!("expected coroutine to have yield/resume types");
-                };
-                let interior = fcx.next_ty_var(TypeVariableOrigin {
+                let interior = self.next_ty_var(TypeVariableOrigin {
                     kind: TypeVariableOriginKind::MiscVariable,
                     span: body.value.span,
                 });
-                fcx.deferred_coroutine_interiors.borrow_mut().push((
+                self.deferred_coroutine_interiors.borrow_mut().push((
                     expr_def_id,
                     body.id(),
                     interior,
@@ -226,9 +187,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     },
                 );
 
-                Ty::new_coroutine(tcx, expr_def_id.to_def_id(), coroutine_args.args)
+                (
+                    Ty::new_coroutine(tcx, expr_def_id.to_def_id(), coroutine_args.args),
+                    Some(CoroutineTypes { resume_ty, yield_ty }),
+                )
             }
-        }
+        };
+
+        check_fn(
+            &mut FnCtxt::new(self, self.param_env, closure.def_id),
+            liberated_sig,
+            coroutine_types,
+            closure.fn_decl,
+            expr_def_id,
+            body,
+            // Closure "rust-call" ABI doesn't support unsized params
+            false,
+        );
+
+        closure_ty
     }
 
     /// Given the expected type, figures out what it can about this closure we
@@ -364,36 +341,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let tcx = self.tcx;
 
         let trait_def_id = projection.trait_def_id(tcx);
-
-        let is_fn = tcx.is_fn_trait(trait_def_id);
-
-        let coroutine_trait = tcx.lang_items().coroutine_trait();
-        let is_gen = coroutine_trait == Some(trait_def_id);
-
-        if !is_fn && !is_gen {
-            debug!("not fn or coroutine");
+        // For now, we only do signature deduction based off of the `Fn` traits.
+        if !tcx.is_fn_trait(trait_def_id) {
             return None;
         }
 
-        // Check that we deduce the signature from the `<_ as std::ops::Coroutine>::Return`
-        // associated item and not yield.
-        if is_gen && self.tcx.associated_item(projection.projection_def_id()).name != sym::Return {
-            debug!("not `Return` assoc item of `Coroutine`");
-            return None;
-        }
-
-        let input_tys = if is_fn {
-            let arg_param_ty = projection.skip_binder().projection_ty.args.type_at(1);
-            let arg_param_ty = self.resolve_vars_if_possible(arg_param_ty);
-            debug!(?arg_param_ty);
+        let arg_param_ty = projection.skip_binder().projection_ty.args.type_at(1);
+        let arg_param_ty = self.resolve_vars_if_possible(arg_param_ty);
+        debug!(?arg_param_ty);
 
-            match arg_param_ty.kind() {
-                &ty::Tuple(tys) => tys,
-                _ => return None,
-            }
-        } else {
-            // Coroutines with a `()` resume type may be defined with 0 or 1 explicit arguments,
-            // else they must have exactly 1 argument. For now though, just give up in this case.
+        let ty::Tuple(input_tys) = *arg_param_ty.kind() else {
             return None;
         };
 
@@ -416,7 +373,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn sig_of_closure(
         &self,
         expr_def_id: LocalDefId,
-        decl: &hir::FnDecl<'_>,
+        decl: &hir::FnDecl<'tcx>,
         closure_kind: hir::ClosureKind,
         expected_sig: Option<ExpectedSig<'tcx>>,
     ) -> ClosureSignatures<'tcx> {
@@ -433,7 +390,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn sig_of_closure_no_expectation(
         &self,
         expr_def_id: LocalDefId,
-        decl: &hir::FnDecl<'_>,
+        decl: &hir::FnDecl<'tcx>,
         closure_kind: hir::ClosureKind,
     ) -> ClosureSignatures<'tcx> {
         let bound_sig = self.supplied_sig_of_closure(expr_def_id, decl, closure_kind);
@@ -492,7 +449,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn sig_of_closure_with_expectation(
         &self,
         expr_def_id: LocalDefId,
-        decl: &hir::FnDecl<'_>,
+        decl: &hir::FnDecl<'tcx>,
         closure_kind: hir::ClosureKind,
         expected_sig: ExpectedSig<'tcx>,
     ) -> ClosureSignatures<'tcx> {
@@ -549,7 +506,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn sig_of_closure_with_mismatched_number_of_arguments(
         &self,
         expr_def_id: LocalDefId,
-        decl: &hir::FnDecl<'_>,
+        decl: &hir::FnDecl<'tcx>,
         expected_sig: ExpectedSig<'tcx>,
     ) -> ClosureSignatures<'tcx> {
         let expr_map_node = self.tcx.hir_node_by_def_id(expr_def_id);
@@ -590,7 +547,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn merge_supplied_sig_with_expectation(
         &self,
         expr_def_id: LocalDefId,
-        decl: &hir::FnDecl<'_>,
+        decl: &hir::FnDecl<'tcx>,
         closure_kind: hir::ClosureKind,
         mut expected_sigs: ClosureSignatures<'tcx>,
     ) -> InferResult<'tcx, ClosureSignatures<'tcx>> {
@@ -684,7 +641,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn supplied_sig_of_closure(
         &self,
         expr_def_id: LocalDefId,
-        decl: &hir::FnDecl<'_>,
+        decl: &hir::FnDecl<'tcx>,
         closure_kind: hir::ClosureKind,
     ) -> ty::PolyFnSig<'tcx> {
         let astconv: &dyn AstConv<'_> = self;
@@ -720,10 +677,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     })
                 }
                 // All `gen {}` and `async gen {}` must return unit.
-                hir::ClosureKind::Coroutine(
-                    hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)
-                    | hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _),
-                ) => self.tcx.types.unit,
+                hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
+                    hir::CoroutineDesugaring::Gen | hir::CoroutineDesugaring::AsyncGen,
+                    _,
+                )) => self.tcx.types.unit,
 
                 // For async blocks, we just fall back to `_` here.
                 // For closures/coroutines, we know nothing about the return
@@ -797,16 +754,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     get_future_output(obligation.predicate, obligation.cause.span)
                 })?
             }
+            ty::Alias(ty::Projection, _) => {
+                return Some(Ty::new_error_with_message(
+                    self.tcx,
+                    closure_span,
+                    "this projection should have been projected to an opaque type",
+                ));
+            }
             ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => self
                 .tcx
                 .explicit_item_bounds(def_id)
                 .iter_instantiated_copied(self.tcx, args)
                 .find_map(|(p, s)| get_future_output(p.as_predicate(), s))?,
             ty::Error(_) => return Some(ret_ty),
-            _ => span_bug!(
-                closure_span,
-                "async fn coroutine return type not an inference variable: {ret_ty}"
-            ),
+            _ => {
+                span_bug!(closure_span, "invalid async fn coroutine return type: {ret_ty:?}")
+            }
         };
 
         let output_ty = self.normalize(closure_span, output_ty);
@@ -880,7 +843,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// all parameters are of type `ty::Error`.
     fn error_sig_of_closure(
         &self,
-        decl: &hir::FnDecl<'_>,
+        decl: &hir::FnDecl<'tcx>,
         guar: ErrorGuaranteed,
     ) -> ty::PolyFnSig<'tcx> {
         let astconv: &dyn AstConv<'_> = self;
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index af47455c16d..aca17ec77a4 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -26,7 +26,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::{
     pluralize, struct_span_code_err, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder,
-    DiagnosticId, ErrorGuaranteed, StashKey,
+    ErrorGuaranteed, StashKey,
 };
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
@@ -941,7 +941,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         let mut err = self.dcx().struct_span_err(op_span, "invalid left-hand side of assignment");
-        err.code(DiagnosticId::Error(err_code.into()));
+        err.code(err_code.into());
         err.span_label(lhs.span, "cannot assign to this expression");
 
         self.comes_from_while_condition(lhs.hir_id, |expr| {
@@ -1315,7 +1315,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn check_method_call(
         &self,
         expr: &'tcx hir::Expr<'tcx>,
-        segment: &hir::PathSegment<'_>,
+        segment: &'tcx hir::PathSegment<'tcx>,
         rcvr: &'tcx hir::Expr<'tcx>,
         args: &'tcx [hir::Expr<'tcx>],
         expected: Expectation<'tcx>,
@@ -1526,13 +1526,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         self.check_repeat_element_needs_copy_bound(element, count, element_ty);
 
-        self.register_wf_obligation(
-            Ty::new_array_with_const_len(tcx, t, count).into(),
-            expr.span,
-            traits::WellFormed(None),
-        );
+        let ty = Ty::new_array_with_const_len(tcx, t, count);
+
+        self.register_wf_obligation(ty.into(), expr.span, traits::WellFormed(None));
 
-        Ty::new_array_with_const_len(tcx, t, count)
+        ty
     }
 
     fn check_repeat_element_needs_copy_bound(
@@ -1629,7 +1627,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         expr: &hir::Expr<'_>,
         expected: Expectation<'tcx>,
-        qpath: &QPath<'_>,
+        qpath: &QPath<'tcx>,
         fields: &'tcx [hir::ExprField<'tcx>],
         base_expr: &'tcx Option<&'tcx hir::Expr<'tcx>>,
     ) -> Ty<'tcx> {
@@ -2104,7 +2102,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let mut items = self
                 .tcx
                 .inherent_impls(def_id)
-                .iter()
+                .into_iter()
+                .flatten()
                 .flat_map(|i| self.tcx.associated_items(i).in_definition_order())
                 // Only assoc fn with no receivers.
                 .filter(|item| {
@@ -3247,6 +3246,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) -> Ty<'tcx> {
         let container = self.to_ty(container).normalized;
 
+        if let Some(ident_2) = fields.get(1)
+            && !self.tcx.features().offset_of_nested
+        {
+            rustc_session::parse::feature_err(
+                &self.tcx.sess,
+                sym::offset_of_nested,
+                ident_2.span,
+                "only a single ident or integer is stable as the field in offset_of",
+            )
+            .emit();
+        }
+
         let mut field_indices = Vec::with_capacity(fields.len());
         let mut current_container = container;
         let mut fields = fields.into_iter();
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index ed3dd1e39df..3ecf6c5e428 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -458,11 +458,15 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
                             needs_to_be_read = true;
                         }
                     }
-                    PatKind::Or(_) | PatKind::Box(_) | PatKind::Ref(..) | PatKind::Wild => {
+                    PatKind::Or(_)
+                    | PatKind::Box(_)
+                    | PatKind::Ref(..)
+                    | PatKind::Wild
+                    | PatKind::Err(_) => {
                         // If the PatKind is Or, Box, or Ref, the decision is made later
                         // as these patterns contains subpatterns
-                        // If the PatKind is Wild, the decision is made based on the other patterns being
-                        // examined
+                        // If the PatKind is Wild or Err, the decision is made based on the other patterns
+                        // being examined
                     }
                 }
             })?
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index a4cd9ccc984..3ea409827b4 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -377,13 +377,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         RawTy { raw: ty, normalized: self.normalize(span, ty) }
     }
 
-    pub fn to_ty(&self, ast_t: &hir::Ty<'_>) -> RawTy<'tcx> {
+    pub fn to_ty(&self, ast_t: &hir::Ty<'tcx>) -> RawTy<'tcx> {
         let t = self.astconv().ast_ty_to_ty(ast_t);
         self.register_wf_obligation(t.into(), ast_t.span, traits::WellFormed(None));
         self.handle_raw_ty(ast_t.span, t)
     }
 
-    pub fn to_ty_saving_user_provided_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
+    pub fn to_ty_saving_user_provided_ty(&self, ast_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
         let ty = self.to_ty(ast_ty);
         debug!("to_ty_saving_user_provided_ty: ty={:?}", ty);
 
@@ -1073,7 +1073,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     #[instrument(skip(self, span), level = "debug")]
     pub fn instantiate_value_path(
         &self,
-        segments: &[hir::PathSegment<'_>],
+        segments: &'tcx [hir::PathSegment<'tcx>],
         self_ty: Option<RawTy<'tcx>>,
         res: Res,
         span: Span,
@@ -1260,13 +1260,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             span: Span,
             path_segs: &'a [PathSeg],
             infer_args_for_err: &'a FxHashSet<usize>,
-            segments: &'a [hir::PathSegment<'a>],
+            segments: &'tcx [hir::PathSegment<'tcx>],
         }
         impl<'tcx, 'a> CreateSubstsForGenericArgsCtxt<'a, 'tcx> for CreateCtorSubstsContext<'a, 'tcx> {
             fn args_for_def_id(
                 &mut self,
                 def_id: DefId,
-            ) -> (Option<&'a hir::GenericArgs<'a>>, bool) {
+            ) -> (Option<&'a hir::GenericArgs<'tcx>>, bool) {
                 if let Some(&PathSeg(_, index)) =
                     self.path_segs.iter().find(|&PathSeg(did, _)| *did == def_id)
                 {
@@ -1287,7 +1287,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             fn provided_kind(
                 &mut self,
                 param: &ty::GenericParamDef,
-                arg: &GenericArg<'_>,
+                arg: &GenericArg<'tcx>,
             ) -> ty::GenericArg<'tcx> {
                 match (&param.kind, arg) {
                     (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
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 76360239c45..1ad79cb78c4 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
@@ -86,7 +86,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // Finally, for ambiguity-related errors, we actually want to look
         // for a parameter that is the source of the inference type left
         // over in this predicate.
-        if let traits::FulfillmentErrorCode::CodeAmbiguity { .. } = error.code {
+        if let traits::FulfillmentErrorCode::Ambiguity { .. } = error.code {
             fallback_param_to_point_at = None;
             self_param_to_point_at = None;
             param_to_point_at =
@@ -361,10 +361,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         error: &traits::FulfillmentError<'tcx>,
         span: Span,
     ) -> bool {
-        if let traits::FulfillmentErrorCode::CodeSelectionError(
-            traits::SelectionError::OutputTypeParameterMismatch(
-                box traits::SelectionOutputTypeParameterMismatch { expected_trait_ref, .. },
-            ),
+        if let traits::FulfillmentErrorCode::SelectionError(
+            traits::SelectionError::SignatureMismatch(box traits::SignatureMismatchData {
+                expected_trait_ref,
+                ..
+            }),
         ) = error.code
             && let ty::Closure(def_id, _) | ty::Coroutine(def_id, ..) =
                 expected_trait_ref.skip_binder().self_ty().kind()
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 8cd5ed3494b..ddb4224b60d 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -9,11 +9,10 @@ use crate::{
     struct_span_code_err, BreakableCtxt, Diverges, Expectation, FnCtxt, Needs, RawTy,
     TupleArgumentsFlag,
 };
+use itertools::Itertools;
 use rustc_ast as ast;
 use rustc_data_structures::fx::FxIndexSet;
-use rustc_errors::{
-    pluralize, Applicability, Diagnostic, DiagnosticId, ErrorGuaranteed, MultiSpan, StashKey,
-};
+use rustc_errors::{pluralize, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan, StashKey};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::DefId;
@@ -421,7 +420,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 formal_input_tys
                     .iter()
                     .copied()
-                    .zip(expected_input_tys.iter().copied())
+                    .zip_eq(expected_input_tys.iter().copied())
                     .map(|vars| self.resolve_vars_if_possible(vars)),
             );
 
@@ -678,7 +677,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 pluralize!("was", provided_args.len())
                             ),
                         );
-                        err.code(DiagnosticId::Error(err_code.to_owned()));
+                        err.code(err_code.to_owned());
                         err.multipart_suggestion_verbose(
                             "wrap these arguments in parentheses to construct a tuple",
                             vec![
@@ -828,7 +827,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         pluralize!("was", provided_args.len())
                     ),
                 )
-                .with_code(DiagnosticId::Error(err_code.to_owned()))
+                .with_code(err_code.to_owned())
         };
 
         // As we encounter issues, keep track of what we want to provide for the suggestion
@@ -1328,7 +1327,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     pub fn check_struct_path(
         &self,
-        qpath: &QPath<'_>,
+        qpath: &QPath<'tcx>,
         hir_id: hir::HirId,
     ) -> Result<(&'tcx ty::VariantDef, Ty<'tcx>), ErrorGuaranteed> {
         let path_span = qpath.span();
@@ -1784,7 +1783,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     // The newly resolved definition is written into `type_dependent_defs`.
     fn finish_resolving_struct_path(
         &self,
-        qpath: &QPath<'_>,
+        qpath: &QPath<'tcx>,
         path_span: Span,
         hir_id: hir::HirId,
     ) -> (Res, RawTy<'tcx>) {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index fde3d41faec..e6c2091d85a 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -190,10 +190,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub fn errors_reported_since_creation(&self) -> bool {
         self.dcx().err_count() > self.err_count_on_creation
     }
-
-    pub fn next_root_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
-        Ty::new_var(self.tcx, self.next_ty_var_id_in_universe(origin, ty::UniverseIndex::ROOT))
-    }
 }
 
 impl<'a, 'tcx> Deref for FnCtxt<'a, 'tcx> {
@@ -287,7 +283,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
         &self,
         span: Span,
         item_def_id: DefId,
-        item_segment: &hir::PathSegment<'_>,
+        item_segment: &hir::PathSegment<'tcx>,
         poly_trait_ref: ty::PolyTraitRef<'tcx>,
     ) -> Ty<'tcx> {
         let trait_ref = self.instantiate_binder_with_fresh_vars(
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index b542132d71c..2778ada655e 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -784,7 +784,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub(in super::super) fn suggest_missing_return_type(
         &self,
         err: &mut Diagnostic,
-        fn_decl: &hir::FnDecl<'_>,
+        fn_decl: &hir::FnDecl<'tcx>,
         expected: Ty<'tcx>,
         found: Ty<'tcx>,
         can_suggest: bool,
@@ -995,7 +995,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         err: &mut Diagnostic,
         expr: &'tcx hir::Expr<'tcx>,
-        fn_decl: &hir::FnDecl<'_>,
+        fn_decl: &hir::FnDecl<'tcx>,
         expected: Ty<'tcx>,
         found: Ty<'tcx>,
         id: hir::HirId,
@@ -1468,7 +1468,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub(crate) fn suggest_associated_const(
         &self,
         err: &mut Diagnostic,
-        expr: &hir::Expr<'_>,
+        expr: &hir::Expr<'tcx>,
         expected_ty: Ty<'tcx>,
     ) -> bool {
         let Some((DefKind::AssocFn, old_def_id)) =
@@ -1623,7 +1623,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 );
             } else {
                 if let Some(errors) =
-                    self.could_impl_trait(clone_trait_did, expected_ty, self.param_env)
+                    self.type_implements_trait_shallow(clone_trait_did, expected_ty, self.param_env)
                 {
                     match &errors[..] {
                         [] => {}
@@ -1648,7 +1648,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         }
                     }
                     for error in errors {
-                        if let traits::FulfillmentErrorCode::CodeSelectionError(
+                        if let traits::FulfillmentErrorCode::SelectionError(
                             traits::SelectionError::Unimplemented,
                         ) = error.code
                             && let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) =
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 36dd06d944c..80467ca9381 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -52,7 +52,7 @@ use crate::expectation::Expectation;
 use crate::fn_ctxt::RawTy;
 use crate::gather_locals::GatherLocalsVisitor;
 use rustc_data_structures::unord::UnordSet;
-use rustc_errors::{struct_span_code_err, DiagnosticId, ErrorGuaranteed};
+use rustc_errors::{struct_span_code_err, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit::Visitor;
@@ -60,6 +60,7 @@ use rustc_hir::{HirIdMap, Node};
 use rustc_hir_analysis::astconv::AstConv;
 use rustc_hir_analysis::check::check_abi;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::traits::ObligationInspector;
 use rustc_middle::query::Providers;
 use rustc_middle::traits;
 use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -139,7 +140,7 @@ fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &UnordSet<LocalDef
 
 fn typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> {
     let fallback = move || tcx.type_of(def_id.to_def_id()).instantiate_identity();
-    typeck_with_fallback(tcx, def_id, fallback)
+    typeck_with_fallback(tcx, def_id, fallback, None)
 }
 
 /// Used only to get `TypeckResults` for type inference during error recovery.
@@ -149,14 +150,28 @@ fn diagnostic_only_typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::T
         let span = tcx.hir().span(tcx.local_def_id_to_hir_id(def_id));
         Ty::new_error_with_message(tcx, span, "diagnostic only typeck table used")
     };
-    typeck_with_fallback(tcx, def_id, fallback)
+    typeck_with_fallback(tcx, def_id, fallback, None)
 }
 
-#[instrument(level = "debug", skip(tcx, fallback), ret)]
+/// Same as `typeck` but `inspect` is invoked on evaluation of each root obligation.
+/// Inspecting obligations only works with the new trait solver.
+/// This function is *only to be used* by external tools, it should not be
+/// called from within rustc. Note, this is not a query, and thus is not cached.
+pub fn inspect_typeck<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    def_id: LocalDefId,
+    inspect: ObligationInspector<'tcx>,
+) -> &'tcx ty::TypeckResults<'tcx> {
+    let fallback = move || tcx.type_of(def_id.to_def_id()).instantiate_identity();
+    typeck_with_fallback(tcx, def_id, fallback, Some(inspect))
+}
+
+#[instrument(level = "debug", skip(tcx, fallback, inspector), ret)]
 fn typeck_with_fallback<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: LocalDefId,
     fallback: impl Fn() -> Ty<'tcx> + 'tcx,
+    inspector: Option<ObligationInspector<'tcx>>,
 ) -> &'tcx ty::TypeckResults<'tcx> {
     // Closures' typeck results come from their outermost function,
     // as they are part of the same "inference environment".
@@ -178,6 +193,9 @@ fn typeck_with_fallback<'tcx>(
     let param_env = tcx.param_env(def_id);
 
     let inh = Inherited::new(tcx, def_id);
+    if let Some(inspector) = inspector {
+        inh.infcx.attach_obligation_inspector(inspector);
+    }
     let mut fcx = FnCtxt::new(&inh, param_env, def_id);
 
     if let Some(hir::FnSig { header, decl, .. }) = fn_sig {
@@ -369,7 +387,7 @@ fn report_unexpected_variant_res(
     let err = tcx
         .dcx()
         .struct_span_err(span, format!("expected {expected}, found {res_descr} `{path_str}`"))
-        .with_code(DiagnosticId::Error(err_code.into()));
+        .with_code(err_code.into());
     match res {
         Res::Def(DefKind::Fn | DefKind::AssocFn, _) if err_code == "E0164" => {
             let patterns_url = "https://doc.rust-lang.org/book/ch18-00-patterns.html";
diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs
index ce3a4b4c80c..1ce0240f7b8 100644
--- a/compiler/rustc_hir_typeck/src/mem_categorization.rs
+++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs
@@ -767,7 +767,8 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
             | PatKind::Lit(..)
             | PatKind::Range(..)
             | PatKind::Never
-            | PatKind::Wild => {
+            | PatKind::Wild
+            | PatKind::Err(_) => {
                 // always ok
             }
         }
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index b2ead3cd40b..6f18cc51b11 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -50,7 +50,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         call_expr: &'tcx hir::Expr<'tcx>,
         unadjusted_self_ty: Ty<'tcx>,
         pick: &probe::Pick<'tcx>,
-        segment: &hir::PathSegment<'_>,
+        segment: &'tcx hir::PathSegment<'tcx>,
     ) -> ConfirmResult<'tcx> {
         debug!(
             "confirm(unadjusted_self_ty={:?}, pick={:?}, generic_args={:?})",
@@ -68,7 +68,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         call_expr: &'tcx hir::Expr<'tcx>,
         unadjusted_self_ty: Ty<'tcx>,
         pick: &probe::Pick<'tcx>,
-        segment: &hir::PathSegment<'_>,
+        segment: &hir::PathSegment<'tcx>,
     ) -> ConfirmResult<'tcx> {
         let mut confirm_cx = ConfirmContext::new(self, span, self_expr, call_expr);
         confirm_cx.skip_record_for_diagnostics = true;
@@ -90,7 +90,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         &mut self,
         unadjusted_self_ty: Ty<'tcx>,
         pick: &probe::Pick<'tcx>,
-        segment: &hir::PathSegment<'_>,
+        segment: &hir::PathSegment<'tcx>,
     ) -> ConfirmResult<'tcx> {
         // Adjust the self expression the user provided and obtain the adjusted type.
         let self_ty = self.adjust_self_ty(unadjusted_self_ty, pick);
@@ -346,7 +346,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
     fn instantiate_method_args(
         &mut self,
         pick: &probe::Pick<'tcx>,
-        seg: &hir::PathSegment<'_>,
+        seg: &hir::PathSegment<'tcx>,
         parent_args: GenericArgsRef<'tcx>,
     ) -> GenericArgsRef<'tcx> {
         // Determine the values for the generic parameters of the method.
@@ -370,13 +370,13 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         struct MethodSubstsCtxt<'a, 'tcx> {
             cfcx: &'a ConfirmContext<'a, 'tcx>,
             pick: &'a probe::Pick<'tcx>,
-            seg: &'a hir::PathSegment<'a>,
+            seg: &'a hir::PathSegment<'tcx>,
         }
         impl<'a, 'tcx> CreateSubstsForGenericArgsCtxt<'a, 'tcx> for MethodSubstsCtxt<'a, 'tcx> {
             fn args_for_def_id(
                 &mut self,
                 def_id: DefId,
-            ) -> (Option<&'a hir::GenericArgs<'a>>, bool) {
+            ) -> (Option<&'a hir::GenericArgs<'tcx>>, bool) {
                 if def_id == self.pick.item.def_id {
                     if let Some(data) = self.seg.args {
                         return (Some(data), false);
@@ -388,7 +388,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
             fn provided_kind(
                 &mut self,
                 param: &ty::GenericParamDef,
-                arg: &GenericArg<'_>,
+                arg: &GenericArg<'tcx>,
             ) -> ty::GenericArg<'tcx> {
                 match (&param.kind, arg) {
                     (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs
index c746fb8af89..af172b59a14 100644
--- a/compiler/rustc_hir_typeck/src/method/mod.rs
+++ b/compiler/rustc_hir_typeck/src/method/mod.rs
@@ -177,7 +177,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub fn lookup_method(
         &self,
         self_ty: Ty<'tcx>,
-        segment: &hir::PathSegment<'_>,
+        segment: &'tcx hir::PathSegment<'tcx>,
         span: Span,
         call_expr: &'tcx hir::Expr<'tcx>,
         self_expr: &'tcx hir::Expr<'tcx>,
@@ -255,7 +255,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub fn lookup_method_for_diagnostic(
         &self,
         self_ty: Ty<'tcx>,
-        segment: &hir::PathSegment<'_>,
+        segment: &hir::PathSegment<'tcx>,
         span: Span,
         call_expr: &'tcx hir::Expr<'tcx>,
         self_expr: &'tcx hir::Expr<'tcx>,
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 10c31d8c641..4dc802008d0 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -711,14 +711,14 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsCandidateKey) else {
             bug!("unexpected incoherent type: {:?}", self_ty)
         };
-        for &impl_def_id in self.tcx.incoherent_impls(simp) {
+        for &impl_def_id in self.tcx.incoherent_impls(simp).into_iter().flatten() {
             self.assemble_inherent_impl_probe(impl_def_id);
         }
     }
 
     fn assemble_inherent_impl_candidates_for_type(&mut self, def_id: DefId) {
-        let impl_def_ids = self.tcx.at(self.span).inherent_impls(def_id);
-        for &impl_def_id in impl_def_ids.iter() {
+        let impl_def_ids = self.tcx.at(self.span).inherent_impls(def_id).into_iter().flatten();
+        for &impl_def_id in impl_def_ids {
             self.assemble_inherent_impl_probe(impl_def_id);
         }
     }
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 1f01c6b7406..0b8a25eedaf 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -359,7 +359,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     if let ty::Adt(adt_def, _) = ty.kind() {
                         self.tcx
                             .inherent_impls(adt_def.did())
-                            .iter()
+                            .into_iter()
+                            .flatten()
                             .any(|def_id| self.associated_value(*def_id, item_name).is_some())
                     } else {
                         false
@@ -825,11 +826,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             "auto trait is invoked with no method error, but no error reported?",
                         );
                     }
-                    Some(Node::Item(hir::Item {
-                        ident,
-                        kind: hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..),
-                        ..
-                    })) => {
+                    Some(
+                        Node::Item(hir::Item {
+                            ident,
+                            kind: hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..),
+                            ..
+                        })
+                        // We may also encounter unsatisfied GAT or method bounds
+                        | Node::TraitItem(hir::TraitItem { ident, .. })
+                        | Node::ImplItem(hir::ImplItem { ident, .. }),
+                    ) => {
                         skip_list.insert(p);
                         let entry = spanned_predicates.entry(ident.span);
                         let entry = entry.or_insert_with(|| {
@@ -840,7 +846,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         entry.1.insert((cause_span, "unsatisfied trait bound introduced here"));
                         entry.2.push(p);
                     }
-                    Some(node) => unreachable!("encountered `{node:?}`"),
+                    Some(node) => unreachable!("encountered `{node:?}` due to `{cause:#?}`"),
                     None => (),
                 }
             }
@@ -1043,7 +1049,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     let mut inherent_impls_candidate = self
                         .tcx
                         .inherent_impls(adt.did())
-                        .iter()
+                        .into_iter()
+                        .flatten()
                         .copied()
                         .filter(|def_id| {
                             if let Some(assoc) = self.associated_value(*def_id, item_name) {
@@ -1098,7 +1105,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             "the {item_kind} was found for\n{type_candidates}{additional_types}"
                         ));
                     } else {
-                        'outer: for inherent_impl_did in self.tcx.inherent_impls(adt.did()) {
+                        'outer: for inherent_impl_did in
+                            self.tcx.inherent_impls(adt.did()).into_iter().flatten()
+                        {
                             for inherent_method in
                                 self.tcx.associated_items(inherent_impl_did).in_definition_order()
                             {
@@ -1452,9 +1461,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let ty::Adt(adt_def, _) = rcvr_ty.kind() else {
             return;
         };
-        let mut items = self
-            .tcx
-            .inherent_impls(adt_def.did())
+        // FIXME(oli-obk): try out bubbling this error up one level and cancelling the other error in that case.
+        let Ok(impls) = self.tcx.inherent_impls(adt_def.did()) else { return };
+        let mut items = impls
             .iter()
             .flat_map(|i| self.tcx.associated_items(i).in_definition_order())
             // Only assoc fn with no receivers.
@@ -1818,7 +1827,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             simplify_type(tcx, ty, TreatParams::AsCandidateKey)
                 .and_then(|simp| {
                     tcx.incoherent_impls(simp)
-                        .iter()
+                        .into_iter()
+                        .flatten()
                         .find_map(|&id| self.associated_value(id, item_name))
                 })
                 .is_some()
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 95813cb68a6..37106867277 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -177,9 +177,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             PatInfo { binding_mode: def_bm, top_info: ti, decl_origin: pat_info.decl_origin };
 
         let ty = match pat.kind {
-            PatKind::Wild => expected,
-            // FIXME(never_patterns): check the type is uninhabited. If that is not possible within
-            // typeck, do that in a later phase.
+            PatKind::Wild | PatKind::Err(_) => expected,
+            // We allow any type here; we ensure that the type is uninhabited during match checking.
             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),
@@ -325,6 +324,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             PatKind::Ref(..) => AdjustMode::Reset,
             // 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.
+            | PatKind::Err(_)
             // Bindings also work with whatever the expected type is,
             // and moreover if we peel references off, that will give us the wrong binding type.
             // Also, we can have a subpattern `binding @ pat`.
@@ -754,7 +755,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         | PatKind::Box(..)
                         | PatKind::Ref(..)
                         | PatKind::Lit(..)
-                        | PatKind::Range(..) => break 'block None,
+                        | PatKind::Range(..)
+                        | PatKind::Err(_) => break 'block None,
                     },
 
                     // Don't provide suggestions in other cases
@@ -856,7 +858,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn check_pat_struct(
         &self,
         pat: &'tcx Pat<'tcx>,
-        qpath: &hir::QPath<'_>,
+        qpath: &hir::QPath<'tcx>,
         fields: &'tcx [hir::PatField<'tcx>],
         has_rest_pat: bool,
         expected: Ty<'tcx>,
diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs
index 7b8d91702b3..6f909a0cc9d 100644
--- a/compiler/rustc_incremental/src/assert_dep_graph.rs
+++ b/compiler/rustc_incremental/src/assert_dep_graph.rs
@@ -128,9 +128,11 @@ impl<'tcx> IfThisChanged<'tcx> {
             if attr.has_name(sym::rustc_if_this_changed) {
                 let dep_node_interned = self.argument(attr);
                 let dep_node = match dep_node_interned {
-                    None => {
-                        DepNode::from_def_path_hash(self.tcx, def_path_hash, dep_kinds::hir_owner)
-                    }
+                    None => DepNode::from_def_path_hash(
+                        self.tcx,
+                        def_path_hash,
+                        dep_kinds::hir_owner_nodes,
+                    ),
                     Some(n) => {
                         match DepNode::from_label_string(self.tcx, n.as_str(), def_path_hash) {
                             Ok(n) => n,
diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs
index f6acc60190a..842cc9fae9b 100644
--- a/compiler/rustc_incremental/src/persist/dirty_clean.rs
+++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs
@@ -57,8 +57,7 @@ const BASE_FN: &[&str] = &[
 
 /// DepNodes for Hir, which is pretty much everything
 const BASE_HIR: &[&str] = &[
-    // hir_owner and hir_owner_nodes should be computed for all nodes
-    label_strs::hir_owner,
+    // hir_owner_nodes should be computed for all nodes
     label_strs::hir_owner_nodes,
 ];
 
diff --git a/compiler/rustc_index_macros/src/lib.rs b/compiler/rustc_index_macros/src/lib.rs
index ac374a41eb6..72567b43a5f 100644
--- a/compiler/rustc_index_macros/src/lib.rs
+++ b/compiler/rustc_index_macros/src/lib.rs
@@ -31,11 +31,17 @@ mod newtype;
 /// - `#[max = 0xFFFF_FFFD]`: specifies the max value, which allows niche
 ///   optimizations. The default max value is 0xFFFF_FF00.
 /// - `#[gate_rustc_only]`: makes parts of the generated code nightly-only.
+///
+/// `SpecOptionPartialEq` is specialized by this macro, so using it requires enabling
+/// `#![feature(min_specialization)]` for the crate.
 #[proc_macro]
 #[cfg_attr(
     feature = "nightly",
     allow_internal_unstable(step_trait, rustc_attrs, trusted_step, spec_option_partial_eq)
 )]
+// FIXME: Remove the above comment about `min_specialization` once bootstrap is bumped,
+// and the corresponding one on SpecOptionPartialEq
+#[cfg_attr(all(feature = "nightly", not(bootstrap)), allow_internal_unstable(min_specialization))]
 pub fn newtype_index(input: TokenStream) -> TokenStream {
     newtype::newtype(input)
 }
diff --git a/compiler/rustc_index_macros/src/newtype.rs b/compiler/rustc_index_macros/src/newtype.rs
index df1318c835e..0b25628b9e1 100644
--- a/compiler/rustc_index_macros/src/newtype.rs
+++ b/compiler/rustc_index_macros/src/newtype.rs
@@ -104,7 +104,7 @@ impl Parse for Newtype {
                 #gate_rustc_only
                 impl<E: ::rustc_serialize::Encoder> ::rustc_serialize::Encodable<E> for #name {
                     fn encode(&self, e: &mut E) {
-                        e.emit_u32(self.private);
+                        e.emit_u32(self.as_u32());
                     }
                 }
             }
@@ -164,7 +164,7 @@ impl Parse for Newtype {
                         #[inline]
                         fn eq(l: &Option<Self>, r: &Option<Self>) -> bool {
                             if #max_val < u32::MAX {
-                                l.map(|i| i.private).unwrap_or(#max_val+1) == r.map(|i| i.private).unwrap_or(#max_val+1)
+                                l.map(|i| i.as_u32()).unwrap_or(#max_val+1) == r.map(|i| i.as_u32()).unwrap_or(#max_val+1)
                             } else {
                                 match (l, r) {
                                     (Some(l), Some(r)) => r == l,
@@ -188,7 +188,7 @@ impl Parse for Newtype {
             #[cfg_attr(#gate_rustc_only_cfg, rustc_layout_scalar_valid_range_end(#max))]
             #[cfg_attr(#gate_rustc_only_cfg, rustc_pass_by_value)]
             #vis struct #name {
-                private: u32,
+                private_use_as_methods_instead: u32,
             }
 
             #(#consts)*
@@ -238,7 +238,7 @@ impl Parse for Newtype {
                 /// Prefer using `from_u32`.
                 #[inline]
                 #vis const unsafe fn from_u32_unchecked(value: u32) -> Self {
-                    Self { private: value }
+                    Self { private_use_as_methods_instead: value }
                 }
 
                 /// Extracts the value of this index as a `usize`.
@@ -250,7 +250,7 @@ impl Parse for Newtype {
                 /// Extracts the value of this index as a `u32`.
                 #[inline]
                 #vis const fn as_u32(self) -> u32 {
-                    self.private
+                    self.private_use_as_methods_instead
                 }
 
                 /// Extracts the value of this index as a `usize`.
@@ -263,6 +263,7 @@ impl Parse for Newtype {
             impl std::ops::Add<usize> for #name {
                 type Output = Self;
 
+                #[inline]
                 fn add(self, other: usize) -> Self {
                     Self::from_usize(self.index() + other)
                 }
diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs
index e60e3ffeaa7..0f1af81d9f0 100644
--- a/compiler/rustc_infer/src/infer/at.rs
+++ b/compiler/rustc_infer/src/infer/at.rs
@@ -90,6 +90,7 @@ impl<'tcx> InferCtxt<'tcx> {
             universe: self.universe.clone(),
             intercrate,
             next_trait_solver: self.next_trait_solver,
+            obligation_inspector: self.obligation_inspector.clone(),
         }
     }
 }
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index 8cca4c6231f..1f071a9ff0b 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -483,7 +483,13 @@ impl<'tcx> InferCtxt<'tcx> {
         let result_subst = CanonicalVarValues {
             var_values: self.tcx.mk_args_from_iter(
                 query_response.variables.iter().enumerate().map(|(index, info)| {
-                    if info.is_existential() {
+                    if info.universe() != ty::UniverseIndex::ROOT {
+                        // A variable from inside a binder of the query. While ideally these shouldn't
+                        // exist at all, we have to deal with them for now.
+                        self.instantiate_canonical_var(cause.span, info, |u| {
+                            universe_map[u.as_usize()]
+                        })
+                    } else if info.is_existential() {
                         match opt_values[BoundVar::new(index)] {
                             Some(k) => k,
                             None => self.instantiate_canonical_var(cause.span, info, |u| {
@@ -491,9 +497,11 @@ impl<'tcx> InferCtxt<'tcx> {
                             }),
                         }
                     } else {
-                        self.instantiate_canonical_var(cause.span, info, |u| {
-                            universe_map[u.as_usize()]
-                        })
+                        // For placeholders which were already part of the input, we simply map this
+                        // universal bound variable back the placeholder of the input.
+                        opt_values[BoundVar::new(index)].expect(
+                            "expected placeholder to be unified with itself during response",
+                        )
                     }
                 }),
             ),
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 4aefadf590d..03c8e08aa01 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
@@ -13,7 +13,9 @@ use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{Body, Closure, Expr, ExprKind, FnRetTy, HirId, Local, LocalSource};
 use rustc_middle::hir::nested_filter;
-use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
+use rustc_middle::infer::unify_key::{
+    ConstVariableOrigin, ConstVariableOriginKind, ConstVariableValue,
+};
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
 use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer};
 use rustc_middle::ty::{self, InferConst};
@@ -41,8 +43,8 @@ pub enum TypeAnnotationNeeded {
     E0284,
 }
 
-impl Into<rustc_errors::DiagnosticId> for TypeAnnotationNeeded {
-    fn into(self) -> rustc_errors::DiagnosticId {
+impl Into<String> for TypeAnnotationNeeded {
+    fn into(self) -> String {
         match self {
             Self::E0282 => rustc_errors::error_code!(E0282),
             Self::E0283 => rustc_errors::error_code!(E0283),
@@ -178,17 +180,23 @@ fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinte
         }
     };
     printer.ty_infer_name_resolver = Some(Box::new(ty_getter));
-    let const_getter = move |ct_vid| {
-        if infcx.probe_const_var(ct_vid).is_ok() {
+    let const_getter = move |ct_vid| match infcx
+        .inner
+        .borrow_mut()
+        .const_unification_table()
+        .probe_value(ct_vid)
+    {
+        ConstVariableValue::Known { value: _ } => {
             warn!("resolved const var in error message");
-        }
-        if let ConstVariableOriginKind::ConstParameterDefinition(name, _) =
-            infcx.inner.borrow_mut().const_unification_table().probe_value(ct_vid).origin.kind
-        {
-            return Some(name);
-        } else {
             None
         }
+        ConstVariableValue::Unknown { origin, universe: _ } => {
+            if let ConstVariableOriginKind::ConstParameterDefinition(name, _) = origin.kind {
+                return Some(name);
+            } else {
+                None
+            }
+        }
     };
     printer.const_infer_name_resolver = Some(Box::new(const_getter));
     printer
@@ -303,7 +311,12 @@ impl<'tcx> InferCtxt<'tcx> {
             GenericArgKind::Const(ct) => {
                 if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.kind() {
                     let origin =
-                        self.inner.borrow_mut().const_unification_table().probe_value(vid).origin;
+                        match self.inner.borrow_mut().const_unification_table().probe_value(vid) {
+                            ConstVariableValue::Known { value } => {
+                                bug!("resolved infer var: {vid:?} {value}")
+                            }
+                            ConstVariableValue::Unknown { origin, universe: _ } => origin,
+                        };
                     if let ConstVariableOriginKind::ConstParameterDefinition(name, def_id) =
                         origin.kind
                     {
diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs
index c7cab048db1..d256994d8d1 100644
--- a/compiler/rustc_infer/src/infer/freshen.rs
+++ b/compiler/rustc_infer/src/infer/freshen.rs
@@ -146,14 +146,8 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for TypeFreshener<'a, 'tcx> {
     fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
         match ct.kind() {
             ty::ConstKind::Infer(ty::InferConst::Var(v)) => {
-                let opt_ct = self
-                    .infcx
-                    .inner
-                    .borrow_mut()
-                    .const_unification_table()
-                    .probe_value(v)
-                    .val
-                    .known();
+                let opt_ct =
+                    self.infcx.inner.borrow_mut().const_unification_table().probe_value(v).known();
                 self.freshen_const(opt_ct, ty::InferConst::Var(v), ty::InferConst::Fresh, ct.ty())
             }
             ty::ConstKind::Infer(ty::InferConst::EffectVar(v)) => {
diff --git a/compiler/rustc_infer/src/infer/fudge.rs b/compiler/rustc_infer/src/infer/fudge.rs
index 8ca97ae1b8e..99033922bdf 100644
--- a/compiler/rustc_infer/src/infer/fudge.rs
+++ b/compiler/rustc_infer/src/infer/fudge.rs
@@ -1,4 +1,4 @@
-use rustc_middle::infer::unify_key::ConstVidKey;
+use rustc_middle::infer::unify_key::{ConstVariableOriginKind, ConstVariableValue, ConstVidKey};
 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
 use rustc_middle::ty::{self, ConstVid, FloatVid, IntVid, RegionVid, Ty, TyCtxt, TyVid};
 
@@ -28,10 +28,17 @@ fn const_vars_since_snapshot<'tcx>(
     snapshot_var_len: usize,
 ) -> (Range<ConstVid>, Vec<ConstVariableOrigin>) {
     let range = vars_since_snapshot(table, snapshot_var_len);
+
     (
         range.start.vid..range.end.vid,
         (range.start.index()..range.end.index())
-            .map(|index| table.probe_value(ConstVid::from_u32(index)).origin)
+            .map(|index| match table.probe_value(ConstVid::from_u32(index)) {
+                ConstVariableValue::Known { value: _ } => ConstVariableOrigin {
+                    kind: ConstVariableOriginKind::MiscVariable,
+                    span: rustc_span::DUMMY_SP,
+                },
+                ConstVariableValue::Unknown { origin, universe: _ } => origin,
+            })
             .collect(),
     )
 }
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index e164041c599..1eab8575fc0 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -13,7 +13,9 @@ use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey};
 use self::opaque_types::OpaqueTypeStorage;
 pub(crate) use self::undo_log::{InferCtxtUndoLogs, Snapshot, UndoLog};
 
-use crate::traits::{self, ObligationCause, PredicateObligations, TraitEngine, TraitEngineExt};
+use crate::traits::{
+    self, ObligationCause, ObligationInspector, PredicateObligations, TraitEngine, TraitEngineExt,
+};
 
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -23,8 +25,8 @@ use rustc_data_structures::unify as ut;
 use rustc_errors::{DiagCtxt, DiagnosticBuilder, ErrorGuaranteed};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues};
-use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue, EffectVarValue};
 use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType};
+use rustc_middle::infer::unify_key::{ConstVariableValue, EffectVarValue};
 use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult};
 use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::traits::{select, DefiningAnchor};
@@ -334,6 +336,8 @@ pub struct InferCtxt<'tcx> {
     pub intercrate: bool,
 
     next_trait_solver: bool,
+
+    pub obligation_inspector: Cell<Option<ObligationInspector<'tcx>>>,
 }
 
 impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> {
@@ -708,6 +712,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
             universe: Cell::new(ty::UniverseIndex::ROOT),
             intercrate,
             next_trait_solver,
+            obligation_inspector: Cell::new(None),
         }
     }
 }
@@ -1086,7 +1091,7 @@ impl<'tcx> InferCtxt<'tcx> {
             .inner
             .borrow_mut()
             .const_unification_table()
-            .new_key(ConstVarValue { origin, val: ConstVariableValue::Unknown { universe } })
+            .new_key(ConstVariableValue::Unknown { origin, universe })
             .vid;
         ty::Const::new_var(self.tcx, vid, ty)
     }
@@ -1095,10 +1100,7 @@ impl<'tcx> InferCtxt<'tcx> {
         self.inner
             .borrow_mut()
             .const_unification_table()
-            .new_key(ConstVarValue {
-                origin,
-                val: ConstVariableValue::Unknown { universe: self.universe() },
-            })
+            .new_key(ConstVariableValue::Unknown { origin, universe: self.universe() })
             .vid
     }
 
@@ -1217,10 +1219,7 @@ impl<'tcx> InferCtxt<'tcx> {
                     .inner
                     .borrow_mut()
                     .const_unification_table()
-                    .new_key(ConstVarValue {
-                        origin,
-                        val: ConstVariableValue::Unknown { universe: self.universe() },
-                    })
+                    .new_key(ConstVariableValue::Unknown { origin, universe: self.universe() })
                     .vid;
                 ty::Const::new_var(
                     self.tcx,
@@ -1410,9 +1409,9 @@ impl<'tcx> InferCtxt<'tcx> {
     }
 
     pub fn probe_const_var(&self, vid: ty::ConstVid) -> Result<ty::Const<'tcx>, ty::UniverseIndex> {
-        match self.inner.borrow_mut().const_unification_table().probe_value(vid).val {
+        match self.inner.borrow_mut().const_unification_table().probe_value(vid) {
             ConstVariableValue::Known { value } => Ok(value),
-            ConstVariableValue::Unknown { universe } => Err(universe),
+            ConstVariableValue::Unknown { origin: _, universe } => Err(universe),
         }
     }
 
@@ -1709,7 +1708,7 @@ impl<'tcx> InferCtxt<'tcx> {
                 // `ty::ConstKind::Infer(ty::InferConst::Var(v))`.
                 //
                 // Not `inlined_probe_value(v)` because this call site is colder.
-                match self.inner.borrow_mut().const_unification_table().probe_value(v).val {
+                match self.inner.borrow_mut().const_unification_table().probe_value(v) {
                     ConstVariableValue::Unknown { .. } => false,
                     ConstVariableValue::Known { .. } => true,
                 }
@@ -1724,6 +1723,15 @@ impl<'tcx> InferCtxt<'tcx> {
             }
         }
     }
+
+    /// Attach a callback to be invoked on each root obligation evaluated in the new trait solver.
+    pub fn attach_obligation_inspector(&self, inspector: ObligationInspector<'tcx>) {
+        debug_assert!(
+            self.obligation_inspector.get().is_none(),
+            "shouldn't override a set obligation inspector"
+        );
+        self.obligation_inspector.set(Some(inspector));
+    }
 }
 
 impl<'tcx> TypeErrCtxt<'_, 'tcx> {
@@ -1876,7 +1884,6 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ShallowResolver<'a, 'tcx> {
                 .borrow_mut()
                 .const_unification_table()
                 .probe_value(vid)
-                .val
                 .known()
                 .unwrap_or(ct),
             ty::ConstKind::Infer(InferConst::EffectVar(vid)) => self
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index 11b5b437eff..db46b39ce25 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -631,13 +631,6 @@ impl<'tcx> InferCtxt<'tcx> {
                 ct_op: |ct| ct,
             });
 
-            if let ty::ClauseKind::Projection(projection) = predicate.kind().skip_binder() {
-                if projection.term.references_error() {
-                    // No point on adding any obligations since there's a type error involved.
-                    obligations.clear();
-                    return;
-                }
-            }
             // Require that the predicate holds for the concrete type.
             debug!(?predicate);
             obligations.push(traits::Obligation::new(
diff --git a/compiler/rustc_infer/src/infer/relate/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs
index 4b254fc7df5..9e1dab12b4d 100644
--- a/compiler/rustc_infer/src/infer/relate/combine.rs
+++ b/compiler/rustc_infer/src/infer/relate/combine.rs
@@ -30,14 +30,12 @@ use super::sub::Sub;
 use crate::infer::{DefineOpaqueTypes, InferCtxt, TypeTrace};
 use crate::traits::{Obligation, PredicateObligations};
 use rustc_middle::infer::canonical::OriginalQueryValues;
-use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue, EffectVarValue};
-use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
+use rustc_middle::infer::unify_key::{ConstVariableValue, EffectVarValue};
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::relate::{RelateResult, TypeRelation};
 use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeVisitableExt};
 use rustc_middle::ty::{AliasRelationDirection, TyVar};
 use rustc_middle::ty::{IntType, UintType};
-use rustc_span::DUMMY_SP;
 
 #[derive(Clone)]
 pub struct CombineFields<'infcx, 'tcx> {
@@ -328,8 +326,12 @@ impl<'tcx> InferCtxt<'tcx> {
         ct: ty::Const<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
     ) -> RelateResult<'tcx, ty::Const<'tcx>> {
-        let span =
-            self.inner.borrow_mut().const_unification_table().probe_value(target_vid).origin.span;
+        let span = match self.inner.borrow_mut().const_unification_table().probe_value(target_vid) {
+            ConstVariableValue::Known { value } => {
+                bug!("instantiating a known const var: {target_vid:?} {value} {ct}")
+            }
+            ConstVariableValue::Unknown { origin, universe: _ } => origin.span,
+        };
         // FIXME(generic_const_exprs): Occurs check failures for unevaluated
         // constants and generic expressions are not yet handled correctly.
         let Generalization { value_may_be_infer: value, needs_wf: _ } = generalize::generalize(
@@ -340,16 +342,10 @@ impl<'tcx> InferCtxt<'tcx> {
             ty::Variance::Invariant,
         )?;
 
-        self.inner.borrow_mut().const_unification_table().union_value(
-            target_vid,
-            ConstVarValue {
-                origin: ConstVariableOrigin {
-                    kind: ConstVariableOriginKind::ConstInference,
-                    span: DUMMY_SP,
-                },
-                val: ConstVariableValue::Known { value },
-            },
-        );
+        self.inner
+            .borrow_mut()
+            .const_unification_table()
+            .union_value(target_vid, ConstVariableValue::Known { value });
         Ok(value)
     }
 
diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs
index 27d37fd9369..417c8695e24 100644
--- a/compiler/rustc_infer/src/infer/relate/generalize.rs
+++ b/compiler/rustc_infer/src/infer/relate/generalize.rs
@@ -3,7 +3,7 @@ use std::mem;
 use rustc_data_structures::sso::SsoHashMap;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir::def_id::DefId;
-use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
+use rustc_middle::infer::unify_key::ConstVariableValue;
 use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
 use rustc_middle::ty::visit::MaxUniverse;
@@ -431,22 +431,19 @@ where
 
                 let mut inner = self.infcx.inner.borrow_mut();
                 let variable_table = &mut inner.const_unification_table();
-                let var_value = variable_table.probe_value(vid);
-                match var_value.val {
+                match variable_table.probe_value(vid) {
                     ConstVariableValue::Known { value: u } => {
                         drop(inner);
                         self.relate(u, u)
                     }
-                    ConstVariableValue::Unknown { universe } => {
+                    ConstVariableValue::Unknown { origin, universe } => {
                         if self.for_universe.can_name(universe) {
                             Ok(c)
                         } else {
                             let new_var_id = variable_table
-                                .new_key(ConstVarValue {
-                                    origin: var_value.origin,
-                                    val: ConstVariableValue::Unknown {
-                                        universe: self.for_universe,
-                                    },
+                                .new_key(ConstVariableValue::Unknown {
+                                    origin,
+                                    universe: self.for_universe,
                                 })
                                 .vid;
                             Ok(ty::Const::new_var(self.tcx(), new_var_id, c.ty()))
diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs
index f317ccee691..959b0903127 100644
--- a/compiler/rustc_infer/src/infer/resolve.rs
+++ b/compiler/rustc_infer/src/infer/resolve.rs
@@ -1,12 +1,8 @@
-use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use super::{FixupError, FixupResult, InferCtxt, Span};
-use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
+use super::{FixupError, FixupResult, InferCtxt};
 use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFolder, TypeSuperFoldable};
-use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitableExt, TypeVisitor};
+use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{self, Const, InferConst, Ty, TyCtxt, TypeFoldable};
 
-use std::ops::ControlFlow;
-
 ///////////////////////////////////////////////////////////////////////////
 // OPPORTUNISTIC VAR RESOLVER
 
@@ -105,88 +101,6 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for OpportunisticRegionResolver<'a, 'tcx
 }
 
 ///////////////////////////////////////////////////////////////////////////
-// UNRESOLVED TYPE FINDER
-
-/// The unresolved type **finder** walks a type searching for
-/// type variables that don't yet have a value. The first unresolved type is stored.
-/// It does not construct the fully resolved type (which might
-/// involve some hashing and so forth).
-pub struct UnresolvedTypeOrConstFinder<'a, 'tcx> {
-    infcx: &'a InferCtxt<'tcx>,
-}
-
-impl<'a, 'tcx> UnresolvedTypeOrConstFinder<'a, 'tcx> {
-    pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self {
-        UnresolvedTypeOrConstFinder { infcx }
-    }
-}
-
-impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for UnresolvedTypeOrConstFinder<'a, 'tcx> {
-    type BreakTy = (ty::Term<'tcx>, Option<Span>);
-    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
-        let t = self.infcx.shallow_resolve(t);
-        if let ty::Infer(infer_ty) = *t.kind() {
-            // Since we called `shallow_resolve` above, this must
-            // be an (as yet...) unresolved inference variable.
-            let ty_var_span = if let ty::TyVar(ty_vid) = infer_ty {
-                let mut inner = self.infcx.inner.borrow_mut();
-                let ty_vars = &inner.type_variables();
-                if let TypeVariableOrigin {
-                    kind: TypeVariableOriginKind::TypeParameterDefinition(_, _),
-                    span,
-                } = ty_vars.var_origin(ty_vid)
-                {
-                    Some(span)
-                } else {
-                    None
-                }
-            } else {
-                None
-            };
-            ControlFlow::Break((t.into(), ty_var_span))
-        } else if !t.has_non_region_infer() {
-            // All const/type variables in inference types must already be resolved,
-            // no need to visit the contents.
-            ControlFlow::Continue(())
-        } else {
-            // Otherwise, keep visiting.
-            t.super_visit_with(self)
-        }
-    }
-
-    fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
-        let ct = self.infcx.shallow_resolve(ct);
-        if let ty::ConstKind::Infer(i) = ct.kind() {
-            // Since we called `shallow_resolve` above, this must
-            // be an (as yet...) unresolved inference variable.
-            let ct_var_span = if let ty::InferConst::Var(vid) = i {
-                let mut inner = self.infcx.inner.borrow_mut();
-                let ct_vars = &mut inner.const_unification_table();
-                if let ConstVariableOrigin {
-                    span,
-                    kind: ConstVariableOriginKind::ConstParameterDefinition(_, _),
-                } = ct_vars.probe_value(vid).origin
-                {
-                    Some(span)
-                } else {
-                    None
-                }
-            } else {
-                None
-            };
-            ControlFlow::Break((ct.into(), ct_var_span))
-        } else if !ct.has_non_region_infer() {
-            // All const/type variables in inference types must already be resolved,
-            // no need to visit the contents.
-            ControlFlow::Continue(())
-        } else {
-            // Otherwise, keep visiting.
-            ct.super_visit_with(self)
-        }
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////
 // FULL TYPE RESOLUTION
 
 /// Full type resolution replaces all type and region variables with
diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs
index b9be178916c..72ec07375ac 100644
--- a/compiler/rustc_infer/src/traits/mod.rs
+++ b/compiler/rustc_infer/src/traits/mod.rs
@@ -13,13 +13,15 @@ use std::hash::{Hash, Hasher};
 
 use hir::def_id::LocalDefId;
 use rustc_hir as hir;
+use rustc_middle::traits::query::NoSolution;
+use rustc_middle::traits::solve::Certainty;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::{self, Const, ToPredicate, Ty, TyCtxt};
 use rustc_span::Span;
 
-pub use self::FulfillmentErrorCode::*;
 pub use self::ImplSource::*;
 pub use self::SelectionError::*;
+use crate::infer::InferCtxt;
 
 pub use self::engine::{TraitEngine, TraitEngineExt};
 pub use self::project::MismatchedProjectionTypes;
@@ -117,6 +119,11 @@ pub type PredicateObligations<'tcx> = Vec<PredicateObligation<'tcx>>;
 
 pub type Selection<'tcx> = ImplSource<'tcx, PredicateObligation<'tcx>>;
 
+/// A callback that can be provided to `inspect_typeck`. Invoked on evaluation
+/// of root obligations.
+pub type ObligationInspector<'tcx> =
+    fn(&InferCtxt<'tcx>, &PredicateObligation<'tcx>, Result<Certainty, NoSolution>);
+
 pub struct FulfillmentError<'tcx> {
     pub obligation: PredicateObligation<'tcx>,
     pub code: FulfillmentErrorCode<'tcx>,
@@ -129,12 +136,12 @@ pub struct FulfillmentError<'tcx> {
 #[derive(Clone)]
 pub enum FulfillmentErrorCode<'tcx> {
     /// Inherently impossible to fulfill; this trait is implemented if and only if it is already implemented.
-    CodeCycle(Vec<PredicateObligation<'tcx>>),
-    CodeSelectionError(SelectionError<'tcx>),
-    CodeProjectionError(MismatchedProjectionTypes<'tcx>),
-    CodeSubtypeError(ExpectedFound<Ty<'tcx>>, TypeError<'tcx>), // always comes from a SubtypePredicate
-    CodeConstEquateError(ExpectedFound<Const<'tcx>>, TypeError<'tcx>),
-    CodeAmbiguity {
+    Cycle(Vec<PredicateObligation<'tcx>>),
+    SelectionError(SelectionError<'tcx>),
+    ProjectionError(MismatchedProjectionTypes<'tcx>),
+    SubtypeError(ExpectedFound<Ty<'tcx>>, TypeError<'tcx>), // always comes from a SubtypePredicate
+    ConstEquateError(ExpectedFound<Const<'tcx>>, TypeError<'tcx>),
+    Ambiguity {
         /// Overflow reported from the new solver `-Znext-solver`, which will
         /// be reported as an regular error as opposed to a fatal error.
         overflow: bool,
diff --git a/compiler/rustc_infer/src/traits/structural_impls.rs b/compiler/rustc_infer/src/traits/structural_impls.rs
index 51c06c8970b..3b4050fcd27 100644
--- a/compiler/rustc_infer/src/traits/structural_impls.rs
+++ b/compiler/rustc_infer/src/traits/structural_impls.rs
@@ -37,18 +37,19 @@ impl<'tcx> fmt::Debug for traits::FulfillmentError<'tcx> {
 
 impl<'tcx> fmt::Debug for traits::FulfillmentErrorCode<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use traits::FulfillmentErrorCode::*;
         match *self {
-            super::CodeSelectionError(ref e) => write!(f, "{e:?}"),
-            super::CodeProjectionError(ref e) => write!(f, "{e:?}"),
-            super::CodeSubtypeError(ref a, ref b) => {
+            SelectionError(ref e) => write!(f, "{e:?}"),
+            ProjectionError(ref e) => write!(f, "{e:?}"),
+            SubtypeError(ref a, ref b) => {
                 write!(f, "CodeSubtypeError({a:?}, {b:?})")
             }
-            super::CodeConstEquateError(ref a, ref b) => {
+            ConstEquateError(ref a, ref b) => {
                 write!(f, "CodeConstEquateError({a:?}, {b:?})")
             }
-            super::CodeAmbiguity { overflow: false } => write!(f, "Ambiguity"),
-            super::CodeAmbiguity { overflow: true } => write!(f, "Overflow"),
-            super::CodeCycle(ref cycle) => write!(f, "Cycle({cycle:?})"),
+            Ambiguity { overflow: false } => write!(f, "Ambiguity"),
+            Ambiguity { overflow: true } => write!(f, "Overflow"),
+            Cycle(ref cycle) => write!(f, "Cycle({cycle:?})"),
         }
     }
 }
diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml
index 319e8175809..a238eacda44 100644
--- a/compiler/rustc_interface/Cargo.toml
+++ b/compiler/rustc_interface/Cargo.toml
@@ -5,7 +5,7 @@ edition = "2021"
 
 [dependencies]
 # tidy-alphabetical-start
-libloading = "0.7.1"
+libloading = "0.8.0"
 rustc-rayon = { version = "0.5.0", optional = true }
 rustc-rayon-core = { version = "0.5.0", optional = true }
 rustc_ast = { path = "../rustc_ast" }
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index 32fba6ade88..5ca88090996 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -218,7 +218,9 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec<String>) -> CheckCfg {
             }
         }
 
-        if values.is_empty() && !values_any_specified && !any_specified {
+        if !values_specified && !any_specified {
+            // `cfg(name)` is equivalent to `cfg(name, values(none()))` so add
+            // an implicit `none()`
             values.insert(None);
         } else if !values.is_empty() && values_any_specified {
             error!(
diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs
index cfa46447845..764306ce6ec 100644
--- a/compiler/rustc_interface/src/lib.rs
+++ b/compiler/rustc_interface/src/lib.rs
@@ -1,9 +1,10 @@
 #![feature(box_patterns)]
 #![feature(decl_macro)]
+#![feature(error_iter)]
 #![feature(internal_output_capture)]
-#![feature(thread_spawn_unchecked)]
 #![feature(lazy_cell)]
 #![feature(let_chains)]
+#![feature(thread_spawn_unchecked)]
 #![feature(try_blocks)]
 #![recursion_limit = "256"]
 #![deny(rustc::untranslatable_diagnostic)]
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 588139a303c..555c822ad6d 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -4,10 +4,10 @@ use rustc_data_structures::profiling::TimePassesFormat;
 use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig};
 use rustc_session::config::{
     build_configuration, build_session_options, rustc_optgroups, BranchProtection, CFGuard, Cfg,
-    DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation, Externs,
-    FunctionReturn, InliningThreshold, Input, InstrumentCoverage, InstrumentXRay,
-    LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli, NextSolverConfig, OomStrategy,
-    Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, Passes, Polonius,
+    CollapseMacroDebuginfo, DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry,
+    ExternLocation, Externs, FunctionReturn, InliningThreshold, Input, InstrumentCoverage,
+    InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli, NextSolverConfig,
+    OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, Passes, Polonius,
     ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion, WasiExecModel,
 };
 use rustc_session::lint::Level;
@@ -742,6 +742,7 @@ fn test_unstable_options_tracking_hash() {
         })
     );
     tracked!(codegen_backend, Some("abc".to_string()));
+    tracked!(collapse_macro_debuginfo, CollapseMacroDebuginfo::Yes);
     tracked!(crate_attr, vec!["abc".to_string()]);
     tracked!(cross_crate_inline_threshold, InliningThreshold::Always);
     tracked!(debug_info_for_profiling, true);
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index 9fd44e46b31..76b9e8de75f 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -162,15 +162,21 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
 }
 
 fn load_backend_from_dylib(early_dcx: &EarlyDiagCtxt, path: &Path) -> MakeBackendFn {
+    fn format_err(e: &(dyn std::error::Error + 'static)) -> String {
+        e.sources().map(|e| format!(": {e}")).collect()
+    }
     let lib = unsafe { Library::new(path) }.unwrap_or_else(|err| {
-        let err = format!("couldn't load codegen backend {path:?}: {err}");
+        let err = format!("couldn't load codegen backend {path:?}{}", format_err(&err));
         early_dcx.early_fatal(err);
     });
 
     let backend_sym = unsafe { lib.get::<MakeBackendFn>(b"__rustc_codegen_backend") }
         .unwrap_or_else(|e| {
-            let err = format!("couldn't load codegen backend: {e}");
-            early_dcx.early_fatal(err);
+            let e = format!(
+                "`__rustc_codegen_backend` symbol lookup in the codegen backend failed{}",
+                format_err(&e)
+            );
+            early_dcx.early_fatal(e);
         });
 
     // Intentionally leak the dynamic library. We can't ever unload it
diff --git a/compiler/rustc_lexer/src/unescape.rs b/compiler/rustc_lexer/src/unescape.rs
index abec12f52a6..0a632c4d12a 100644
--- a/compiler/rustc_lexer/src/unescape.rs
+++ b/compiler/rustc_lexer/src/unescape.rs
@@ -59,6 +59,9 @@ pub enum EscapeError {
     /// Non-ascii character in byte literal, byte string literal, or raw byte string literal.
     NonAsciiCharInByte,
 
+    // `\0` in a C string literal.
+    NulInCStr,
+
     /// After a line ending with '\', the next line contains whitespace
     /// characters that are not skipped.
     UnskippedWhitespaceWarning,
@@ -122,10 +125,20 @@ where
 {
     match mode {
         CStr => {
-            unescape_non_raw_common(src, mode, callback);
+            unescape_non_raw_common(src, mode, &mut |r, mut result| {
+                if let Ok(CStrUnit::Byte(0) | CStrUnit::Char('\0')) = result {
+                    result = Err(EscapeError::NulInCStr);
+                }
+                callback(r, result)
+            });
         }
         RawCStr => {
-            check_raw_common(src, mode, &mut |r, result| callback(r, result.map(CStrUnit::Char)));
+            check_raw_common(src, mode, &mut |r, mut result| {
+                if let Ok('\0') = result {
+                    result = Err(EscapeError::NulInCStr);
+                }
+                callback(r, result.map(CStrUnit::Char))
+            });
         }
         Char | Byte | Str | RawStr | ByteStr | RawByteStr => unreachable!(),
     }
diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs
index 9e6a6f70eac..312874db3f5 100644
--- a/compiler/rustc_lint/src/context/diagnostics.rs
+++ b/compiler/rustc_lint/src/context/diagnostics.rs
@@ -354,6 +354,15 @@ pub(super) fn builtin(
                         Applicability::MaybeIncorrect,
                     );
                 }
+            } else {
+                db.note(format!("no expected values for `{name}`"));
+
+                let sp = if let Some((_value, value_span)) = value {
+                    name_span.to(value_span)
+                } else {
+                    name_span
+                };
+                db.span_suggestion(sp, "remove the condition", "", Applicability::MaybeIncorrect);
             }
 
             // We don't want to suggest adding values to well known names
@@ -373,6 +382,8 @@ pub(super) fn builtin(
                 if name == sym::feature {
                     if let Some((value, _value_span)) = value {
                         db.help(format!("consider adding `{value}` as a feature in `Cargo.toml`"));
+                    } else {
+                        db.help("consider defining some features in `Cargo.toml`");
                     }
                 } else if !is_cfg_a_well_know_name {
                     db.help(format!("consider using a Cargo feature instead or adding `println!(\"cargo:rustc-check-cfg={inst}\");` to the top of a `build.rs`"));
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 0f4528d1d5c..39decf1faab 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -1166,7 +1166,7 @@ impl EarlyLintPass for UnusedParens {
             // Do not lint on `(..)` as that will result in the other arms being useless.
             Paren(_)
             // The other cases do not contain sub-patterns.
-            | Wild | Never | Rest | Lit(..) | MacCall(..) | Range(..) | Ident(.., None) | Path(..) => {},
+            | Wild | Never | Rest | Lit(..) | MacCall(..) | Range(..) | Ident(.., None) | Path(..) | Err(_) => {},
             // These are list-like patterns; parens can always be removed.
             TupleStruct(_, _, ps) | Tuple(ps) | Slice(ps) | Or(ps) => for p in ps {
                 self.check_unused_parens_pat(cx, p, false, false, keep_space);
diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
index fb908fe2db1..0b7ecff8148 100644
--- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
+++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
@@ -211,7 +211,7 @@ impl DiagnosticDeriveVariantBuilder {
 
                     let code = nested.parse::<syn::LitStr>()?;
                     tokens.extend(quote! {
-                        diag.code(rustc_errors::DiagnosticId::Error(#code.to_string()));
+                        diag.code(#code.to_string());
                     });
                 } else {
                     span_err(path.span().unwrap(), "unknown argument")
diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml
index 08cc8173eb0..79d3482472a 100644
--- a/compiler/rustc_metadata/Cargo.toml
+++ b/compiler/rustc_metadata/Cargo.toml
@@ -6,7 +6,7 @@ edition = "2021"
 [dependencies]
 # tidy-alphabetical-start
 bitflags = "2.4.1"
-libloading = "0.7.1"
+libloading = "0.8.0"
 odht = { version = "0.3.1", features = ["nightly"] }
 rustc_ast = { path = "../rustc_ast" }
 rustc_attr = { path = "../rustc_attr" }
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 49e849964be..20e3ae3ba94 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -1027,6 +1027,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             self.root.edition,
             Symbol::intern(name),
             &attrs,
+            false,
         )
     }
 
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 912c2f36eb3..c3d6c21c402 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -283,7 +283,7 @@ provide! { tcx, def_id, other, cdata,
         tcx.arena.alloc_from_iter(cdata.get_associated_item_or_field_def_ids(def_id.index))
     }
     associated_item => { cdata.get_associated_item(def_id.index, tcx.sess) }
-    inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) }
+    inherent_impls => { Ok(cdata.get_inherent_implementations_for_type(tcx, def_id.index)) }
     item_attrs => { tcx.arena.alloc_from_iter(cdata.get_item_attrs(def_id.index, tcx.sess)) }
     is_mir_available => { cdata.is_item_mir_available(def_id.index) }
     is_ctfe_mir_available => { cdata.is_ctfe_mir_available(def_id.index) }
@@ -328,7 +328,7 @@ provide! { tcx, def_id, other, cdata,
     traits => { tcx.arena.alloc_from_iter(cdata.get_traits()) }
     trait_impls_in_crate => { tcx.arena.alloc_from_iter(cdata.get_trait_impls()) }
     implementations_of_trait => { cdata.get_implementations_of_trait(tcx, other) }
-    crate_incoherent_impls => { cdata.get_incoherent_impls(tcx, other) }
+    crate_incoherent_impls => { Ok(cdata.get_incoherent_impls(tcx, other)) }
 
     dep_kind => { cdata.dep_kind }
     module_children => {
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index a458b528a97..2d4e49e27d9 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1485,7 +1485,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         }
 
         let inherent_impls = tcx.with_stable_hashing_context(|hcx| {
-            tcx.crate_inherent_impls(()).inherent_impls.to_sorted(&hcx, true)
+            tcx.crate_inherent_impls(()).unwrap().inherent_impls.to_sorted(&hcx, true)
         });
         for (def_id, impls) in inherent_impls {
             record_defaulted_array!(self.tables.inherent_impls[def_id.to_def_id()] <- impls.iter().map(|def_id| {
@@ -2028,7 +2028,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         empty_proc_macro!(self);
         let tcx = self.tcx;
         let all_impls = tcx.with_stable_hashing_context(|hcx| {
-            tcx.crate_inherent_impls(()).incoherent_impls.to_sorted(&hcx, true)
+            tcx.crate_inherent_impls(()).unwrap().incoherent_impls.to_sorted(&hcx, true)
         });
 
         let all_impls: Vec<_> = all_impls
diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml
index 8e6ca645f80..82e56c9cbe2 100644
--- a/compiler/rustc_middle/Cargo.toml
+++ b/compiler/rustc_middle/Cargo.toml
@@ -10,7 +10,7 @@ derive_more = "0.99.17"
 either = "1.5.0"
 field-offset = "0.3.5"
 gsgdt = "0.1.2"
-measureme = "10.0.0"
+measureme = "11"
 polonius-engine = "0.13.0"
 rustc-rayon = { version = "0.5.0", optional = true }
 rustc-rayon-core = { version = "0.5.0", optional = true }
diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs
index 8a4fd01437f..e745913fabc 100644
--- a/compiler/rustc_middle/src/arena.rs
+++ b/compiler/rustc_middle/src/arena.rs
@@ -114,6 +114,7 @@ macro_rules! arena_types {
             [] mod_child: rustc_middle::metadata::ModChild,
             [] features: rustc_feature::Features,
             [decode] specialization_graph: rustc_middle::traits::specialization_graph::Graph,
+            [] crate_inherent_impls: rustc_middle::ty::CrateInherentImpls,
         ]);
     )
 }
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 1574f0f1b31..949b786e3a7 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -1,4 +1,4 @@
-use crate::hir::{ModuleItems, Owner};
+use crate::hir::ModuleItems;
 use crate::middle::debugger_visualizer::DebuggerVisualizerFile;
 use crate::query::LocalCrate;
 use crate::ty::TyCtxt;
@@ -108,7 +108,7 @@ impl<'hir> Iterator for ParentOwnerIterator<'hir> {
         if self.current_id.local_id.index() != 0 {
             self.current_id.local_id = ItemLocalId::new(0);
             if let Some(node) = self.map.tcx.hir_owner(self.current_id.owner) {
-                return Some((self.current_id.owner, node.node));
+                return Some((self.current_id.owner, node));
             }
         }
         if self.current_id == CRATE_HIR_ID {
@@ -126,23 +126,23 @@ impl<'hir> Iterator for ParentOwnerIterator<'hir> {
 
             // If this `HirId` doesn't have an entry, skip it and look for its `parent_id`.
             if let Some(node) = self.map.tcx.hir_owner(self.current_id.owner) {
-                return Some((self.current_id.owner, node.node));
+                return Some((self.current_id.owner, node));
             }
         }
     }
 }
 
 impl<'tcx> TyCtxt<'tcx> {
+    #[inline]
+    fn hir_owner(self, owner: OwnerId) -> Option<OwnerNode<'tcx>> {
+        Some(self.hir_owner_nodes(owner).as_owner()?.node())
+    }
+
     /// Retrieves the `hir::Node` corresponding to `id`, returning `None` if cannot be found.
     pub fn opt_hir_node(self, id: HirId) -> Option<Node<'tcx>> {
-        if id.local_id == ItemLocalId::from_u32(0) {
-            let owner = self.hir_owner(id.owner)?;
-            Some(owner.node.into())
-        } else {
-            let owner = self.hir_owner_nodes(id.owner).as_owner()?;
-            let node = owner.nodes[id.local_id].as_ref()?;
-            Some(node.node)
-        }
+        let owner = self.hir_owner_nodes(id.owner).as_owner()?;
+        let node = owner.nodes[id.local_id].as_ref()?;
+        Some(node.node)
     }
 
     /// Retrieves the `hir::Node` corresponding to `id`, returning `None` if cannot be found.
@@ -174,7 +174,7 @@ impl<'hir> Map<'hir> {
 
     #[inline]
     pub fn root_module(self) -> &'hir Mod<'hir> {
-        match self.tcx.hir_owner(CRATE_OWNER_ID).map(|o| o.node) {
+        match self.tcx.hir_owner(CRATE_OWNER_ID) {
             Some(OwnerNode::Crate(item)) => item,
             _ => bug!(),
         }
@@ -242,27 +242,27 @@ impl<'hir> Map<'hir> {
 
     pub fn get_generics(self, id: LocalDefId) -> Option<&'hir Generics<'hir>> {
         let node = self.tcx.hir_owner(OwnerId { def_id: id })?;
-        node.node.generics()
+        node.generics()
     }
 
     pub fn owner(self, id: OwnerId) -> OwnerNode<'hir> {
-        self.tcx.hir_owner(id).unwrap_or_else(|| bug!("expected owner for {:?}", id)).node
+        self.tcx.hir_owner(id).unwrap_or_else(|| bug!("expected owner for {:?}", id))
     }
 
     pub fn item(self, id: ItemId) -> &'hir Item<'hir> {
-        self.tcx.hir_owner(id.owner_id).unwrap().node.expect_item()
+        self.tcx.hir_owner(id.owner_id).unwrap().expect_item()
     }
 
     pub fn trait_item(self, id: TraitItemId) -> &'hir TraitItem<'hir> {
-        self.tcx.hir_owner(id.owner_id).unwrap().node.expect_trait_item()
+        self.tcx.hir_owner(id.owner_id).unwrap().expect_trait_item()
     }
 
     pub fn impl_item(self, id: ImplItemId) -> &'hir ImplItem<'hir> {
-        self.tcx.hir_owner(id.owner_id).unwrap().node.expect_impl_item()
+        self.tcx.hir_owner(id.owner_id).unwrap().expect_impl_item()
     }
 
     pub fn foreign_item(self, id: ForeignItemId) -> &'hir ForeignItem<'hir> {
-        self.tcx.hir_owner(id.owner_id).unwrap().node.expect_foreign_item()
+        self.tcx.hir_owner(id.owner_id).unwrap().expect_foreign_item()
     }
 
     pub fn body(self, id: BodyId) -> &'hir Body<'hir> {
@@ -436,7 +436,7 @@ impl<'hir> Map<'hir> {
 
     pub fn get_module(self, module: LocalModDefId) -> (&'hir Mod<'hir>, Span, HirId) {
         let hir_id = HirId::make_owner(module.to_local_def_id());
-        match self.tcx.hir_owner(hir_id.owner).map(|o| o.node) {
+        match self.tcx.hir_owner(hir_id.owner) {
             Some(OwnerNode::Item(&Item { span, kind: ItemKind::Mod(m), .. })) => (m, span, hir_id),
             Some(OwnerNode::Crate(item)) => (item, item.spans.inner_span, hir_id),
             node => panic!("not a module: {node:?}"),
@@ -726,11 +726,10 @@ impl<'hir> Map<'hir> {
 
     pub fn get_foreign_abi(self, hir_id: HirId) -> Abi {
         let parent = self.get_parent_item(hir_id);
-        if let Some(node) = self.tcx.hir_owner(parent) {
-            if let OwnerNode::Item(Item { kind: ItemKind::ForeignMod { abi, .. }, .. }) = node.node
-            {
-                return *abi;
-            }
+        if let Some(node) = self.tcx.hir_owner(parent)
+            && let OwnerNode::Item(Item { kind: ItemKind::ForeignMod { abi, .. }, .. }) = node
+        {
+            return *abi;
         }
         bug!(
             "expected foreign mod or inlined parent, found {}",
@@ -742,33 +741,32 @@ impl<'hir> Map<'hir> {
         self.tcx
             .hir_owner(OwnerId { def_id })
             .unwrap_or_else(|| bug!("expected owner for {:?}", def_id))
-            .node
     }
 
     pub fn expect_item(self, id: LocalDefId) -> &'hir Item<'hir> {
         match self.tcx.hir_owner(OwnerId { def_id: id }) {
-            Some(Owner { node: OwnerNode::Item(item), .. }) => item,
+            Some(OwnerNode::Item(item)) => item,
             _ => bug!("expected item, found {}", self.node_to_string(HirId::make_owner(id))),
         }
     }
 
     pub fn expect_impl_item(self, id: LocalDefId) -> &'hir ImplItem<'hir> {
         match self.tcx.hir_owner(OwnerId { def_id: id }) {
-            Some(Owner { node: OwnerNode::ImplItem(item), .. }) => item,
+            Some(OwnerNode::ImplItem(item)) => item,
             _ => bug!("expected impl item, found {}", self.node_to_string(HirId::make_owner(id))),
         }
     }
 
     pub fn expect_trait_item(self, id: LocalDefId) -> &'hir TraitItem<'hir> {
         match self.tcx.hir_owner(OwnerId { def_id: id }) {
-            Some(Owner { node: OwnerNode::TraitItem(item), .. }) => item,
+            Some(OwnerNode::TraitItem(item)) => item,
             _ => bug!("expected trait item, found {}", self.node_to_string(HirId::make_owner(id))),
         }
     }
 
     pub fn get_fn_output(self, def_id: LocalDefId) -> Option<&'hir FnRetTy<'hir>> {
         match self.tcx.hir_owner(OwnerId { def_id }) {
-            Some(Owner { node, .. }) => node.fn_decl().map(|fn_decl| &fn_decl.output),
+            Some(node) => node.fn_decl().map(|fn_decl| &fn_decl.output),
             _ => None,
         }
     }
@@ -782,7 +780,7 @@ impl<'hir> Map<'hir> {
 
     pub fn expect_foreign_item(self, id: OwnerId) -> &'hir ForeignItem<'hir> {
         match self.tcx.hir_owner(id) {
-            Some(Owner { node: OwnerNode::ForeignItem(item), .. }) => item,
+            Some(OwnerNode::ForeignItem(item)) => item,
             _ => {
                 bug!(
                     "expected foreign item, found {}",
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index af99c7d55c3..2d4d5deaefa 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -8,34 +8,12 @@ pub mod place;
 
 use crate::query::Providers;
 use crate::ty::{EarlyBinder, ImplSubject, TyCtxt};
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::{try_par_for_each_in, DynSend, DynSync};
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
 use rustc_hir::*;
-use rustc_query_system::ich::StableHashingContext;
 use rustc_span::{ErrorGuaranteed, ExpnId, DUMMY_SP};
 
-/// Top-level HIR node for current owner. This only contains the node for which
-/// `HirId::local_id == 0`, and excludes bodies.
-///
-/// This struct exists to encapsulate all access to the hir_owner query in this module, and to
-/// implement HashStable without hashing bodies.
-#[derive(Copy, Clone, Debug)]
-pub struct Owner<'tcx> {
-    node: OwnerNode<'tcx>,
-}
-
-impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Owner<'tcx> {
-    #[inline]
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        // Perform a shallow hash instead using the deep hash saved in `OwnerNodes`. This lets us
-        // differentiate queries that depend on the full HIR tree from those that only depend on
-        // the item signature.
-        hcx.without_hir_bodies(|hcx| self.node.hash_stable(hcx, hasher));
-    }
-}
-
 /// Gather the LocalDefId for each item-like within a module, including items contained within
 /// bodies. The Ids are in visitor order. This is used to partition a pass between modules.
 #[derive(Debug, HashStable, Encodable, Decodable)]
@@ -149,11 +127,6 @@ pub fn provide(providers: &mut Providers) {
     providers.hir_crate_items = map::hir_crate_items;
     providers.crate_hash = map::crate_hash;
     providers.hir_module_items = map::hir_module_items;
-    providers.hir_owner = |tcx, id| {
-        let owner = tcx.hir_crate(()).owners.get(id.def_id)?.as_owner()?;
-        let node = owner.node();
-        Some(Owner { node })
-    };
     providers.opt_local_def_id_to_hir_id = |tcx, id| {
         let owner = tcx.hir_crate(()).owners[id].map(|_| ());
         Some(match owner {
@@ -162,7 +135,13 @@ pub fn provide(providers: &mut Providers) {
             MaybeOwner::NonOwner(hir_id) => hir_id,
         })
     };
-    providers.hir_owner_nodes = |tcx, id| tcx.hir_crate(()).owners[id.def_id].map(|i| &i.nodes);
+    providers.hir_owner_nodes = |tcx, id| {
+        if let Some(i) = tcx.hir_crate(()).owners.get(id.def_id) {
+            i.map(|i| &i.nodes)
+        } else {
+            MaybeOwner::Phantom
+        }
+    };
     providers.hir_owner_parent = |tcx, id| {
         // Accessing the local_parent is ok since its value is hashed as part of `id`'s DefPathHash.
         tcx.opt_local_parent(id.def_id).map_or(CRATE_HIR_ID, |parent| {
diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs
index 6e50e894046..c35799ef47f 100644
--- a/compiler/rustc_middle/src/infer/unify_key.rs
+++ b/compiler/rustc_middle/src/infer/unify_key.rs
@@ -120,7 +120,7 @@ pub enum ConstVariableOriginKind {
 #[derive(Copy, Clone, Debug)]
 pub enum ConstVariableValue<'tcx> {
     Known { value: ty::Const<'tcx> },
-    Unknown { universe: ty::UniverseIndex },
+    Unknown { origin: ConstVariableOrigin, universe: ty::UniverseIndex },
 }
 
 impl<'tcx> ConstVariableValue<'tcx> {
@@ -134,12 +134,6 @@ impl<'tcx> ConstVariableValue<'tcx> {
     }
 }
 
-#[derive(Copy, Clone, Debug)]
-pub struct ConstVarValue<'tcx> {
-    pub origin: ConstVariableOrigin,
-    pub val: ConstVariableValue<'tcx>,
-}
-
 #[derive(PartialEq, Copy, Clone, Debug)]
 pub struct ConstVidKey<'tcx> {
     pub vid: ty::ConstVid,
@@ -153,7 +147,7 @@ impl<'tcx> From<ty::ConstVid> for ConstVidKey<'tcx> {
 }
 
 impl<'tcx> UnifyKey for ConstVidKey<'tcx> {
-    type Value = ConstVarValue<'tcx>;
+    type Value = ConstVariableValue<'tcx>;
     #[inline]
     fn index(&self) -> u32 {
         self.vid.as_u32()
@@ -167,23 +161,23 @@ impl<'tcx> UnifyKey for ConstVidKey<'tcx> {
     }
 }
 
-impl<'tcx> UnifyValue for ConstVarValue<'tcx> {
+impl<'tcx> UnifyValue for ConstVariableValue<'tcx> {
     type Error = NoError;
 
     fn unify_values(&value1: &Self, &value2: &Self) -> Result<Self, Self::Error> {
-        Ok(match (value1.val, value2.val) {
+        match (value1, value2) {
             (ConstVariableValue::Known { .. }, ConstVariableValue::Known { .. }) => {
                 bug!("equating two const variables, both of which have known values")
             }
 
             // If one side is known, prefer that one.
-            (ConstVariableValue::Known { .. }, ConstVariableValue::Unknown { .. }) => value1,
-            (ConstVariableValue::Unknown { .. }, ConstVariableValue::Known { .. }) => value2,
+            (ConstVariableValue::Known { .. }, ConstVariableValue::Unknown { .. }) => Ok(value1),
+            (ConstVariableValue::Unknown { .. }, ConstVariableValue::Known { .. }) => Ok(value2),
 
             // If both sides are *unknown*, it hardly matters, does it?
             (
-                ConstVariableValue::Unknown { universe: universe1 },
-                ConstVariableValue::Unknown { universe: universe2 },
+                ConstVariableValue::Unknown { origin, universe: universe1 },
+                ConstVariableValue::Unknown { origin: _, universe: universe2 },
             ) => {
                 // If we unify two unbound variables, ?T and ?U, then whatever
                 // value they wind up taking (which must be the same value) must
@@ -191,12 +185,9 @@ impl<'tcx> UnifyValue for ConstVarValue<'tcx> {
                 // universe is the minimum of the two universes, because that is
                 // the one which contains the fewest names in scope.
                 let universe = cmp::min(universe1, universe2);
-                ConstVarValue {
-                    val: ConstVariableValue::Unknown { universe },
-                    origin: value1.origin,
-                }
+                Ok(ConstVariableValue::Unknown { origin, universe })
             }
-        })
+        }
     }
 }
 
diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs
index c5e4dfaf19e..4ab16cf19ba 100644
--- a/compiler/rustc_middle/src/lint.rs
+++ b/compiler/rustc_middle/src/lint.rs
@@ -2,7 +2,7 @@ use std::cmp;
 
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::sorted_map::SortedMap;
-use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, MultiSpan};
+use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticMessage, MultiSpan};
 use rustc_hir::{HirId, ItemLocalId};
 use rustc_session::lint::{
     builtin::{self, FORBIDDEN_LINT_GROUPS},
@@ -322,8 +322,6 @@ pub fn struct_lint_level(
             err.span(span);
         }
 
-        err.is_lint();
-
         // If this code originates in a foreign macro, aka something that this crate
         // did not itself author, then it's likely that there's nothing this crate
         // can do about it. We probably want to skip the lint entirely.
@@ -351,8 +349,7 @@ pub fn struct_lint_level(
         // suppressed the lint due to macros.
         err.primary_message(msg);
 
-        let name = lint.name_lower();
-        err.code(DiagnosticId::Lint { name, has_future_breakage });
+        err.is_lint(lint.name_lower(), has_future_breakage);
 
         // Lint diagnostics that are covered by the expect level will not be emitted outside
         // the compiler. It is therefore not necessary to add any information for the user.
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs
index 092b59deeff..b20df1b2343 100644
--- a/compiler/rustc_middle/src/mir/interpret/queries.rs
+++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -145,7 +145,7 @@ impl<'tcx> TyCtxt<'tcx> {
     ) -> EvalToConstValueResult<'tcx> {
         // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should
         // improve caching of queries.
-        let inputs = self.erase_regions(param_env.and(cid));
+        let inputs = self.erase_regions(param_env.with_reveal_all_normalized(self).and(cid));
         if let Some(span) = span {
             // The query doesn't know where it is being invoked, so we need to fix the span.
             self.at(span).eval_to_const_value_raw(inputs).map_err(|e| e.with_span(span))
@@ -164,7 +164,7 @@ impl<'tcx> TyCtxt<'tcx> {
     ) -> EvalToValTreeResult<'tcx> {
         // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should
         // improve caching of queries.
-        let inputs = self.erase_regions(param_env.and(cid));
+        let inputs = self.erase_regions(param_env.with_reveal_all_normalized(self).and(cid));
         debug!(?inputs);
         if let Some(span) = span {
             // The query doesn't know where it is being invoked, so we need to fix the span.
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 36f5ba161d5..624ae8c22f9 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -1672,13 +1672,19 @@ mod size_asserts {
     use super::*;
     use rustc_data_structures::static_assert_size;
     // tidy-alphabetical-start
-    static_assert_size!(BasicBlockData<'_>, 136);
+    // This can be removed after i128:128 is in the bootstrap compiler's target.
+    #[cfg(not(bootstrap))]
+    static_assert_size!(BasicBlockData<'_>, 144);
     static_assert_size!(LocalDecl<'_>, 40);
     static_assert_size!(SourceScopeData<'_>, 72);
     static_assert_size!(Statement<'_>, 32);
     static_assert_size!(StatementKind<'_>, 16);
-    static_assert_size!(Terminator<'_>, 104);
-    static_assert_size!(TerminatorKind<'_>, 88);
+    // This can be removed after i128:128 is in the bootstrap compiler's target.
+    #[cfg(not(bootstrap))]
+    static_assert_size!(Terminator<'_>, 112);
+    // This can be removed after i128:128 is in the bootstrap compiler's target.
+    #[cfg(not(bootstrap))]
+    static_assert_size!(TerminatorKind<'_>, 96);
     static_assert_size!(VarDebugInfo<'_>, 88);
     // tidy-alphabetical-end
 }
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 1a6b0f4031d..3b60eba2dfe 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -142,15 +142,17 @@ fn dump_matched_mir_node<'tcx, F>(
     }
 }
 
-/// Returns the file basename portion (without extension) of a filename path
-/// where we should dump a MIR representation output files.
-fn dump_file_basename<'tcx>(
+/// Returns the path to the filename where we should dump a given MIR.
+/// Also used by other bits of code (e.g., NLL inference) that dump
+/// graphviz data or other things.
+fn dump_path<'tcx>(
     tcx: TyCtxt<'tcx>,
+    extension: &str,
     pass_num: bool,
     pass_name: &str,
     disambiguator: &dyn Display,
     body: &Body<'tcx>,
-) -> String {
+) -> PathBuf {
     let source = body.source;
     let promotion_id = match source.promoted {
         Some(id) => format!("-{id:?}"),
@@ -186,32 +188,31 @@ fn dump_file_basename<'tcx>(
         _ => String::new(),
     };
 
-    format!(
-        "{crate_name}.{item_name}{shim_disambiguator}{promotion_id}{pass_num}.{pass_name}.{disambiguator}",
-    )
-}
-
-/// Returns the path to the filename where we should dump a given MIR.
-/// Also used by other bits of code (e.g., NLL inference) that dump
-/// graphviz data or other things.
-fn dump_path(tcx: TyCtxt<'_>, basename: &str, extension: &str) -> PathBuf {
     let mut file_path = PathBuf::new();
     file_path.push(Path::new(&tcx.sess.opts.unstable_opts.dump_mir_dir));
 
-    let file_name = format!("{basename}.{extension}",);
+    let file_name = format!(
+        "{crate_name}.{item_name}{shim_disambiguator}{promotion_id}{pass_num}.{pass_name}.{disambiguator}.{extension}",
+    );
 
     file_path.push(&file_name);
 
     file_path
 }
 
-/// Attempts to open the MIR dump file with the given name and extension.
-fn create_dump_file_with_basename(
-    tcx: TyCtxt<'_>,
-    file_basename: &str,
+/// Attempts to open a file where we should dump a given MIR or other
+/// bit of MIR-related data. Used by `mir-dump`, but also by other
+/// bits of code (e.g., NLL inference) that dump graphviz data or
+/// other things, and hence takes the extension as an argument.
+pub fn create_dump_file<'tcx>(
+    tcx: TyCtxt<'tcx>,
     extension: &str,
+    pass_num: bool,
+    pass_name: &str,
+    disambiguator: &dyn Display,
+    body: &Body<'tcx>,
 ) -> io::Result<io::BufWriter<fs::File>> {
-    let file_path = dump_path(tcx, file_basename, extension);
+    let file_path = dump_path(tcx, extension, pass_num, pass_name, disambiguator, body);
     if let Some(parent) = file_path.parent() {
         fs::create_dir_all(parent).map_err(|e| {
             io::Error::new(
@@ -225,25 +226,6 @@ fn create_dump_file_with_basename(
     })?))
 }
 
-/// Attempts to open a file where we should dump a given MIR or other
-/// bit of MIR-related data. Used by `mir-dump`, but also by other
-/// bits of code (e.g., NLL inference) that dump graphviz data or
-/// other things, and hence takes the extension as an argument.
-pub fn create_dump_file<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    extension: &str,
-    pass_num: bool,
-    pass_name: &str,
-    disambiguator: &dyn Display,
-    body: &Body<'tcx>,
-) -> io::Result<io::BufWriter<fs::File>> {
-    create_dump_file_with_basename(
-        tcx,
-        &dump_file_basename(tcx, pass_num, pass_name, disambiguator, body),
-        extension,
-    )
-}
-
 ///////////////////////////////////////////////////////////////////////////
 // Whole MIR bodies
 
@@ -785,7 +767,7 @@ impl<'tcx> TerminatorKind<'tcx> {
             Call { func, args, destination, .. } => {
                 write!(fmt, "{destination:?} = ")?;
                 write!(fmt, "{func:?}(")?;
-                for (index, arg) in args.iter().enumerate() {
+                for (index, arg) in args.iter().map(|a| &a.node).enumerate() {
                     if index > 0 {
                         write!(fmt, ", ")?;
                     }
@@ -1116,10 +1098,10 @@ fn pre_fmt_projection(projection: &[PlaceElem<'_>], fmt: &mut Formatter<'_>) ->
             | ProjectionElem::Subtype(_)
             | ProjectionElem::Downcast(_, _)
             | ProjectionElem::Field(_, _) => {
-                write!(fmt, "(").unwrap();
+                write!(fmt, "(")?;
             }
             ProjectionElem::Deref => {
-                write!(fmt, "(*").unwrap();
+                write!(fmt, "(*")?;
             }
             ProjectionElem::Index(_)
             | ProjectionElem::ConstantIndex { .. }
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 462076d750f..6ebe57e29da 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -16,6 +16,7 @@ use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_hir::def_id::DefId;
 use rustc_hir::{self, CoroutineKind};
 use rustc_index::IndexVec;
+use rustc_span::source_map::Spanned;
 use rustc_target::abi::{FieldIdx, VariantIdx};
 
 use rustc_ast::Mutability;
@@ -673,7 +674,9 @@ pub enum TerminatorKind<'tcx> {
         /// These are owned by the callee, which is free to modify them.
         /// This allows the memory occupied by "by-value" arguments to be
         /// reused across function calls without duplicating the contents.
-        args: Vec<Operand<'tcx>>,
+        /// The span for each arg is also included
+        /// (e.g. `a` and `b` in `x.foo(a, b)`).
+        args: Vec<Spanned<Operand<'tcx>>>,
         /// Where the returned value will be written
         destination: Place<'tcx>,
         /// Where to go after this call returns. If none, the call necessarily diverges.
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
index 234ccee5546..5597609c7d7 100644
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -229,6 +229,18 @@ impl<'tcx> Operand<'tcx> {
             Operand::Constant(c) => c.const_.ty(),
         }
     }
+
+    pub fn span<D: ?Sized>(&self, local_decls: &D) -> Span
+    where
+        D: HasLocalDecls<'tcx>,
+    {
+        match self {
+            &Operand::Copy(ref l) | &Operand::Move(ref l) => {
+                local_decls.local_decls()[l.local].source_info.span
+            }
+            Operand::Constant(c) => c.span,
+        }
+    }
 }
 
 impl<'tcx> BinOp {
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 2ccf5a9f6f7..4696f54c897 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -524,7 +524,7 @@ macro_rules! make_mir_visitor {
                     } => {
                         self.visit_operand(func, location);
                         for arg in args {
-                            self.visit_operand(arg, location);
+                            self.visit_operand(&$($mutability)? arg.node, location);
                         }
                         self.visit_place(
                             destination,
diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs
index b9200f1abf1..778b4308d2e 100644
--- a/compiler/rustc_middle/src/query/erase.rs
+++ b/compiler/rustc_middle/src/query/erase.rs
@@ -74,10 +74,18 @@ impl<T> EraseType for Result<&'_ T, traits::query::NoSolution> {
     type Result = [u8; size_of::<Result<&'static (), traits::query::NoSolution>>()];
 }
 
+impl<T> EraseType for Result<&'_ [T], traits::query::NoSolution> {
+    type Result = [u8; size_of::<Result<&'static [()], traits::query::NoSolution>>()];
+}
+
 impl<T> EraseType for Result<&'_ T, rustc_errors::ErrorGuaranteed> {
     type Result = [u8; size_of::<Result<&'static (), rustc_errors::ErrorGuaranteed>>()];
 }
 
+impl<T> EraseType for Result<&'_ [T], rustc_errors::ErrorGuaranteed> {
+    type Result = [u8; size_of::<Result<&'static [()], rustc_errors::ErrorGuaranteed>>()];
+}
+
 impl<T> EraseType for Result<&'_ T, traits::CodegenObligationError> {
     type Result = [u8; size_of::<Result<&'static (), traits::CodegenObligationError>>()];
 }
@@ -160,10 +168,6 @@ impl<T> EraseType for Option<&'_ [T]> {
     type Result = [u8; size_of::<Option<&'static [()]>>()];
 }
 
-impl EraseType for Option<rustc_middle::hir::Owner<'_>> {
-    type Result = [u8; size_of::<Option<rustc_middle::hir::Owner<'static>>>()];
-}
-
 impl EraseType for Option<mir::DestructuredConstant<'_>> {
     type Result = [u8; size_of::<Option<mir::DestructuredConstant<'static>>>()];
 }
@@ -320,7 +324,6 @@ macro_rules! tcx_lifetime {
 }
 
 tcx_lifetime! {
-    rustc_middle::hir::Owner,
     rustc_middle::middle::exported_symbols::ExportedSymbol,
     rustc_middle::mir::Const,
     rustc_middle::mir::DestructuredConstant,
diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs
index 945f17d5df2..69d3974184d 100644
--- a/compiler/rustc_middle/src/query/keys.rs
+++ b/compiler/rustc_middle/src/query/keys.rs
@@ -9,6 +9,7 @@ use crate::ty::{self, Ty, TyCtxt};
 use crate::ty::{GenericArg, GenericArgsRef};
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalModDefId, ModDefId, LOCAL_CRATE};
 use rustc_hir::hir_id::{HirId, OwnerId};
+use rustc_query_system::query::DefIdCacheSelector;
 use rustc_query_system::query::{DefaultCacheSelector, SingleCacheSelector, VecCacheSelector};
 use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
@@ -152,7 +153,7 @@ impl Key for LocalDefId {
 }
 
 impl Key for DefId {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type CacheSelector = DefIdCacheSelector;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         tcx.def_span(*self)
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 1dc77220881..a9dc7f5d11a 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -174,14 +174,6 @@ rustc_queries! {
         cache_on_disk_if { true }
     }
 
-    /// Gives access to the HIR node for the HIR owner `key`.
-    ///
-    /// This can be conveniently accessed by methods on `tcx.hir()`.
-    /// Avoid calling this query directly.
-    query hir_owner(key: hir::OwnerId) -> Option<crate::hir::Owner<'tcx>> {
-        desc { |tcx| "getting HIR owner of `{}`", tcx.def_path_str(key) }
-    }
-
     /// Gives access to the HIR ID for the given `LocalDefId` owner `key` if any.
     ///
     /// Definitions that were generated with no HIR, would be fed to return `None`.
@@ -859,13 +851,13 @@ rustc_queries! {
     /// Maps a `DefId` of a type to a list of its inherent impls.
     /// Contains implementations of methods that are inherent to a type.
     /// Methods in these implementations don't need to be exported.
-    query inherent_impls(key: DefId) -> &'tcx [DefId] {
+    query inherent_impls(key: DefId) -> Result<&'tcx [DefId], ErrorGuaranteed> {
         desc { |tcx| "collecting inherent impls for `{}`", tcx.def_path_str(key) }
         cache_on_disk_if { key.is_local() }
         separate_provide_extern
     }
 
-    query incoherent_impls(key: SimplifiedType) -> &'tcx [DefId] {
+    query incoherent_impls(key: SimplifiedType) -> Result<&'tcx [DefId], ErrorGuaranteed> {
         desc { |tcx| "collecting all inherent impls for `{:?}`", key }
     }
 
@@ -961,8 +953,9 @@ rustc_queries! {
         desc { |tcx| "checking deathness of variables in {}", describe_as_module(key, tcx) }
     }
 
-    query check_mod_impl_wf(key: LocalModDefId) -> () {
+    query check_mod_impl_wf(key: LocalModDefId) -> Result<(), ErrorGuaranteed> {
         desc { |tcx| "checking that impls are well-formed in {}", describe_as_module(key, tcx) }
+        ensure_forwards_result_if_red
     }
 
     query check_mod_type_wf(key: LocalModDefId) -> Result<(), ErrorGuaranteed> {
@@ -1011,15 +1004,16 @@ rustc_queries! {
 
     /// Gets a complete map from all types to their inherent impls.
     /// Not meant to be used directly outside of coherence.
-    query crate_inherent_impls(k: ()) -> &'tcx CrateInherentImpls {
-        arena_cache
+    query crate_inherent_impls(k: ()) -> Result<&'tcx CrateInherentImpls, ErrorGuaranteed> {
         desc { "finding all inherent impls defined in crate" }
+        ensure_forwards_result_if_red
     }
 
     /// Checks all types in the crate for overlap in their inherent impls. Reports errors.
     /// Not meant to be used directly outside of coherence.
-    query crate_inherent_impls_overlap_check(_: ()) -> () {
+    query crate_inherent_impls_overlap_check(_: ()) -> Result<(), ErrorGuaranteed> {
         desc { "check for overlap between inherent impls defined in this crate" }
+        ensure_forwards_result_if_red
     }
 
     /// Checks whether all impls in the crate pass the overlap check, returning
@@ -1645,7 +1639,7 @@ rustc_queries! {
     ///
     /// Do not call this directly, but instead use the `incoherent_impls` query.
     /// This query is only used to get the data necessary for that query.
-    query crate_incoherent_impls(key: (CrateNum, SimplifiedType)) -> &'tcx [DefId] {
+    query crate_incoherent_impls(key: (CrateNum, SimplifiedType)) -> Result<&'tcx [DefId], ErrorGuaranteed> {
         desc { |tcx| "collecting all impls for a type in a crate" }
         separate_provide_extern
     }
@@ -1949,7 +1943,7 @@ rustc_queries! {
         desc { "normalizing `{}`", goal.value }
     }
 
-    query implied_outlives_bounds(
+    query implied_outlives_bounds_compat(
         goal: CanonicalTyGoal<'tcx>
     ) -> Result<
         &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec<OutlivesBound<'tcx>>>>,
@@ -1958,6 +1952,15 @@ rustc_queries! {
         desc { "computing implied outlives bounds for `{}`", goal.value.value }
     }
 
+    query implied_outlives_bounds(
+        goal: CanonicalTyGoal<'tcx>
+    ) -> Result<
+        &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec<OutlivesBound<'tcx>>>>,
+        NoSolution,
+    > {
+        desc { "computing implied outlives bounds v2 for `{}`", goal.value.value }
+    }
+
     /// Do not call this query directly:
     /// invoke `DropckOutlives::new(dropped_ty)).fully_perform(typeck.infcx)` instead.
     query dropck_outlives(
diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs
index a41d4f1ad58..8d88488e167 100644
--- a/compiler/rustc_middle/src/query/plumbing.rs
+++ b/compiler/rustc_middle/src/query/plumbing.rs
@@ -174,7 +174,7 @@ pub fn query_ensure<'tcx, Cache>(
 }
 
 #[inline]
-pub fn query_ensure_error_guaranteed<'tcx, Cache>(
+pub fn query_ensure_error_guaranteed<'tcx, Cache, T>(
     tcx: TyCtxt<'tcx>,
     execute_query: fn(TyCtxt<'tcx>, Span, Cache::Key, QueryMode) -> Option<Cache::Value>,
     query_cache: &Cache,
@@ -182,14 +182,16 @@ pub fn query_ensure_error_guaranteed<'tcx, Cache>(
     check_cache: bool,
 ) -> Result<(), ErrorGuaranteed>
 where
-    Cache: QueryCache<Value = super::erase::Erase<Result<(), ErrorGuaranteed>>>,
+    Cache: QueryCache<Value = super::erase::Erase<Result<T, ErrorGuaranteed>>>,
+    Result<T, ErrorGuaranteed>: EraseType,
 {
     let key = key.into_query_param();
     if let Some(res) = try_get_cached(tcx, query_cache, &key) {
-        super::erase::restore(res)
+        super::erase::restore(res).map(drop)
     } else {
         execute_query(tcx, DUMMY_SP, key, QueryMode::Ensure { check_cache })
             .map(super::erase::restore)
+            .map(|res| res.map(drop))
             // Either we actually executed the query, which means we got a full `Result`,
             // or we can just assume the query succeeded, because it was green in the
             // incremental cache. If it is green, that means that the previous compilation
@@ -205,7 +207,7 @@ macro_rules! query_ensure {
         query_ensure($($args)*)
     };
     ([(ensure_forwards_result_if_red) $($rest:tt)*]$($args:tt)*) => {
-        query_ensure_error_guaranteed($($args)*)
+        query_ensure_error_guaranteed($($args)*).map(|_| ())
     };
     ([$other:tt $($modifiers:tt)*]$($args:tt)*) => {
         query_ensure!([$($modifiers)*]$($args)*)
@@ -667,5 +669,7 @@ mod sealed {
 
 pub use sealed::IntoQueryParam;
 
+use super::erase::EraseType;
+
 #[derive(Copy, Clone, Debug, HashStable)]
 pub struct CyclePlaceholder(pub ErrorGuaranteed);
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index bebee8df10e..135680b9349 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -604,7 +604,7 @@ pub enum SelectionError<'tcx> {
     /// After a closure impl has selected, its "outputs" were evaluated
     /// (which for closures includes the "input" type params) and they
     /// didn't resolve. See `confirm_poly_trait_refs` for more.
-    OutputTypeParameterMismatch(Box<SelectionOutputTypeParameterMismatch<'tcx>>),
+    SignatureMismatch(Box<SignatureMismatchData<'tcx>>),
     /// The trait pointed by `DefId` is not object safe.
     TraitNotObjectSafe(DefId),
     /// A given constant couldn't be evaluated.
@@ -618,7 +618,7 @@ pub enum SelectionError<'tcx> {
 }
 
 #[derive(Clone, Debug, TypeVisitable)]
-pub struct SelectionOutputTypeParameterMismatch<'tcx> {
+pub struct SignatureMismatchData<'tcx> {
     pub found_trait_ref: ty::PolyTraitRef<'tcx>,
     pub expected_trait_ref: ty::PolyTraitRef<'tcx>,
     pub terr: ty::error::TypeError<'tcx>,
diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs
index 5f02dd22961..61d96cad57d 100644
--- a/compiler/rustc_middle/src/traits/query.rs
+++ b/compiler/rustc_middle/src/traits/query.rs
@@ -191,7 +191,7 @@ pub struct NormalizationResult<'tcx> {
 /// case they are called implied bounds). They are fed to the
 /// `OutlivesEnv` which in turn is supplied to the region checker and
 /// other parts of the inference system.
-#[derive(Clone, Debug, TypeFoldable, TypeVisitable, HashStable)]
+#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, HashStable)]
 pub enum OutlivesBound<'tcx> {
     RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>),
     RegionSubParam(ty::Region<'tcx>, ty::ParamTy),
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index ad9296a4cc8..a5d9e0fcf44 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -2535,8 +2535,7 @@ impl<'tcx> TyCtxt<'tcx> {
         if self.sess.opts.unstable_opts.debug_macros || !span.from_expansion() {
             return span;
         }
-        let collapse_debuginfo_enabled = self.features().collapse_debuginfo;
-        hygiene::walk_chain_collapsed(span, upto, collapse_debuginfo_enabled)
+        hygiene::walk_chain_collapsed(span, upto, self.features().collapse_debuginfo)
     }
 
     #[inline]
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index a10bdc6012c..4028de27cae 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -15,7 +15,6 @@ use rustc_hir::def::{self, CtorKind, DefKind, Namespace};
 use rustc_hir::def_id::{DefIdMap, DefIdSet, ModDefId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::definitions::{DefKey, DefPathDataName};
 use rustc_hir::LangItem;
-use rustc_session::config::TrimmedDefPaths;
 use rustc_session::cstore::{ExternCrate, ExternCrateSource};
 use rustc_session::Limit;
 use rustc_span::symbol::{kw, Ident, Symbol};
@@ -365,26 +364,19 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
 
     /// Try to see if this path can be trimmed to a unique symbol name.
     fn try_print_trimmed_def_path(&mut self, def_id: DefId) -> Result<bool, PrintError> {
-        if with_forced_trimmed_paths() {
-            let trimmed = self.force_print_trimmed_def_path(def_id)?;
-            if trimmed {
-                return Ok(true);
-            }
+        if with_forced_trimmed_paths() && self.force_print_trimmed_def_path(def_id)? {
+            return Ok(true);
         }
-        if !self.tcx().sess.opts.unstable_opts.trim_diagnostic_paths
-            || matches!(self.tcx().sess.opts.trimmed_def_paths, TrimmedDefPaths::Never)
-            || with_no_trimmed_paths()
-            || with_crate_prefix()
+        if self.tcx().sess.opts.unstable_opts.trim_diagnostic_paths
+            && self.tcx().sess.opts.trimmed_def_paths
+            && !with_no_trimmed_paths()
+            && !with_crate_prefix()
+            && let Some(symbol) = self.tcx().trimmed_def_paths(()).get(&def_id)
         {
-            return Ok(false);
-        }
-
-        match self.tcx().trimmed_def_paths(()).get(&def_id) {
-            None => Ok(false),
-            Some(symbol) => {
-                write!(self, "{}", Ident::with_dummy_span(*symbol))?;
-                Ok(true)
-            }
+            write!(self, "{}", Ident::with_dummy_span(*symbol))?;
+            Ok(true)
+        } else {
+            Ok(false)
         }
     }
 
@@ -1021,7 +1013,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                                 .extend(
                                     // Group the return ty with its def id, if we had one.
                                     entry.return_ty.map(|ty| {
-                                        (tcx.require_lang_item(LangItem::FnOnce, None), ty)
+                                        (tcx.require_lang_item(LangItem::FnOnceOutput, None), ty)
                                     }),
                                 );
                         }
@@ -3080,18 +3072,19 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N
 /// See also [`DelayDm`](rustc_error_messages::DelayDm) and [`with_no_trimmed_paths!`].
 // this is pub to be able to intra-doc-link it
 pub fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> DefIdMap<Symbol> {
-    let mut map: DefIdMap<Symbol> = Default::default();
-
-    if let TrimmedDefPaths::GoodPath = tcx.sess.opts.trimmed_def_paths {
-        // Trimming paths is expensive and not optimized, since we expect it to only be used for error reporting.
-        //
-        // For good paths causing this bug, the `rustc_middle::ty::print::with_no_trimmed_paths`
-        // wrapper can be used to suppress this query, in exchange for full paths being formatted.
-        tcx.sess.good_path_delayed_bug(
-            "trimmed_def_paths constructed but no error emitted; use `DelayDm` for lints or `with_no_trimmed_paths` for debugging",
-        );
-    }
-
+    assert!(tcx.sess.opts.trimmed_def_paths);
+
+    // Trimming paths is expensive and not optimized, since we expect it to only be used for error
+    // reporting.
+    //
+    // For good paths causing this bug, the `rustc_middle::ty::print::with_no_trimmed_paths`
+    // wrapper can be used to suppress this query, in exchange for full paths being formatted.
+    tcx.sess.good_path_delayed_bug(
+        "trimmed_def_paths constructed but no error emitted; use `DelayDm` for lints or `with_no_trimmed_paths` for debugging",
+    );
+
+    // Once constructed, unique namespace+symbol pairs will have a `Some(_)` entry, while
+    // non-unique pairs will have a `None` entry.
     let unique_symbols_rev: &mut FxHashMap<(Namespace, Symbol), Option<DefId>> =
         &mut FxHashMap::default();
 
@@ -3121,6 +3114,8 @@ pub fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> DefIdMap<Symbol> {
         }
     });
 
+    // Put the symbol from all the unique namespace+symbol pairs into `map`.
+    let mut map: DefIdMap<Symbol> = Default::default();
     for ((_, symbol), opt_def_id) in unique_symbols_rev.drain() {
         use std::collections::hash_map::Entry::{Occupied, Vacant};
 
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 7c869adbd83..11b579a1f85 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -9,6 +9,7 @@ use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer};
 use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
 use crate::ty::{self, AliasTy, InferConst, Lift, Term, TermKind, Ty, TyCtxt};
 use rustc_hir::def::Namespace;
+use rustc_span::source_map::Spanned;
 use rustc_target::abi::TyAndLayout;
 use rustc_type_ir::{ConstKind, DebugWithInfcx, InferCtxtLike, WithInfcx};
 
@@ -819,3 +820,27 @@ impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for TyAndLayout<'tcx, Ty<'tcx>> {
         visitor.visit_ty(self.ty)
     }
 }
+
+impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>> + Debug + Clone> TypeVisitable<TyCtxt<'tcx>>
+    for Spanned<T>
+{
+    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+        self.node.visit_with(visitor)?;
+        self.span.visit_with(visitor)?;
+        ControlFlow::Continue(())
+    }
+}
+
+impl<'tcx, T: TypeFoldable<TyCtxt<'tcx>> + Debug + Clone> TypeFoldable<TyCtxt<'tcx>>
+    for Spanned<T>
+{
+    fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
+        Ok(Spanned {
+            node: self.node.try_fold_with(folder)?,
+            span: self.span.try_fold_with(folder)?,
+        })
+    }
+}
diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs
index 227a0753d04..d85b541d363 100644
--- a/compiler/rustc_middle/src/ty/trait_def.rs
+++ b/compiler/rustc_middle/src/ty/trait_def.rs
@@ -254,16 +254,28 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait
 }
 
 /// Query provider for `incoherent_impls`.
-pub(super) fn incoherent_impls_provider(tcx: TyCtxt<'_>, simp: SimplifiedType) -> &[DefId] {
+pub(super) fn incoherent_impls_provider(
+    tcx: TyCtxt<'_>,
+    simp: SimplifiedType,
+) -> Result<&[DefId], ErrorGuaranteed> {
     let mut impls = Vec::new();
 
+    let mut res = Ok(());
     for cnum in iter::once(LOCAL_CRATE).chain(tcx.crates(()).iter().copied()) {
-        for &impl_def_id in tcx.crate_incoherent_impls((cnum, simp)) {
+        let incoherent_impls = match tcx.crate_incoherent_impls((cnum, simp)) {
+            Ok(impls) => impls,
+            Err(e) => {
+                res = Err(e);
+                continue;
+            }
+        };
+        for &impl_def_id in incoherent_impls {
             impls.push(impl_def_id)
         }
     }
 
     debug!(?impls);
+    res?;
 
-    tcx.arena.alloc_slice(&impls)
+    Ok(tcx.arena.alloc_slice(&impls))
 }
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 372f11a5acc..ef621f29bfd 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -604,19 +604,15 @@ impl<'tcx> TyCtxt<'tcx> {
     /// wrapped in a binder.
     pub fn closure_env_ty(
         self,
-        closure_def_id: DefId,
-        closure_args: GenericArgsRef<'tcx>,
+        closure_ty: Ty<'tcx>,
+        closure_kind: ty::ClosureKind,
         env_region: ty::Region<'tcx>,
-    ) -> Option<Ty<'tcx>> {
-        let closure_ty = Ty::new_closure(self, closure_def_id, closure_args);
-        let closure_kind_ty = closure_args.as_closure().kind_ty();
-        let closure_kind = closure_kind_ty.to_opt_closure_kind()?;
-        let env_ty = match closure_kind {
+    ) -> Ty<'tcx> {
+        match closure_kind {
             ty::ClosureKind::Fn => Ty::new_imm_ref(self, env_region, closure_ty),
             ty::ClosureKind::FnMut => Ty::new_mut_ref(self, env_region, closure_ty),
             ty::ClosureKind::FnOnce => closure_ty,
-        };
-        Some(env_ty)
+        }
     }
 
     /// Returns `true` if the node pointed to by `def_id` is a `static` item.
diff --git a/compiler/rustc_middle/src/util/find_self_call.rs b/compiler/rustc_middle/src/util/find_self_call.rs
index 9f1e4ac11c2..0ca4fce5da9 100644
--- a/compiler/rustc_middle/src/util/find_self_call.rs
+++ b/compiler/rustc_middle/src/util/find_self_call.rs
@@ -2,6 +2,7 @@ use crate::mir::*;
 use crate::ty::GenericArgsRef;
 use crate::ty::{self, TyCtxt};
 use rustc_span::def_id::DefId;
+use rustc_span::source_map::Spanned;
 
 /// Checks if the specified `local` is used as the `self` parameter of a method call
 /// in the provided `BasicBlock`. If it is, then the `DefId` of the called method is
@@ -23,7 +24,13 @@ pub fn find_self_call<'tcx>(
                     tcx.opt_associated_item(def_id)
                 {
                     debug!("find_self_call: args={:?}", fn_args);
-                    if let [Operand::Move(self_place) | Operand::Copy(self_place), ..] = **args {
+                    if let [
+                        Spanned {
+                            node: Operand::Move(self_place) | Operand::Copy(self_place), ..
+                        },
+                        ..,
+                    ] = **args
+                    {
                         if self_place.as_local() == Some(local) {
                             return Some((def_id, fn_args));
                         }
diff --git a/compiler/rustc_mir_build/Cargo.toml b/compiler/rustc_mir_build/Cargo.toml
index 6d681dc295e..d71f7121322 100644
--- a/compiler/rustc_mir_build/Cargo.toml
+++ b/compiler/rustc_mir_build/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2021"
 [dependencies]
 # tidy-alphabetical-start
 either = "1"
+itertools = "0.11"
 rustc_apfloat = "0.2.0"
 rustc_arena = { path = "../rustc_arena" }
 rustc_ast = { path = "../rustc_ast" }
diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl
index 615b553434f..2f11cb123ee 100644
--- a/compiler/rustc_mir_build/messages.ftl
+++ b/compiler/rustc_mir_build/messages.ftl
@@ -234,6 +234,11 @@ mir_build_mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsa
 
 mir_build_non_const_path = runtime values cannot be referenced in patterns
 
+mir_build_non_empty_never_pattern =
+    mismatched types
+    .label = a never pattern must be used on an uninhabited type
+    .note = the matched value is of type `{$ty}`
+
 mir_build_non_exhaustive_match_all_arms_guarded =
     match arms with guards don't count towards exhaustivity
 
diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
index e3dea2212df..5428333a116 100644
--- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
+++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
@@ -2,6 +2,7 @@ use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::ty::cast::mir_cast_kind;
 use rustc_middle::{mir::*, thir::*, ty};
+use rustc_span::source_map::Spanned;
 use rustc_span::Span;
 use rustc_target::abi::{FieldIdx, VariantIdx};
 
@@ -162,7 +163,9 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
                 let fun = self.parse_operand(*fun)?;
                 let args = args
                     .iter()
-                    .map(|arg| self.parse_operand(*arg))
+                    .map(|arg|
+                        Ok(Spanned { node: self.parse_operand(*arg)?, span: self.thir.exprs[*arg].span  } )
+                    )
                     .collect::<PResult<Vec<_>>>()?;
                 Ok(TerminatorKind::Call {
                     func: fun,
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 f799be165ec..6e8af7bb6df 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -2,6 +2,7 @@
 
 use rustc_index::{Idx, IndexVec};
 use rustc_middle::ty::util::IntTypeExt;
+use rustc_span::source_map::Spanned;
 use rustc_target::abi::{Abi, FieldIdx, Primitive};
 
 use crate::build::expr::as_place::PlaceBase;
@@ -15,7 +16,7 @@ use rustc_middle::thir::*;
 use rustc_middle::ty::cast::{mir_cast_kind, CastTy};
 use rustc_middle::ty::layout::IntegerExt;
 use rustc_middle::ty::{self, Ty, UpvarArgs};
-use rustc_span::Span;
+use rustc_span::{Span, DUMMY_SP};
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Returns an rvalue suitable for use until the end of the current
@@ -156,7 +157,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     synth_info,
                     TerminatorKind::Call {
                         func: exchange_malloc,
-                        args: vec![Operand::Move(size), Operand::Move(align)],
+                        args: vec![
+                            Spanned { node: Operand::Move(size), span: DUMMY_SP },
+                            Spanned { node: Operand::Move(align), span: DUMMY_SP },
+                        ],
                         destination: storage,
                         target: Some(success),
                         unwind: UnwindAction::Continue,
@@ -733,7 +737,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 this.diverge_from(block);
                 block = success;
             }
-            this.record_operands_moved(&[value_operand]);
+            this.record_operands_moved(&[Spanned { node: value_operand, span: DUMMY_SP }]);
         }
         block.and(Rvalue::Aggregate(Box::new(AggregateKind::Array(elem_ty)), IndexVec::new()))
     }
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index 060a3b521a4..2978491d646 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -9,6 +9,7 @@ use rustc_hir as hir;
 use rustc_middle::mir::*;
 use rustc_middle::thir::*;
 use rustc_middle::ty::CanonicalUserTypeAnnotation;
+use rustc_span::source_map::Spanned;
 use std::iter;
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
@@ -248,7 +249,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 let args: Vec<_> = args
                     .into_iter()
                     .copied()
-                    .map(|arg| unpack!(block = this.as_local_call_operand(block, arg)))
+                    .map(|arg| Spanned {
+                        node: unpack!(block = this.as_local_call_operand(block, arg)),
+                        span: this.thir.exprs[arg].span,
+                    })
                     .collect();
 
                 let success = this.cfg.start_new_block();
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index 53e5d70f946..990be30b2d6 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -17,8 +17,9 @@ use rustc_middle::ty::util::IntTypeExt;
 use rustc_middle::ty::GenericArg;
 use rustc_middle::ty::{self, adjustment::PointerCoercion, Ty, TyCtxt};
 use rustc_span::def_id::DefId;
+use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{sym, Symbol};
-use rustc_span::Span;
+use rustc_span::{Span, DUMMY_SP};
 use rustc_target::abi::VariantIdx;
 
 use std::cmp::Ordering;
@@ -271,7 +272,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                                 user_ty: None,
                                 const_: method,
                             })),
-                            args: vec![Operand::Move(ref_string)],
+                            args: vec![Spanned { node: Operand::Move(ref_string), span: DUMMY_SP }],
                             destination: ref_str,
                             target: Some(eq_block),
                             unwind: UnwindAction::Continue,
@@ -526,7 +527,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
                     const_: method,
                 })),
-                args: vec![Operand::Copy(val), expect],
+                args: vec![
+                    Spanned { node: Operand::Copy(val), span: DUMMY_SP },
+                    Spanned { node: expect, span: DUMMY_SP },
+                ],
                 destination: eq_result,
                 target: Some(eq_block),
                 unwind: UnwindAction::Continue,
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index b8d08319422..714c5f2686e 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -1,5 +1,6 @@
 use crate::build::expr::as_place::PlaceBuilder;
 use crate::build::scope::DropKind;
+use itertools::Itertools;
 use rustc_apfloat::ieee::{Double, Single};
 use rustc_apfloat::Float;
 use rustc_ast::attr;
@@ -654,7 +655,7 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) -
                         ty::ClosureKind::FnOnce => closure_ty,
                     };
                     (
-                        [self_ty].into_iter().chain(sig.inputs().to_vec()).collect(),
+                        [self_ty].into_iter().chain(sig.inputs()[0].tuple_fields()).collect(),
                         sig.output(),
                         None,
                     )
@@ -835,7 +836,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         self.upvars = tcx
             .closure_captures(self.def_id)
             .iter()
-            .zip(capture_tys)
+            .zip_eq(capture_tys)
             .enumerate()
             .map(|(i, (captured_place, ty))| {
                 let name = captured_place.to_symbol();
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index 48b237f3ae6..6827797df37 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -91,6 +91,7 @@ use rustc_middle::middle::region;
 use rustc_middle::mir::*;
 use rustc_middle::thir::{ExprId, LintLevel};
 use rustc_session::lint::Level;
+use rustc_span::source_map::Spanned;
 use rustc_span::{Span, DUMMY_SP};
 
 #[derive(Debug)]
@@ -1020,14 +1021,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// spurious borrow-check errors -- the problem, ironically, is
     /// not the `DROP(_X)` itself, but the (spurious) unwind pathways
     /// that it creates. See #64391 for an example.
-    pub(crate) fn record_operands_moved(&mut self, operands: &[Operand<'tcx>]) {
+    pub(crate) fn record_operands_moved(&mut self, operands: &[Spanned<Operand<'tcx>>]) {
         let local_scope = self.local_scope();
         let scope = self.scopes.scopes.last_mut().unwrap();
 
         assert_eq!(scope.region_scope, local_scope, "local scope is not the topmost scope!",);
 
         // look for moves of a local variable, like `MOVE(_X)`
-        let locals_moved = operands.iter().flat_map(|operand| match operand {
+        let locals_moved = operands.iter().flat_map(|operand| match operand.node {
             Operand::Copy(_) | Operand::Constant(_) => None,
             Operand::Move(place) => place.as_local(),
         });
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index 61ad99acf38..e3cc21cef11 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -788,6 +788,16 @@ pub struct FloatPattern;
 #[diag(mir_build_pointer_pattern)]
 pub struct PointerPattern;
 
+#[derive(Diagnostic)]
+#[diag(mir_build_non_empty_never_pattern)]
+#[note]
+pub struct NonEmptyNeverPattern<'tcx> {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    pub ty: Ty<'tcx>,
+}
+
 #[derive(LintDiagnostic)]
 #[diag(mir_build_indirect_structural_match)]
 #[note(mir_build_type_not_structural_tip)]
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 78d72b30284..22094c112fc 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -2,6 +2,7 @@ use crate::errors;
 use crate::thir::cx::region::Scope;
 use crate::thir::cx::Cx;
 use crate::thir::util::UserAnnotatedTyHelpers;
+use itertools::Itertools;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
@@ -565,7 +566,7 @@ impl<'tcx> Cx<'tcx> {
                     .tcx
                     .closure_captures(def_id)
                     .iter()
-                    .zip(args.upvar_tys())
+                    .zip_eq(args.upvar_tys())
                     .map(|(captured_place, ty)| {
                         let upvars = self.capture_upvar(expr, captured_place, ty);
                         self.thir.exprs.push(upvars)
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index fa3dd2afa85..5d0bb3954cc 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -117,50 +117,32 @@ impl<'tcx> Cx<'tcx> {
         pat_from_hir(self.tcx, self.param_env, self.typeck_results(), p)
     }
 
-    fn closure_env_param(&self, owner_def: LocalDefId, owner_id: HirId) -> Option<Param<'tcx>> {
-        match self.tcx.def_kind(owner_def) {
-            DefKind::Closure if self.tcx.is_coroutine(owner_def.to_def_id()) => {
-                let coroutine_ty = self.typeck_results.node_type(owner_id);
-                let coroutine_param = Param {
-                    ty: coroutine_ty,
-                    pat: None,
-                    ty_span: None,
-                    self_kind: None,
-                    hir_id: None,
-                };
-                Some(coroutine_param)
+    fn closure_env_param(&self, owner_def: LocalDefId, expr_id: HirId) -> Option<Param<'tcx>> {
+        if self.tcx.def_kind(owner_def) != DefKind::Closure {
+            return None;
+        }
+
+        let closure_ty = self.typeck_results.node_type(expr_id);
+        Some(match *closure_ty.kind() {
+            ty::Coroutine(..) => {
+                Param { ty: closure_ty, pat: None, ty_span: None, self_kind: None, hir_id: None }
             }
-            DefKind::Closure => {
-                let closure_ty = self.typeck_results.node_type(owner_id);
-
-                let ty::Closure(closure_def_id, closure_args) = *closure_ty.kind() else {
-                    bug!("closure expr does not have closure type: {:?}", closure_ty);
-                };
-
-                let bound_vars =
-                    self.tcx.mk_bound_variable_kinds(&[ty::BoundVariableKind::Region(ty::BrEnv)]);
-                let br = ty::BoundRegion {
-                    var: ty::BoundVar::from_usize(bound_vars.len() - 1),
-                    kind: ty::BrEnv,
-                };
-                let env_region = ty::Region::new_bound(self.tcx, ty::INNERMOST, br);
-                let closure_env_ty =
-                    self.tcx.closure_env_ty(closure_def_id, closure_args, env_region).unwrap();
-                let liberated_closure_env_ty = self.tcx.instantiate_bound_regions_with_erased(
-                    ty::Binder::bind_with_vars(closure_env_ty, bound_vars),
+            ty::Closure(_, closure_args) => {
+                let closure_env_ty = self.tcx.closure_env_ty(
+                    closure_ty,
+                    closure_args.as_closure().kind(),
+                    self.tcx.lifetimes.re_erased,
                 );
-                let env_param = Param {
-                    ty: liberated_closure_env_ty,
+                Param {
+                    ty: closure_env_ty,
                     pat: None,
                     ty_span: None,
                     self_kind: None,
                     hir_id: None,
-                };
-
-                Some(env_param)
+                }
             }
-            _ => None,
-        }
+            _ => bug!("unexpected closure type: {closure_ty}"),
+        })
     }
 
     fn explicit_params<'a>(
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 f6c5e4a5cd6..693dc49c6e8 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -276,10 +276,13 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
         } else {
             // Check the pattern for some things unrelated to exhaustiveness.
             let refutable = if cx.refutable { Refutable } else { Irrefutable };
+            let mut err = Ok(());
             pat.walk_always(|pat| {
                 check_borrow_conflicts_in_at_patterns(self, pat);
                 check_for_bindings_named_same_as_variants(self, pat, refutable);
+                err = err.and(check_never_pattern(cx, pat));
             });
+            err?;
             Ok(cx.pattern_arena.alloc(cx.lower_pat(pat)))
         }
     }
@@ -289,7 +292,8 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
     fn is_known_valid_scrutinee(&self, scrutinee: &Expr<'tcx>) -> bool {
         use ExprKind::*;
         match &scrutinee.kind {
-            // Both pointers and references can validly point to a place with invalid data.
+            // Pointers can validly point to a place with invalid data. It is undecided whether
+            // references can too, so we conservatively assume they can.
             Deref { .. } => false,
             // Inherit validity of the parent place, unless the parent is an union.
             Field { lhs, .. } => {
@@ -811,6 +815,19 @@ fn check_for_bindings_named_same_as_variants(
     }
 }
 
+/// Check that never patterns are only used on inhabited types.
+fn check_never_pattern<'tcx>(
+    cx: &MatchCheckCtxt<'_, 'tcx>,
+    pat: &Pat<'tcx>,
+) -> Result<(), ErrorGuaranteed> {
+    if let PatKind::Never = pat.kind {
+        if !cx.is_uninhabited(pat.ty) {
+            return Err(cx.tcx.dcx().emit_err(NonEmptyNeverPattern { span: pat.span, ty: pat.ty }));
+        }
+    }
+    Ok(())
+}
+
 fn report_irrefutable_let_patterns(
     tcx: TyCtxt<'_>,
     id: HirId,
@@ -1113,7 +1130,7 @@ fn collect_non_exhaustive_tys<'tcx>(
         non_exhaustive_tys.insert(pat.ty().inner());
     }
     if let Constructor::IntRange(range) = pat.ctor() {
-        if cx.is_range_beyond_boundaries(range, pat.ty()) {
+        if cx.is_range_beyond_boundaries(range, *pat.ty()) {
             // The range denotes the values before `isize::MIN` or the values after `usize::MAX`/`isize::MAX`.
             non_exhaustive_tys.insert(pat.ty().inner());
         }
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index c4987634b78..ff7e985bdfd 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -345,6 +345,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
             }
 
             hir::PatKind::Or(pats) => PatKind::Or { pats: self.lower_patterns(pats) },
+
+            hir::PatKind::Err(guar) => PatKind::Error(guar),
         };
 
         Box::new(Pat { span, ty, kind })
diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
index c9930565186..862876f53c7 100644
--- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
@@ -7,6 +7,8 @@ use rustc_middle::traits::Reveal;
 use rustc_middle::ty::util::IntTypeExt;
 use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_span::source_map::Spanned;
+use rustc_span::DUMMY_SP;
 use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
 use std::{fmt, iter};
 
@@ -652,7 +654,10 @@ where
                         [ty.into()],
                         self.source_info.span,
                     ),
-                    args: vec![Operand::Move(Place::from(ref_place))],
+                    args: vec![Spanned {
+                        node: Operand::Move(Place::from(ref_place)),
+                        span: DUMMY_SP,
+                    }],
                     destination: unit_temp,
                     target: Some(succ),
                     unwind: unwind.into_action(),
diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs
index f0b21fd4184..b805f8ca23e 100644
--- a/compiler/rustc_mir_dataflow/src/lib.rs
+++ b/compiler/rustc_mir_dataflow/src/lib.rs
@@ -34,6 +34,7 @@ mod errors;
 mod framework;
 pub mod impls;
 pub mod move_paths;
+pub mod points;
 pub mod rustc_peek;
 pub mod storage;
 pub mod un_derefer;
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
index cae35765308..38ee26c5a87 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
@@ -469,7 +469,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> {
             } => {
                 self.gather_operand(func);
                 for arg in args {
-                    self.gather_operand(arg);
+                    self.gather_operand(&arg.node);
                 }
                 if let Some(_bb) = target {
                     self.create_move_path(destination);
diff --git a/compiler/rustc_mir_dataflow/src/points.rs b/compiler/rustc_mir_dataflow/src/points.rs
new file mode 100644
index 00000000000..ff17ce1fe07
--- /dev/null
+++ b/compiler/rustc_mir_dataflow/src/points.rs
@@ -0,0 +1,156 @@
+use crate::framework::{visit_results, ResultsVisitable, ResultsVisitor};
+use rustc_index::bit_set::ChunkedBitSet;
+use rustc_index::interval::SparseIntervalMatrix;
+use rustc_index::Idx;
+use rustc_index::IndexVec;
+use rustc_middle::mir::{self, BasicBlock, Body, Location};
+
+/// Maps between a `Location` and a `PointIndex` (and vice versa).
+pub struct DenseLocationMap {
+    /// For each basic block, how many points are contained within?
+    statements_before_block: IndexVec<BasicBlock, usize>,
+
+    /// Map backward from each point to the basic block that it
+    /// belongs to.
+    basic_blocks: IndexVec<PointIndex, BasicBlock>,
+
+    num_points: usize,
+}
+
+impl DenseLocationMap {
+    #[inline]
+    pub fn new(body: &Body<'_>) -> Self {
+        let mut num_points = 0;
+        let statements_before_block: IndexVec<BasicBlock, usize> = body
+            .basic_blocks
+            .iter()
+            .map(|block_data| {
+                let v = num_points;
+                num_points += block_data.statements.len() + 1;
+                v
+            })
+            .collect();
+
+        let mut basic_blocks = IndexVec::with_capacity(num_points);
+        for (bb, bb_data) in body.basic_blocks.iter_enumerated() {
+            basic_blocks.extend((0..=bb_data.statements.len()).map(|_| bb));
+        }
+
+        Self { statements_before_block, basic_blocks, num_points }
+    }
+
+    /// Total number of point indices
+    #[inline]
+    pub fn num_points(&self) -> usize {
+        self.num_points
+    }
+
+    /// Converts a `Location` into a `PointIndex`. O(1).
+    #[inline]
+    pub fn point_from_location(&self, location: Location) -> PointIndex {
+        let Location { block, statement_index } = location;
+        let start_index = self.statements_before_block[block];
+        PointIndex::new(start_index + statement_index)
+    }
+
+    /// Returns the `PointIndex` for the first statement in the given `BasicBlock`. O(1).
+    #[inline]
+    pub fn entry_point(&self, block: BasicBlock) -> PointIndex {
+        let start_index = self.statements_before_block[block];
+        PointIndex::new(start_index)
+    }
+
+    /// Return the PointIndex for the block start of this index.
+    #[inline]
+    pub fn to_block_start(&self, index: PointIndex) -> PointIndex {
+        PointIndex::new(self.statements_before_block[self.basic_blocks[index]])
+    }
+
+    /// Converts a `PointIndex` back to a location. O(1).
+    #[inline]
+    pub fn to_location(&self, index: PointIndex) -> Location {
+        assert!(index.index() < self.num_points);
+        let block = self.basic_blocks[index];
+        let start_index = self.statements_before_block[block];
+        let statement_index = index.index() - start_index;
+        Location { block, statement_index }
+    }
+
+    /// Sometimes we get point-indices back from bitsets that may be
+    /// out of range (because they round up to the nearest 2^N number
+    /// of bits). Use this function to filter such points out if you
+    /// like.
+    #[inline]
+    pub fn point_in_range(&self, index: PointIndex) -> bool {
+        index.index() < self.num_points
+    }
+}
+
+rustc_index::newtype_index! {
+    /// A single integer representing a `Location` in the MIR control-flow
+    /// graph. Constructed efficiently from `DenseLocationMap`.
+    #[orderable]
+    #[debug_format = "PointIndex({})"]
+    pub struct PointIndex {}
+}
+
+/// Add points depending on the result of the given dataflow analysis.
+pub fn save_as_intervals<'tcx, N, R>(
+    elements: &DenseLocationMap,
+    body: &mir::Body<'tcx>,
+    mut results: R,
+) -> SparseIntervalMatrix<N, PointIndex>
+where
+    N: Idx,
+    R: ResultsVisitable<'tcx, FlowState = ChunkedBitSet<N>>,
+{
+    let values = SparseIntervalMatrix::new(elements.num_points());
+    let mut visitor = Visitor { elements, values };
+    visit_results(
+        body,
+        body.basic_blocks.reverse_postorder().iter().copied(),
+        &mut results,
+        &mut visitor,
+    );
+    visitor.values
+}
+
+struct Visitor<'a, N: Idx> {
+    elements: &'a DenseLocationMap,
+    values: SparseIntervalMatrix<N, PointIndex>,
+}
+
+impl<'mir, 'tcx, R, N> ResultsVisitor<'mir, 'tcx, R> for Visitor<'_, N>
+where
+    N: Idx,
+{
+    type FlowState = ChunkedBitSet<N>;
+
+    fn visit_statement_after_primary_effect(
+        &mut self,
+        _results: &mut R,
+        state: &Self::FlowState,
+        _statement: &'mir mir::Statement<'tcx>,
+        location: Location,
+    ) {
+        let point = self.elements.point_from_location(location);
+        // Use internal iterator manually as it is much more efficient.
+        state.iter().for_each(|node| {
+            self.values.insert(node, point);
+        });
+    }
+
+    fn visit_terminator_after_primary_effect(
+        &mut self,
+        _results: &mut R,
+        state: &Self::FlowState,
+        _terminator: &'mir mir::Terminator<'tcx>,
+        location: Location,
+    ) {
+        let point = self.elements.point_from_location(location);
+        // Use internal iterator manually as it is much more efficient.
+        state.iter().for_each(|node| {
+            self.values.insert(node, point);
+        });
+    }
+}
diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs
index 5373876d1c2..08a5d70fb6f 100644
--- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs
+++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs
@@ -209,7 +209,7 @@ impl PeekCall {
 
                 assert_eq!(fn_args.len(), 1);
                 let kind = PeekCallKind::from_arg_ty(fn_args.type_at(0));
-                let arg = match &args[0] {
+                let arg = match &args[0].node {
                     Operand::Copy(place) | Operand::Move(place) => {
                         if let Some(local) = place.as_local() {
                             local
diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs
index 379e96e263c..eaa36e0cc91 100644
--- a/compiler/rustc_mir_transform/src/coroutine.rs
+++ b/compiler/rustc_mir_transform/src/coroutine.rs
@@ -675,9 +675,9 @@ fn eliminate_get_context_call<'tcx>(bb_data: &mut BasicBlockData<'tcx>) -> Local
     let terminator = bb_data.terminator.take().unwrap();
     if let TerminatorKind::Call { mut args, destination, target, .. } = terminator.kind {
         let arg = args.pop().unwrap();
-        let local = arg.place().unwrap().local;
+        let local = arg.node.place().unwrap().local;
 
-        let arg = Rvalue::Use(arg);
+        let arg = Rvalue::Use(arg.node);
         let assign = Statement {
             source_info: terminator.source_info,
             kind: StatementKind::Assign(Box::new((destination, arg))),
@@ -1865,7 +1865,7 @@ impl<'tcx> Visitor<'tcx> for EnsureCoroutineFieldAssignmentsNeverAlias<'_> {
                 self.check_assigned_place(*destination, |this| {
                     this.visit_operand(func, location);
                     for arg in args {
-                        this.visit_operand(arg, location);
+                        this.visit_operand(&arg.node, location);
                     }
                 });
             }
diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs
index 263bfdaaaba..c6badbe78a4 100644
--- a/compiler/rustc_mir_transform/src/coverage/graph.rs
+++ b/compiler/rustc_mir_transform/src/coverage/graph.rs
@@ -1,9 +1,10 @@
 use rustc_data_structures::captures::Captures;
+use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::graph::dominators::{self, Dominators};
 use rustc_data_structures::graph::{self, GraphSuccessors, WithNumNodes, WithStartNode};
 use rustc_index::bit_set::BitSet;
-use rustc_index::{IndexSlice, IndexVec};
-use rustc_middle::mir::{self, BasicBlock, TerminatorKind};
+use rustc_index::IndexVec;
+use rustc_middle::mir::{self, BasicBlock, Terminator, TerminatorKind};
 
 use std::cmp::Ordering;
 use std::collections::VecDeque;
@@ -30,23 +31,16 @@ impl CoverageGraph {
         // `SwitchInt` to have multiple targets to the same destination `BasicBlock`, so
         // de-duplication is required. This is done without reordering the successors.
 
-        let mut seen = IndexVec::from_elem(false, &bcbs);
         let successors = IndexVec::from_fn_n(
             |bcb| {
-                for b in seen.iter_mut() {
-                    *b = false;
-                }
-                let bcb_data = &bcbs[bcb];
-                let mut bcb_successors = Vec::new();
-                for successor in bcb_filtered_successors(mir_body, bcb_data.last_bb())
+                let mut seen_bcbs = FxHashSet::default();
+                let terminator = mir_body[bcbs[bcb].last_bb()].terminator();
+                bcb_filtered_successors(terminator)
+                    .into_iter()
                     .filter_map(|successor_bb| bb_to_bcb[successor_bb])
-                {
-                    if !seen[successor] {
-                        seen[successor] = true;
-                        bcb_successors.push(successor);
-                    }
-                }
-                bcb_successors
+                    // Remove duplicate successor BCBs, keeping only the first.
+                    .filter(|&successor_bcb| seen_bcbs.insert(successor_bcb))
+                    .collect::<Vec<_>>()
             },
             bcbs.len(),
         );
@@ -80,9 +74,23 @@ impl CoverageGraph {
         IndexVec<BasicBlock, Option<BasicCoverageBlock>>,
     ) {
         let num_basic_blocks = mir_body.basic_blocks.len();
-        let mut bcbs = IndexVec::with_capacity(num_basic_blocks);
+        let mut bcbs = IndexVec::<BasicCoverageBlock, _>::with_capacity(num_basic_blocks);
         let mut bb_to_bcb = IndexVec::from_elem_n(None, num_basic_blocks);
 
+        let mut add_basic_coverage_block = |basic_blocks: &mut Vec<BasicBlock>| {
+            // Take the accumulated list of blocks, leaving the vector empty
+            // to be used by subsequent BCBs.
+            let basic_blocks = std::mem::take(basic_blocks);
+
+            let bcb = bcbs.next_index();
+            for &bb in basic_blocks.iter() {
+                bb_to_bcb[bb] = Some(bcb);
+            }
+            let bcb_data = BasicCoverageBlockData::from(basic_blocks);
+            debug!("adding bcb{}: {:?}", bcb.index(), bcb_data);
+            bcbs.push(bcb_data);
+        };
+
         // Walk the MIR CFG using a Preorder traversal, which starts from `START_BLOCK` and follows
         // each block terminator's `successors()`. Coverage spans must map to actual source code,
         // so compiler generated blocks and paths can be ignored. To that end, the CFG traversal
@@ -90,102 +98,42 @@ impl CoverageGraph {
         // FIXME(#78544): MIR InstrumentCoverage: Improve coverage of `#[should_panic]` tests and
         // `catch_unwind()` handlers.
 
+        // Accumulates a chain of blocks that will be combined into one BCB.
         let mut basic_blocks = Vec::new();
-        for bb in short_circuit_preorder(mir_body, bcb_filtered_successors) {
-            if let Some(last) = basic_blocks.last() {
-                let predecessors = &mir_body.basic_blocks.predecessors()[bb];
-                if predecessors.len() > 1 || !predecessors.contains(last) {
-                    // The `bb` has more than one _incoming_ edge, and should start its own
-                    // `BasicCoverageBlockData`. (Note, the `basic_blocks` vector does not yet
-                    // include `bb`; it contains a sequence of one or more sequential basic_blocks
-                    // with no intermediate branches in or out. Save these as a new
-                    // `BasicCoverageBlockData` before starting the new one.)
-                    Self::add_basic_coverage_block(
-                        &mut bcbs,
-                        &mut bb_to_bcb,
-                        basic_blocks.split_off(0),
-                    );
-                    debug!(
-                        "  because {}",
-                        if predecessors.len() > 1 {
-                            "predecessors.len() > 1".to_owned()
-                        } else {
-                            format!("bb {} is not in predecessors: {:?}", bb.index(), predecessors)
-                        }
-                    );
-                }
-            }
-            basic_blocks.push(bb);
 
-            let term = mir_body[bb].terminator();
-
-            match term.kind {
-                TerminatorKind::Return { .. }
-                | TerminatorKind::UnwindTerminate(_)
-                | TerminatorKind::Yield { .. }
-                | TerminatorKind::SwitchInt { .. } => {
-                    // The `bb` has more than one _outgoing_ edge, or exits the function. Save the
-                    // current sequence of `basic_blocks` gathered to this point, as a new
-                    // `BasicCoverageBlockData`.
-                    Self::add_basic_coverage_block(
-                        &mut bcbs,
-                        &mut bb_to_bcb,
-                        basic_blocks.split_off(0),
-                    );
-                    debug!("  because term.kind = {:?}", term.kind);
-                    // Note that this condition is based on `TerminatorKind`, even though it
-                    // theoretically boils down to `successors().len() != 1`; that is, either zero
-                    // (e.g., `Return`, `Terminate`) or multiple successors (e.g., `SwitchInt`), but
-                    // since the BCB CFG ignores things like unwind branches (which exist in the
-                    // `Terminator`s `successors()` list) checking the number of successors won't
-                    // work.
-                }
-
-                // The following `TerminatorKind`s are either not expected outside an unwind branch,
-                // or they should not (under normal circumstances) branch. Coverage graphs are
-                // simplified by assuring coverage results are accurate for program executions that
-                // don't panic.
-                //
-                // Programs that panic and unwind may record slightly inaccurate coverage results
-                // for a coverage region containing the `Terminator` that began the panic. This
-                // is as intended. (See Issue #78544 for a possible future option to support
-                // coverage in test programs that panic.)
-                TerminatorKind::Goto { .. }
-                | TerminatorKind::UnwindResume
-                | TerminatorKind::Unreachable
-                | TerminatorKind::Drop { .. }
-                | TerminatorKind::Call { .. }
-                | TerminatorKind::CoroutineDrop
-                | TerminatorKind::Assert { .. }
-                | TerminatorKind::FalseEdge { .. }
-                | TerminatorKind::FalseUnwind { .. }
-                | TerminatorKind::InlineAsm { .. } => {}
+        let filtered_successors = |bb| bcb_filtered_successors(mir_body[bb].terminator());
+        for bb in short_circuit_preorder(mir_body, filtered_successors)
+            .filter(|&bb| mir_body[bb].terminator().kind != TerminatorKind::Unreachable)
+        {
+            // If the previous block can't be chained into `bb`, flush the accumulated
+            // blocks into a new BCB, then start building the next chain.
+            if let Some(&prev) = basic_blocks.last()
+                && (!filtered_successors(prev).is_chainable() || {
+                    // If `bb` has multiple predecessor blocks, or `prev` isn't
+                    // one of its predecessors, we can't chain and must flush.
+                    let predecessors = &mir_body.basic_blocks.predecessors()[bb];
+                    predecessors.len() > 1 || !predecessors.contains(&prev)
+                })
+            {
+                debug!(
+                    terminator_kind = ?mir_body[prev].terminator().kind,
+                    predecessors = ?&mir_body.basic_blocks.predecessors()[bb],
+                    "can't chain from {prev:?} to {bb:?}"
+                );
+                add_basic_coverage_block(&mut basic_blocks);
             }
+
+            basic_blocks.push(bb);
         }
 
         if !basic_blocks.is_empty() {
-            // process any remaining basic_blocks into a final `BasicCoverageBlockData`
-            Self::add_basic_coverage_block(&mut bcbs, &mut bb_to_bcb, basic_blocks.split_off(0));
-            debug!("  because the end of the MIR CFG was reached while traversing");
+            debug!("flushing accumulated blocks into one last BCB");
+            add_basic_coverage_block(&mut basic_blocks);
         }
 
         (bcbs, bb_to_bcb)
     }
 
-    fn add_basic_coverage_block(
-        bcbs: &mut IndexVec<BasicCoverageBlock, BasicCoverageBlockData>,
-        bb_to_bcb: &mut IndexSlice<BasicBlock, Option<BasicCoverageBlock>>,
-        basic_blocks: Vec<BasicBlock>,
-    ) {
-        let bcb = bcbs.next_index();
-        for &bb in basic_blocks.iter() {
-            bb_to_bcb[bb] = Some(bcb);
-        }
-        let bcb_data = BasicCoverageBlockData::from(basic_blocks);
-        debug!("adding bcb{}: {:?}", bcb.index(), bcb_data);
-        bcbs.push(bcb_data);
-    }
-
     #[inline(always)]
     pub fn iter_enumerated(
         &self,
@@ -346,28 +294,76 @@ impl BasicCoverageBlockData {
     }
 }
 
+/// Holds the coverage-relevant successors of a basic block's terminator, and
+/// indicates whether that block can potentially be combined into the same BCB
+/// as its sole successor.
+#[derive(Clone, Copy, Debug)]
+enum CoverageSuccessors<'a> {
+    /// The terminator has exactly one straight-line successor, so its block can
+    /// potentially be combined into the same BCB as that successor.
+    Chainable(BasicBlock),
+    /// The block cannot be combined into the same BCB as its successor(s).
+    NotChainable(&'a [BasicBlock]),
+}
+
+impl CoverageSuccessors<'_> {
+    fn is_chainable(&self) -> bool {
+        match self {
+            Self::Chainable(_) => true,
+            Self::NotChainable(_) => false,
+        }
+    }
+}
+
+impl IntoIterator for CoverageSuccessors<'_> {
+    type Item = BasicBlock;
+    type IntoIter = impl DoubleEndedIterator<Item = Self::Item>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        match self {
+            Self::Chainable(bb) => Some(bb).into_iter().chain((&[]).iter().copied()),
+            Self::NotChainable(bbs) => None.into_iter().chain(bbs.iter().copied()),
+        }
+    }
+}
+
 // Returns the subset of a block's successors that are relevant to the coverage
-// graph, i.e. those that do not represent unwinds or unreachable branches.
+// graph, i.e. those that do not represent unwinds or false edges.
 // FIXME(#78544): MIR InstrumentCoverage: Improve coverage of `#[should_panic]` tests and
 // `catch_unwind()` handlers.
-fn bcb_filtered_successors<'a, 'tcx>(
-    body: &'a mir::Body<'tcx>,
-    bb: BasicBlock,
-) -> impl Iterator<Item = BasicBlock> + Captures<'a> + Captures<'tcx> {
-    let terminator = body[bb].terminator();
-
-    let take_n_successors = match terminator.kind {
-        // SwitchInt successors are never unwinds, so all of them should be traversed.
-        TerminatorKind::SwitchInt { .. } => usize::MAX,
-        // For all other kinds, return only the first successor (if any), ignoring any
-        // unwind successors.
-        _ => 1,
-    };
-
-    terminator
-        .successors()
-        .take(take_n_successors)
-        .filter(move |&successor| body[successor].terminator().kind != TerminatorKind::Unreachable)
+fn bcb_filtered_successors<'a, 'tcx>(terminator: &'a Terminator<'tcx>) -> CoverageSuccessors<'a> {
+    use TerminatorKind::*;
+    match terminator.kind {
+        // A switch terminator can have many coverage-relevant successors.
+        // (If there is exactly one successor, we still treat it as not chainable.)
+        SwitchInt { ref targets, .. } => CoverageSuccessors::NotChainable(targets.all_targets()),
+
+        // A yield terminator has exactly 1 successor, but should not be chained,
+        // because its resume edge has a different execution count.
+        Yield { ref resume, .. } => CoverageSuccessors::NotChainable(std::slice::from_ref(resume)),
+
+        // These terminators have exactly one coverage-relevant successor,
+        // and can be chained into it.
+        Assert { target, .. }
+        | Drop { target, .. }
+        | FalseEdge { real_target: target, .. }
+        | FalseUnwind { real_target: target, .. }
+        | Goto { target } => CoverageSuccessors::Chainable(target),
+
+        // These terminators can normally be chained, except when they have no
+        // successor because they are known to diverge.
+        Call { target: maybe_target, .. } | InlineAsm { destination: maybe_target, .. } => {
+            match maybe_target {
+                Some(target) => CoverageSuccessors::Chainable(target),
+                None => CoverageSuccessors::NotChainable(&[]),
+            }
+        }
+
+        // These terminators have no coverage-relevant successors.
+        CoroutineDrop | Return | Unreachable | UnwindResume | UnwindTerminate(_) => {
+            CoverageSuccessors::NotChainable(&[])
+        }
+    }
 }
 
 /// Maintains separate worklists for each loop in the BasicCoverageBlock CFG, plus one for the
@@ -544,8 +540,8 @@ fn short_circuit_preorder<'a, 'tcx, F, Iter>(
     filtered_successors: F,
 ) -> impl Iterator<Item = BasicBlock> + Captures<'a> + Captures<'tcx>
 where
-    F: Fn(&'a mir::Body<'tcx>, BasicBlock) -> Iter,
-    Iter: Iterator<Item = BasicBlock>,
+    F: Fn(BasicBlock) -> Iter,
+    Iter: IntoIterator<Item = BasicBlock>,
 {
     let mut visited = BitSet::new_empty(body.basic_blocks.len());
     let mut worklist = vec![mir::START_BLOCK];
@@ -556,7 +552,7 @@ where
                 continue;
             }
 
-            worklist.extend(filtered_successors(body, bb));
+            worklist.extend(filtered_successors(bb));
 
             return Some(bb);
         }
diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs
index 3d74ef7e327..e6317e5469c 100644
--- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs
+++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs
@@ -52,7 +52,7 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             live.seek_to_block_end(bb);
             let mut state = live.get().clone();
 
-            for (index, arg) in args.iter().enumerate().rev() {
+            for (index, arg) in args.iter().map(|a| &a.node).enumerate().rev() {
                 if let Operand::Copy(place) = *arg
                     && !place.is_indirect()
                     // Do not skip the transformation if the local is in debuginfo, as we do
@@ -119,17 +119,25 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         let TerminatorKind::Call { ref mut args, .. } = bbs[block].terminator_mut().kind else {
             bug!()
         };
-        let arg = &mut args[argument_index];
+        let arg = &mut args[argument_index].node;
         let Operand::Copy(place) = *arg else { bug!() };
         *arg = Operand::Move(place);
     }
-
-    crate::simplify::simplify_locals(body, tcx)
 }
 
-pub struct DeadStoreElimination;
+pub enum DeadStoreElimination {
+    Initial,
+    Final,
+}
 
 impl<'tcx> MirPass<'tcx> for DeadStoreElimination {
+    fn name(&self) -> &'static str {
+        match self {
+            DeadStoreElimination::Initial => "DeadStoreElimination-initial",
+            DeadStoreElimination::Final => "DeadStoreElimination-final",
+        }
+    }
+
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
         sess.mir_opt_level() >= 2
     }
diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
index 990cfb05e60..a6750911394 100644
--- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
+++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
@@ -111,7 +111,7 @@ impl<'tcx> Visitor<'tcx> for DeduceReadOnly {
 
         if let TerminatorKind::Call { ref args, .. } = terminator.kind {
             for arg in args {
-                if let Operand::Move(place) = *arg {
+                if let Operand::Move(place) = arg.node {
                     let local = place.local;
                     if place.is_indirect()
                         || local == RETURN_PLACE
diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs
index 49b0edc0db8..0ac4ab61d40 100644
--- a/compiler/rustc_mir_transform/src/dest_prop.rs
+++ b/compiler/rustc_mir_transform/src/dest_prop.rs
@@ -134,6 +134,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::mir::visit::{MutVisitor, PlaceContext, Visitor};
 use rustc_middle::mir::HasLocalDecls;
 use rustc_middle::mir::{dump_mir, PassWhere};
@@ -143,7 +144,8 @@ use rustc_middle::mir::{
 };
 use rustc_middle::ty::TyCtxt;
 use rustc_mir_dataflow::impls::MaybeLiveLocals;
-use rustc_mir_dataflow::{Analysis, ResultsCursor};
+use rustc_mir_dataflow::points::{save_as_intervals, DenseLocationMap, PointIndex};
+use rustc_mir_dataflow::Analysis;
 
 pub struct DestinationPropagation;
 
@@ -167,6 +169,13 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation {
 
         let borrowed = rustc_mir_dataflow::impls::borrowed_locals(body);
 
+        let live = MaybeLiveLocals
+            .into_engine(tcx, body)
+            .pass_name("MaybeLiveLocals-DestinationPropagation")
+            .iterate_to_fixpoint();
+        let points = DenseLocationMap::new(body);
+        let mut live = save_as_intervals(&points, body, live);
+
         // In order to avoid having to collect data for every single pair of locals in the body, we
         // do not allow doing more than one merge for places that are derived from the same local at
         // once. To avoid missed opportunities, we instead iterate to a fixed point - we'll refer to
@@ -190,22 +199,19 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation {
                 &mut allocations.candidates_reverse,
             );
             trace!(?candidates);
-            let mut live = MaybeLiveLocals
-                .into_engine(tcx, body)
-                .iterate_to_fixpoint()
-                .into_results_cursor(body);
-            dest_prop_mir_dump(tcx, body, &mut live, round_count);
+            dest_prop_mir_dump(tcx, body, &points, &live, round_count);
 
             FilterInformation::filter_liveness(
                 &mut candidates,
-                &mut live,
+                &points,
+                &live,
                 &mut allocations.write_info,
                 body,
             );
 
-            // Because we do not update liveness information, it is unsound to use a local for more
-            // than one merge operation within a single round of optimizations. We store here which
-            // ones we have already used.
+            // Because we only filter once per round, it is unsound to use a local for more than
+            // one merge operation within a single round of optimizations. We store here which ones
+            // we have already used.
             let mut merged_locals: BitSet<Local> = BitSet::new_empty(body.local_decls.len());
 
             // This is the set of merges we will apply this round. It is a subset of the candidates.
@@ -224,9 +230,15 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation {
                 }) {
                     break;
                 }
+
+                // Replace `src` by `dest` everywhere.
                 merges.insert(*src, *dest);
                 merged_locals.insert(*src);
                 merged_locals.insert(*dest);
+
+                // Update liveness information based on the merge we just performed.
+                // Every location where `src` was live, `dest` will be live.
+                live.union_rows(*src, *dest);
             }
             trace!(merging = ?merges);
 
@@ -349,7 +361,8 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Merger<'a, 'tcx> {
 
 struct FilterInformation<'a, 'body, 'alloc, 'tcx> {
     body: &'body Body<'tcx>,
-    live: &'a mut ResultsCursor<'body, 'tcx, MaybeLiveLocals>,
+    points: &'a DenseLocationMap,
+    live: &'a SparseIntervalMatrix<Local, PointIndex>,
     candidates: &'a mut Candidates<'alloc>,
     write_info: &'alloc mut WriteInfo,
     at: Location,
@@ -452,12 +465,14 @@ impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> {
     /// locals as also being read from.
     fn filter_liveness<'b>(
         candidates: &mut Candidates<'alloc>,
-        live: &mut ResultsCursor<'b, 'tcx, MaybeLiveLocals>,
+        points: &DenseLocationMap,
+        live: &SparseIntervalMatrix<Local, PointIndex>,
         write_info_alloc: &'alloc mut WriteInfo,
         body: &'b Body<'tcx>,
     ) {
         let mut this = FilterInformation {
             body,
+            points,
             live,
             candidates,
             // We don't actually store anything at this scope, we just keep things here to be able
@@ -472,13 +487,11 @@ impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> {
     fn internal_filter_liveness(&mut self) {
         for (block, data) in traversal::preorder(self.body) {
             self.at = Location { block, statement_index: data.statements.len() };
-            self.live.seek_after_primary_effect(self.at);
             self.write_info.for_terminator(&data.terminator().kind);
             self.apply_conflicts();
 
             for (i, statement) in data.statements.iter().enumerate().rev() {
                 self.at = Location { block, statement_index: i };
-                self.live.seek_after_primary_effect(self.at);
                 self.write_info.for_statement(&statement.kind, self.body);
                 self.apply_conflicts();
             }
@@ -497,6 +510,7 @@ impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> {
                     None
                 }
             });
+            let at = self.points.point_from_location(self.at);
             self.candidates.filter_candidates_by(
                 *p,
                 |q| {
@@ -508,7 +522,7 @@ impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> {
                     // calls or inline asm. Because of this, we also mark locals as
                     // conflicting when both of them are written to in the same
                     // statement.
-                    if self.live.contains(q) || writes.contains(&q) {
+                    if self.live.contains(q, at) || writes.contains(&q) {
                         CandidateFilter::Remove
                     } else {
                         CandidateFilter::Keep
@@ -609,7 +623,7 @@ impl WriteInfo {
                 self.add_place(*destination);
                 self.add_operand(func);
                 for arg in args {
-                    self.add_operand(arg);
+                    self.add_operand(&arg.node);
                 }
             }
             TerminatorKind::InlineAsm { operands, .. } => {
@@ -801,38 +815,17 @@ fn is_local_required(local: Local, body: &Body<'_>) -> bool {
 fn dest_prop_mir_dump<'body, 'tcx>(
     tcx: TyCtxt<'tcx>,
     body: &'body Body<'tcx>,
-    live: &mut ResultsCursor<'body, 'tcx, MaybeLiveLocals>,
+    points: &DenseLocationMap,
+    live: &SparseIntervalMatrix<Local, PointIndex>,
     round: usize,
 ) {
-    let mut reachable = None;
+    let locals_live_at = |location| {
+        let location = points.point_from_location(location);
+        live.rows().filter(|&r| live.contains(r, location)).collect::<Vec<_>>()
+    };
     dump_mir(tcx, false, "DestinationPropagation-dataflow", &round, body, |pass_where, w| {
-        let reachable = reachable.get_or_insert_with(|| traversal::reachable_as_bitset(body));
-
-        match pass_where {
-            PassWhere::BeforeLocation(loc) if reachable.contains(loc.block) => {
-                live.seek_after_primary_effect(loc);
-                writeln!(w, "        // live: {:?}", live.get())?;
-            }
-            PassWhere::AfterTerminator(bb) if reachable.contains(bb) => {
-                let loc = body.terminator_loc(bb);
-                live.seek_before_primary_effect(loc);
-                writeln!(w, "        // live: {:?}", live.get())?;
-            }
-
-            PassWhere::BeforeBlock(bb) if reachable.contains(bb) => {
-                live.seek_to_block_start(bb);
-                writeln!(w, "    // live: {:?}", live.get())?;
-            }
-
-            PassWhere::BeforeCFG | PassWhere::AfterCFG | PassWhere::AfterLocation(_) => {}
-
-            PassWhere::BeforeLocation(_) | PassWhere::AfterTerminator(_) => {
-                writeln!(w, "        // live: <unreachable>")?;
-            }
-
-            PassWhere::BeforeBlock(_) => {
-                writeln!(w, "    // live: <unreachable>")?;
-            }
+        if let PassWhere::BeforeLocation(loc) = pass_where {
+            writeln!(w, "        // live: {:?}", locals_live_at(loc))?;
         }
 
         Ok(())
diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs
index 446f13feff0..2ee660ddc9b 100644
--- a/compiler/rustc_mir_transform/src/errors.rs
+++ b/compiler/rustc_mir_transform/src/errors.rs
@@ -66,7 +66,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for RequiresUnsafe {
     #[track_caller]
     fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> {
         let mut diag = DiagnosticBuilder::new(dcx, level, fluent::mir_transform_requires_unsafe);
-        diag.code(rustc_errors::DiagnosticId::Error("E0133".to_string()));
+        diag.code("E0133".to_string());
         diag.span(self.span);
         diag.span_label(self.span, self.details.label());
         let desc = dcx.eagerly_translate_to_string(self.details.label(), [].into_iter());
diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs
index 340bb1948eb..61d99f1f018 100644
--- a/compiler/rustc_mir_transform/src/function_item_references.rs
+++ b/compiler/rustc_mir_transform/src/function_item_references.rs
@@ -4,6 +4,7 @@ use rustc_middle::mir::visit::Visitor;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, EarlyBinder, GenericArgsRef, Ty, TyCtxt};
 use rustc_session::lint::builtin::FUNCTION_ITEM_REFERENCES;
+use rustc_span::source_map::Spanned;
 use rustc_span::{symbol::sym, Span};
 use rustc_target::spec::abi::Abi;
 
@@ -43,7 +44,7 @@ impl<'tcx> Visitor<'tcx> for FunctionItemRefChecker<'_, 'tcx> {
             if let ty::FnDef(def_id, args_ref) = *func_ty.kind() {
                 // Handle calls to `transmute`
                 if self.tcx.is_diagnostic_item(sym::transmute, def_id) {
-                    let arg_ty = args[0].ty(self.body, self.tcx);
+                    let arg_ty = args[0].node.ty(self.body, self.tcx);
                     for inner_ty in arg_ty.walk().filter_map(|arg| arg.as_type()) {
                         if let Some((fn_id, fn_args)) = FunctionItemRefChecker::is_fn_ref(inner_ty)
                         {
@@ -67,7 +68,7 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
         &self,
         def_id: DefId,
         args_ref: GenericArgsRef<'tcx>,
-        args: &[Operand<'tcx>],
+        args: &[Spanned<Operand<'tcx>>],
         source_info: SourceInfo,
     ) {
         let param_env = self.tcx.param_env(def_id);
@@ -134,8 +135,8 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
             .unwrap_or(None)
     }
 
-    fn nth_arg_span(&self, args: &[Operand<'tcx>], n: usize) -> Span {
-        match &args[n] {
+    fn nth_arg_span(&self, args: &[Spanned<Operand<'tcx>>], n: usize) -> Span {
+        match &args[n].node {
             Operand::Copy(place) | Operand::Move(place) => {
                 self.body.local_decls[place.local].source_info.span
             }
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index 2551c8aca88..390ec3e1a36 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -84,7 +84,7 @@
 
 use rustc_const_eval::interpret::{intern_const_alloc_for_constprop, MemoryKind};
 use rustc_const_eval::interpret::{ImmTy, InterpCx, OpTy, Projectable, Scalar};
-use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
+use rustc_data_structures::fx::FxIndexSet;
 use rustc_data_structures::graph::dominators::Dominators;
 use rustc_hir::def::DefKind;
 use rustc_index::bit_set::BitSet;
@@ -99,6 +99,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt, TypeAndMut};
 use rustc_span::def_id::DefId;
 use rustc_span::DUMMY_SP;
 use rustc_target::abi::{self, Abi, Size, VariantIdx, FIRST_VARIANT};
+use smallvec::SmallVec;
 use std::borrow::Cow;
 
 use crate::dataflow_const_prop::DummyMachine;
@@ -238,14 +239,18 @@ struct VnState<'body, 'tcx> {
     local_decls: &'body LocalDecls<'tcx>,
     /// Value stored in each local.
     locals: IndexVec<Local, Option<VnIndex>>,
-    /// First local to be assigned that value.
-    rev_locals: FxHashMap<VnIndex, Vec<Local>>,
+    /// Locals that are assigned that value.
+    // This vector does not hold all the values of `VnIndex` that we create.
+    // It stops at the largest value created in the first phase of collecting assignments.
+    rev_locals: IndexVec<VnIndex, SmallVec<[Local; 1]>>,
     values: FxIndexSet<Value<'tcx>>,
     /// Values evaluated as constants if possible.
     evaluated: IndexVec<VnIndex, Option<OpTy<'tcx>>>,
     /// Counter to generate different values.
     /// This is an option to stop creating opaques during replacement.
     next_opaque: Option<usize>,
+    /// Cache the value of the `unsized_locals` features, to avoid fetching it repeatedly in a loop.
+    feature_unsized_locals: bool,
     ssa: &'body SsaLocals,
     dominators: &'body Dominators<BasicBlock>,
     reused_locals: BitSet<Local>,
@@ -265,10 +270,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
             param_env,
             local_decls,
             locals: IndexVec::from_elem(None, local_decls),
-            rev_locals: FxHashMap::default(),
+            rev_locals: IndexVec::default(),
             values: FxIndexSet::default(),
             evaluated: IndexVec::new(),
             next_opaque: Some(0),
+            feature_unsized_locals: tcx.features().unsized_locals,
             ssa,
             dominators,
             reused_locals: BitSet::new_empty(local_decls.len()),
@@ -316,10 +322,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
         self.locals[local] = Some(value);
 
         // Only register the value if its type is `Sized`, as we will emit copies of it.
-        let is_sized = !self.tcx.features().unsized_locals
+        let is_sized = !self.feature_unsized_locals
             || self.local_decls[local].ty.is_sized(self.tcx, self.param_env);
         if is_sized {
-            self.rev_locals.entry(value).or_default().push(local);
+            self.rev_locals.ensure_contains_elem(value, SmallVec::new);
+            self.rev_locals[value].push(local);
         }
     }
 
@@ -338,11 +345,20 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
         Some(self.insert(Value::Constant { value, disambiguator }))
     }
 
+    fn insert_bool(&mut self, flag: bool) -> VnIndex {
+        // Booleans are deterministic.
+        self.insert(Value::Constant { value: Const::from_bool(self.tcx, flag), disambiguator: 0 })
+    }
+
     fn insert_scalar(&mut self, scalar: Scalar, ty: Ty<'tcx>) -> VnIndex {
         self.insert_constant(Const::from_scalar(self.tcx, scalar, ty))
             .expect("scalars are deterministic")
     }
 
+    fn insert_tuple(&mut self, values: Vec<VnIndex>) -> VnIndex {
+        self.insert(Value::Aggregate(AggregateTy::Tuple, VariantIdx::from_u32(0), values))
+    }
+
     #[instrument(level = "trace", skip(self), ret)]
     fn eval_to_const(&mut self, value: VnIndex) -> Option<OpTy<'tcx>> {
         use Value::*;
@@ -630,6 +646,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
         if place.is_indirect()
             && let Some(base) = self.locals[place.local]
             && let Some(new_local) = self.try_as_local(base, location)
+            && place.local != new_local
         {
             place.local = new_local;
             self.reused_locals.insert(new_local);
@@ -639,8 +656,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
 
         for i in 0..projection.len() {
             let elem = projection[i];
-            if let ProjectionElem::Index(idx) = elem
-                && let Some(idx) = self.locals[idx]
+            if let ProjectionElem::Index(idx_local) = elem
+                && let Some(idx) = self.locals[idx_local]
             {
                 if let Some(offset) = self.evaluated[idx].as_ref()
                     && let Ok(offset) = self.ecx.read_target_usize(offset)
@@ -648,9 +665,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
                 {
                     projection.to_mut()[i] =
                         ProjectionElem::ConstantIndex { offset, min_length, from_end: false };
-                } else if let Some(new_idx) = self.try_as_local(idx, location) {
-                    projection.to_mut()[i] = ProjectionElem::Index(new_idx);
-                    self.reused_locals.insert(new_idx);
+                } else if let Some(new_idx_local) = self.try_as_local(idx, location)
+                    && idx_local != new_idx_local
+                {
+                    projection.to_mut()[i] = ProjectionElem::Index(new_idx_local);
+                    self.reused_locals.insert(new_idx_local);
                 }
             }
         }
@@ -757,10 +776,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
             }
 
             // Operations.
-            Rvalue::Len(ref mut place) => {
-                let place = self.simplify_place_value(place, location)?;
-                Value::Len(place)
-            }
+            Rvalue::Len(ref mut place) => return self.simplify_len(place, location),
             Rvalue::Cast(kind, ref mut value, to) => {
                 let from = value.ty(self.local_decls, self.tcx);
                 let value = self.simplify_operand(value, location)?;
@@ -775,17 +791,36 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
                 Value::Cast { kind, value, from, to }
             }
             Rvalue::BinaryOp(op, box (ref mut lhs, ref mut rhs)) => {
+                let ty = lhs.ty(self.local_decls, self.tcx);
                 let lhs = self.simplify_operand(lhs, location);
                 let rhs = self.simplify_operand(rhs, location);
-                Value::BinaryOp(op, lhs?, rhs?)
+                // Only short-circuit options after we called `simplify_operand`
+                // on both operands for side effect.
+                let lhs = lhs?;
+                let rhs = rhs?;
+                if let Some(value) = self.simplify_binary(op, false, ty, lhs, rhs) {
+                    return Some(value);
+                }
+                Value::BinaryOp(op, lhs, rhs)
             }
             Rvalue::CheckedBinaryOp(op, box (ref mut lhs, ref mut rhs)) => {
+                let ty = lhs.ty(self.local_decls, self.tcx);
                 let lhs = self.simplify_operand(lhs, location);
                 let rhs = self.simplify_operand(rhs, location);
-                Value::CheckedBinaryOp(op, lhs?, rhs?)
+                // Only short-circuit options after we called `simplify_operand`
+                // on both operands for side effect.
+                let lhs = lhs?;
+                let rhs = rhs?;
+                if let Some(value) = self.simplify_binary(op, true, ty, lhs, rhs) {
+                    return Some(value);
+                }
+                Value::CheckedBinaryOp(op, lhs, rhs)
             }
             Rvalue::UnaryOp(op, ref mut arg) => {
                 let arg = self.simplify_operand(arg, location)?;
+                if let Some(value) = self.simplify_unary(op, arg) {
+                    return Some(value);
+                }
                 Value::UnaryOp(op, arg)
             }
             Rvalue::Discriminant(ref mut place) => {
@@ -884,6 +919,150 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
 
         Some(self.insert(Value::Aggregate(ty, variant_index, fields)))
     }
+
+    #[instrument(level = "trace", skip(self), ret)]
+    fn simplify_unary(&mut self, op: UnOp, value: VnIndex) -> Option<VnIndex> {
+        let value = match (op, self.get(value)) {
+            (UnOp::Not, Value::UnaryOp(UnOp::Not, inner)) => return Some(*inner),
+            (UnOp::Neg, Value::UnaryOp(UnOp::Neg, inner)) => return Some(*inner),
+            (UnOp::Not, Value::BinaryOp(BinOp::Eq, lhs, rhs)) => {
+                Value::BinaryOp(BinOp::Ne, *lhs, *rhs)
+            }
+            (UnOp::Not, Value::BinaryOp(BinOp::Ne, lhs, rhs)) => {
+                Value::BinaryOp(BinOp::Eq, *lhs, *rhs)
+            }
+            _ => return None,
+        };
+
+        Some(self.insert(value))
+    }
+
+    #[instrument(level = "trace", skip(self), ret)]
+    fn simplify_binary(
+        &mut self,
+        op: BinOp,
+        checked: bool,
+        lhs_ty: Ty<'tcx>,
+        lhs: VnIndex,
+        rhs: VnIndex,
+    ) -> Option<VnIndex> {
+        // Floats are weird enough that none of the logic below applies.
+        let reasonable_ty =
+            lhs_ty.is_integral() || lhs_ty.is_bool() || lhs_ty.is_char() || lhs_ty.is_any_ptr();
+        if !reasonable_ty {
+            return None;
+        }
+
+        let layout = self.ecx.layout_of(lhs_ty).ok()?;
+
+        let as_bits = |value| {
+            let constant = self.evaluated[value].as_ref()?;
+            if layout.abi.is_scalar() {
+                let scalar = self.ecx.read_scalar(constant).ok()?;
+                scalar.to_bits(constant.layout.size).ok()
+            } else {
+                // `constant` is a wide pointer. Do not evaluate to bits.
+                None
+            }
+        };
+
+        // Represent the values as `Left(bits)` or `Right(VnIndex)`.
+        use Either::{Left, Right};
+        let a = as_bits(lhs).map_or(Right(lhs), Left);
+        let b = as_bits(rhs).map_or(Right(rhs), Left);
+        let result = match (op, a, b) {
+            // Neutral elements.
+            (BinOp::Add | BinOp::BitOr | BinOp::BitXor, Left(0), Right(p))
+            | (
+                BinOp::Add
+                | BinOp::BitOr
+                | BinOp::BitXor
+                | BinOp::Sub
+                | BinOp::Offset
+                | BinOp::Shl
+                | BinOp::Shr,
+                Right(p),
+                Left(0),
+            )
+            | (BinOp::Mul, Left(1), Right(p))
+            | (BinOp::Mul | BinOp::Div, Right(p), Left(1)) => p,
+            // Attempt to simplify `x & ALL_ONES` to `x`, with `ALL_ONES` depending on type size.
+            (BinOp::BitAnd, Right(p), Left(ones)) | (BinOp::BitAnd, Left(ones), Right(p))
+                if ones == layout.size.truncate(u128::MAX)
+                    || (layout.ty.is_bool() && ones == 1) =>
+            {
+                p
+            }
+            // Absorbing elements.
+            (BinOp::Mul | BinOp::BitAnd, _, Left(0))
+            | (BinOp::Rem, _, Left(1))
+            | (
+                BinOp::Mul | BinOp::Div | BinOp::Rem | BinOp::BitAnd | BinOp::Shl | BinOp::Shr,
+                Left(0),
+                _,
+            ) => self.insert_scalar(Scalar::from_uint(0u128, layout.size), lhs_ty),
+            // Attempt to simplify `x | ALL_ONES` to `ALL_ONES`.
+            (BinOp::BitOr, _, Left(ones)) | (BinOp::BitOr, Left(ones), _)
+                if ones == layout.size.truncate(u128::MAX)
+                    || (layout.ty.is_bool() && ones == 1) =>
+            {
+                self.insert_scalar(Scalar::from_uint(ones, layout.size), lhs_ty)
+            }
+            // Sub/Xor with itself.
+            (BinOp::Sub | BinOp::BitXor, a, b) if a == b => {
+                self.insert_scalar(Scalar::from_uint(0u128, layout.size), lhs_ty)
+            }
+            // Comparison:
+            // - if both operands can be computed as bits, just compare the bits;
+            // - if we proved that both operands have the same value, we can insert true/false;
+            // - otherwise, do nothing, as we do not try to prove inequality.
+            (BinOp::Eq, Left(a), Left(b)) => self.insert_bool(a == b),
+            (BinOp::Eq, a, b) if a == b => self.insert_bool(true),
+            (BinOp::Ne, Left(a), Left(b)) => self.insert_bool(a != b),
+            (BinOp::Ne, a, b) if a == b => self.insert_bool(false),
+            _ => return None,
+        };
+
+        if checked {
+            let false_val = self.insert_bool(false);
+            Some(self.insert_tuple(vec![result, false_val]))
+        } else {
+            Some(result)
+        }
+    }
+
+    fn simplify_len(&mut self, place: &mut Place<'tcx>, location: Location) -> Option<VnIndex> {
+        // Trivial case: we are fetching a statically known length.
+        let place_ty = place.ty(self.local_decls, self.tcx).ty;
+        if let ty::Array(_, len) = place_ty.kind() {
+            return self.insert_constant(Const::from_ty_const(*len, self.tcx));
+        }
+
+        let mut inner = self.simplify_place_value(place, location)?;
+
+        // The length information is stored in the fat pointer.
+        // Reborrowing copies length information from one pointer to the other.
+        while let Value::Address { place: borrowed, .. } = self.get(inner)
+            && let [PlaceElem::Deref] = borrowed.projection[..]
+            && let Some(borrowed) = self.locals[borrowed.local]
+        {
+            inner = borrowed;
+        }
+
+        // We have an unsizing cast, which assigns the length to fat pointer metadata.
+        if let Value::Cast { kind, from, to, .. } = self.get(inner)
+            && let CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize) = kind
+            && let Some(from) = from.builtin_deref(true)
+            && let ty::Array(_, len) = from.ty.kind()
+            && let Some(to) = to.builtin_deref(true)
+            && let ty::Slice(..) = to.ty.kind()
+        {
+            return self.insert_constant(Const::from_ty_const(*len, self.tcx));
+        }
+
+        // Fallback: a symbolic `Len`.
+        Some(self.insert(Value::Len(inner)))
+    }
 }
 
 fn op_to_prop_const<'tcx>(
@@ -986,11 +1165,11 @@ impl<'tcx> VnState<'_, 'tcx> {
     /// If there is a local which is assigned `index`, and its assignment strictly dominates `loc`,
     /// return it.
     fn try_as_local(&mut self, index: VnIndex, loc: Location) -> Option<Local> {
-        let other = self.rev_locals.get(&index)?;
+        let other = self.rev_locals.get(index)?;
         other
             .iter()
+            .find(|&&other| self.ssa.assignment_dominates(self.dominators, other, loc))
             .copied()
-            .find(|&other| self.ssa.assignment_dominates(self.dominators, other, loc))
     }
 }
 
@@ -1008,23 +1187,32 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
     }
 
     fn visit_statement(&mut self, stmt: &mut Statement<'tcx>, location: Location) {
-        if let StatementKind::Assign(box (_, ref mut rvalue)) = stmt.kind
+        if let StatementKind::Assign(box (ref mut lhs, ref mut rvalue)) = stmt.kind {
+            self.simplify_place_projection(lhs, location);
+
             // Do not try to simplify a constant, it's already in canonical shape.
-            && !matches!(rvalue, Rvalue::Use(Operand::Constant(_)))
-        {
-            if let Some(value) = self.simplify_rvalue(rvalue, location) {
-                if let Some(const_) = self.try_as_constant(value) {
-                    *rvalue = Rvalue::Use(Operand::Constant(Box::new(const_)));
-                } else if let Some(local) = self.try_as_local(value, location)
-                    && *rvalue != Rvalue::Use(Operand::Move(local.into()))
-                {
-                    *rvalue = Rvalue::Use(Operand::Copy(local.into()));
-                    self.reused_locals.insert(local);
-                }
+            if matches!(rvalue, Rvalue::Use(Operand::Constant(_))) {
+                return;
             }
-        } else {
-            self.super_statement(stmt, location);
+
+            let value = lhs
+                .as_local()
+                .and_then(|local| self.locals[local])
+                .or_else(|| self.simplify_rvalue(rvalue, location));
+            let Some(value) = value else { return };
+
+            if let Some(const_) = self.try_as_constant(value) {
+                *rvalue = Rvalue::Use(Operand::Constant(Box::new(const_)));
+            } else if let Some(local) = self.try_as_local(value, location)
+                && *rvalue != Rvalue::Use(Operand::Move(local.into()))
+            {
+                *rvalue = Rvalue::Use(Operand::Copy(local.into()));
+                self.reused_locals.insert(local);
+            }
+
+            return;
         }
+        self.super_statement(stmt, location);
     }
 }
 
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index ebefc3b47cc..67668a216de 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -11,6 +11,7 @@ use rustc_middle::mir::*;
 use rustc_middle::ty::TypeVisitableExt;
 use rustc_middle::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt};
 use rustc_session::config::OptLevel;
+use rustc_span::source_map::Spanned;
 use rustc_target::abi::FieldIdx;
 use rustc_target::spec::abi::Abi;
 
@@ -172,7 +173,7 @@ impl<'tcx> Inliner<'tcx> {
         let TerminatorKind::Call { args, destination, .. } = &terminator.kind else { bug!() };
         let destination_ty = destination.ty(&caller_body.local_decls, self.tcx).ty;
         for arg in args {
-            if !arg.ty(&caller_body.local_decls, self.tcx).is_sized(self.tcx, self.param_env) {
+            if !arg.node.ty(&caller_body.local_decls, self.tcx).is_sized(self.tcx, self.param_env) {
                 // We do not allow inlining functions with unsized params. Inlining these functions
                 // could create unsized locals, which are unsound and being phased out.
                 return Err("Call has unsized argument");
@@ -238,9 +239,9 @@ impl<'tcx> Inliner<'tcx> {
             };
 
             let self_arg_ty =
-                self_arg.map(|self_arg| self_arg.ty(&caller_body.local_decls, self.tcx));
+                self_arg.map(|self_arg| self_arg.node.ty(&caller_body.local_decls, self.tcx));
 
-            let arg_tuple_ty = arg_tuple.ty(&caller_body.local_decls, self.tcx);
+            let arg_tuple_ty = arg_tuple.node.ty(&caller_body.local_decls, self.tcx);
             let ty::Tuple(arg_tuple_tys) = *arg_tuple_ty.kind() else {
                 bug!("Closure arguments are not passed as a tuple");
             };
@@ -263,7 +264,7 @@ impl<'tcx> Inliner<'tcx> {
         } else {
             for (arg, input) in args.iter().zip(callee_body.args_iter()) {
                 let input_type = callee_body.local_decls[input].ty;
-                let arg_ty = arg.ty(&caller_body.local_decls, self.tcx);
+                let arg_ty = arg.node.ty(&caller_body.local_decls, self.tcx);
                 if !util::relate_types(
                     self.tcx,
                     self.param_env,
@@ -694,7 +695,7 @@ impl<'tcx> Inliner<'tcx> {
 
     fn make_call_args(
         &self,
-        args: Vec<Operand<'tcx>>,
+        args: Vec<Spanned<Operand<'tcx>>>,
         callsite: &CallSite<'tcx>,
         caller_body: &mut Body<'tcx>,
         callee_body: &Body<'tcx>,
@@ -728,13 +729,13 @@ impl<'tcx> Inliner<'tcx> {
         if callsite.fn_sig.abi() == Abi::RustCall && callee_body.spread_arg.is_none() {
             let mut args = args.into_iter();
             let self_ = self.create_temp_if_necessary(
-                args.next().unwrap(),
+                args.next().unwrap().node,
                 callsite,
                 caller_body,
                 return_block,
             );
             let tuple = self.create_temp_if_necessary(
-                args.next().unwrap(),
+                args.next().unwrap().node,
                 callsite,
                 caller_body,
                 return_block,
@@ -761,7 +762,7 @@ impl<'tcx> Inliner<'tcx> {
             closure_ref_arg.chain(tuple_tmp_args).collect()
         } else {
             args.into_iter()
-                .map(|a| self.create_temp_if_necessary(a, callsite, caller_body, return_block))
+                .map(|a| self.create_temp_if_necessary(a.node, callsite, caller_body, return_block))
                 .collect()
         }
     }
diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs
index 4f0f63d22a4..a28db0defc9 100644
--- a/compiler/rustc_mir_transform/src/instsimplify.rs
+++ b/compiler/rustc_mir_transform/src/instsimplify.rs
@@ -215,7 +215,7 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> {
 
         // These types are easily available from locals, so check that before
         // doing DefId lookups to figure out what we're actually calling.
-        let arg_ty = args[0].ty(self.local_decls, self.tcx);
+        let arg_ty = args[0].node.ty(self.local_decls, self.tcx);
 
         let ty::Ref(_region, inner_ty, Mutability::Not) = *arg_ty.kind() else { return };
 
@@ -238,7 +238,7 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> {
             return;
         }
 
-        let Some(arg_place) = args.pop().unwrap().place() else { return };
+        let Some(arg_place) = args.pop().unwrap().node.place() else { return };
 
         statements.push(Statement {
             source_info: terminator.source_info,
diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs
index dcab124505e..e87f68a0905 100644
--- a/compiler/rustc_mir_transform/src/jump_threading.rs
+++ b/compiler/rustc_mir_transform/src/jump_threading.rs
@@ -36,16 +36,21 @@
 //! cost by `MAX_COST`.
 
 use rustc_arena::DroplessArena;
+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::mir::interpret::Scalar;
 use rustc_middle::mir::visit::Visitor;
 use rustc_middle::mir::*;
-use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
+use rustc_middle::ty::layout::LayoutOf;
+use rustc_middle::ty::{self, ScalarInt, TyCtxt};
 use rustc_mir_dataflow::value_analysis::{Map, PlaceIndex, State, TrackElem};
+use rustc_span::DUMMY_SP;
 use rustc_target::abi::{TagEncoding, Variants};
 
 use crate::cost_checker::CostChecker;
+use crate::dataflow_const_prop::DummyMachine;
 
 pub struct JumpThreading;
 
@@ -71,6 +76,7 @@ impl<'tcx> MirPass<'tcx> for JumpThreading {
         let mut finder = TOFinder {
             tcx,
             param_env,
+            ecx: InterpCx::new(tcx, DUMMY_SP, param_env, DummyMachine),
             body,
             arena: &arena,
             map: &map,
@@ -88,7 +94,7 @@ impl<'tcx> MirPass<'tcx> for JumpThreading {
             debug!(?discr, ?bb);
 
             let discr_ty = discr.ty(body, tcx).ty;
-            let Ok(discr_layout) = tcx.layout_of(param_env.and(discr_ty)) else { continue };
+            let Ok(discr_layout) = finder.ecx.layout_of(discr_ty) else { continue };
 
             let Some(discr) = finder.map.find(discr.as_ref()) else { continue };
             debug!(?discr);
@@ -142,6 +148,7 @@ struct ThreadingOpportunity {
 struct TOFinder<'tcx, 'a> {
     tcx: TyCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
+    ecx: InterpCx<'tcx, 'tcx, DummyMachine>,
     body: &'a Body<'tcx>,
     map: &'a Map,
     loop_headers: &'a BitSet<BasicBlock>,
@@ -329,11 +336,11 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> {
     }
 
     #[instrument(level = "trace", skip(self))]
-    fn process_operand(
+    fn process_immediate(
         &mut self,
         bb: BasicBlock,
         lhs: PlaceIndex,
-        rhs: &Operand<'tcx>,
+        rhs: ImmTy<'tcx>,
         state: &mut State<ConditionSet<'a>>,
     ) -> Option<!> {
         let register_opportunity = |c: Condition| {
@@ -341,13 +348,70 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> {
             self.opportunities.push(ThreadingOpportunity { chain: vec![bb], target: c.target })
         };
 
+        let conditions = state.try_get_idx(lhs, self.map)?;
+        if let Immediate::Scalar(Scalar::Int(int)) = *rhs {
+            conditions.iter_matches(int).for_each(register_opportunity);
+        }
+
+        None
+    }
+
+    /// If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`.
+    #[instrument(level = "trace", skip(self))]
+    fn process_constant(
+        &mut self,
+        bb: BasicBlock,
+        lhs: PlaceIndex,
+        constant: OpTy<'tcx>,
+        state: &mut State<ConditionSet<'a>>,
+    ) {
+        self.map.for_each_projection_value(
+            lhs,
+            constant,
+            &mut |elem, op| match elem {
+                TrackElem::Field(idx) => self.ecx.project_field(op, idx.as_usize()).ok(),
+                TrackElem::Variant(idx) => self.ecx.project_downcast(op, idx).ok(),
+                TrackElem::Discriminant => {
+                    let variant = self.ecx.read_discriminant(op).ok()?;
+                    let discr_value =
+                        self.ecx.discriminant_for_variant(op.layout.ty, variant).ok()?;
+                    Some(discr_value.into())
+                }
+                TrackElem::DerefLen => {
+                    let op: OpTy<'_> = self.ecx.deref_pointer(op).ok()?.into();
+                    let len_usize = op.len(&self.ecx).ok()?;
+                    let layout = self.ecx.layout_of(self.tcx.types.usize).unwrap();
+                    Some(ImmTy::from_uint(len_usize, layout).into())
+                }
+            },
+            &mut |place, op| {
+                if let Some(conditions) = state.try_get_idx(place, self.map)
+                    && let Ok(imm) = self.ecx.read_immediate_raw(op)
+                    && let Some(imm) = imm.right()
+                    && let Immediate::Scalar(Scalar::Int(int)) = *imm
+                {
+                    conditions.iter_matches(int).for_each(|c: Condition| {
+                        self.opportunities
+                            .push(ThreadingOpportunity { chain: vec![bb], target: c.target })
+                    })
+                }
+            },
+        );
+    }
+
+    #[instrument(level = "trace", skip(self))]
+    fn process_operand(
+        &mut self,
+        bb: BasicBlock,
+        lhs: PlaceIndex,
+        rhs: &Operand<'tcx>,
+        state: &mut State<ConditionSet<'a>>,
+    ) -> Option<!> {
         match rhs {
             // If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`.
             Operand::Constant(constant) => {
-                let conditions = state.try_get_idx(lhs, self.map)?;
-                let constant =
-                    constant.const_.normalize(self.tcx, self.param_env).try_to_scalar_int()?;
-                conditions.iter_matches(constant).for_each(register_opportunity);
+                let constant = self.ecx.eval_mir_constant(&constant.const_, None, None).ok()?;
+                self.process_constant(bb, lhs, constant, state);
             }
             // Transfer the conditions on the copied rhs.
             Operand::Move(rhs) | Operand::Copy(rhs) => {
@@ -360,6 +424,84 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> {
     }
 
     #[instrument(level = "trace", skip(self))]
+    fn process_assign(
+        &mut self,
+        bb: BasicBlock,
+        lhs_place: &Place<'tcx>,
+        rhs: &Rvalue<'tcx>,
+        state: &mut State<ConditionSet<'a>>,
+    ) -> Option<!> {
+        let lhs = self.map.find(lhs_place.as_ref())?;
+        match rhs {
+            Rvalue::Use(operand) => self.process_operand(bb, lhs, operand, state)?,
+            // Transfer the conditions on the copy rhs.
+            Rvalue::CopyForDeref(rhs) => {
+                self.process_operand(bb, lhs, &Operand::Copy(*rhs), state)?
+            }
+            Rvalue::Discriminant(rhs) => {
+                let rhs = self.map.find_discr(rhs.as_ref())?;
+                state.insert_place_idx(rhs, lhs, self.map);
+            }
+            // If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`.
+            Rvalue::Aggregate(box ref kind, ref operands) => {
+                let agg_ty = lhs_place.ty(self.body, self.tcx).ty;
+                let lhs = match kind {
+                    // Do not support unions.
+                    AggregateKind::Adt(.., Some(_)) => return None,
+                    AggregateKind::Adt(_, variant_index, ..) if agg_ty.is_enum() => {
+                        if let Some(discr_target) = self.map.apply(lhs, TrackElem::Discriminant)
+                            && let Ok(discr_value) =
+                                self.ecx.discriminant_for_variant(agg_ty, *variant_index)
+                        {
+                            self.process_immediate(bb, discr_target, discr_value, state);
+                        }
+                        self.map.apply(lhs, TrackElem::Variant(*variant_index))?
+                    }
+                    _ => lhs,
+                };
+                for (field_index, operand) in operands.iter_enumerated() {
+                    if let Some(field) = self.map.apply(lhs, TrackElem::Field(field_index)) {
+                        self.process_operand(bb, field, operand, state);
+                    }
+                }
+            }
+            // Transfer the conditions on the copy rhs, after inversing polarity.
+            Rvalue::UnaryOp(UnOp::Not, Operand::Move(place) | Operand::Copy(place)) => {
+                let conditions = state.try_get_idx(lhs, self.map)?;
+                let place = self.map.find(place.as_ref())?;
+                let conds = conditions.map(self.arena, Condition::inv);
+                state.insert_value_idx(place, conds, self.map);
+            }
+            // We expect `lhs ?= A`. We found `lhs = Eq(rhs, B)`.
+            // Create a condition on `rhs ?= B`.
+            Rvalue::BinaryOp(
+                op,
+                box (Operand::Move(place) | Operand::Copy(place), Operand::Constant(value))
+                | box (Operand::Constant(value), Operand::Move(place) | Operand::Copy(place)),
+            ) => {
+                let conditions = state.try_get_idx(lhs, self.map)?;
+                let place = self.map.find(place.as_ref())?;
+                let equals = match op {
+                    BinOp::Eq => ScalarInt::TRUE,
+                    BinOp::Ne => ScalarInt::FALSE,
+                    _ => return None,
+                };
+                let value = value.const_.normalize(self.tcx, self.param_env).try_to_scalar_int()?;
+                let conds = conditions.map(self.arena, |c| Condition {
+                    value,
+                    polarity: if c.matches(equals) { Polarity::Eq } else { Polarity::Ne },
+                    ..c
+                });
+                state.insert_value_idx(place, conds, self.map);
+            }
+
+            _ => {}
+        }
+
+        None
+    }
+
+    #[instrument(level = "trace", skip(self))]
     fn process_statement(
         &mut self,
         bb: BasicBlock,
@@ -374,18 +516,6 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> {
         // Below, `lhs` is the return value of `mutated_statement`,
         // the place to which `conditions` apply.
 
-        let discriminant_for_variant = |enum_ty: Ty<'tcx>, variant_index| {
-            let discr = enum_ty.discriminant_for_variant(self.tcx, variant_index)?;
-            let discr_layout = self.tcx.layout_of(self.param_env.and(discr.ty)).ok()?;
-            let scalar = ScalarInt::try_from_uint(discr.val, discr_layout.size)?;
-            Some(Operand::const_from_scalar(
-                self.tcx,
-                discr.ty,
-                scalar.into(),
-                rustc_span::DUMMY_SP,
-            ))
-        };
-
         match &stmt.kind {
             // If we expect `discriminant(place) ?= A`,
             // we have an opportunity if `variant_index ?= A`.
@@ -395,7 +525,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> {
                 // `SetDiscriminant` may be a no-op if the assigned variant is the untagged variant
                 // of a niche encoding. If we cannot ensure that we write to the discriminant, do
                 // nothing.
-                let enum_layout = self.tcx.layout_of(self.param_env.and(enum_ty)).ok()?;
+                let enum_layout = self.ecx.layout_of(enum_ty).ok()?;
                 let writes_discriminant = match enum_layout.variants {
                     Variants::Single { index } => {
                         assert_eq!(index, *variant_index);
@@ -408,8 +538,8 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> {
                     } => *variant_index != untagged_variant,
                 };
                 if writes_discriminant {
-                    let discr = discriminant_for_variant(enum_ty, *variant_index)?;
-                    self.process_operand(bb, discr_target, &discr, state)?;
+                    let discr = self.ecx.discriminant_for_variant(enum_ty, *variant_index).ok()?;
+                    self.process_immediate(bb, discr_target, discr, state)?;
                 }
             }
             // If we expect `lhs ?= true`, we have an opportunity if we assume `lhs == true`.
@@ -420,89 +550,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> {
                 conditions.iter_matches(ScalarInt::TRUE).for_each(register_opportunity);
             }
             StatementKind::Assign(box (lhs_place, rhs)) => {
-                if let Some(lhs) = self.map.find(lhs_place.as_ref()) {
-                    match rhs {
-                        Rvalue::Use(operand) => self.process_operand(bb, lhs, operand, state)?,
-                        // Transfer the conditions on the copy rhs.
-                        Rvalue::CopyForDeref(rhs) => {
-                            self.process_operand(bb, lhs, &Operand::Copy(*rhs), state)?
-                        }
-                        Rvalue::Discriminant(rhs) => {
-                            let rhs = self.map.find_discr(rhs.as_ref())?;
-                            state.insert_place_idx(rhs, lhs, self.map);
-                        }
-                        // If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`.
-                        Rvalue::Aggregate(box ref kind, ref operands) => {
-                            let agg_ty = lhs_place.ty(self.body, self.tcx).ty;
-                            let lhs = match kind {
-                                // Do not support unions.
-                                AggregateKind::Adt(.., Some(_)) => return None,
-                                AggregateKind::Adt(_, variant_index, ..) if agg_ty.is_enum() => {
-                                    if let Some(discr_target) =
-                                        self.map.apply(lhs, TrackElem::Discriminant)
-                                        && let Some(discr_value) =
-                                            discriminant_for_variant(agg_ty, *variant_index)
-                                    {
-                                        self.process_operand(bb, discr_target, &discr_value, state);
-                                    }
-                                    self.map.apply(lhs, TrackElem::Variant(*variant_index))?
-                                }
-                                _ => lhs,
-                            };
-                            for (field_index, operand) in operands.iter_enumerated() {
-                                if let Some(field) =
-                                    self.map.apply(lhs, TrackElem::Field(field_index))
-                                {
-                                    self.process_operand(bb, field, operand, state);
-                                }
-                            }
-                        }
-                        // Transfer the conditions on the copy rhs, after inversing polarity.
-                        Rvalue::UnaryOp(UnOp::Not, Operand::Move(place) | Operand::Copy(place)) => {
-                            let conditions = state.try_get_idx(lhs, self.map)?;
-                            let place = self.map.find(place.as_ref())?;
-                            let conds = conditions.map(self.arena, Condition::inv);
-                            state.insert_value_idx(place, conds, self.map);
-                        }
-                        // We expect `lhs ?= A`. We found `lhs = Eq(rhs, B)`.
-                        // Create a condition on `rhs ?= B`.
-                        Rvalue::BinaryOp(
-                            op,
-                            box (
-                                Operand::Move(place) | Operand::Copy(place),
-                                Operand::Constant(value),
-                            )
-                            | box (
-                                Operand::Constant(value),
-                                Operand::Move(place) | Operand::Copy(place),
-                            ),
-                        ) => {
-                            let conditions = state.try_get_idx(lhs, self.map)?;
-                            let place = self.map.find(place.as_ref())?;
-                            let equals = match op {
-                                BinOp::Eq => ScalarInt::TRUE,
-                                BinOp::Ne => ScalarInt::FALSE,
-                                _ => return None,
-                            };
-                            let value = value
-                                .const_
-                                .normalize(self.tcx, self.param_env)
-                                .try_to_scalar_int()?;
-                            let conds = conditions.map(self.arena, |c| Condition {
-                                value,
-                                polarity: if c.matches(equals) {
-                                    Polarity::Eq
-                                } else {
-                                    Polarity::Ne
-                                },
-                                ..c
-                            });
-                            state.insert_value_idx(place, conds, self.map);
-                        }
-
-                        _ => {}
-                    }
-                }
+                self.process_assign(bb, lhs_place, rhs, state)?;
             }
             _ => {}
         }
@@ -577,7 +625,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> {
 
         let discr = discr.place()?;
         let discr_ty = discr.ty(self.body, self.tcx).ty;
-        let discr_layout = self.tcx.layout_of(self.param_env.and(discr_ty)).ok()?;
+        let discr_layout = self.ecx.layout_of(discr_ty).ok()?;
         let conditions = state.try_get(discr.as_ref(), self.map)?;
 
         if let Some((value, _)) = targets.iter().find(|&(_, target)| target == target_bb) {
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index ce9043ec287..19bfed4333c 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -4,6 +4,7 @@
 #![feature(box_patterns)]
 #![feature(cow_is_borrowed)]
 #![feature(decl_macro)]
+#![feature(impl_trait_in_assoc_type)]
 #![feature(is_sorted)]
 #![feature(let_chains)]
 #![feature(map_try_insert)]
@@ -40,7 +41,7 @@ use rustc_middle::mir::{
 };
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
-use rustc_span::sym;
+use rustc_span::{source_map::Spanned, sym, DUMMY_SP};
 use rustc_trait_selection::traits;
 
 #[macro_use]
@@ -169,13 +170,13 @@ fn remap_mir_for_const_eval_select<'tcx>(
             {
                 let [tupled_args, called_in_const, called_at_rt]: [_; 3] =
                     std::mem::take(args).try_into().unwrap();
-                let ty = tupled_args.ty(&body.local_decls, tcx);
+                let ty = tupled_args.node.ty(&body.local_decls, tcx);
                 let fields = ty.tuple_fields();
                 let num_args = fields.len();
                 let func =
                     if context == hir::Constness::Const { called_in_const } else { called_at_rt };
                 let (method, place): (fn(Place<'tcx>) -> Operand<'tcx>, Place<'tcx>) =
-                    match tupled_args {
+                    match tupled_args.node {
                         Operand::Constant(_) => {
                             // there is no good way of extracting a tuple arg from a constant (const generic stuff)
                             // so we just create a temporary and deconstruct that.
@@ -184,7 +185,7 @@ fn remap_mir_for_const_eval_select<'tcx>(
                                 source_info: SourceInfo::outermost(fn_span),
                                 kind: StatementKind::Assign(Box::new((
                                     local.into(),
-                                    Rvalue::Use(tupled_args.clone()),
+                                    Rvalue::Use(tupled_args.node.clone()),
                                 ))),
                             });
                             (Operand::Move, local.into())
@@ -199,11 +200,11 @@ fn remap_mir_for_const_eval_select<'tcx>(
                         place_elems.push(ProjectionElem::Field(x.into(), fields[x]));
                         let projection = tcx.mk_place_elems(&place_elems);
                         let place = Place { local: place.local, projection };
-                        method(place)
+                        Spanned { node: method(place), span: DUMMY_SP }
                     })
                     .collect();
                 terminator.kind = TerminatorKind::Call {
-                    func,
+                    func: func.node,
                     args: arguments,
                     destination,
                     target,
@@ -595,24 +596,25 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             &multiple_return_terminators::MultipleReturnTerminators,
             &instsimplify::InstSimplify,
             &simplify::SimplifyLocals::BeforeConstProp,
-            &copy_prop::CopyProp,
+            &dead_store_elimination::DeadStoreElimination::Initial,
+            &gvn::GVN,
+            &simplify::SimplifyLocals::AfterGVN,
             // Perform `SeparateConstSwitch` after SSA-based analyses, as cloning blocks may
             // destroy the SSA property. It should still happen before const-propagation, so the
             // latter pass will leverage the created opportunities.
             &separate_const_switch::SeparateConstSwitch,
-            &gvn::GVN,
-            &simplify::SimplifyLocals::AfterGVN,
             &dataflow_const_prop::DataflowConstProp,
             &const_debuginfo::ConstDebugInfo,
             &o1(simplify_branches::SimplifyConstCondition::AfterConstProp),
             &jump_threading::JumpThreading,
             &early_otherwise_branch::EarlyOtherwiseBranch,
             &simplify_comparison_integral::SimplifyComparisonIntegral,
-            &dead_store_elimination::DeadStoreElimination,
             &dest_prop::DestinationPropagation,
             &o1(simplify_branches::SimplifyConstCondition::Final),
             &o1(remove_noop_landing_pads::RemoveNoopLandingPads),
             &o1(simplify::SimplifyCfg::Final),
+            &copy_prop::CopyProp,
+            &dead_store_elimination::DeadStoreElimination::Final,
             &nrvo::RenameReturnPlace,
             &simplify::SimplifyLocals::Final,
             &multiple_return_terminators::MultipleReturnTerminators,
diff --git a/compiler/rustc_mir_transform/src/lint.rs b/compiler/rustc_mir_transform/src/lint.rs
index c0c0a3f5ee6..5b269185e87 100644
--- a/compiler/rustc_mir_transform/src/lint.rs
+++ b/compiler/rustc_mir_transform/src/lint.rs
@@ -131,7 +131,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Lint<'a, 'tcx> {
                 self.places.insert(destination.as_ref());
                 let mut has_duplicates = false;
                 for arg in args {
-                    if let Operand::Move(place) = arg {
+                    if let Operand::Move(place) = &arg.node {
                         has_duplicates |= !self.places.insert(place.as_ref());
                     }
                 }
diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
index 18f588dccf6..897375e0e16 100644
--- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs
+++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
@@ -45,9 +45,9 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
                             kind: StatementKind::Intrinsic(Box::new(
                                 NonDivergingIntrinsic::CopyNonOverlapping(
                                     rustc_middle::mir::CopyNonOverlapping {
-                                        src: args.next().unwrap(),
-                                        dst: args.next().unwrap(),
-                                        count: args.next().unwrap(),
+                                        src: args.next().unwrap().node,
+                                        dst: args.next().unwrap().node,
+                                        count: args.next().unwrap().node,
                                     },
                                 ),
                             )),
@@ -66,7 +66,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
                         block.statements.push(Statement {
                             source_info: terminator.source_info,
                             kind: StatementKind::Intrinsic(Box::new(
-                                NonDivergingIntrinsic::Assume(args.next().unwrap()),
+                                NonDivergingIntrinsic::Assume(args.next().unwrap().node),
                             )),
                         });
                         assert_eq!(
@@ -112,7 +112,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
                             source_info: terminator.source_info,
                             kind: StatementKind::Assign(Box::new((
                                 *destination,
-                                Rvalue::BinaryOp(bin_op, Box::new((lhs, rhs))),
+                                Rvalue::BinaryOp(bin_op, Box::new((lhs.node, rhs.node))),
                             ))),
                         });
                         terminator.kind = TerminatorKind::Goto { target };
@@ -136,7 +136,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
                                 source_info: terminator.source_info,
                                 kind: StatementKind::Assign(Box::new((
                                     *destination,
-                                    Rvalue::CheckedBinaryOp(bin_op, Box::new((lhs, rhs))),
+                                    Rvalue::CheckedBinaryOp(bin_op, Box::new((lhs.node, rhs.node))),
                                 ))),
                             });
                             terminator.kind = TerminatorKind::Goto { target };
@@ -164,7 +164,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
                         let [arg] = args.as_slice() else {
                             span_bug!(terminator.source_info.span, "Wrong number of arguments");
                         };
-                        let derefed_place = if let Some(place) = arg.place()
+                        let derefed_place = if let Some(place) = arg.node.place()
                             && let Some(local) = place.as_local()
                         {
                             tcx.mk_place_deref(local.into())
@@ -200,7 +200,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
                                 "Wrong number of arguments for write_via_move intrinsic",
                             );
                         };
-                        let derefed_place = if let Some(place) = ptr.place()
+                        let derefed_place = if let Some(place) = ptr.node.place()
                             && let Some(local) = place.as_local()
                         {
                             tcx.mk_place_deref(local.into())
@@ -214,13 +214,13 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
                             source_info: terminator.source_info,
                             kind: StatementKind::Assign(Box::new((
                                 derefed_place,
-                                Rvalue::Use(val),
+                                Rvalue::Use(val.node),
                             ))),
                         });
                         terminator.kind = TerminatorKind::Goto { target };
                     }
                     sym::discriminant_value => {
-                        if let (Some(target), Some(arg)) = (*target, args[0].place()) {
+                        if let (Some(target), Some(arg)) = (*target, args[0].node.place()) {
                             let arg = tcx.mk_place_deref(arg);
                             block.statements.push(Statement {
                                 source_info: terminator.source_info,
@@ -244,7 +244,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
                             source_info: terminator.source_info,
                             kind: StatementKind::Assign(Box::new((
                                 *destination,
-                                Rvalue::BinaryOp(BinOp::Offset, Box::new((ptr, delta))),
+                                Rvalue::BinaryOp(BinOp::Offset, Box::new((ptr.node, delta.node))),
                             ))),
                         });
                         terminator.kind = TerminatorKind::Goto { target };
@@ -265,7 +265,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
                             source_info: terminator.source_info,
                             kind: StatementKind::Assign(Box::new((
                                 *destination,
-                                Rvalue::Cast(CastKind::Transmute, arg, dst_ty),
+                                Rvalue::Cast(CastKind::Transmute, arg.node, dst_ty),
                             ))),
                         });
 
diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs
index daeb56666f4..8137525a332 100644
--- a/compiler/rustc_mir_transform/src/lower_slice_len.rs
+++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs
@@ -50,7 +50,7 @@ fn lower_slice_len_call<'tcx>(
     } = &terminator.kind
         // some heuristics for fast rejection
         && let [arg] = &args[..]
-        && let Some(arg) = arg.place()
+        && let Some(arg) = arg.node.place()
         && let ty::FnDef(fn_def_id, _) = func.ty(local_decls, tcx).kind()
         && *fn_def_id == slice_len_fn_item_def_id
     {
diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs
index 841b86fed45..c00093ea27e 100644
--- a/compiler/rustc_mir_transform/src/promote_consts.rs
+++ b/compiler/rustc_mir_transform/src/promote_consts.rs
@@ -22,6 +22,7 @@ use rustc_middle::ty::{self, List, Ty, TyCtxt, TypeVisitableExt};
 use rustc_span::Span;
 
 use rustc_index::{Idx, IndexSlice, IndexVec};
+use rustc_span::source_map::Spanned;
 
 use std::assert_matches::assert_matches;
 use std::cell::Cell;
@@ -565,7 +566,7 @@ impl<'tcx> Validator<'_, 'tcx> {
     fn validate_call(
         &mut self,
         callee: &Operand<'tcx>,
-        args: &[Operand<'tcx>],
+        args: &[Spanned<Operand<'tcx>>],
     ) -> Result<(), Unpromotable> {
         let fn_ty = callee.ty(self.body, self.tcx);
 
@@ -595,7 +596,7 @@ impl<'tcx> Validator<'_, 'tcx> {
 
         self.validate_operand(callee)?;
         for arg in args {
-            self.validate_operand(arg)?;
+            self.validate_operand(&arg.node)?;
         }
 
         Ok(())
@@ -731,7 +732,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
                 } => {
                     self.visit_operand(&mut func, loc);
                     for arg in &mut args {
-                        self.visit_operand(arg, loc);
+                        self.visit_operand(&mut arg.node, loc);
                     }
 
                     let last = self.promoted.basic_blocks.last_index().unwrap();
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index f6b820bfcd0..89414ce940e 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -9,7 +9,7 @@ use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
 
 use rustc_index::{Idx, IndexVec};
 
-use rustc_span::Span;
+use rustc_span::{source_map::Spanned, Span, DUMMY_SP};
 use rustc_target::spec::abi::Abi;
 
 use std::fmt;
@@ -526,7 +526,7 @@ impl<'tcx> CloneShimBuilder<'tcx> {
             vec![statement],
             TerminatorKind::Call {
                 func,
-                args: vec![Operand::Move(ref_loc)],
+                args: vec![Spanned { node: Operand::Move(ref_loc), span: DUMMY_SP }],
                 destination: dest,
                 target: Some(next),
                 unwind: UnwindAction::Cleanup(cleanup),
@@ -811,6 +811,7 @@ fn build_call_shim<'tcx>(
     };
 
     // BB #0
+    let args = args.into_iter().map(|a| Spanned { node: a, span: DUMMY_SP }).collect::<Vec<_>>();
     block(
         &mut blocks,
         statements,
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 92f001cc321..20e70f87b75 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -614,8 +614,8 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> {
     }
 
     fn check_operand_move_size(&mut self, operand: &mir::Operand<'tcx>, location: Location) {
-        let limit = self.tcx.move_size_limit().0;
-        if limit == 0 {
+        let limit = self.tcx.move_size_limit();
+        if limit.0 == 0 {
             return;
         }
 
@@ -627,48 +627,19 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> {
             return;
         }
 
-        let limit = Size::from_bytes(limit);
-        let ty = operand.ty(self.body, self.tcx);
-        let ty = self.monomorphize(ty);
-        let Ok(layout) = self.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)) else { return };
-        if layout.size <= limit {
-            return;
-        }
-        debug!(?layout);
         let source_info = self.body.source_info(location);
         debug!(?source_info);
-        for span in &self.move_size_spans {
-            if span.overlaps(source_info.span) {
-                return;
-            }
-        }
-        let lint_root = source_info.scope.lint_root(&self.body.source_scopes);
-        debug!(?lint_root);
-        let Some(lint_root) = lint_root else {
-            // This happens when the issue is in a function from a foreign crate that
-            // we monomorphized in the current crate. We can't get a `HirId` for things
-            // in other crates.
-            // FIXME: Find out where to report the lint on. Maybe simply crate-level lint root
-            // but correct span? This would make the lint at least accept crate-level lint attributes.
-            return;
+
+        if let Some(too_large_size) = self.operand_size_if_too_large(limit, operand) {
+            self.lint_large_assignment(limit.0, too_large_size, location, source_info.span);
         };
-        self.tcx.emit_spanned_lint(
-            LARGE_ASSIGNMENTS,
-            lint_root,
-            source_info.span,
-            LargeAssignmentsLint {
-                span: source_info.span,
-                size: layout.size.bytes(),
-                limit: limit.bytes(),
-            },
-        );
-        self.move_size_spans.push(source_info.span);
     }
 
     fn check_fn_args_move_size(
         &mut self,
         callee_ty: Ty<'tcx>,
-        args: &[mir::Operand<'tcx>],
+        args: &[Spanned<mir::Operand<'tcx>>],
+        fn_span: Span,
         location: Location,
     ) {
         let limit = self.tcx.move_size_limit();
@@ -692,10 +663,65 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> {
             return;
         }
 
+        debug!(?def_id, ?fn_span);
+
         for arg in args {
-            self.check_operand_move_size(arg, location);
+            if let Some(too_large_size) = self.operand_size_if_too_large(limit, &arg.node) {
+                self.lint_large_assignment(limit.0, too_large_size, location, arg.span);
+            };
+        }
+    }
+
+    fn operand_size_if_too_large(
+        &mut self,
+        limit: Limit,
+        operand: &mir::Operand<'tcx>,
+    ) -> Option<Size> {
+        let ty = operand.ty(self.body, self.tcx);
+        let ty = self.monomorphize(ty);
+        let Ok(layout) = self.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)) else {
+            return None;
+        };
+        if layout.size.bytes_usize() > limit.0 {
+            debug!(?layout);
+            Some(layout.size)
+        } else {
+            None
         }
     }
+
+    fn lint_large_assignment(
+        &mut self,
+        limit: usize,
+        too_large_size: Size,
+        location: Location,
+        span: Span,
+    ) {
+        let source_info = self.body.source_info(location);
+        debug!(?source_info);
+        for reported_span in &self.move_size_spans {
+            if reported_span.overlaps(span) {
+                return;
+            }
+        }
+        let lint_root = source_info.scope.lint_root(&self.body.source_scopes);
+        debug!(?lint_root);
+        let Some(lint_root) = lint_root else {
+            // This happens when the issue is in a function from a foreign crate that
+            // we monomorphized in the current crate. We can't get a `HirId` for things
+            // in other crates.
+            // FIXME: Find out where to report the lint on. Maybe simply crate-level lint root
+            // but correct span? This would make the lint at least accept crate-level lint attributes.
+            return;
+        };
+        self.tcx.emit_spanned_lint(
+            LARGE_ASSIGNMENTS,
+            lint_root,
+            span,
+            LargeAssignmentsLint { span, size: too_large_size.bytes(), limit: limit as u64 },
+        );
+        self.move_size_spans.push(span);
+    }
 }
 
 impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
@@ -813,11 +839,11 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
         };
 
         match terminator.kind {
-            mir::TerminatorKind::Call { ref func, ref args, .. } => {
+            mir::TerminatorKind::Call { ref func, ref args, ref fn_span, .. } => {
                 let callee_ty = func.ty(self.body, tcx);
                 let callee_ty = self.monomorphize(callee_ty);
-                self.check_fn_args_move_size(callee_ty, args, location);
-                visit_fn_use(self.tcx, callee_ty, true, source, self.output)
+                self.check_fn_args_move_size(callee_ty, args, *fn_span, location);
+                visit_fn_use(self.tcx, callee_ty, true, source, &mut self.output)
             }
             mir::TerminatorKind::Drop { ref place, .. } => {
                 let ty = place.ty(self.body, self.tcx).ty;
@@ -1407,7 +1433,7 @@ fn collect_alloc<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIt
 }
 
 fn assoc_fn_of_type<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, fn_ident: Ident) -> Option<DefId> {
-    for impl_def_id in tcx.inherent_impls(def_id) {
+    for impl_def_id in tcx.inherent_impls(def_id).ok()? {
         if let Some(new) = tcx.associated_items(impl_def_id).find_by_name_and_kind(
             tcx,
             fn_ident,
diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs
index 2c40cd4d8f2..7ff182381b8 100644
--- a/compiler/rustc_monomorphize/src/partitioning.rs
+++ b/compiler/rustc_monomorphize/src/partitioning.rs
@@ -182,7 +182,7 @@ where
     }
 
     // Ensure CGUs are sorted by name, so that we get deterministic results.
-    if !codegen_units.is_sorted_by(|a, b| Some(a.name().as_str().cmp(b.name().as_str()))) {
+    if !codegen_units.is_sorted_by(|a, b| a.name().as_str() <= b.name().as_str()) {
         let mut names = String::new();
         for cgu in codegen_units.iter() {
             names += &format!("- {}\n", cgu.name());
@@ -317,7 +317,7 @@ fn merge_codegen_units<'tcx>(
     assert!(cx.tcx.sess.codegen_units().as_usize() >= 1);
 
     // A sorted order here ensures merging is deterministic.
-    assert!(codegen_units.is_sorted_by(|a, b| Some(a.name().as_str().cmp(b.name().as_str()))));
+    assert!(codegen_units.is_sorted_by(|a, b| a.name().as_str() <= b.name().as_str()));
 
     // This map keeps track of what got merged into what.
     let mut cgu_contents: FxHashMap<Symbol, Vec<Symbol>> =
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index c11a6fab7e5..f904e0c44ea 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -407,6 +407,9 @@ parse_invalid_logical_operator = `{$incorrect}` is not a logical operator
 
 parse_invalid_meta_item = expected unsuffixed literal or identifier, found `{$token}`
 
+parse_invalid_meta_item_unquoted_ident = expected unsuffixed literal, found `{$token}`
+    .suggestion = surround the identifier with quotation marks to parse it as a string
+
 parse_invalid_offset_of = offset_of expects dot-separated field and variant names
 
 parse_invalid_unicode_escape = invalid unicode character escape
@@ -613,6 +616,8 @@ parse_note_mut_pattern_usage = `mut` may be followed by `variable` and `variable
 
 parse_note_pattern_alternatives_use_single_vert = alternatives in or-patterns are separated with `|`, not `||`
 
+parse_nul_in_c_str = null characters in C string literals are not supported
+
 parse_or_pattern_not_allowed_in_fn_parameters = top-level or-patterns are not allowed in function parameters
 parse_or_pattern_not_allowed_in_let_binding = top-level or-patterns are not allowed in `let` bindings
 parse_out_of_range_hex_escape = out of range hex escape
@@ -719,6 +724,8 @@ parse_sugg_turbofish_syntax = use `::<...>` instead of `<...>` to specify lifeti
 
 parse_sugg_wrap_expression_in_parentheses = wrap the expression in parentheses
 
+parse_sugg_wrap_macro_in_parentheses = use parentheses instead of braces for this macro
+
 parse_sugg_wrap_pattern_in_parens = wrap the pattern in parentheses
 
 parse_switch_mut_let_order =
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 0de252707bd..40852048293 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -722,19 +722,32 @@ pub(crate) struct LabeledLoopInBreak {
     #[primary_span]
     pub span: Span,
     #[subdiagnostic]
-    pub sub: WrapExpressionInParentheses,
+    pub sub: WrapInParentheses,
 }
 
 #[derive(Subdiagnostic)]
-#[multipart_suggestion(
-    parse_sugg_wrap_expression_in_parentheses,
-    applicability = "machine-applicable"
-)]
-pub(crate) struct WrapExpressionInParentheses {
-    #[suggestion_part(code = "(")]
-    pub left: Span,
-    #[suggestion_part(code = ")")]
-    pub right: Span,
+
+pub(crate) enum WrapInParentheses {
+    #[multipart_suggestion(
+        parse_sugg_wrap_expression_in_parentheses,
+        applicability = "machine-applicable"
+    )]
+    Expression {
+        #[suggestion_part(code = "(")]
+        left: Span,
+        #[suggestion_part(code = ")")]
+        right: Span,
+    },
+    #[multipart_suggestion(
+        parse_sugg_wrap_macro_in_parentheses,
+        applicability = "machine-applicable"
+    )]
+    MacroArgs {
+        #[suggestion_part(code = "(")]
+        left: Span,
+        #[suggestion_part(code = ")")]
+        right: Span,
+    },
 }
 
 #[derive(Diagnostic)]
@@ -936,7 +949,7 @@ pub(crate) struct InvalidExpressionInLetElse {
     pub span: Span,
     pub operator: &'static str,
     #[subdiagnostic]
-    pub sugg: WrapExpressionInParentheses,
+    pub sugg: WrapInParentheses,
 }
 
 #[derive(Diagnostic)]
@@ -945,7 +958,7 @@ pub(crate) struct InvalidCurlyInLetElse {
     #[primary_span]
     pub span: Span,
     #[subdiagnostic]
-    pub sugg: WrapExpressionInParentheses,
+    pub sugg: WrapInParentheses,
 }
 
 #[derive(Diagnostic)]
@@ -973,6 +986,25 @@ pub(crate) struct InvalidMetaItem {
     pub token: Token,
 }
 
+#[derive(Diagnostic)]
+#[diag(parse_invalid_meta_item_unquoted_ident)]
+pub(crate) struct InvalidMetaItemUnquotedIdent {
+    #[primary_span]
+    pub span: Span,
+    pub token: Token,
+    #[subdiagnostic]
+    pub sugg: InvalidMetaItemSuggQuoteIdent,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")]
+pub(crate) struct InvalidMetaItemSuggQuoteIdent {
+    #[suggestion_part(code = "\"")]
+    pub before: Span,
+    #[suggestion_part(code = "\"")]
+    pub after: Span,
+}
+
 #[derive(Subdiagnostic)]
 #[suggestion(
     parse_sugg_escape_identifier,
@@ -2144,6 +2176,11 @@ pub enum UnescapeError {
         #[subdiagnostic]
         suggestion: MoreThanOneCharSugg,
     },
+    #[diag(parse_nul_in_c_str)]
+    NulInCStr {
+        #[primary_span]
+        span: Span,
+    },
 }
 
 #[derive(Subdiagnostic)]
diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
index fbc77f28780..3238f8e23bb 100644
--- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
+++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
@@ -262,6 +262,9 @@ pub(crate) fn emit_unescape_error(
         EscapeError::LoneSlash => {
             dcx.emit_err(UnescapeError::LoneSlash(err_span));
         }
+        EscapeError::NulInCStr => {
+            dcx.emit_err(UnescapeError::NulInCStr { span: err_span });
+        }
         EscapeError::UnskippedWhitespaceWarning => {
             let (c, char_span) = last_char();
             dcx.emit_warn(UnescapeError::UnskippedWhitespace {
diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs
index 02dab95233a..a92609c2c2f 100644
--- a/compiler/rustc_parse/src/parser/attr.rs
+++ b/compiler/rustc_parse/src/parser/attr.rs
@@ -1,4 +1,7 @@
-use crate::errors::{InvalidMetaItem, SuffixedLiteralInAttribute};
+use crate::errors::{
+    InvalidMetaItem, InvalidMetaItemSuggQuoteIdent, InvalidMetaItemUnquotedIdent,
+    SuffixedLiteralInAttribute,
+};
 use crate::fluent_generated as fluent;
 
 use super::{AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, PathStyle};
@@ -417,9 +420,26 @@ impl<'a> Parser<'a> {
             Err(err) => err.cancel(),
         }
 
-        Err(self
-            .dcx()
-            .create_err(InvalidMetaItem { span: self.token.span, token: self.token.clone() }))
+        let token = self.token.clone();
+
+        // Check for unquoted idents in meta items, e.g.: #[cfg(key = foo)]
+        // `from_expansion()` ensures we don't suggest for cases such as
+        // `#[cfg(feature = $expr)]` in macros
+        if self.prev_token == token::Eq && !self.token.span.from_expansion() {
+            let before = self.token.span.shrink_to_lo();
+            while matches!(self.token.kind, token::Ident(..)) {
+                self.bump();
+            }
+            let after = self.prev_token.span.shrink_to_hi();
+            let sugg = InvalidMetaItemSuggQuoteIdent { before, after };
+            return Err(self.dcx().create_err(InvalidMetaItemUnquotedIdent {
+                span: token.span,
+                token,
+                sugg,
+            }));
+        }
+
+        Err(self.dcx().create_err(InvalidMetaItem { span: token.span, token }))
     }
 }
 
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 8ca02452342..ae3661a530b 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -33,7 +33,6 @@ use rustc_session::errors::{report_lit_error, ExprParenthesesNeeded};
 use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
 use rustc_session::lint::BuiltinLintDiagnostics;
 use rustc_span::source_map::{self, Spanned};
-use rustc_span::symbol::kw::PathRoot;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{BytePos, Pos, Span};
 use thin_vec::{thin_vec, ThinVec};
@@ -642,26 +641,13 @@ impl<'a> Parser<'a> {
     }
 
     /// Parse `box expr` - this syntax has been removed, but we still parse this
-    /// for now to provide an automated way to fix usages of it
-    fn parse_expr_box(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
-        let (span, expr) = self.parse_expr_prefix_common(lo)?;
-        let code = self.sess.source_map().span_to_snippet(span.with_lo(lo.hi())).unwrap();
-        self.dcx().emit_err(errors::BoxSyntaxRemoved { span, code: code.trim() });
-        // So typechecking works, parse `box <expr>` as `::std::boxed::Box::new(expr)`
-        let path = Path {
-            span,
-            segments: [
-                PathSegment::from_ident(Ident::with_dummy_span(PathRoot)),
-                PathSegment::from_ident(Ident::with_dummy_span(sym::std)),
-                PathSegment::from_ident(Ident::from_str("boxed")),
-                PathSegment::from_ident(Ident::from_str("Box")),
-                PathSegment::from_ident(Ident::with_dummy_span(sym::new)),
-            ]
-            .into(),
-            tokens: None,
-        };
-        let path = self.mk_expr(span, ExprKind::Path(None, path));
-        Ok((span, self.mk_call(path, ThinVec::from([expr]))))
+    /// for now to provide a more useful error
+    fn parse_expr_box(&mut self, box_kw: Span) -> PResult<'a, (Span, ExprKind)> {
+        let (span, _) = self.parse_expr_prefix_common(box_kw)?;
+        let inner_span = span.with_lo(box_kw.hi());
+        let code = self.sess.source_map().span_to_snippet(inner_span).unwrap();
+        self.dcx().emit_err(errors::BoxSyntaxRemoved { span: span, code: code.trim() });
+        Ok((span, ExprKind::Err))
     }
 
     fn is_mistaken_not_ident_negation(&self) -> bool {
@@ -1844,7 +1830,7 @@ impl<'a> Parser<'a> {
             let lexpr = self.parse_expr_labeled(label, true)?;
             self.dcx().emit_err(errors::LabeledLoopInBreak {
                 span: lexpr.span,
-                sub: errors::WrapExpressionInParentheses {
+                sub: errors::WrapInParentheses::Expression {
                     left: lexpr.span.shrink_to_lo(),
                     right: lexpr.span.shrink_to_hi(),
                 },
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index 1a8bbf0a157..1bae5b32240 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -389,7 +389,7 @@ impl<'a> Parser<'a> {
                 self.dcx().emit_err(errors::InvalidExpressionInLetElse {
                     span: init.span,
                     operator: op.node.as_str(),
-                    sugg: errors::WrapExpressionInParentheses {
+                    sugg: errors::WrapInParentheses::Expression {
                         left: init.span.shrink_to_lo(),
                         right: init.span.shrink_to_hi(),
                     },
@@ -400,12 +400,19 @@ impl<'a> Parser<'a> {
 
     fn check_let_else_init_trailing_brace(&self, init: &ast::Expr) {
         if let Some(trailing) = classify::expr_trailing_brace(init) {
-            self.dcx().emit_err(errors::InvalidCurlyInLetElse {
-                span: trailing.span.with_lo(trailing.span.hi() - BytePos(1)),
-                sugg: errors::WrapExpressionInParentheses {
+            let sugg = match &trailing.kind {
+                ExprKind::MacCall(mac) => errors::WrapInParentheses::MacroArgs {
+                    left: mac.args.dspan.open,
+                    right: mac.args.dspan.close,
+                },
+                _ => errors::WrapInParentheses::Expression {
                     left: trailing.span.shrink_to_lo(),
                     right: trailing.span.shrink_to_hi(),
                 },
+            };
+            self.dcx().emit_err(errors::InvalidCurlyInLetElse {
+                span: trailing.span.with_lo(trailing.span.hi() - BytePos(1)),
+                sugg,
             });
         }
     }
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index ac2ca23ad41..d7f17ac4547 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -57,7 +57,7 @@ struct MarkSymbolVisitor<'tcx> {
     tcx: TyCtxt<'tcx>,
     maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>,
     live_symbols: LocalDefIdSet,
-    repr_has_repr_c: bool,
+    repr_unconditionally_treats_fields_as_live: bool,
     repr_has_repr_simd: bool,
     in_pat: bool,
     ignore_variant_stack: Vec<DefId>,
@@ -128,7 +128,10 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
         if let Some(def_id) = self.typeck_results().type_dependent_def_id(id) {
             self.check_def_id(def_id);
         } else {
-            bug!("no type-dependent def for method");
+            assert!(
+                self.typeck_results().tainted_by_errors.is_some(),
+                "no type-dependent def for method"
+            );
         }
     }
 
@@ -362,15 +365,17 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
             return;
         }
 
-        let had_repr_c = self.repr_has_repr_c;
+        let unconditionally_treated_fields_as_live =
+            self.repr_unconditionally_treats_fields_as_live;
         let had_repr_simd = self.repr_has_repr_simd;
-        self.repr_has_repr_c = false;
+        self.repr_unconditionally_treats_fields_as_live = false;
         self.repr_has_repr_simd = false;
         match node {
             Node::Item(item) => match item.kind {
                 hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => {
                     let def = self.tcx.adt_def(item.owner_id);
-                    self.repr_has_repr_c = def.repr().c();
+                    self.repr_unconditionally_treats_fields_as_live =
+                        def.repr().c() || def.repr().transparent();
                     self.repr_has_repr_simd = def.repr().simd();
 
                     intravisit::walk_item(self, item)
@@ -408,7 +413,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
             _ => {}
         }
         self.repr_has_repr_simd = had_repr_simd;
-        self.repr_has_repr_c = had_repr_c;
+        self.repr_unconditionally_treats_fields_as_live = unconditionally_treated_fields_as_live;
     }
 
     fn mark_as_used_if_union(&mut self, adt: ty::AdtDef<'tcx>, fields: &[hir::ExprField<'_>]) {
@@ -432,11 +437,11 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
 
     fn visit_variant_data(&mut self, def: &'tcx hir::VariantData<'tcx>) {
         let tcx = self.tcx;
-        let has_repr_c = self.repr_has_repr_c;
+        let unconditionally_treat_fields_as_live = self.repr_unconditionally_treats_fields_as_live;
         let has_repr_simd = self.repr_has_repr_simd;
         let live_fields = def.fields().iter().filter_map(|f| {
             let def_id = f.def_id;
-            if has_repr_c || (f.is_positional() && has_repr_simd) {
+            if unconditionally_treat_fields_as_live || (f.is_positional() && has_repr_simd) {
                 return Some(def_id);
             }
             if !tcx.visibility(f.hir_id.owner.def_id).is_public() {
@@ -738,7 +743,7 @@ fn live_symbols_and_ignored_derived_traits(
         tcx,
         maybe_typeck_results: None,
         live_symbols: Default::default(),
-        repr_has_repr_c: false,
+        repr_unconditionally_treats_fields_as_live: false,
         repr_has_repr_simd: false,
         in_pat: false,
         ignore_variant_stack: vec![],
diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs
index a9d0e0d2dd3..25ca685cbfa 100644
--- a/compiler/rustc_passes/src/entry.rs
+++ b/compiler/rustc_passes/src/entry.rs
@@ -180,8 +180,8 @@ fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) {
         Default::default()
     });
     let main_def_opt = tcx.resolutions(()).main_def;
-    let diagnostic_id = error_code!(E0601);
-    let add_teach_note = tcx.sess.teach(&diagnostic_id);
+    let code = error_code!(E0601);
+    let add_teach_note = tcx.sess.teach(&code);
     // The file may be empty, which leads to the diagnostic machinery not emitting this
     // note. This is a relatively simple way to detect that case and emit a span-less
     // note instead.
diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs
index ff29fc5929c..528a52f4225 100644
--- a/compiler/rustc_passes/src/hir_stats.rs
+++ b/compiler/rustc_passes/src/hir_stats.rs
@@ -303,7 +303,8 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
                 Ref,
                 Lit,
                 Range,
-                Slice
+                Slice,
+                Err
             ]
         );
         hir_visit::walk_pat(self, p)
@@ -576,7 +577,8 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
                 Rest,
                 Never,
                 Paren,
-                MacCall
+                MacCall,
+                Err
             ]
         );
         ast_visit::walk_pat(self, p)
diff --git a/compiler/rustc_pattern_analysis/Cargo.toml b/compiler/rustc_pattern_analysis/Cargo.toml
index 2152f9fda00..1d0e1cb7e6a 100644
--- a/compiler/rustc_pattern_analysis/Cargo.toml
+++ b/compiler/rustc_pattern_analysis/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2021"
 [dependencies]
 # tidy-alphabetical-start
 derivative = "2.2.0"
+rustc-hash = "1.1.0"
 rustc_apfloat = "0.2.0"
 rustc_arena = { path = "../rustc_arena", optional = true }
 rustc_data_structures = { path = "../rustc_data_structures", optional = true }
@@ -20,13 +21,10 @@ rustc_span = { path = "../rustc_span", optional = true }
 rustc_target = { path = "../rustc_target", optional = true }
 smallvec = { version = "1.8.1", features = ["union"] }
 tracing = "0.1"
-typed-arena = { version = "2.0.2", optional = true }
 # tidy-alphabetical-end
 
 [features]
 default = ["rustc"]
-# It's not possible to only enable the `typed_arena` dependency when the `rustc` feature is off, so
-# we use another feature instead. The crate won't compile if one of these isn't enabled.
 rustc = [
     "dep:rustc_arena",
     "dep:rustc_data_structures",
@@ -41,6 +39,3 @@ rustc = [
     "smallvec/may_dangle",
     "rustc_index/nightly",
 ]
-stable = [
-    "dep:typed-arena",
-]
diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs
index 15ff4ceb5b3..eba71a23435 100644
--- a/compiler/rustc_pattern_analysis/src/constructor.rs
+++ b/compiler/rustc_pattern_analysis/src/constructor.rs
@@ -155,13 +155,13 @@ use std::iter::once;
 use smallvec::SmallVec;
 
 use rustc_apfloat::ieee::{DoubleS, IeeeFloat, SingleS};
-use rustc_index::bit_set::{BitSet, GrowableBitSet};
-use rustc_index::IndexVec;
+use rustc_index::bit_set::GrowableBitSet;
 
 use self::Constructor::*;
 use self::MaybeInfiniteInt::*;
 use self::SliceKind::*;
 
+use crate::index;
 use crate::usefulness::PlaceCtxt;
 use crate::TypeCx;
 
@@ -718,7 +718,7 @@ impl<Cx: TypeCx> Constructor<Cx> {
 
     /// The number of fields for this constructor. This must be kept in sync with
     /// `Fields::wildcards`.
-    pub(crate) fn arity(&self, pcx: &PlaceCtxt<'_, '_, Cx>) -> usize {
+    pub(crate) fn arity(&self, pcx: &PlaceCtxt<'_, Cx>) -> usize {
         pcx.ctor_arity(self)
     }
 
@@ -727,7 +727,7 @@ impl<Cx: TypeCx> Constructor<Cx> {
     /// this checks for inclusion.
     // We inline because this has a single call site in `Matrix::specialize_constructor`.
     #[inline]
-    pub(crate) fn is_covered_by<'p>(&self, pcx: &PlaceCtxt<'_, 'p, Cx>, other: &Self) -> bool {
+    pub(crate) fn is_covered_by(&self, pcx: &PlaceCtxt<'_, Cx>, other: &Self) -> bool {
         match (self, other) {
             (Wildcard, _) => pcx
                 .mcx
@@ -804,7 +804,10 @@ pub enum ConstructorSet<Cx: TypeCx> {
     Struct { empty: bool },
     /// This type has the following list of constructors. If `variants` is empty and
     /// `non_exhaustive` is false, don't use this; use `NoConstructors` instead.
-    Variants { variants: IndexVec<Cx::VariantIdx, VariantVisibility>, non_exhaustive: bool },
+    Variants {
+        variants: index::IdxContainer<Cx::VariantIdx, VariantVisibility>,
+        non_exhaustive: bool,
+    },
     /// The type is `&T`.
     Ref,
     /// The type is a union.
@@ -858,12 +861,14 @@ impl<Cx: TypeCx> ConstructorSet<Cx> {
     /// any) are missing; 2/ split constructors to handle non-trivial intersections e.g. on ranges
     /// or slices. This can get subtle; see [`SplitConstructorSet`] for details of this operation
     /// and its invariants.
-    #[instrument(level = "debug", skip(self, pcx, ctors), ret)]
+    #[instrument(level = "debug", skip(self, ctors), ret)]
     pub(crate) fn split<'a>(
         &self,
-        pcx: &PlaceCtxt<'a, '_, Cx>,
         ctors: impl Iterator<Item = &'a Constructor<Cx>> + Clone,
-    ) -> SplitConstructorSet<Cx> {
+    ) -> SplitConstructorSet<Cx>
+    where
+        Cx: 'a,
+    {
         let mut present: SmallVec<[_; 1]> = SmallVec::new();
         // Empty constructors found missing.
         let mut missing_empty = Vec::new();
@@ -904,7 +909,7 @@ impl<Cx: TypeCx> ConstructorSet<Cx> {
                 }
             }
             ConstructorSet::Variants { variants, non_exhaustive } => {
-                let mut seen_set: BitSet<_> = BitSet::new_empty(variants.len());
+                let mut seen_set = index::IdxSet::new_empty(variants.len());
                 for idx in seen.iter().map(|c| c.as_variant().unwrap()) {
                     seen_set.insert(idx);
                 }
@@ -1003,17 +1008,6 @@ impl<Cx: TypeCx> ConstructorSet<Cx> {
             }
         }
 
-        // We have now grouped all the constructors into 3 buckets: present, missing, missing_empty.
-        // In the absence of the `exhaustive_patterns` feature however, we don't count nested empty
-        // types as empty. Only non-nested `!` or `enum Foo {}` are considered empty.
-        if !pcx.mcx.tycx.is_exhaustive_patterns_feature_on()
-            && !(pcx.is_scrutinee && matches!(self, Self::NoConstructors))
-        {
-            // Treat all missing constructors as nonempty.
-            // This clears `missing_empty`.
-            missing.append(&mut missing_empty);
-        }
-
         SplitConstructorSet { present, missing, missing_empty }
     }
 }
diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs
index 374914055d8..4fd01b5e638 100644
--- a/compiler/rustc_pattern_analysis/src/lib.rs
+++ b/compiler/rustc_pattern_analysis/src/lib.rs
@@ -21,30 +21,59 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
 
 use std::fmt;
 
-use rustc_index::Idx;
+#[cfg(feature = "rustc")]
+pub mod index {
+    // Faster version when the indices of variants are `0..variants.len()`.
+    pub use rustc_index::bit_set::BitSet as IdxSet;
+    pub use rustc_index::Idx;
+    pub use rustc_index::IndexVec as IdxContainer;
+}
+#[cfg(not(feature = "rustc"))]
+pub mod index {
+    // Slower version when the indices of variants are something else.
+    pub trait Idx: Copy + PartialEq + Eq + std::hash::Hash {}
+    impl<T: Copy + PartialEq + Eq + std::hash::Hash> Idx for T {}
+
+    #[derive(Debug)]
+    pub struct IdxContainer<K, V>(pub rustc_hash::FxHashMap<K, V>);
+    impl<K: Idx, V> IdxContainer<K, V> {
+        pub fn len(&self) -> usize {
+            self.0.len()
+        }
+        pub fn iter_enumerated(&self) -> impl Iterator<Item = (K, &V)> {
+            self.0.iter().map(|(k, v)| (*k, v))
+        }
+    }
+
+    #[derive(Debug)]
+    pub struct IdxSet<T>(pub rustc_hash::FxHashSet<T>);
+    impl<T: Idx> IdxSet<T> {
+        pub fn new_empty(_len: usize) -> Self {
+            Self(Default::default())
+        }
+        pub fn contains(&self, elem: T) -> bool {
+            self.0.contains(&elem)
+        }
+        pub fn insert(&mut self, elem: T) {
+            self.0.insert(elem);
+        }
+    }
+}
+
 #[cfg(feature = "rustc")]
 use rustc_middle::ty::Ty;
 #[cfg(feature = "rustc")]
 use rustc_span::ErrorGuaranteed;
 
-use crate::constructor::{Constructor, ConstructorSet};
+use crate::constructor::{Constructor, ConstructorSet, IntRange};
 #[cfg(feature = "rustc")]
-use crate::lints::{
-    lint_nonexhaustive_missing_variants, lint_overlapping_range_endpoints, PatternColumn,
-};
+use crate::lints::{lint_nonexhaustive_missing_variants, PatternColumn};
 use crate::pat::DeconstructedPat;
 #[cfg(feature = "rustc")]
 use crate::rustc::RustcMatchCheckCtxt;
 #[cfg(feature = "rustc")]
 use crate::usefulness::{compute_match_usefulness, ValidityConstraint};
 
-// It's not possible to only enable the `typed_arena` dependency when the `rustc` feature is off, so
-// we use another feature instead. The crate won't compile if one of these isn't enabled.
-#[cfg(feature = "rustc")]
-pub(crate) use rustc_arena::TypedArena;
-#[cfg(feature = "stable")]
-pub(crate) use typed_arena::Arena as TypedArena;
-
 pub trait Captures<'a> {}
 impl<'a, T: ?Sized> Captures<'a> for T {}
 
@@ -53,11 +82,11 @@ impl<'a, T: ?Sized> Captures<'a> for T {}
 /// Most of the crate is parameterized on a type that implements this trait.
 pub trait TypeCx: Sized + fmt::Debug {
     /// The type of a pattern.
-    type Ty: Copy + Clone + fmt::Debug; // FIXME: remove Copy
+    type Ty: Clone + fmt::Debug;
     /// Errors that can abort analysis.
     type Error: fmt::Debug;
     /// The index of an enum variant.
-    type VariantIdx: Clone + Idx;
+    type VariantIdx: Clone + index::Idx + fmt::Debug;
     /// A string literal
     type StrLit: Clone + PartialEq + fmt::Debug;
     /// Extra data to store in a match arm.
@@ -68,32 +97,41 @@ pub trait TypeCx: Sized + fmt::Debug {
     fn is_exhaustive_patterns_feature_on(&self) -> bool;
 
     /// The number of fields for this constructor.
-    fn ctor_arity(&self, ctor: &Constructor<Self>, ty: Self::Ty) -> usize;
+    fn ctor_arity(&self, ctor: &Constructor<Self>, ty: &Self::Ty) -> usize;
 
     /// The types of the fields for this constructor. The result must have a length of
     /// `ctor_arity()`.
-    fn ctor_sub_tys(&self, ctor: &Constructor<Self>, ty: Self::Ty) -> &[Self::Ty];
+    fn ctor_sub_tys(&self, ctor: &Constructor<Self>, ty: &Self::Ty) -> &[Self::Ty];
 
     /// The set of all the constructors for `ty`.
     ///
     /// This must follow the invariants of `ConstructorSet`
-    fn ctors_for_ty(&self, ty: Self::Ty) -> Result<ConstructorSet<Self>, Self::Error>;
+    fn ctors_for_ty(&self, ty: &Self::Ty) -> Result<ConstructorSet<Self>, Self::Error>;
 
     /// Best-effort `Debug` implementation.
     fn debug_pat(f: &mut fmt::Formatter<'_>, pat: &DeconstructedPat<'_, Self>) -> fmt::Result;
 
     /// Raise a bug.
     fn bug(&self, fmt: fmt::Arguments<'_>) -> !;
+
+    /// Lint that the range `pat` overlapped with all the ranges in `overlaps_with`, where the range
+    /// they overlapped over is `overlaps_on`. We only detect singleton overlaps.
+    /// The default implementation does nothing.
+    fn lint_overlapping_range_endpoints(
+        &self,
+        _pat: &DeconstructedPat<'_, Self>,
+        _overlaps_on: IntRange,
+        _overlaps_with: &[&DeconstructedPat<'_, Self>],
+    ) {
+    }
 }
 
 /// Context that provides information global to a match.
 #[derive(derivative::Derivative)]
 #[derivative(Clone(bound = ""), Copy(bound = ""))]
-pub struct MatchCtxt<'a, 'p, Cx: TypeCx> {
+pub struct MatchCtxt<'a, Cx: TypeCx> {
     /// The context for type information.
     pub tycx: &'a Cx,
-    /// An arena to store the wildcards we produce during analysis.
-    pub wildcard_arena: &'p TypedArena<DeconstructedPat<'p, Cx>>,
 }
 
 /// The arm of a match expression.
@@ -114,24 +152,16 @@ pub fn analyze_match<'p, 'tcx>(
     arms: &[rustc::MatchArm<'p, 'tcx>],
     scrut_ty: Ty<'tcx>,
 ) -> Result<rustc::UsefulnessReport<'p, 'tcx>, ErrorGuaranteed> {
-    // Arena to store the extra wildcards we construct during analysis.
-    let wildcard_arena = tycx.pattern_arena;
     let scrut_ty = tycx.reveal_opaque_ty(scrut_ty);
     let scrut_validity = ValidityConstraint::from_bool(tycx.known_valid_scrutinee);
-    let cx = MatchCtxt { tycx, wildcard_arena };
+    let cx = MatchCtxt { tycx };
 
     let report = compute_match_usefulness(cx, arms, scrut_ty, scrut_validity)?;
 
-    let pat_column = PatternColumn::new(arms);
-
-    // Lint ranges that overlap on their endpoints, which is likely a mistake.
-    if !report.overlapping_range_endpoints.is_empty() {
-        lint_overlapping_range_endpoints(cx, &report.overlapping_range_endpoints);
-    }
-
     // Run the non_exhaustive_omitted_patterns lint. Only run on refutable patterns to avoid hitting
     // `if let`s. Only run if the match is exhaustive otherwise the error is redundant.
     if tycx.refutable && report.non_exhaustiveness_witnesses.is_empty() {
+        let pat_column = PatternColumn::new(arms);
         lint_nonexhaustive_missing_variants(cx, arms, &pat_column, scrut_ty)?;
     }
 
diff --git a/compiler/rustc_pattern_analysis/src/lints.rs b/compiler/rustc_pattern_analysis/src/lints.rs
index cfe4ca3ce93..f9f065fbe8b 100644
--- a/compiler/rustc_pattern_analysis/src/lints.rs
+++ b/compiler/rustc_pattern_analysis/src/lints.rs
@@ -1,14 +1,11 @@
-use rustc_session::lint;
 use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
 use rustc_span::ErrorGuaranteed;
 
-use crate::errors::{
-    self, NonExhaustiveOmittedPattern, NonExhaustiveOmittedPatternLintOnArm, Uncovered,
-};
+use crate::errors::{NonExhaustiveOmittedPattern, NonExhaustiveOmittedPatternLintOnArm, Uncovered};
 use crate::pat::PatOrWild;
 use crate::rustc::{
-    self, Constructor, DeconstructedPat, MatchArm, MatchCtxt, PlaceCtxt, RevealedTy,
-    RustcMatchCheckCtxt, SplitConstructorSet, WitnessPat,
+    Constructor, DeconstructedPat, MatchArm, MatchCtxt, PlaceCtxt, RevealedTy, RustcMatchCheckCtxt,
+    SplitConstructorSet, WitnessPat,
 };
 
 /// A column of patterns in the matrix, where a column is the intuitive notion of "subpatterns that
@@ -49,7 +46,7 @@ impl<'p, 'tcx> PatternColumn<'p, 'tcx> {
     }
 
     fn head_ty(&self) -> Option<RevealedTy<'tcx>> {
-        self.patterns.first().map(|pat| pat.ty())
+        self.patterns.first().map(|pat| *pat.ty())
     }
 
     /// Do constructor splitting on the constructors of the column.
@@ -59,7 +56,7 @@ impl<'p, 'tcx> PatternColumn<'p, 'tcx> {
     ) -> Result<SplitConstructorSet<'p, 'tcx>, ErrorGuaranteed> {
         let column_ctors = self.patterns.iter().map(|p| p.ctor());
         let ctors_for_ty = &pcx.ctors_for_ty()?;
-        Ok(ctors_for_ty.split(pcx, column_ctors))
+        Ok(ctors_for_ty.split(column_ctors))
     }
 
     /// Does specialization: given a constructor, this takes the patterns from the column that match
@@ -104,7 +101,7 @@ fn collect_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
     let Some(ty) = column.head_ty() else {
         return Ok(Vec::new());
     };
-    let pcx = &PlaceCtxt::new_dummy(cx, ty);
+    let pcx = &PlaceCtxt::new_dummy(cx, &ty);
 
     let set = column.analyze_ctors(pcx)?;
     if set.present.is_empty() {
@@ -196,26 +193,3 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
     }
     Ok(())
 }
-
-pub(crate) fn lint_overlapping_range_endpoints<'a, 'p, 'tcx>(
-    cx: MatchCtxt<'a, 'p, 'tcx>,
-    overlapping_range_endpoints: &[rustc::OverlappingRanges<'p, 'tcx>],
-) {
-    let rcx = cx.tycx;
-    for overlap in overlapping_range_endpoints {
-        let overlap_as_pat = rcx.hoist_pat_range(&overlap.overlaps_on, overlap.pat.ty());
-        let overlaps: Vec<_> = overlap
-            .overlaps_with
-            .iter()
-            .map(|pat| pat.data().unwrap().span)
-            .map(|span| errors::Overlap { range: overlap_as_pat.clone(), span })
-            .collect();
-        let pat_span = overlap.pat.data().unwrap().span;
-        rcx.tcx.emit_spanned_lint(
-            lint::builtin::OVERLAPPING_RANGE_ENDPOINTS,
-            rcx.match_lint_level,
-            pat_span,
-            errors::OverlappingRangeEndpoints { overlap: overlaps, range: pat_span },
-        );
-    }
-}
diff --git a/compiler/rustc_pattern_analysis/src/pat.rs b/compiler/rustc_pattern_analysis/src/pat.rs
index 2f5dc241cb7..8cd0ecb073c 100644
--- a/compiler/rustc_pattern_analysis/src/pat.rs
+++ b/compiler/rustc_pattern_analysis/src/pat.rs
@@ -54,8 +54,8 @@ impl<'p, Cx: TypeCx> DeconstructedPat<'p, Cx> {
     pub fn ctor(&self) -> &Constructor<Cx> {
         &self.ctor
     }
-    pub fn ty(&self) -> Cx::Ty {
-        self.ty
+    pub fn ty(&self) -> &Cx::Ty {
+        &self.ty
     }
     /// Returns the extra data stored in a pattern. Returns `None` if the pattern is a wildcard that
     /// does not correspond to a user-supplied pattern.
@@ -240,17 +240,17 @@ impl<Cx: TypeCx> WitnessPat<Cx> {
     /// Construct a pattern that matches everything that starts with this constructor.
     /// For example, if `ctor` is a `Constructor::Variant` for `Option::Some`, we get the pattern
     /// `Some(_)`.
-    pub(crate) fn wild_from_ctor(pcx: &PlaceCtxt<'_, '_, Cx>, ctor: Constructor<Cx>) -> Self {
+    pub(crate) fn wild_from_ctor(pcx: &PlaceCtxt<'_, Cx>, ctor: Constructor<Cx>) -> Self {
         let field_tys = pcx.ctor_sub_tys(&ctor);
-        let fields = field_tys.iter().map(|ty| Self::wildcard(*ty)).collect();
-        Self::new(ctor, fields, pcx.ty)
+        let fields = field_tys.iter().cloned().map(|ty| Self::wildcard(ty)).collect();
+        Self::new(ctor, fields, pcx.ty.clone())
     }
 
     pub fn ctor(&self) -> &Constructor<Cx> {
         &self.ctor
     }
-    pub fn ty(&self) -> Cx::Ty {
-        self.ty
+    pub fn ty(&self) -> &Cx::Ty {
+        &self.ty
     }
 
     pub fn iter_fields(&self) -> impl Iterator<Item = &WitnessPat<Cx>> {
diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs
index a17cd2c81b9..27b25802427 100644
--- a/compiler/rustc_pattern_analysis/src/rustc.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc.rs
@@ -1,3 +1,4 @@
+use smallvec::SmallVec;
 use std::fmt;
 use std::iter::once;
 
@@ -5,24 +6,21 @@ use rustc_arena::{DroplessArena, TypedArena};
 use rustc_data_structures::captures::Captures;
 use rustc_hir::def_id::DefId;
 use rustc_hir::HirId;
-use rustc_index::Idx;
-use rustc_index::IndexVec;
+use rustc_index::{Idx, IndexVec};
 use rustc_middle::middle::stability::EvalResult;
 use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::mir::{self, Const};
 use rustc_middle::thir::{FieldPat, Pat, PatKind, PatRange, PatRangeBoundary};
 use rustc_middle::ty::layout::IntegerExt;
-use rustc_middle::ty::TypeVisitableExt;
-use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, VariantDef};
-use rustc_span::ErrorGuaranteed;
-use rustc_span::{Span, DUMMY_SP};
+use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeVisitableExt, VariantDef};
+use rustc_session::lint;
+use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP};
 use rustc_target::abi::{FieldIdx, Integer, VariantIdx, FIRST_VARIANT};
-use smallvec::SmallVec;
 
 use crate::constructor::{
     IntRange, MaybeInfiniteInt, OpaqueId, RangeEnd, Slice, SliceKind, VariantVisibility,
 };
-use crate::TypeCx;
+use crate::{errors, TypeCx};
 
 use crate::constructor::Constructor::*;
 
@@ -33,11 +31,9 @@ pub type ConstructorSet<'p, 'tcx> =
 pub type DeconstructedPat<'p, 'tcx> =
     crate::pat::DeconstructedPat<'p, RustcMatchCheckCtxt<'p, 'tcx>>;
 pub type MatchArm<'p, 'tcx> = crate::MatchArm<'p, RustcMatchCheckCtxt<'p, 'tcx>>;
-pub type MatchCtxt<'a, 'p, 'tcx> = crate::MatchCtxt<'a, 'p, RustcMatchCheckCtxt<'p, 'tcx>>;
-pub type OverlappingRanges<'p, 'tcx> =
-    crate::usefulness::OverlappingRanges<'p, RustcMatchCheckCtxt<'p, 'tcx>>;
+pub type MatchCtxt<'a, 'p, 'tcx> = crate::MatchCtxt<'a, RustcMatchCheckCtxt<'p, 'tcx>>;
 pub(crate) type PlaceCtxt<'a, 'p, 'tcx> =
-    crate::usefulness::PlaceCtxt<'a, 'p, RustcMatchCheckCtxt<'p, 'tcx>>;
+    crate::usefulness::PlaceCtxt<'a, RustcMatchCheckCtxt<'p, 'tcx>>;
 pub(crate) type SplitConstructorSet<'p, 'tcx> =
     crate::constructor::SplitConstructorSet<RustcMatchCheckCtxt<'p, 'tcx>>;
 pub type Usefulness<'p, 'tcx> = crate::usefulness::Usefulness<'p, RustcMatchCheckCtxt<'p, 'tcx>>;
@@ -80,7 +76,9 @@ pub struct RustcMatchCheckCtxt<'p, 'tcx> {
     /// outside its module and should not be matchable with an empty match statement.
     pub module: DefId,
     pub param_env: ty::ParamEnv<'tcx>,
+    /// To allocate lowered patterns
     pub pattern_arena: &'p TypedArena<DeconstructedPat<'p, 'tcx>>,
+    /// To allocate the result of `self.ctor_sub_tys()`
     pub dropless_arena: &'p DroplessArena,
     /// Lint level at the match.
     pub match_lint_level: HirId,
@@ -768,7 +766,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> {
         let mut subpatterns = pat.iter_fields().map(|p| Box::new(cx.hoist_witness_pat(p)));
         let kind = match pat.ctor() {
             Bool(b) => PatKind::Constant { value: mir::Const::from_bool(cx.tcx, *b) },
-            IntRange(range) => return self.hoist_pat_range(range, pat.ty()),
+            IntRange(range) => return self.hoist_pat_range(range, *pat.ty()),
             Struct | Variant(_) | UnionField => match pat.ty().kind() {
                 ty::Tuple(..) => PatKind::Leaf {
                     subpatterns: subpatterns
@@ -787,7 +785,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> {
                         RustcMatchCheckCtxt::variant_index_for_adt(&pat.ctor(), *adt_def);
                     let variant = &adt_def.variant(variant_index);
                     let subpatterns = cx
-                        .list_variant_nonhidden_fields(pat.ty(), variant)
+                        .list_variant_nonhidden_fields(*pat.ty(), variant)
                         .zip(subpatterns)
                         .map(|((field, _ty), pattern)| FieldPat { field, pattern })
                         .collect();
@@ -798,7 +796,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> {
                         PatKind::Leaf { subpatterns }
                     }
                 }
-                _ => bug!("unexpected ctor for type {:?} {:?}", pat.ctor(), pat.ty()),
+                _ => bug!("unexpected ctor for type {:?} {:?}", pat.ctor(), *pat.ty()),
             },
             // Note: given the expansion of `&str` patterns done in `expand_pattern`, we should
             // be careful to reconstruct the correct constant pattern here. However a string
@@ -963,21 +961,21 @@ impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> {
         self.tcx.features().exhaustive_patterns
     }
 
-    fn ctor_arity(&self, ctor: &crate::constructor::Constructor<Self>, ty: Self::Ty) -> usize {
-        self.ctor_arity(ctor, ty)
+    fn ctor_arity(&self, ctor: &crate::constructor::Constructor<Self>, ty: &Self::Ty) -> usize {
+        self.ctor_arity(ctor, *ty)
     }
     fn ctor_sub_tys(
         &self,
         ctor: &crate::constructor::Constructor<Self>,
-        ty: Self::Ty,
+        ty: &Self::Ty,
     ) -> &[Self::Ty] {
-        self.ctor_sub_tys(ctor, ty)
+        self.ctor_sub_tys(ctor, *ty)
     }
     fn ctors_for_ty(
         &self,
-        ty: Self::Ty,
+        ty: &Self::Ty,
     ) -> Result<crate::constructor::ConstructorSet<Self>, Self::Error> {
-        self.ctors_for_ty(ty)
+        self.ctors_for_ty(*ty)
     }
 
     fn debug_pat(
@@ -989,6 +987,27 @@ impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> {
     fn bug(&self, fmt: fmt::Arguments<'_>) -> ! {
         span_bug!(self.scrut_span, "{}", fmt)
     }
+
+    fn lint_overlapping_range_endpoints(
+        &self,
+        pat: &crate::pat::DeconstructedPat<'_, Self>,
+        overlaps_on: IntRange,
+        overlaps_with: &[&crate::pat::DeconstructedPat<'_, Self>],
+    ) {
+        let overlap_as_pat = self.hoist_pat_range(&overlaps_on, *pat.ty());
+        let overlaps: Vec<_> = overlaps_with
+            .iter()
+            .map(|pat| pat.data().unwrap().span)
+            .map(|span| errors::Overlap { range: overlap_as_pat.clone(), span })
+            .collect();
+        let pat_span = pat.data().unwrap().span;
+        self.tcx.emit_spanned_lint(
+            lint::builtin::OVERLAPPING_RANGE_ENDPOINTS,
+            self.match_lint_level,
+            pat_span,
+            errors::OverlappingRangeEndpoints { overlap: overlaps, range: pat_span },
+        );
+    }
 }
 
 /// Recursively expand this pattern into its subpatterns. Only useful for or-patterns.
diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs
index 85b6a6a3b6c..d7852a2b2cb 100644
--- a/compiler/rustc_pattern_analysis/src/usefulness.rs
+++ b/compiler/rustc_pattern_analysis/src/usefulness.rs
@@ -732,20 +732,19 @@ pub fn ensure_sufficient_stack<R>(f: impl FnOnce() -> R) -> R {
 /// Context that provides information local to a place under investigation.
 #[derive(derivative::Derivative)]
 #[derivative(Debug(bound = ""), Clone(bound = ""), Copy(bound = ""))]
-pub(crate) struct PlaceCtxt<'a, 'p, Cx: TypeCx> {
+pub(crate) struct PlaceCtxt<'a, Cx: TypeCx> {
     #[derivative(Debug = "ignore")]
-    pub(crate) mcx: MatchCtxt<'a, 'p, Cx>,
+    pub(crate) mcx: MatchCtxt<'a, Cx>,
     /// Type of the place under investigation.
-    pub(crate) ty: Cx::Ty,
-    /// Whether the place is the original scrutinee place, as opposed to a subplace of it.
-    pub(crate) is_scrutinee: bool,
+    #[derivative(Clone(clone_with = "Clone::clone"))] // See rust-derivative#90
+    pub(crate) ty: &'a Cx::Ty,
 }
 
-impl<'a, 'p, Cx: TypeCx> PlaceCtxt<'a, 'p, Cx> {
+impl<'a, Cx: TypeCx> PlaceCtxt<'a, Cx> {
     /// A `PlaceCtxt` when code other than `is_useful` needs one.
     #[cfg_attr(not(feature = "rustc"), allow(dead_code))]
-    pub(crate) fn new_dummy(mcx: MatchCtxt<'a, 'p, Cx>, ty: Cx::Ty) -> Self {
-        PlaceCtxt { mcx, ty, is_scrutinee: false }
+    pub(crate) fn new_dummy(mcx: MatchCtxt<'a, Cx>, ty: &'a Cx::Ty) -> Self {
+        PlaceCtxt { mcx, ty }
     }
 
     pub(crate) fn ctor_arity(&self, ctor: &Constructor<Cx>) -> usize {
@@ -768,9 +767,6 @@ impl<'a, 'p, Cx: TypeCx> PlaceCtxt<'a, 'p, Cx> {
 pub enum ValidityConstraint {
     ValidOnly,
     MaybeInvalid,
-    /// Option for backwards compatibility: the place is not known to be valid but we allow omitting
-    /// `useful && !reachable` arms anyway.
-    MaybeInvalidButAllowOmittingArms,
 }
 
 impl ValidityConstraint {
@@ -778,20 +774,9 @@ impl ValidityConstraint {
         if is_valid_only { ValidOnly } else { MaybeInvalid }
     }
 
-    fn allow_omitting_side_effecting_arms(self) -> Self {
-        match self {
-            MaybeInvalid | MaybeInvalidButAllowOmittingArms => MaybeInvalidButAllowOmittingArms,
-            // There are no side-effecting empty arms here, nothing to do.
-            ValidOnly => ValidOnly,
-        }
-    }
-
     fn is_known_valid(self) -> bool {
         matches!(self, ValidOnly)
     }
-    fn allows_omitting_empty_arms(self) -> bool {
-        matches!(self, ValidOnly | MaybeInvalidButAllowOmittingArms)
-    }
 
     /// If the place has validity given by `self` and we read that the value at the place has
     /// constructor `ctor`, this computes what we can assume about the validity of the constructor
@@ -814,7 +799,7 @@ impl fmt::Display for ValidityConstraint {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let s = match self {
             ValidOnly => "✓",
-            MaybeInvalid | MaybeInvalidButAllowOmittingArms => "?",
+            MaybeInvalid => "?",
         };
         write!(f, "{s}")
     }
@@ -1039,8 +1024,8 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> {
         matrix
     }
 
-    fn head_ty(&self) -> Option<Cx::Ty> {
-        self.place_ty.first().copied()
+    fn head_ty(&self) -> Option<&Cx::Ty> {
+        self.place_ty.first()
     }
     fn column_count(&self) -> usize {
         self.place_ty.len()
@@ -1067,14 +1052,14 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> {
     /// This computes `specialize(ctor, self)`. See top of the file for explanations.
     fn specialize_constructor(
         &self,
-        pcx: &PlaceCtxt<'_, 'p, Cx>,
+        pcx: &PlaceCtxt<'_, Cx>,
         ctor: &Constructor<Cx>,
         ctor_is_relevant: bool,
     ) -> Matrix<'p, Cx> {
         let ctor_sub_tys = pcx.ctor_sub_tys(ctor);
         let arity = ctor_sub_tys.len();
         let specialized_place_ty =
-            ctor_sub_tys.iter().chain(self.place_ty[1..].iter()).copied().collect();
+            ctor_sub_tys.iter().chain(self.place_ty[1..].iter()).cloned().collect();
         let ctor_sub_validity = self.place_validity[0].specialize(ctor);
         let specialized_place_validity = std::iter::repeat(ctor_sub_validity)
             .take(arity)
@@ -1226,11 +1211,11 @@ impl<Cx: TypeCx> WitnessStack<Cx> {
     /// pats: [(false, "foo"), _, true]
     /// result: [Enum::Variant { a: (false, "foo"), b: _ }, true]
     /// ```
-    fn apply_constructor(&mut self, pcx: &PlaceCtxt<'_, '_, Cx>, ctor: &Constructor<Cx>) {
+    fn apply_constructor(&mut self, pcx: &PlaceCtxt<'_, Cx>, ctor: &Constructor<Cx>) {
         let len = self.0.len();
         let arity = ctor.arity(pcx);
         let fields = self.0.drain((len - arity)..).rev().collect();
-        let pat = WitnessPat::new(ctor.clone(), fields, pcx.ty);
+        let pat = WitnessPat::new(ctor.clone(), fields, pcx.ty.clone());
         self.0.push(pat);
     }
 }
@@ -1277,7 +1262,7 @@ impl<Cx: TypeCx> WitnessMatrix<Cx> {
     /// Reverses specialization by `ctor`. See the section on `unspecialize` at the top of the file.
     fn apply_constructor(
         &mut self,
-        pcx: &PlaceCtxt<'_, '_, Cx>,
+        pcx: &PlaceCtxt<'_, Cx>,
         missing_ctors: &[Constructor<Cx>],
         ctor: &Constructor<Cx>,
         report_individual_missing_ctors: bool,
@@ -1340,10 +1325,10 @@ impl<Cx: TypeCx> WitnessMatrix<Cx> {
 /// We can however get false negatives because exhaustiveness does not explore all cases. See the
 /// section on relevancy at the top of the file.
 fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>(
+    mcx: MatchCtxt<'_, Cx>,
     overlap_range: IntRange,
     matrix: &Matrix<'p, Cx>,
     specialized_matrix: &Matrix<'p, Cx>,
-    overlapping_range_endpoints: &mut Vec<OverlappingRanges<'p, Cx>>,
 ) {
     let overlap = overlap_range.lo;
     // Ranges that look like `lo..=overlap`.
@@ -1373,11 +1358,7 @@ fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>(
                     .map(|&(_, pat)| pat)
                     .collect();
                 if !overlaps_with.is_empty() {
-                    overlapping_range_endpoints.push(OverlappingRanges {
-                        pat,
-                        overlaps_on: overlap_range,
-                        overlaps_with,
-                    });
+                    mcx.tycx.lint_overlapping_range_endpoints(pat, overlap_range, &overlaps_with);
                 }
             }
             suffixes.push((child_row_id, pat))
@@ -1393,11 +1374,7 @@ fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>(
                     .map(|&(_, pat)| pat)
                     .collect();
                 if !overlaps_with.is_empty() {
-                    overlapping_range_endpoints.push(OverlappingRanges {
-                        pat,
-                        overlaps_on: overlap_range,
-                        overlaps_with,
-                    });
+                    mcx.tycx.lint_overlapping_range_endpoints(pat, overlap_range, &overlaps_with);
                 }
             }
             prefixes.push((child_row_id, pat))
@@ -1421,9 +1398,8 @@ fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>(
 /// This is all explained at the top of the file.
 #[instrument(level = "debug", skip(mcx, is_top_level), ret)]
 fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
-    mcx: MatchCtxt<'a, 'p, Cx>,
+    mcx: MatchCtxt<'a, Cx>,
     matrix: &mut Matrix<'p, Cx>,
-    overlapping_range_endpoints: &mut Vec<OverlappingRanges<'p, Cx>>,
     is_top_level: bool,
 ) -> Result<WitnessMatrix<Cx>, Cx::Error> {
     debug_assert!(matrix.rows().all(|r| r.len() == matrix.column_count()));
@@ -1435,7 +1411,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
         return Ok(WitnessMatrix::empty());
     }
 
-    let Some(ty) = matrix.head_ty() else {
+    let Some(ty) = matrix.head_ty().cloned() else {
         // The base case: there are no columns in the matrix. We are morally pattern-matching on ().
         // A row is useful iff it has no (unguarded) rows above it.
         let mut useful = true; // Whether the next row is useful.
@@ -1456,41 +1432,44 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
     };
 
     debug!("ty: {ty:?}");
-    let pcx = &PlaceCtxt { mcx, ty, is_scrutinee: is_top_level };
+    let pcx = &PlaceCtxt { mcx, ty: &ty };
+    let ctors_for_ty = pcx.ctors_for_ty()?;
 
     // Whether the place/column we are inspecting is known to contain valid data.
     let place_validity = matrix.place_validity[0];
-    // For backwards compability we allow omitting some empty arms that we ideally shouldn't.
-    let place_validity = place_validity.allow_omitting_side_effecting_arms();
+    // We treat match scrutinees of type `!` or `EmptyEnum` differently.
+    let is_toplevel_exception =
+        is_top_level && matches!(ctors_for_ty, ConstructorSet::NoConstructors);
+    // Whether empty patterns can be omitted for exhaustiveness.
+    let can_omit_empty_arms = is_toplevel_exception || mcx.tycx.is_exhaustive_patterns_feature_on();
+    // Whether empty patterns are counted as useful or not.
+    let empty_arms_are_unreachable = place_validity.is_known_valid() && can_omit_empty_arms;
 
     // Analyze the constructors present in this column.
     let ctors = matrix.heads().map(|p| p.ctor());
-    let ctors_for_ty = pcx.ctors_for_ty()?;
-    let is_integers = matches!(ctors_for_ty, ConstructorSet::Integers { .. }); // For diagnostics.
-    let split_set = ctors_for_ty.split(pcx, ctors);
+    let mut split_set = ctors_for_ty.split(ctors);
     let all_missing = split_set.present.is_empty();
-
     // Build the set of constructors we will specialize with. It must cover the whole type.
+    // We need to iterate over a full set of constructors, so we add `Missing` to represent the
+    // missing ones. This is explained under "Constructor Splitting" at the top of this file.
     let mut split_ctors = split_set.present;
-    if !split_set.missing.is_empty() {
-        // We need to iterate over a full set of constructors, so we add `Missing` to represent the
-        // missing ones. This is explained under "Constructor Splitting" at the top of this file.
-        split_ctors.push(Constructor::Missing);
-    } else if !split_set.missing_empty.is_empty() && !place_validity.is_known_valid() {
-        // The missing empty constructors are reachable if the place can contain invalid data.
+    if !(split_set.missing.is_empty()
+        && (split_set.missing_empty.is_empty() || empty_arms_are_unreachable))
+    {
         split_ctors.push(Constructor::Missing);
     }
 
     // Decide what constructors to report.
+    let is_integers = matches!(ctors_for_ty, ConstructorSet::Integers { .. });
     let always_report_all = is_top_level && !is_integers;
     // Whether we should report "Enum::A and Enum::C are missing" or "_ is missing".
     let report_individual_missing_ctors = always_report_all || !all_missing;
     // Which constructors are considered missing. We ensure that `!missing_ctors.is_empty() =>
-    // split_ctors.contains(Missing)`. The converse usually holds except in the
-    // `MaybeInvalidButAllowOmittingArms` backwards-compatibility case.
+    // split_ctors.contains(Missing)`. The converse usually holds except when
+    // `!place_validity.is_known_valid()`.
     let mut missing_ctors = split_set.missing;
-    if !place_validity.allows_omitting_empty_arms() {
-        missing_ctors.extend(split_set.missing_empty);
+    if !can_omit_empty_arms {
+        missing_ctors.append(&mut split_set.missing_empty);
     }
 
     let mut ret = WitnessMatrix::empty();
@@ -1503,12 +1482,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
         let ctor_is_relevant = matches!(ctor, Constructor::Missing) || missing_ctors.is_empty();
         let mut spec_matrix = matrix.specialize_constructor(pcx, &ctor, ctor_is_relevant);
         let mut witnesses = ensure_sufficient_stack(|| {
-            compute_exhaustiveness_and_usefulness(
-                mcx,
-                &mut spec_matrix,
-                overlapping_range_endpoints,
-                false,
-            )
+            compute_exhaustiveness_and_usefulness(mcx, &mut spec_matrix, false)
         })?;
 
         // Transform witnesses for `spec_matrix` into witnesses for `matrix`.
@@ -1537,12 +1511,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
                 && spec_matrix.rows.len() >= 2
                 && spec_matrix.rows.iter().any(|row| !row.intersects.is_empty())
             {
-                collect_overlapping_range_endpoints(
-                    overlap_range,
-                    matrix,
-                    &spec_matrix,
-                    overlapping_range_endpoints,
-                );
+                collect_overlapping_range_endpoints(mcx, overlap_range, matrix, &spec_matrix);
             }
         }
     }
@@ -1569,15 +1538,6 @@ pub enum Usefulness<'p, Cx: TypeCx> {
     Redundant,
 }
 
-/// Indicates that the range `pat` overlapped with all the ranges in `overlaps_with`, where the
-/// range they overlapped over is `overlaps_on`. We only detect singleton overlaps.
-#[derive(Clone, Debug)]
-pub struct OverlappingRanges<'p, Cx: TypeCx> {
-    pub pat: &'p DeconstructedPat<'p, Cx>,
-    pub overlaps_on: IntRange,
-    pub overlaps_with: Vec<&'p DeconstructedPat<'p, Cx>>,
-}
-
 /// The output of checking a match for exhaustiveness and arm usefulness.
 pub struct UsefulnessReport<'p, Cx: TypeCx> {
     /// For each arm of the input, whether that arm is useful after the arms above it.
@@ -1585,25 +1545,19 @@ pub struct UsefulnessReport<'p, Cx: TypeCx> {
     /// If the match is exhaustive, this is empty. If not, this contains witnesses for the lack of
     /// exhaustiveness.
     pub non_exhaustiveness_witnesses: Vec<WitnessPat<Cx>>,
-    pub overlapping_range_endpoints: Vec<OverlappingRanges<'p, Cx>>,
 }
 
 /// Computes whether a match is exhaustive and which of its arms are useful.
 #[instrument(skip(cx, arms), level = "debug")]
 pub fn compute_match_usefulness<'p, Cx: TypeCx>(
-    cx: MatchCtxt<'_, 'p, Cx>,
+    cx: MatchCtxt<'_, Cx>,
     arms: &[MatchArm<'p, Cx>],
     scrut_ty: Cx::Ty,
     scrut_validity: ValidityConstraint,
 ) -> Result<UsefulnessReport<'p, Cx>, Cx::Error> {
-    let mut overlapping_range_endpoints = Vec::new();
     let mut matrix = Matrix::new(arms, scrut_ty, scrut_validity);
-    let non_exhaustiveness_witnesses = compute_exhaustiveness_and_usefulness(
-        cx,
-        &mut matrix,
-        &mut overlapping_range_endpoints,
-        true,
-    )?;
+    let non_exhaustiveness_witnesses =
+        compute_exhaustiveness_and_usefulness(cx, &mut matrix, true)?;
 
     let non_exhaustiveness_witnesses: Vec<_> = non_exhaustiveness_witnesses.single_column();
     let arm_usefulness: Vec<_> = arms
@@ -1621,9 +1575,5 @@ pub fn compute_match_usefulness<'p, Cx: TypeCx>(
         })
         .collect();
 
-    Ok(UsefulnessReport {
-        arm_usefulness,
-        non_exhaustiveness_witnesses,
-        overlapping_range_endpoints,
-    })
+    Ok(UsefulnessReport { arm_usefulness, non_exhaustiveness_witnesses })
 }
diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml
index 88eb4603069..c57f22a0da2 100644
--- a/compiler/rustc_query_impl/Cargo.toml
+++ b/compiler/rustc_query_impl/Cargo.toml
@@ -6,7 +6,7 @@ edition = "2021"
 [dependencies]
 # tidy-alphabetical-start
 field-offset = "0.3.5"
-measureme = "10.0.0"
+measureme = "11"
 rustc-rayon-core = { version = "0.5.0", optional = true }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs
index 1f09de0ed70..0f57688063e 100644
--- a/compiler/rustc_query_system/src/dep_graph/graph.rs
+++ b/compiler/rustc_query_system/src/dep_graph/graph.rs
@@ -891,7 +891,7 @@ impl<D: Deps> DepGraphData<D> {
                       insertion for {dep_node:?}"
         );
 
-        if !side_effects.is_empty() {
+        if side_effects.maybe_any() {
             qcx.dep_context().dep_graph().with_query_deserialization(|| {
                 self.emit_side_effects(qcx, dep_node_index, side_effects)
             });
diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs
index 504763f6cdb..f6f6aa07cb3 100644
--- a/compiler/rustc_query_system/src/dep_graph/serialized.rs
+++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs
@@ -169,6 +169,7 @@ impl EdgeHeader {
     }
 }
 
+#[inline]
 fn mask(bits: usize) -> usize {
     usize::MAX >> ((std::mem::size_of::<usize>() * 8) - bits)
 }
diff --git a/compiler/rustc_query_system/src/ich/hcx.rs b/compiler/rustc_query_system/src/ich/hcx.rs
index eec0433ae68..e7eb9694f47 100644
--- a/compiler/rustc_query_system/src/ich/hcx.rs
+++ b/compiler/rustc_query_system/src/ich/hcx.rs
@@ -1,10 +1,8 @@
 use crate::ich;
 
 use rustc_ast as ast;
-use rustc_data_structures::sorted_map::SortedMap;
 use rustc_data_structures::stable_hasher::{HashStable, HashingControls, StableHasher};
 use rustc_data_structures::sync::Lrc;
-use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::definitions::DefPathHash;
 use rustc_session::cstore::Untracked;
@@ -23,7 +21,6 @@ pub struct StableHashingContext<'a> {
     // The value of `-Z incremental-ignore-spans`.
     // This field should only be used by `unstable_opts_incremental_ignore_span`
     incremental_ignore_spans: bool,
-    pub(super) body_resolver: BodyResolver<'a>,
     // Very often, we are hashing something that does not need the
     // `CachingSourceMapView`, so we initialize it lazily.
     raw_source_map: &'a SourceMap,
@@ -31,26 +28,12 @@ pub struct StableHashingContext<'a> {
     hashing_controls: HashingControls,
 }
 
-/// The `BodyResolver` allows mapping a `BodyId` to the corresponding `hir::Body`.
-/// We could also just store a plain reference to the `hir::Crate` but we want
-/// to avoid that the crate is used to get untracked access to all of the HIR.
-#[derive(Clone, Copy)]
-pub(super) enum BodyResolver<'tcx> {
-    Forbidden,
-    Ignore,
-    Traverse {
-        owner: hir::OwnerId,
-        bodies: &'tcx SortedMap<hir::ItemLocalId, &'tcx hir::Body<'tcx>>,
-    },
-}
-
 impl<'a> StableHashingContext<'a> {
     #[inline]
     pub fn new(sess: &'a Session, untracked: &'a Untracked) -> Self {
         let hash_spans_initial = !sess.opts.unstable_opts.incremental_ignore_spans;
 
         StableHashingContext {
-            body_resolver: BodyResolver::Forbidden,
             untracked,
             incremental_ignore_spans: sess.opts.unstable_opts.incremental_ignore_spans,
             caching_source_map: None,
@@ -60,24 +43,6 @@ impl<'a> StableHashingContext<'a> {
     }
 
     #[inline]
-    pub fn without_hir_bodies(&mut self, f: impl FnOnce(&mut StableHashingContext<'_>)) {
-        f(&mut StableHashingContext { body_resolver: BodyResolver::Ignore, ..self.clone() });
-    }
-
-    #[inline]
-    pub fn with_hir_bodies(
-        &mut self,
-        owner: hir::OwnerId,
-        bodies: &SortedMap<hir::ItemLocalId, &hir::Body<'_>>,
-        f: impl FnOnce(&mut StableHashingContext<'_>),
-    ) {
-        f(&mut StableHashingContext {
-            body_resolver: BodyResolver::Traverse { owner, bodies },
-            ..self.clone()
-        });
-    }
-
-    #[inline]
     pub fn while_hashing_spans<F: FnOnce(&mut Self)>(&mut self, hash_spans: bool, f: F) {
         let prev_hash_spans = self.hashing_controls.hash_spans;
         self.hashing_controls.hash_spans = hash_spans;
diff --git a/compiler/rustc_query_system/src/ich/impls_hir.rs b/compiler/rustc_query_system/src/ich/impls_hir.rs
deleted file mode 100644
index aa008d404c3..00000000000
--- a/compiler/rustc_query_system/src/ich/impls_hir.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-//! This module contains `HashStable` implementations for various HIR data
-//! types in no particular order.
-
-use crate::ich::hcx::BodyResolver;
-use crate::ich::StableHashingContext;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_hir as hir;
-
-impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> {
-    #[inline]
-    fn hash_body_id(&mut self, id: hir::BodyId, hasher: &mut StableHasher) {
-        let hcx = self;
-        match hcx.body_resolver {
-            BodyResolver::Forbidden => panic!("Hashing HIR bodies is forbidden."),
-            BodyResolver::Ignore => {}
-            BodyResolver::Traverse { owner, bodies } => {
-                assert_eq!(id.hir_id.owner, owner);
-                bodies[&id.hir_id.local_id].hash_stable(hcx, hasher);
-            }
-        }
-    }
-}
diff --git a/compiler/rustc_query_system/src/ich/impls_syntax.rs b/compiler/rustc_query_system/src/ich/impls_syntax.rs
index d170cd36ca6..5bd4fe04848 100644
--- a/compiler/rustc_query_system/src/ich/impls_syntax.rs
+++ b/compiler/rustc_query_system/src/ich/impls_syntax.rs
@@ -57,6 +57,8 @@ impl<'ctx> rustc_ast::HashStableContext for StableHashingContext<'ctx> {
     }
 }
 
+impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> {}
+
 impl<'a> HashStable<StableHashingContext<'a>> for SourceFile {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
         let SourceFile {
diff --git a/compiler/rustc_query_system/src/ich/mod.rs b/compiler/rustc_query_system/src/ich/mod.rs
index 0a1c350b2db..86e3ecb1edd 100644
--- a/compiler/rustc_query_system/src/ich/mod.rs
+++ b/compiler/rustc_query_system/src/ich/mod.rs
@@ -4,7 +4,6 @@ pub use self::hcx::StableHashingContext;
 use rustc_span::symbol::{sym, Symbol};
 
 mod hcx;
-mod impls_hir;
 mod impls_syntax;
 
 pub const IGNORED_ATTRIBUTES: &[Symbol] = &[
diff --git a/compiler/rustc_query_system/src/query/caches.rs b/compiler/rustc_query_system/src/query/caches.rs
index 0240f012da0..674a0984ae9 100644
--- a/compiler/rustc_query_system/src/query/caches.rs
+++ b/compiler/rustc_query_system/src/query/caches.rs
@@ -2,8 +2,11 @@ use crate::dep_graph::DepNodeIndex;
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sharded::{self, Sharded};
-use rustc_data_structures::sync::OnceLock;
+use rustc_data_structures::sync::{Lock, OnceLock};
+use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_index::{Idx, IndexVec};
+use rustc_span::def_id::DefId;
+use rustc_span::def_id::DefIndex;
 use std::fmt::Debug;
 use std::hash::Hash;
 use std::marker::PhantomData;
@@ -148,6 +151,8 @@ where
 
     #[inline(always)]
     fn lookup(&self, key: &K) -> Option<(V, DepNodeIndex)> {
+        // FIXME: lock_shard_by_hash will use high bits which are usually zero in the index() passed
+        // here. This makes sharding essentially useless, always selecting the zero'th shard.
         let lock = self.cache.lock_shard_by_hash(key.index() as u64);
         if let Some(Some(value)) = lock.get(*key) { Some(*value) } else { None }
     }
@@ -168,3 +173,75 @@ where
         }
     }
 }
+
+pub struct DefIdCacheSelector;
+
+impl<'tcx, V: 'tcx> CacheSelector<'tcx, V> for DefIdCacheSelector {
+    type Cache = DefIdCache<V>
+    where
+        V: Copy;
+}
+
+pub struct DefIdCache<V> {
+    /// Stores the local DefIds in a dense map. Local queries are much more often dense, so this is
+    /// a win over hashing query keys at marginal memory cost (~5% at most) compared to FxHashMap.
+    ///
+    /// The second element of the tuple is the set of keys actually present in the IndexVec, used
+    /// for faster iteration in `iter()`.
+    // FIXME: This may want to be sharded, like VecCache. However *how* to shard an IndexVec isn't
+    // super clear; VecCache is effectively not sharded today (see FIXME there). For now just omit
+    // that complexity here.
+    local: Lock<(IndexVec<DefIndex, Option<(V, DepNodeIndex)>>, Vec<DefIndex>)>,
+    foreign: DefaultCache<DefId, V>,
+}
+
+impl<V> Default for DefIdCache<V> {
+    fn default() -> Self {
+        DefIdCache { local: Default::default(), foreign: Default::default() }
+    }
+}
+
+impl<V> QueryCache for DefIdCache<V>
+where
+    V: Copy,
+{
+    type Key = DefId;
+    type Value = V;
+
+    #[inline(always)]
+    fn lookup(&self, key: &DefId) -> Option<(V, DepNodeIndex)> {
+        if key.krate == LOCAL_CRATE {
+            let cache = self.local.lock();
+            cache.0.get(key.index).and_then(|v| *v)
+        } else {
+            self.foreign.lookup(key)
+        }
+    }
+
+    #[inline]
+    fn complete(&self, key: DefId, value: V, index: DepNodeIndex) {
+        if key.krate == LOCAL_CRATE {
+            let mut cache = self.local.lock();
+            let (cache, present) = &mut *cache;
+            let slot = cache.ensure_contains_elem(key.index, Default::default);
+            if slot.is_none() {
+                // FIXME: Only store the present set when running in incremental mode. `iter` is not
+                // used outside of saving caches to disk and self-profile.
+                present.push(key.index);
+            }
+            *slot = Some((value, index));
+        } else {
+            self.foreign.complete(key, value, index)
+        }
+    }
+
+    fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) {
+        let guard = self.local.lock();
+        let (cache, present) = &*guard;
+        for &idx in present.iter() {
+            let value = cache[idx].unwrap();
+            f(&DefId { krate: LOCAL_CRATE, index: idx }, &value.0, value.1);
+        }
+        self.foreign.iter(f);
+    }
+}
diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs
index 9ff04c4e910..02b3c740b63 100644
--- a/compiler/rustc_query_system/src/query/mod.rs
+++ b/compiler/rustc_query_system/src/query/mod.rs
@@ -10,7 +10,8 @@ pub use self::job::{
 
 mod caches;
 pub use self::caches::{
-    CacheSelector, DefaultCacheSelector, QueryCache, SingleCacheSelector, VecCacheSelector,
+    CacheSelector, DefIdCacheSelector, DefaultCacheSelector, QueryCache, SingleCacheSelector,
+    VecCacheSelector,
 };
 
 mod config;
@@ -92,10 +93,13 @@ pub struct QuerySideEffects {
 }
 
 impl QuerySideEffects {
+    /// Returns true if there might be side effects.
     #[inline]
-    pub fn is_empty(&self) -> bool {
+    pub fn maybe_any(&self) -> bool {
         let QuerySideEffects { diagnostics } = self;
-        diagnostics.is_empty()
+        // Use `has_capacity` so that the destructor for `self.diagnostics` can be skipped
+        // if `maybe_any` is known to be false.
+        diagnostics.has_capacity()
     }
     pub fn append(&mut self, other: QuerySideEffects) {
         let QuerySideEffects { diagnostics } = self;
diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs
index 3bb2cc5634f..9158ba00901 100644
--- a/compiler/rustc_query_system/src/query/plumbing.rs
+++ b/compiler/rustc_query_system/src/query/plumbing.rs
@@ -538,10 +538,9 @@ where
 
     prof_timer.finish_with_query_invocation_id(dep_node_index.into());
 
-    let diagnostics = diagnostics.into_inner();
-    let side_effects = QuerySideEffects { diagnostics };
+    let side_effects = QuerySideEffects { diagnostics: diagnostics.into_inner() };
 
-    if std::intrinsics::unlikely(!side_effects.is_empty()) {
+    if std::intrinsics::unlikely(side_effects.maybe_any()) {
         if query.anon() {
             qcx.store_side_effects_for_anon_node(dep_node_index, side_effects);
         } else {
diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl
index 3f8df16e03f..c8ec10cad17 100644
--- a/compiler/rustc_resolve/messages.ftl
+++ b/compiler/rustc_resolve/messages.ftl
@@ -36,6 +36,10 @@ resolve_attempt_to_use_non_constant_value_in_constant_with_suggestion =
 resolve_attempt_to_use_non_constant_value_in_constant_without_suggestion =
     this would need to be a `{$suggestion}`
 
+resolve_binding_in_never_pattern =
+    never patterns cannot contain variable bindings
+    .suggestion = use a wildcard `_` instead
+
 resolve_binding_shadows_something_unacceptable =
     {$shadowing_binding}s cannot shadow {$shadowed_binding}s
     .label = cannot be named the same as {$article} {$shadowed_binding}
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index b5700661385..4a0c522b6ec 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -959,6 +959,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 .create_err(errs::TraitImplDuplicate { span, name, trait_item_span, old_span }),
             ResolutionError::InvalidAsmSym => self.dcx().create_err(errs::InvalidAsmSym { span }),
             ResolutionError::LowercaseSelf => self.dcx().create_err(errs::LowercaseSelf { span }),
+            ResolutionError::BindingInNeverPattern => {
+                self.dcx().create_err(errs::BindingInNeverPattern { span })
+            }
         }
     }
 
diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs
index 1fdb193e571..821b1e946f3 100644
--- a/compiler/rustc_resolve/src/errors.rs
+++ b/compiler/rustc_resolve/src/errors.rs
@@ -486,6 +486,15 @@ pub(crate) struct LowercaseSelf {
     pub(crate) span: Span,
 }
 
+#[derive(Debug)]
+#[derive(Diagnostic)]
+#[diag(resolve_binding_in_never_pattern)]
+pub(crate) struct BindingInNeverPattern {
+    #[primary_span]
+    #[suggestion(code = "_", applicability = "machine-applicable", style = "short")]
+    pub(crate) span: Span,
+}
+
 #[derive(Diagnostic)]
 #[diag(resolve_trait_impl_duplicate, code = "E0201")]
 pub(crate) struct TraitImplDuplicate {
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 82f50227911..abd724a6cc2 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -16,7 +16,7 @@ use rustc_ast::ptr::P;
 use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor};
 use rustc_ast::*;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
-use rustc_errors::{Applicability, DiagnosticArgValue, DiagnosticId, IntoDiagnosticArg};
+use rustc_errors::{Applicability, DiagnosticArgValue, IntoDiagnosticArg};
 use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS};
 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
@@ -65,6 +65,8 @@ enum IsRepeatExpr {
     Yes,
 }
 
+struct IsNeverPattern;
+
 /// Describes whether an `AnonConst` is a type level const arg or
 /// some other form of anon const (i.e. inline consts or enum discriminants)
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -531,7 +533,7 @@ impl<'a> PathSource<'a> {
         }
     }
 
-    fn error_code(self, has_unexpected_resolution: bool) -> DiagnosticId {
+    fn error_code(self, has_unexpected_resolution: bool) -> String {
         use rustc_errors::error_code;
         match (self, has_unexpected_resolution) {
             (PathSource::Trait(_), true) => error_code!(E0404),
@@ -3246,12 +3248,31 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
         self.resolve_pattern_top(&local.pat, PatternSource::Let);
     }
 
-    /// build a map from pattern identifiers to binding-info's.
-    /// this is done hygienically. This could arise for a macro
-    /// that expands into an or-pattern where one 'x' was from the
-    /// user and one 'x' came from the macro.
-    fn binding_mode_map(&mut self, pat: &Pat) -> FxIndexMap<Ident, BindingInfo> {
+    /// Build a map from pattern identifiers to binding-info's, and check the bindings are
+    /// consistent when encountering or-patterns and never patterns.
+    /// This is done hygienically: this could arise for a macro that expands into an or-pattern
+    /// where one 'x' was from the user and one 'x' came from the macro.
+    ///
+    /// A never pattern by definition indicates an unreachable case. For example, matching on
+    /// `Result<T, &!>` could look like:
+    /// ```rust
+    /// # #![feature(never_type)]
+    /// # #![feature(never_patterns)]
+    /// # fn bar(_x: u32) {}
+    /// let foo: Result<u32, &!> = Ok(0);
+    /// match foo {
+    ///     Ok(x) => bar(x),
+    ///     Err(&!),
+    /// }
+    /// ```
+    /// This extends to product types: `(x, !)` is likewise unreachable. So it doesn't make sense to
+    /// have a binding here, and we tell the user to use `_` instead.
+    fn compute_and_check_binding_map(
+        &mut self,
+        pat: &Pat,
+    ) -> Result<FxIndexMap<Ident, BindingInfo>, IsNeverPattern> {
         let mut binding_map = FxIndexMap::default();
+        let mut is_never_pat = false;
 
         pat.walk(&mut |pat| {
             match pat.kind {
@@ -3263,18 +3284,27 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                 PatKind::Or(ref ps) => {
                     // Check the consistency of this or-pattern and
                     // then add all bindings to the larger map.
-                    for bm in self.check_consistent_bindings(ps) {
-                        binding_map.extend(bm);
+                    match self.compute_and_check_or_pat_binding_map(ps) {
+                        Ok(bm) => binding_map.extend(bm),
+                        Err(IsNeverPattern) => is_never_pat = true,
                     }
                     return false;
                 }
+                PatKind::Never => is_never_pat = true,
                 _ => {}
             }
 
             true
         });
 
-        binding_map
+        if is_never_pat {
+            for (_, binding) in binding_map {
+                self.report_error(binding.span, ResolutionError::BindingInNeverPattern);
+            }
+            Err(IsNeverPattern)
+        } else {
+            Ok(binding_map)
+        }
     }
 
     fn is_base_res_local(&self, nid: NodeId) -> bool {
@@ -3284,33 +3314,52 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
         )
     }
 
-    /// Checks that all of the arms in an or-pattern have exactly the
-    /// same set of bindings, with the same binding modes for each.
-    fn check_consistent_bindings(
+    /// Compute the binding map for an or-pattern. Checks that all of the arms in the or-pattern
+    /// have exactly the same set of bindings, with the same binding modes for each.
+    /// Returns the computed binding map and a boolean indicating whether the pattern is a never
+    /// pattern.
+    ///
+    /// A never pattern by definition indicates an unreachable case. For example, destructuring a
+    /// `Result<T, &!>` could look like:
+    /// ```rust
+    /// # #![feature(never_type)]
+    /// # #![feature(never_patterns)]
+    /// # fn foo() -> Result<bool, &'static !> { Ok(true) }
+    /// let (Ok(x) | Err(&!)) = foo();
+    /// # let _ = x;
+    /// ```
+    /// Because the `Err(&!)` branch is never reached, it does not need to have the same bindings as
+    /// the other branches of the or-pattern. So we must ignore never pattern when checking the
+    /// bindings of an or-pattern.
+    /// Moreover, if all the subpatterns are never patterns (e.g. `Ok(!) | Err(!)`), then the
+    /// pattern as a whole counts as a never pattern (since it's definitionallly unreachable).
+    fn compute_and_check_or_pat_binding_map(
         &mut self,
         pats: &[P<Pat>],
-    ) -> Vec<FxIndexMap<Ident, BindingInfo>> {
-        // pats is consistent.
+    ) -> Result<FxIndexMap<Ident, BindingInfo>, IsNeverPattern> {
         let mut missing_vars = FxIndexMap::default();
         let mut inconsistent_vars = FxIndexMap::default();
 
-        // 1) Compute the binding maps of all arms.
-        let maps = pats.iter().map(|pat| self.binding_mode_map(pat)).collect::<Vec<_>>();
+        // 1) Compute the binding maps of all arms; we must ignore never patterns here.
+        let not_never_pats = pats
+            .iter()
+            .filter_map(|pat| {
+                let binding_map = self.compute_and_check_binding_map(pat).ok()?;
+                Some((binding_map, pat))
+            })
+            .collect::<Vec<_>>();
 
         // 2) Record any missing bindings or binding mode inconsistencies.
-        for (map_outer, pat_outer) in maps.iter().zip(pats.iter()) {
+        for (map_outer, pat_outer) in not_never_pats.iter() {
             // Check against all arms except for the same pattern which is always self-consistent.
-            let inners = maps
+            let inners = not_never_pats
                 .iter()
-                .zip(pats.iter())
                 .filter(|(_, pat)| pat.id != pat_outer.id)
-                .flat_map(|(map, _)| map)
-                .map(|(key, binding)| (key.name, map_outer.get(key), binding));
-
-            let inners = inners.collect::<Vec<_>>();
+                .flat_map(|(map, _)| map);
 
-            for (name, info, &binding_inner) in inners {
-                match info {
+            for (key, binding_inner) in inners {
+                let name = key.name;
+                match map_outer.get(key) {
                     None => {
                         // The inner binding is missing in the outer.
                         let binding_error =
@@ -3351,19 +3400,32 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             self.report_error(v.0, ResolutionError::VariableBoundWithDifferentMode(name, v.1));
         }
 
-        // 5) Finally bubble up all the binding maps.
-        maps
+        // 5) Bubble up the final binding map.
+        if not_never_pats.is_empty() {
+            // All the patterns are never patterns, so the whole or-pattern is one too.
+            Err(IsNeverPattern)
+        } else {
+            let mut binding_map = FxIndexMap::default();
+            for (bm, _) in not_never_pats {
+                binding_map.extend(bm);
+            }
+            Ok(binding_map)
+        }
     }
 
-    /// Check the consistency of the outermost or-patterns.
-    fn check_consistent_bindings_top(&mut self, pat: &'ast Pat) {
+    /// Check the consistency of bindings wrt or-patterns and never patterns.
+    fn check_consistent_bindings(&mut self, pat: &'ast Pat) {
+        let mut is_or_or_never = false;
         pat.walk(&mut |pat| match pat.kind {
-            PatKind::Or(ref ps) => {
-                self.check_consistent_bindings(ps);
+            PatKind::Or(..) | PatKind::Never => {
+                is_or_or_never = true;
                 false
             }
             _ => true,
-        })
+        });
+        if is_or_or_never {
+            let _ = self.compute_and_check_binding_map(pat);
+        }
     }
 
     fn resolve_arm(&mut self, arm: &'ast Arm) {
@@ -3392,7 +3454,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
         visit::walk_pat(self, pat);
         self.resolve_pattern_inner(pat, pat_src, bindings);
         // This has to happen *after* we determine which pat_idents are variants:
-        self.check_consistent_bindings_top(pat);
+        self.check_consistent_bindings(pat);
     }
 
     /// Resolve bindings in a pattern. This is a helper to `resolve_pattern`.
@@ -3759,7 +3821,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             swap(&mut err.span, &mut parent_err.span);
             err.children = take(&mut parent_err.children);
             err.sort_span = parent_err.sort_span;
-            err.is_lint = parent_err.is_lint;
+            err.is_lint = parent_err.is_lint.clone();
 
             // merge the parent's suggestions with the typo suggestions
             fn append_result<T, E>(res1: &mut Result<Vec<T>, E>, res2: Result<Vec<T>, E>) {
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 58ff4d8c793..abb0a7a465a 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -1745,12 +1745,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
             // Doing analysis on local `DefId`s would cause infinite recursion.
             return;
         }
+        let Ok(impls) = self.r.tcx.inherent_impls(def_id) else { return };
         // Look at all the associated functions without receivers in the type's
         // inherent impls to look for builders that return `Self`
-        let mut items = self
-            .r
-            .tcx
-            .inherent_impls(def_id)
+        let mut items = impls
             .iter()
             .flat_map(|i| self.r.tcx.associated_items(i).in_definition_order())
             // Only assoc fn with no receivers.
@@ -2569,8 +2567,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                     debug!(?param.ident, ?param.ident.span, ?use_span);
 
                     let elidable = matches!(use_ctxt, LifetimeCtxt::Ref);
+                    let deletion_span =
+                        if param.bounds.is_empty() { deletion_span() } else { None };
 
-                    let deletion_span = deletion_span();
                     self.r.lint_buffer.buffer_lint_with_diagnostic(
                         lint::builtin::SINGLE_USE_LIFETIMES,
                         param.id,
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 90aa7d79bf0..341c566d97f 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -257,7 +257,7 @@ enum ResolutionError<'a> {
         kind: &'static str,
         trait_path: String,
         trait_item_span: Span,
-        code: rustc_errors::DiagnosticId,
+        code: String,
     },
     /// Error E0201: multiple impl items for the same trait item.
     TraitImplDuplicate { name: Symbol, trait_item_span: Span, old_span: Span },
@@ -265,6 +265,8 @@ enum ResolutionError<'a> {
     InvalidAsmSym,
     /// `self` used instead of `Self` in a generic parameter
     LowercaseSelf,
+    /// A never pattern has a binding.
+    BindingInNeverPattern,
 }
 
 enum VisResolutionError<'a> {
diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs
index 35275821453..48bee4cd2f0 100644
--- a/compiler/rustc_serialize/src/lib.rs
+++ b/compiler/rustc_serialize/src/lib.rs
@@ -16,7 +16,6 @@
 #![feature(min_specialization)]
 #![feature(never_type)]
 #![feature(ptr_sub_ptr)]
-#![feature(slice_first_last_chunk)]
 #![cfg_attr(test, feature(test))]
 #![allow(rustc::internal)]
 #![deny(rustc::untranslatable_diagnostic)]
diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl
index 53bdef6dfa0..af8c962a2ed 100644
--- a/compiler/rustc_session/messages.ftl
+++ b/compiler/rustc_session/messages.ftl
@@ -75,8 +75,6 @@ session_not_circumvent_feature = `-Zunleash-the-miri-inside-of-you` may not be u
 
 session_not_supported = not supported
 
-session_nul_in_c_str = null characters in C string literals are not supported
-
 session_octal_float_literal_not_supported = octal float literal is not supported
 
 session_optimization_fuel_exhausted = optimization-fuel-exhausted: {$msg}
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index fe1166457ba..e751ff13a34 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -533,21 +533,6 @@ impl Default for ErrorOutputType {
     }
 }
 
-/// Parameter to control path trimming.
-#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
-pub enum TrimmedDefPaths {
-    /// `try_print_trimmed_def_path` never prints a trimmed path and never calls the expensive
-    /// query.
-    #[default]
-    Never,
-    /// `try_print_trimmed_def_path` calls the expensive query, the query doesn't call
-    /// `good_path_delayed_bug`.
-    Always,
-    /// `try_print_trimmed_def_path` calls the expensive query, the query calls
-    /// `good_path_delayed_bug`.
-    GoodPath,
-}
-
 #[derive(Clone, Hash, Debug)]
 pub enum ResolveDocLinks {
     /// Do not resolve doc links.
@@ -1089,7 +1074,7 @@ impl Default for Options {
             debug_assertions: true,
             actually_rustdoc: false,
             resolve_doc_links: ResolveDocLinks::None,
-            trimmed_def_paths: TrimmedDefPaths::default(),
+            trimmed_def_paths: false,
             cli_forced_codegen_units: None,
             cli_forced_local_thinlto_off: false,
             remap_path_prefix: Vec::new(),
@@ -2926,7 +2911,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
         debug_assertions,
         actually_rustdoc: false,
         resolve_doc_links: ResolveDocLinks::ExportedMetadata,
-        trimmed_def_paths: TrimmedDefPaths::default(),
+        trimmed_def_paths: false,
         cli_forced_codegen_units: codegen_units,
         cli_forced_local_thinlto_off: disable_local_thinlto,
         remap_path_prefix,
@@ -3205,12 +3190,12 @@ pub enum WasiExecModel {
 /// how the hash should be calculated when adding a new command-line argument.
 pub(crate) mod dep_tracking {
     use super::{
-        BranchProtection, CFGuard, CFProtection, CrateType, DebugInfo, DebugInfoCompression,
-        ErrorOutputType, FunctionReturn, InliningThreshold, InstrumentCoverage, InstrumentXRay,
-        LinkerPluginLto, LocationDetail, LtoCli, NextSolverConfig, OomStrategy, OptLevel,
-        OutFileName, OutputType, OutputTypes, Polonius, RemapPathScopeComponents, ResolveDocLinks,
-        SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion,
-        TrimmedDefPaths, WasiExecModel,
+        BranchProtection, CFGuard, CFProtection, CollapseMacroDebuginfo, CrateType, DebugInfo,
+        DebugInfoCompression, ErrorOutputType, FunctionReturn, InliningThreshold,
+        InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail, LtoCli,
+        NextSolverConfig, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes, Polonius,
+        RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind,
+        SwitchWithOptPath, SymbolManglingVersion, WasiExecModel,
     };
     use crate::lint;
     use crate::utils::NativeLib;
@@ -3289,6 +3274,7 @@ pub(crate) mod dep_tracking {
         LtoCli,
         DebugInfo,
         DebugInfoCompression,
+        CollapseMacroDebuginfo,
         UnstableFeatures,
         NativeLib,
         SanitizerSet,
@@ -3305,7 +3291,6 @@ pub(crate) mod dep_tracking {
         SymbolManglingVersion,
         RemapPathScopeComponents,
         SourceFileHashAlgorithm,
-        TrimmedDefPaths,
         OutFileName,
         OutputType,
         RealFileName,
@@ -3453,6 +3438,25 @@ pub enum ProcMacroExecutionStrategy {
     CrossThread,
 }
 
+/// How to perform collapse macros debug info
+/// if-ext - if macro from different crate (related to callsite code)
+/// | cmd \ attr    | no  | (unspecified) | external | yes |
+/// | no            | no  | no            | no       | no  |
+/// | (unspecified) | no  | no            | if-ext   | yes |
+/// | external      | no  | if-ext        | if-ext   | yes |
+/// | yes           | yes | yes           | yes      | yes |
+#[derive(Clone, Copy, PartialEq, Hash, Debug)]
+pub enum CollapseMacroDebuginfo {
+    /// Don't collapse debuginfo for the macro
+    No = 0,
+    /// Unspecified value
+    Unspecified = 1,
+    /// Collapse debuginfo if the macro comes from a different crate
+    External = 2,
+    /// Collapse debuginfo for the macro
+    Yes = 3,
+}
+
 /// Which format to use for `-Z dump-mono-stats`
 #[derive(Clone, Copy, PartialEq, Hash, Debug)]
 pub enum DumpMonoStatsFormat {
diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs
index 21a206798af..e19f0fd84de 100644
--- a/compiler/rustc_session/src/errors.rs
+++ b/compiler/rustc_session/src/errors.rs
@@ -6,7 +6,7 @@ use rustc_errors::{
     error_code, DiagCtxt, DiagnosticBuilder, DiagnosticMessage, IntoDiagnostic, Level, MultiSpan,
 };
 use rustc_macros::Diagnostic;
-use rustc_span::{BytePos, Span, Symbol};
+use rustc_span::{Span, Symbol};
 use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple};
 
 use crate::parse::ParseSess;
@@ -346,13 +346,6 @@ pub(crate) struct BinaryFloatLiteralNotSupported {
     pub span: Span,
 }
 
-#[derive(Diagnostic)]
-#[diag(session_nul_in_c_str)]
-pub(crate) struct NulInCStr {
-    #[primary_span]
-    pub span: Span,
-}
-
 pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span: Span) {
     // Checks if `s` looks like i32 or u1234 etc.
     fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool {
@@ -432,12 +425,6 @@ pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span:
             };
             dcx.emit_err(IntLiteralTooLarge { span, limit });
         }
-        LitError::NulInCStr(range) => {
-            let lo = BytePos(span.lo().0 + range.start as u32 + 2);
-            let hi = BytePos(span.lo().0 + range.end as u32 + 2);
-            let span = span.with_lo(lo).with_hi(hi);
-            dcx.emit_err(NulInCStr { span });
-        }
     }
 }
 
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 2d91a3fbd91..1337ade62c0 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -183,7 +183,7 @@ top_level_options!(
         resolve_doc_links: ResolveDocLinks [TRACKED],
 
         /// Control path trimming.
-        trimmed_def_paths: TrimmedDefPaths [TRACKED],
+        trimmed_def_paths: bool [TRACKED],
 
         /// Specifications of codegen units / ThinLTO which are forced as a
         /// result of parsing command line options. These are not necessarily
@@ -388,6 +388,7 @@ mod desc {
     pub const parse_cfprotection: &str = "`none`|`no`|`n` (default), `branch`, `return`, or `full`|`yes`|`y` (equivalent to `branch` and `return`)";
     pub const parse_debuginfo: &str = "either an integer (0, 1, 2), `none`, `line-directives-only`, `line-tables-only`, `limited`, or `full`";
     pub const parse_debuginfo_compression: &str = "one of `none`, `zlib`, or `zstd`";
+    pub const parse_collapse_macro_debuginfo: &str = "one of `no`, `external`, or `yes`";
     pub const parse_strip: &str = "either `none`, `debuginfo`, or `symbols`";
     pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavorCli::one_of();
     pub const parse_optimization_fuel: &str = "crate=integer";
@@ -1302,6 +1303,19 @@ mod parse {
         true
     }
 
+    pub(crate) fn parse_collapse_macro_debuginfo(
+        slot: &mut CollapseMacroDebuginfo,
+        v: Option<&str>,
+    ) -> bool {
+        *slot = match v {
+            Some("no") => CollapseMacroDebuginfo::No,
+            Some("external") => CollapseMacroDebuginfo::External,
+            Some("yes") => CollapseMacroDebuginfo::Yes,
+            _ => return false,
+        };
+        true
+    }
+
     pub(crate) fn parse_proc_macro_execution_strategy(
         slot: &mut ProcMacroExecutionStrategy,
         v: Option<&str>,
@@ -1534,6 +1548,9 @@ options! {
         "instrument control-flow architecture protection"),
     codegen_backend: Option<String> = (None, parse_opt_string, [TRACKED],
         "the backend to use"),
+    collapse_macro_debuginfo: CollapseMacroDebuginfo = (CollapseMacroDebuginfo::Unspecified,
+        parse_collapse_macro_debuginfo, [TRACKED],
+        "set option to collapse debuginfo for macros"),
     combine_cgu: bool = (false, parse_bool, [TRACKED],
         "combine CGUs into a single one"),
     crate_attr: Vec<String> = (Vec::new(), parse_string_push, [TRACKED],
@@ -1724,6 +1741,8 @@ options! {
         "run all passes except codegen; no output"),
     no_generate_arange_section: bool = (false, parse_no_flag, [TRACKED],
         "omit DWARF address ranges that give faster lookups"),
+    no_implied_bounds_compat: bool = (false, parse_bool, [TRACKED],
+        "disable the compatibility version of the `implied_bounds_ty` query"),
     no_jump_tables: bool = (false, parse_no_flag, [TRACKED],
         "disable the jump tables and lookup tables that can be generated from a switch case lowering"),
     no_leak_check: bool = (false, parse_no_flag, [UNTRACKED],
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index c629c9884c8..16036e5be38 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -15,8 +15,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::{AppendOnlyVec, Lock, Lrc};
 use rustc_errors::{emitter::SilentEmitter, DiagCtxt};
 use rustc_errors::{
-    fallback_fluent_bundle, Diagnostic, DiagnosticBuilder, DiagnosticId, DiagnosticMessage,
-    MultiSpan, StashKey,
+    fallback_fluent_bundle, Diagnostic, DiagnosticBuilder, DiagnosticMessage, MultiSpan, StashKey,
 };
 use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures};
 use rustc_span::edition::Edition;
@@ -148,7 +147,7 @@ pub fn feature_warn_issue(
     // Decorate this as a future-incompatibility lint as in rustc_middle::lint::struct_lint_level
     let lint = UNSTABLE_SYNTAX_PRE_EXPANSION;
     let future_incompatible = lint.future_incompatible.as_ref().unwrap();
-    err.code(DiagnosticId::Lint { name: lint.name_lower(), has_future_breakage: false });
+    err.is_lint(lint.name_lower(), /* has_future_breakage */ false);
     err.warn(lint.desc);
     err.note(format!("for more information, see {}", future_incompatible.reference));
 
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 1c3d5a3cb88..cba6ce0d235 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -14,15 +14,16 @@ use rustc_data_structures::flock;
 use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
 use rustc_data_structures::jobserver::{self, Client};
 use rustc_data_structures::profiling::{SelfProfiler, SelfProfilerRef};
-use rustc_data_structures::sync::{AtomicU64, DynSend, DynSync, Lock, Lrc, OneThread};
+use rustc_data_structures::sync::{
+    AtomicU64, DynSend, DynSync, Lock, Lrc, MappedReadGuard, ReadGuard, RwLock,
+};
 use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitter;
 use rustc_errors::emitter::{DynEmitter, HumanEmitter, HumanReadableErrorType};
 use rustc_errors::json::JsonEmitter;
 use rustc_errors::registry::Registry;
 use rustc_errors::{
-    error_code, fallback_fluent_bundle, DiagCtxt, DiagnosticBuilder, DiagnosticId,
-    DiagnosticMessage, ErrorGuaranteed, FatalAbort, FluentBundle, IntoDiagnostic,
-    LazyFallbackBundle, TerminalUrl,
+    error_code, fallback_fluent_bundle, DiagCtxt, DiagnosticBuilder, DiagnosticMessage,
+    ErrorGuaranteed, FatalAbort, FluentBundle, IntoDiagnostic, LazyFallbackBundle, TerminalUrl,
 };
 use rustc_macros::HashStable_Generic;
 pub use rustc_span::def_id::StableCrateId;
@@ -36,7 +37,6 @@ use rustc_target::spec::{
 };
 
 use std::any::Any;
-use std::cell::{self, RefCell};
 use std::env;
 use std::fmt;
 use std::ops::{Div, Mul};
@@ -150,7 +150,7 @@ pub struct Session {
     /// Input, input file path and output file path to this compilation process.
     pub io: CompilerIO,
 
-    incr_comp_session: OneThread<RefCell<IncrCompSession>>,
+    incr_comp_session: RwLock<IncrCompSession>,
 
     /// Used by `-Z self-profile`.
     pub prof: SelfProfilerRef,
@@ -534,9 +534,9 @@ impl Session {
         *incr_comp_session = IncrCompSession::InvalidBecauseOfErrors { session_directory };
     }
 
-    pub fn incr_comp_session_dir(&self) -> cell::Ref<'_, PathBuf> {
+    pub fn incr_comp_session_dir(&self) -> MappedReadGuard<'_, PathBuf> {
         let incr_comp_session = self.incr_comp_session.borrow();
-        cell::Ref::map(incr_comp_session, |incr_comp_session| match *incr_comp_session {
+        ReadGuard::map(incr_comp_session, |incr_comp_session| match *incr_comp_session {
             IncrCompSession::NotInitialized => panic!(
                 "trying to get session directory from `IncrCompSession`: {:?}",
                 *incr_comp_session,
@@ -549,7 +549,7 @@ impl Session {
         })
     }
 
-    pub fn incr_comp_session_dir_opt(&self) -> Option<cell::Ref<'_, PathBuf>> {
+    pub fn incr_comp_session_dir_opt(&self) -> Option<MappedReadGuard<'_, PathBuf>> {
         self.opts.incremental.as_ref().map(|_| self.incr_comp_session_dir())
     }
 
@@ -906,7 +906,7 @@ impl Session {
         CodegenUnits::Default(16)
     }
 
-    pub fn teach(&self, code: &DiagnosticId) -> bool {
+    pub fn teach(&self, code: &str) -> bool {
         self.opts.unstable_opts.teach && self.dcx().must_teach(code)
     }
 
@@ -1177,7 +1177,7 @@ pub fn build_session(
         parse_sess,
         sysroot,
         io,
-        incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)),
+        incr_comp_session: RwLock::new(IncrCompSession::NotInitialized),
         prof,
         code_stats: Default::default(),
         optimization_fuel,
diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs
index 4bac98909ad..b99640d2f2d 100644
--- a/compiler/rustc_smir/src/rustc_internal/mod.rs
+++ b/compiler/rustc_smir/src/rustc_internal/mod.rs
@@ -190,35 +190,120 @@ where
     stable_mir::compiler_interface::run(&tables, || init(&tables, f))
 }
 
+/// Instantiate and run the compiler with the provided arguments and callback.
+///
+/// The callback will be invoked after the compiler ran all its analyses, but before code generation.
+/// Note that this macro accepts two different formats for the callback:
+/// 1. An ident that resolves to a function that accepts no argument and returns `ControlFlow<B, C>`
+/// ```ignore(needs-extern-crate)
+/// # extern crate rustc_driver;
+/// # extern crate rustc_interface;
+/// # #[macro_use]
+/// # extern crate rustc_smir;
+/// # extern crate stable_mir;
+/// #
+/// # fn main() {
+/// #   use std::ops::ControlFlow;
+/// #   use stable_mir::CompilerError;
+///     fn analyze_code() -> ControlFlow<(), ()> {
+///         // Your code goes in here.
+/// #       ControlFlow::Continue(())
+///     }
+/// #   let args = vec!["--verbose".to_string()];
+///     let result = run!(args, analyze_code);
+/// #   assert_eq!(result, Err(CompilerError::Skipped))
+/// # }
+/// ```
+/// 2. A closure expression:
+/// ```ignore(needs-extern-crate)
+/// # extern crate rustc_driver;
+/// # extern crate rustc_interface;
+/// # #[macro_use]
+/// # extern crate rustc_smir;
+/// # extern crate stable_mir;
+/// #
+/// # fn main() {
+/// #   use std::ops::ControlFlow;
+/// #   use stable_mir::CompilerError;
+///     fn analyze_code(extra_args: Vec<String>) -> ControlFlow<(), ()> {
+/// #       let _ = extra_args;
+///         // Your code goes in here.
+/// #       ControlFlow::Continue(())
+///     }
+/// #   let args = vec!["--verbose".to_string()];
+/// #   let extra_args = vec![];
+///     let result = run!(args, || analyze_code(extra_args));
+/// #   assert_eq!(result, Err(CompilerError::Skipped))
+/// # }
+/// ```
 #[macro_export]
 macro_rules! run {
+    ($args:expr, $callback_fn:ident) => {
+        run_driver!($args, || $callback_fn())
+    };
+    ($args:expr, $callback:expr) => {
+        run_driver!($args, $callback)
+    };
+}
+
+/// Instantiate and run the compiler with the provided arguments and callback.
+///
+/// This is similar to `run` but it invokes the callback with the compiler's `TyCtxt`,
+/// which can be used to invoke internal APIs.
+#[macro_export]
+macro_rules! run_with_tcx {
+    ($args:expr, $callback_fn:ident) => {
+        run_driver!($args, |tcx| $callback_fn(tcx), with_tcx)
+    };
     ($args:expr, $callback:expr) => {
-        run!($args, tcx, $callback)
+        run_driver!($args, $callback, with_tcx)
+    };
+}
+
+/// Optionally include an ident. This is needed due to macro hygiene.
+#[macro_export]
+#[doc(hidden)]
+macro_rules! optional {
+    (with_tcx $ident:ident) => {
+        $ident
     };
-    ($args:expr, $tcx:ident, $callback:expr) => {{
+}
+
+/// Prefer using [run!] and [run_with_tcx] instead.
+///
+/// This macro implements the instantiation of a StableMIR driver, and it will invoke
+/// the given callback after the compiler analyses.
+///
+/// The third argument determines whether the callback requires `tcx` as an argument.
+#[macro_export]
+#[doc(hidden)]
+macro_rules! run_driver {
+    ($args:expr, $callback:expr $(, $with_tcx:ident)?) => {{
         use rustc_driver::{Callbacks, Compilation, RunCompiler};
         use rustc_interface::{interface, Queries};
         use stable_mir::CompilerError;
         use std::ops::ControlFlow;
 
-        pub struct StableMir<B = (), C = ()>
+        pub struct StableMir<B = (), C = (), F = fn($(optional!($with_tcx TyCtxt))?) -> ControlFlow<B, C>>
         where
             B: Send,
             C: Send,
+            F: FnOnce($(optional!($with_tcx TyCtxt))?) -> ControlFlow<B, C> + Send,
         {
             args: Vec<String>,
-            callback: fn(TyCtxt<'_>) -> ControlFlow<B, C>,
+            callback: Option<F>,
             result: Option<ControlFlow<B, C>>,
         }
 
-        impl<B, C> StableMir<B, C>
+        impl<B, C, F> StableMir<B, C, F>
         where
             B: Send,
             C: Send,
+            F: FnOnce($(optional!($with_tcx TyCtxt))?) -> ControlFlow<B, C> + Send,
         {
             /// Creates a new `StableMir` instance, with given test_function and arguments.
-            pub fn new(args: Vec<String>, callback: fn(TyCtxt<'_>) -> ControlFlow<B, C>) -> Self {
-                StableMir { args, callback, result: None }
+            pub fn new(args: Vec<String>, callback: F) -> Self {
+                StableMir { args, callback: Some(callback), result: None }
             }
 
             /// Runs the compiler against given target and tests it with `test_function`
@@ -238,10 +323,11 @@ macro_rules! run {
             }
         }
 
-        impl<B, C> Callbacks for StableMir<B, C>
+        impl<B, C, F> Callbacks for StableMir<B, C, F>
         where
             B: Send,
             C: Send,
+            F: FnOnce($(optional!($with_tcx TyCtxt))?) -> ControlFlow<B, C> + Send,
         {
             /// Called after analysis. Return value instructs the compiler whether to
             /// continue the compilation afterwards (defaults to `Compilation::Continue`)
@@ -251,20 +337,24 @@ macro_rules! run {
                 queries: &'tcx Queries<'tcx>,
             ) -> Compilation {
                 queries.global_ctxt().unwrap().enter(|tcx| {
-                    rustc_internal::run(tcx, || {
-                        self.result = Some((self.callback)(tcx));
-                    })
-                    .unwrap();
-                    if self.result.as_ref().is_some_and(|val| val.is_continue()) {
-                        Compilation::Continue
+                    if let Some(callback) = self.callback.take() {
+                        rustc_internal::run(tcx, || {
+                            self.result = Some(callback($(optional!($with_tcx tcx))?));
+                        })
+                        .unwrap();
+                        if self.result.as_ref().is_some_and(|val| val.is_continue()) {
+                            Compilation::Continue
+                        } else {
+                            Compilation::Stop
+                        }
                     } else {
-                        Compilation::Stop
+                        Compilation::Continue
                     }
                 })
             }
         }
 
-        StableMir::new($args, |$tcx| $callback).run()
+        StableMir::new($args, $callback).run()
     }};
 }
 
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
index c5fb6f7a26f..2f3d9d69b85 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
@@ -609,7 +609,7 @@ impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> {
                 fn_span: _,
             } => TerminatorKind::Call {
                 func: func.stable(tables),
-                args: args.iter().map(|arg| arg.stable(tables)).collect(),
+                args: args.iter().map(|arg| arg.node.stable(tables)).collect(),
                 destination: destination.stable(tables),
                 target: target.map(|t| t.as_usize()),
                 unwind: unwind.stable(tables),
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index d03965b539c..3d26efec5a6 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -330,7 +330,7 @@ pub(crate) struct HygieneData {
     /// would have collisions without a disambiguator.
     /// The keys of this map are always computed with `ExpnData.disambiguator`
     /// set to 0.
-    expn_data_disambiguators: FxHashMap<Hash64, u32>,
+    expn_data_disambiguators: UnhashMap<Hash64, u32>,
 }
 
 impl HygieneData {
@@ -359,7 +359,7 @@ impl HygieneData {
                 dollar_crate_name: kw::DollarCrate,
             }],
             syntax_context_map: FxHashMap::default(),
-            expn_data_disambiguators: FxHashMap::default(),
+            expn_data_disambiguators: UnhashMap::default(),
         }
     }
 
@@ -464,12 +464,15 @@ impl HygieneData {
         &self,
         mut span: Span,
         to: Span,
-        collapse_debuginfo_enabled: bool,
+        collapse_debuginfo_feature_enabled: bool,
     ) -> Span {
         let orig_span = span;
         let mut ret_span = span;
 
-        debug!("walk_chain_collapsed({:?}, {:?})", span, to);
+        debug!(
+            "walk_chain_collapsed({:?}, {:?}), feature_enable={}",
+            span, to, collapse_debuginfo_feature_enabled,
+        );
         debug!("walk_chain_collapsed: span ctxt = {:?}", span.ctxt());
         while !span.eq_ctxt(to) && span.from_expansion() {
             let outer_expn = self.outer_expn(span.ctxt());
@@ -477,7 +480,7 @@ impl HygieneData {
             let expn_data = self.expn_data(outer_expn);
             debug!("walk_chain_collapsed({:?}): expn_data={:?}", span, expn_data);
             span = expn_data.call_site;
-            if !collapse_debuginfo_enabled || expn_data.collapse_debuginfo {
+            if !collapse_debuginfo_feature_enabled || expn_data.collapse_debuginfo {
                 ret_span = span;
             }
         }
@@ -601,8 +604,14 @@ pub fn walk_chain(span: Span, to: SyntaxContext) -> Span {
     HygieneData::with(|data| data.walk_chain(span, to))
 }
 
-pub fn walk_chain_collapsed(span: Span, to: Span, collapse_debuginfo_enabled: bool) -> Span {
-    HygieneData::with(|hdata| hdata.walk_chain_collapsed(span, to, collapse_debuginfo_enabled))
+pub fn walk_chain_collapsed(
+    span: Span,
+    to: Span,
+    collapse_debuginfo_feature_enabled: bool,
+) -> Span {
+    HygieneData::with(|hdata| {
+        hdata.walk_chain_collapsed(span, to, collapse_debuginfo_feature_enabled)
+    })
 }
 
 pub fn update_dollar_crate_names(mut get_name: impl FnMut(SyntaxContext) -> Symbol) {
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index 8253ffefcaa..df7635e447d 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -10,8 +10,8 @@
 //! information, source code snippets, etc.
 
 use crate::*;
-use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::{IntoDynSyncSend, MappedReadGuard, ReadGuard, RwLock};
+use rustc_data_structures::unhash::UnhashMap;
 use std::fs;
 use std::io::{self, BorrowedBuf, Read};
 use std::path::{self};
@@ -70,7 +70,7 @@ mod monotonic {
     impl<T> !DerefMut for MonotonicVec<T> {}
 }
 
-#[derive(Clone, Encodable, Decodable, Debug, Copy, HashStable_Generic)]
+#[derive(Clone, Encodable, Decodable, Debug, Copy, PartialEq, Hash, HashStable_Generic)]
 pub struct Spanned<T> {
     pub node: T,
     pub span: Span,
@@ -164,7 +164,7 @@ impl FileLoader for RealFileLoader {
 #[derive(Default)]
 struct SourceMapFiles {
     source_files: monotonic::MonotonicVec<Lrc<SourceFile>>,
-    stable_id_to_source_file: FxHashMap<StableSourceFileId, Lrc<SourceFile>>,
+    stable_id_to_source_file: UnhashMap<StableSourceFileId, Lrc<SourceFile>>,
 }
 
 pub struct SourceMap {
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 72b62a795fc..7b0138d50ba 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -749,6 +749,7 @@ symbols! {
         extern_in_paths,
         extern_prelude,
         extern_types,
+        external,
         external_doc,
         f,
         f16c_target_feature,
@@ -1152,6 +1153,7 @@ symbols! {
         offset,
         offset_of,
         offset_of_enum,
+        offset_of_nested,
         ok_or_else,
         omit_gdb_pretty_printer_section,
         on,
@@ -1811,6 +1813,7 @@ symbols! {
         xmm_reg,
         yeet_desugar_details,
         yeet_expr,
+        yes,
         yield_expr,
         ymm_reg,
         zmm_reg,
diff --git a/compiler/rustc_target/src/spec/base/freebsd.rs b/compiler/rustc_target/src/spec/base/freebsd.rs
index 8c141aaaec3..80b3da8a752 100644
--- a/compiler/rustc_target/src/spec/base/freebsd.rs
+++ b/compiler/rustc_target/src/spec/base/freebsd.rs
@@ -6,6 +6,7 @@ pub fn opts() -> TargetOptions {
         dynamic_linking: true,
         families: cvs!["unix"],
         has_rpath: true,
+        crt_static_respected: true,
         position_independent_executables: true,
         relro_level: RelroLevel::Full,
         abi_return_struct_as_int: true,
diff --git a/compiler/rustc_target/src/spec/targets/asmjs_unknown_emscripten.rs b/compiler/rustc_target/src/spec/targets/asmjs_unknown_emscripten.rs
deleted file mode 100644
index e4768c67af5..00000000000
--- a/compiler/rustc_target/src/spec/targets/asmjs_unknown_emscripten.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-use crate::spec::{targets::wasm32_unknown_emscripten, LinkerFlavor, Target};
-
-pub fn target() -> Target {
-    let mut target = wasm32_unknown_emscripten::target();
-    target.add_post_link_args(LinkerFlavor::EmCc, &["-sWASM=0", "--memory-init-file", "0"]);
-    target
-}
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 13f8b6b5a0a..a221538b902 100644
--- a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs
@@ -11,7 +11,7 @@ pub fn target() -> Target {
         llvm_target: ios_sim_llvm_target(arch).into(),
         pointer_width: 32,
         data_layout: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
-            f64:32:64-f80:128-n8:16:32-S128"
+            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) },
diff --git a/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs b/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs
index 3ebf4bcf523..ea8b919e748 100644
--- a/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs
+++ b/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs
@@ -5,7 +5,7 @@ pub fn target() -> Target {
         llvm_target: "i586-pc-unknown".into(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
-            f64:32:64-f80:32-n8:16:32-S128"
+            i128:128-f64:32:64-f80:32-n8:16:32-S128"
             .into(),
         arch: "x86".into(),
         options: TargetOptions {
diff --git a/compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs
index 8375fa4c0c0..574dc658b78 100644
--- a/compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs
@@ -10,7 +10,7 @@ pub fn target() -> Target {
         llvm_target: "i586-unknown-netbsdelf".into(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
-            f64:32:64-f80:32-n8:16:32-S128"
+            i128:128-f64:32:64-f80:32-n8:16:32-S128"
             .into(),
         arch: "x86".into(),
         options: TargetOptions { mcount: "__mcount".into(), ..base },
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 59069fe4e3a..25617b4436c 100644
--- a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
@@ -18,7 +18,7 @@ pub fn target() -> Target {
         llvm_target: macos_llvm_target(Arch::I686).into(),
         pointer_width: 32,
         data_layout: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
-            f64:32:64-f80:128-n8:16:32-S128"
+            i128:128-f64:32:64-f80:128-n8:16:32-S128"
             .into(),
         arch: arch.target_arch(),
         options: TargetOptions { mcount: "\u{1}mcount".into(), ..base },
diff --git a/compiler/rustc_target/src/spec/targets/i686_linux_android.rs b/compiler/rustc_target/src/spec/targets/i686_linux_android.rs
index 79471040f0d..12ebf0c72f8 100644
--- a/compiler/rustc_target/src/spec/targets/i686_linux_android.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_linux_android.rs
@@ -17,7 +17,7 @@ pub fn target() -> Target {
         llvm_target: "i686-linux-android".into(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
-            f64:32:64-f80:32-n8:16:32-S128"
+            i128:128-f64:32:64-f80:32-n8:16:32-S128"
             .into(),
         arch: "x86".into(),
         options: TargetOptions { supported_sanitizers: SanitizerSet::ADDRESS, ..base },
diff --git a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs
index 8d4a39b5811..11818034414 100644
--- a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs
@@ -19,7 +19,7 @@ pub fn target() -> Target {
         llvm_target: "i686-pc-windows-gnu".into(),
         pointer_width: 32,
         data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
-            i64:64-f80:32-n8:16:32-a:0:32-S32"
+            i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32"
             .into(),
         arch: "x86".into(),
         options: base,
diff --git a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs
index bb410cd8caf..f4e33b88178 100644
--- a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs
@@ -18,7 +18,7 @@ pub fn target() -> Target {
         llvm_target: "i686-pc-windows-gnu".into(),
         pointer_width: 32,
         data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
-            i64:64-f80:32-n8:16:32-a:0:32-S32"
+            i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32"
             .into(),
         arch: "x86".into(),
         options: base,
diff --git a/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs
index 5abc3017bf8..9f1c8f4676c 100644
--- a/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs
@@ -25,7 +25,7 @@ pub fn target() -> Target {
         llvm_target: "i686-pc-windows-msvc".into(),
         pointer_width: 32,
         data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
-            i64:64-f80:128-n8:16:32-a:0:32-S32"
+            i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32"
             .into(),
         arch: "x86".into(),
         options: base,
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs
index 927b2ab877d..d90f481c68c 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs
@@ -11,7 +11,7 @@ pub fn target() -> Target {
         llvm_target: "i686-unknown-freebsd".into(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
-            f64:32:64-f80:32-n8:16:32-S128"
+            i128:128-f64:32:64-f80:32-n8:16:32-S128"
             .into(),
         arch: "x86".into(),
         options: base,
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs
index bc7fd6fbc68..330a390c981 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs
@@ -11,7 +11,7 @@ pub fn target() -> Target {
         llvm_target: "i686-unknown-haiku".into(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
-            f64:32:64-f80:32-n8:16:32-S128"
+            i128:128-f64:32:64-f80:32-n8:16:32-S128"
             .into(),
         arch: "x86".into(),
         options: base,
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs
index 6884e078c27..c32f7177c1a 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs
@@ -11,7 +11,7 @@ pub fn target() -> Target {
         llvm_target: "i686-unknown-hurd-gnu".into(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
-            f64:32:64-f80:32-n8:16:32-S128"
+            i128:128-f64:32:64-f80:32-n8:16:32-S128"
             .into(),
         arch: "x86".into(),
         options: base,
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs
index 3b7be48dbbc..9bc38a72f4d 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs
@@ -12,7 +12,7 @@ pub fn target() -> Target {
         llvm_target: "i686-unknown-linux-gnu".into(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
-            f64:32:64-f80:32-n8:16:32-S128"
+            i128:128-f64:32:64-f80:32-n8:16:32-S128"
             .into(),
         arch: "x86".into(),
         options: base,
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs
index ef58b4fb458..4a82e0986c7 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs
@@ -25,7 +25,7 @@ pub fn target() -> Target {
         llvm_target: "i686-unknown-linux-musl".into(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
-            f64:32:64-f80:32-n8:16:32-S128"
+            i128:128-f64:32:64-f80:32-n8:16:32-S128"
             .into(),
         arch: "x86".into(),
         options: base,
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs
index 5f3afbe5afd..ea72656607e 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs
@@ -11,7 +11,7 @@ pub fn target() -> Target {
         llvm_target: "i686-unknown-netbsdelf".into(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
-            f64:32:64-f80:32-n8:16:32-S128"
+            i128:128-f64:32:64-f80:32-n8:16:32-S128"
             .into(),
         arch: "x86".into(),
         options: TargetOptions { mcount: "__mcount".into(), ..base },
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs
index f44584a10be..945dc0f8967 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs
@@ -11,7 +11,7 @@ pub fn target() -> Target {
         llvm_target: "i686-unknown-openbsd".into(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
-            f64:32:64-f80:32-n8:16:32-S128"
+            i128:128-f64:32:64-f80:32-n8:16:32-S128"
             .into(),
         arch: "x86".into(),
         options: base,
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs
index 25315e19cdd..37d57c1cdf3 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs
@@ -80,7 +80,7 @@ pub fn target() -> Target {
         llvm_target: "i686-unknown-windows-gnu".into(),
         pointer_width: 32,
         data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
-            i64:64-f80:32-n8:16:32-a:0:32-S32"
+            i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32"
             .into(),
         arch: "x86".into(),
 
diff --git a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs
index ec211a710eb..0830033dc23 100644
--- a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs
@@ -18,7 +18,7 @@ pub fn target() -> Target {
         llvm_target: "i686-pc-windows-gnu".into(),
         pointer_width: 32,
         data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
-            i64:64-f80:32-n8:16:32-a:0:32-S32"
+            i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32"
             .into(),
         arch: "x86".into(),
         options: base,
diff --git a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs
index 7cca2fc6b9f..534dd6ee54f 100644
--- a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs
@@ -9,7 +9,7 @@ pub fn target() -> Target {
         llvm_target: "i686-pc-windows-msvc".into(),
         pointer_width: 32,
         data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
-            i64:64-f80:128-n8:16:32-a:0:32-S32"
+            i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32"
             .into(),
         arch: "x86".into(),
         options: base,
diff --git a/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs
index 5b91682e168..35ad81dc052 100644
--- a/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs
@@ -25,7 +25,7 @@ pub fn target() -> Target {
         llvm_target: "i686-pc-windows-msvc".into(),
         pointer_width: 32,
         data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
-            i64:64-f80:128-n8:16:32-a:0:32-S32"
+            i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32"
             .into(),
         arch: "x86".into(),
         options: base,
diff --git a/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs
index ee501c5165e..30c2295e402 100644
--- a/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs
@@ -11,7 +11,7 @@ pub fn target() -> Target {
         llvm_target: "i686-unknown-linux-gnu".into(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
-            f64:32:64-f80:32-n8:16:32-S128"
+            i128:128-f64:32:64-f80:32-n8:16:32-S128"
             .into(),
         arch: "x86".into(),
         options: base,
diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs
index e2e707f4a1a..90df3c69684 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs
@@ -11,7 +11,7 @@ pub fn target() -> Target {
     Target {
         llvm_target: "powerpc64-unknown-linux-musl".into(),
         pointer_width: 64,
-        data_layout: "E-m:e-Fi64-i64:64-n32:64-S128-v256:256:256-v512:512:512".into(),
+        data_layout: "E-m:e-Fn32-i64:64-n32:64-S128-v256:256:256-v512:512:512".into(),
         arch: "powerpc64".into(),
         options: TargetOptions { endian: Endian::Big, mcount: "_mcount".into(), ..base },
     }
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 59df3937ea6..356c6721868 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
@@ -17,8 +17,8 @@ pub fn target() -> Target {
         // correctly, we do too.
         llvm_target: macos_llvm_target(arch).into(),
         pointer_width: 64,
-        data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .into(),
+        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 { mcount: "\u{1}mcount".into(), ..base },
     }
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 d0e2ac44a2a..55165ea4ec6 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
@@ -9,8 +9,8 @@ pub fn target() -> Target {
     Target {
         llvm_target: ios_sim_llvm_target(arch).into(),
         pointer_width: 64,
-        data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .into(),
+        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), ..base },
     }
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 8ef4b88b8b1..ff21e489333 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
@@ -12,8 +12,8 @@ pub fn target() -> Target {
     Target {
         llvm_target: llvm_target.into(),
         pointer_width: 64,
-        data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .into(),
+        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), ..base },
     }
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 17efd437f2f..20b01612553 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
@@ -6,8 +6,8 @@ pub fn target() -> Target {
     Target {
         llvm_target: tvos_sim_llvm_target(arch).into(),
         pointer_width: 64,
-        data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .into(),
+        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) },
     }
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 b1f72ee2f21..806a58e980b 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
@@ -6,8 +6,8 @@ pub fn target() -> Target {
     Target {
         llvm_target: watchos_sim_llvm_target(arch).into(),
         pointer_width: 64,
-        data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .into(),
+        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) },
     }
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs b/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs
index f4117edc3ff..c38a1a08536 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs
@@ -75,8 +75,8 @@ pub fn target() -> Target {
     Target {
         llvm_target: "x86_64-elf".into(),
         pointer_width: 64,
-        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .into(),
+        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: opts,
     }
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs b/compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs
index 0e6d41abc9b..30b1ee73630 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs
@@ -16,8 +16,8 @@ pub fn target() -> Target {
     Target {
         llvm_target: "x86_64-linux-android".into(),
         pointer_width: 64,
-        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .into(),
+        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: TargetOptions { supported_sanitizers: SanitizerSet::ADDRESS, ..base },
     }
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs
index 93aec4c425a..0ef01597399 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs
@@ -4,8 +4,8 @@ pub fn target() -> Target {
     Target {
         llvm_target: "x86_64-pc-unknown".into(),
         pointer_width: 64,
-        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .into(),
+        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: TargetOptions {
             cpu: "x86-64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs
index f15ad8dda63..ade4dd6d431 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs
@@ -13,8 +13,8 @@ pub fn target() -> Target {
     Target {
         llvm_target: "x86_64-pc-solaris".into(),
         pointer_width: 64,
-        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .into(),
+        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_64_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs
index 6d3e0727051..9e964d248bf 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs
@@ -16,8 +16,8 @@ pub fn target() -> Target {
     Target {
         llvm_target: "x86_64-pc-windows-gnu".into(),
         pointer_width: 64,
-        data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .into(),
+        data_layout:
+            "e-m:w-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_64_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs
index a56ebfa585e..1facf9450cd 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs
@@ -11,8 +11,8 @@ pub fn target() -> Target {
     Target {
         llvm_target: "x86_64-pc-windows-gnu".into(),
         pointer_width: 64,
-        data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .into(),
+        data_layout:
+            "e-m:w-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_64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs
index 3a4da91c244..357261073a8 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs
@@ -10,8 +10,8 @@ pub fn target() -> Target {
     Target {
         llvm_target: "x86_64-pc-windows-msvc".into(),
         pointer_width: 64,
-        data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .into(),
+        data_layout:
+            "e-m:w-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_64_unikraft_linux_musl.rs b/compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs
index e6159fca3ae..6c9d1147548 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs
@@ -5,8 +5,8 @@ pub fn target() -> Target {
         llvm_target: "x86_64-unknown-linux-musl".into(),
         pointer_width: 64,
         arch: "x86_64".into(),
-        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .into(),
+        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(),
         options: TargetOptions {
             cpu: "x86-64".into(),
             plt_by_default: false,
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs
index 80adb8fa2d9..ce682bb8005 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs
@@ -11,8 +11,8 @@ pub fn target() -> Target {
     Target {
         llvm_target: "x86_64-unknown-dragonfly".into(),
         pointer_width: 64,
-        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .into(),
+        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_64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs
index fa321035367..6d6940e7891 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs
@@ -14,8 +14,8 @@ pub fn target() -> Target {
     Target {
         llvm_target: "x86_64-unknown-freebsd".into(),
         pointer_width: 64,
-        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .into(),
+        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_64_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs
index 5b19ed1b5ff..50139e5c1d8 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs
@@ -12,8 +12,8 @@ pub fn target() -> Target {
     Target {
         llvm_target: "x86_64-unknown-fuchsia".into(),
         pointer_width: 64,
-        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .into(),
+        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_64_unknown_haiku.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs
index 0f927be962b..c00c689f7ef 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs
@@ -13,8 +13,8 @@ pub fn target() -> Target {
     Target {
         llvm_target: "x86_64-unknown-haiku".into(),
         pointer_width: 64,
-        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .into(),
+        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_64_unknown_hermit.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs
index df191f515bd..fb46848ba8c 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs
@@ -5,8 +5,8 @@ pub fn target() -> Target {
         llvm_target: "x86_64-unknown-hermit".into(),
         pointer_width: 64,
         arch: "x86_64".into(),
-        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .into(),
+        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(),
         options: TargetOptions {
             cpu: "x86-64".into(),
             features: "+rdrnd,+rdseed".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs
index eb2b13cb5c2..3e3f4921322 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs
@@ -13,8 +13,8 @@ pub fn target() -> Target {
         // so we still pass Solaris to it
         llvm_target: "x86_64-pc-solaris".into(),
         pointer_width: 64,
-        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .into(),
+        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_64_unknown_l4re_uclibc.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs
index 7b86fe738b1..646623668c6 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs
@@ -10,8 +10,8 @@ pub fn target() -> Target {
     Target {
         llvm_target: "x86_64-unknown-l4re-uclibc".into(),
         pointer_width: 64,
-        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .into(),
+        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_64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs
index bf10f7e5d2d..2296b58f45d 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs
@@ -19,8 +19,8 @@ pub fn target() -> Target {
     Target {
         llvm_target: "x86_64-unknown-linux-gnu".into(),
         pointer_width: 64,
-        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .into(),
+        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_64_unknown_linux_gnux32.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs
index 1856c6afd52..d4b6519262e 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs
@@ -16,7 +16,7 @@ pub fn target() -> Target {
         llvm_target: "x86_64-unknown-linux-gnux32".into(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
-            i64:64-f80:128-n8:16:32:64-S128"
+            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_64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs
index 8dc5503e336..c71dc65670c 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs
@@ -18,8 +18,8 @@ pub fn target() -> Target {
     Target {
         llvm_target: "x86_64-unknown-linux-musl".into(),
         pointer_width: 64,
-        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .into(),
+        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_64_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs
index 35862656aa2..c25105f6e35 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs
@@ -18,8 +18,8 @@ pub fn target() -> Target {
         // LLVM 15 doesn't support OpenHarmony yet, use a linux target instead.
         llvm_target: "x86_64-unknown-linux-musl".into(),
         pointer_width: 64,
-        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .into(),
+        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_64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs
index e2cee0513ba..466498acb0b 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs
@@ -19,8 +19,8 @@ pub fn target() -> Target {
     Target {
         llvm_target: "x86_64-unknown-netbsd".into(),
         pointer_width: 64,
-        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .into(),
+        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: TargetOptions { mcount: "__mcount".into(), ..base },
     }
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs
index 8f7655d8ccd..ceded7790a6 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs
@@ -30,8 +30,8 @@ pub fn target() -> Target {
     Target {
         llvm_target: "x86_64-unknown-none-elf".into(),
         pointer_width: 64,
-        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .into(),
+        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: opts,
     }
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs
index 1133b50f3d2..b542a569bbd 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs
@@ -12,8 +12,8 @@ pub fn target() -> Target {
     Target {
         llvm_target: "x86_64-unknown-openbsd".into(),
         pointer_width: 64,
-        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .into(),
+        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_64_unknown_redox.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs
index c1f57311292..550b7a3d282 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs
@@ -11,8 +11,8 @@ pub fn target() -> Target {
     Target {
         llvm_target: "x86_64-unknown-redox".into(),
         pointer_width: 64,
-        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .into(),
+        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_64_unknown_uefi.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs
index 5abfb8162f7..95847e57a0f 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs
@@ -32,8 +32,8 @@ pub fn target() -> Target {
     Target {
         llvm_target: "x86_64-unknown-windows".into(),
         pointer_width: 64,
-        data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .into(),
+        data_layout:
+            "e-m:w-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_64_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs
index a46d3a0e27b..c2981ddbad6 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs
@@ -15,8 +15,8 @@ pub fn target() -> Target {
     Target {
         llvm_target: "x86_64-pc-windows-gnu".into(),
         pointer_width: 64,
-        data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .into(),
+        data_layout:
+            "e-m:w-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_64_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs
index a3bc27aa065..3f0702c7ad6 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs
@@ -9,8 +9,8 @@ pub fn target() -> Target {
     Target {
         llvm_target: "x86_64-pc-windows-msvc".into(),
         pointer_width: 64,
-        data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .into(),
+        data_layout:
+            "e-m:w-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_64_win7_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs
index 5a59839ebc6..fd26b6e8cae 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs
@@ -10,8 +10,8 @@ pub fn target() -> Target {
     Target {
         llvm_target: "x86_64-win7-windows-msvc".into(),
         pointer_width: 64,
-        data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .into(),
+        data_layout:
+            "e-m:w-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_64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs
index 765239bdd39..f7a78b48f95 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs
@@ -12,8 +12,8 @@ pub fn target() -> Target {
     Target {
         llvm_target: "x86_64-unknown-linux-gnu".into(),
         pointer_width: 64,
-        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .into(),
+        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 0c731e369eb..e0e4cb93e31 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
@@ -35,8 +35,8 @@ pub fn target() -> Target {
         // correctly, we do too.
         llvm_target: macos_llvm_target(arch).into(),
         pointer_width: 64,
-        data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .into(),
+        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 { mcount: "\u{1}mcount".into(), ..base },
     }
diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs
index 251f0628a71..ef4a0f52f9e 100644
--- a/compiler/rustc_trait_selection/src/infer.rs
+++ b/compiler/rustc_trait_selection/src/infer.rs
@@ -1,13 +1,14 @@
-use crate::solve::FulfillmentCtxt;
 use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
-use crate::traits::{self, DefiningAnchor, ObligationCtxt};
+use crate::traits::{self, DefiningAnchor, ObligationCtxt, SelectionContext};
 
+use crate::traits::TraitEngineExt as _;
 use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
-use rustc_infer::traits::{TraitEngine, TraitEngineExt};
+use rustc_infer::traits::{Obligation, TraitEngine, TraitEngineExt as _};
 use rustc_middle::arena::ArenaAllocatable;
 use rustc_middle::infer::canonical::{Canonical, CanonicalQueryResponse, QueryResponse};
 use rustc_middle::traits::query::NoSolution;
+use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
 use rustc_middle::ty::{GenericArg, ToPredicate};
 use rustc_span::DUMMY_SP;
@@ -21,7 +22,8 @@ pub trait InferCtxtExt<'tcx> {
 
     fn type_is_sized_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool;
 
-    /// Check whether a `ty` implements given trait(trait_def_id).
+    /// Check whether a `ty` implements given trait(trait_def_id) without side-effects.
+    ///
     /// The inputs are:
     ///
     /// - the def-id of the trait
@@ -29,8 +31,8 @@ pub trait InferCtxtExt<'tcx> {
     /// - the parameter environment
     ///
     /// Invokes `evaluate_obligation`, so in the event that evaluating
-    /// `Ty: Trait` causes overflow, EvaluatedToErrStackDependent (or EvaluatedToAmbigStackDependent)
-    /// will be returned.
+    /// `Ty: Trait` causes overflow, EvaluatedToErrStackDependent
+    /// (or EvaluatedToAmbigStackDependent) will be returned.
     fn type_implements_trait(
         &self,
         trait_def_id: DefId,
@@ -38,7 +40,18 @@ pub trait InferCtxtExt<'tcx> {
         param_env: ty::ParamEnv<'tcx>,
     ) -> traits::EvaluationResult;
 
-    fn could_impl_trait(
+    /// Returns `Some` if a type implements a trait shallowly, without side-effects,
+    /// along with any errors that would have been reported upon further obligation
+    /// processing.
+    ///
+    /// - If this returns `Some([])`, then the trait holds modulo regions.
+    /// - If this returns `Some([errors..])`, then the trait has an impl for
+    /// the self type, but some nested obligations do not hold.
+    /// - If this returns `None`, no implementation that applies could be found.
+    ///
+    /// FIXME(-Znext-solver): Due to the recursive nature of the new solver,
+    /// this will probably only ever return `Some([])` or `None`.
+    fn type_implements_trait_shallow(
         &self,
         trait_def_id: DefId,
         ty: Ty<'tcx>,
@@ -86,64 +99,26 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
         self.evaluate_obligation(&obligation).unwrap_or(traits::EvaluationResult::EvaluatedToErr)
     }
 
-    fn could_impl_trait(
+    fn type_implements_trait_shallow(
         &self,
         trait_def_id: DefId,
         ty: Ty<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
     ) -> Option<Vec<traits::FulfillmentError<'tcx>>> {
         self.probe(|_snapshot| {
-            if let ty::Adt(def, args) = ty.kind()
-                && let Some((impl_def_id, _)) = self
-                    .tcx
-                    .all_impls(trait_def_id)
-                    .filter_map(|impl_def_id| {
-                        self.tcx.impl_trait_ref(impl_def_id).map(|r| (impl_def_id, r))
-                    })
-                    .map(|(impl_def_id, imp)| (impl_def_id, imp.skip_binder()))
-                    .find(|(_, imp)| match imp.self_ty().peel_refs().kind() {
-                        ty::Adt(i_def, _) if i_def.did() == def.did() => true,
-                        _ => false,
-                    })
-            {
-                let mut fulfill_cx = FulfillmentCtxt::new(self);
-                // We get all obligations from the impl to talk about specific
-                // trait bounds.
-                let obligations = self
-                    .tcx
-                    .predicates_of(impl_def_id)
-                    .instantiate(self.tcx, args)
-                    .into_iter()
-                    .map(|(clause, span)| {
-                        traits::Obligation::new(
-                            self.tcx,
-                            traits::ObligationCause::dummy_with_span(span),
-                            param_env,
-                            clause,
-                        )
-                    })
-                    .collect::<Vec<_>>();
-                fulfill_cx.register_predicate_obligations(self, obligations);
-                let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, [ty]);
-                let obligation = traits::Obligation::new(
-                    self.tcx,
-                    traits::ObligationCause::dummy(),
-                    param_env,
-                    trait_ref,
-                );
-                fulfill_cx.register_predicate_obligation(self, obligation);
-                let mut errors = fulfill_cx.select_all_or_error(self);
-                // We remove the last predicate failure, which corresponds to
-                // the top-level obligation, because most of the type we only
-                // care about the other ones, *except* when it is the only one.
-                // This seems to only be relevant for arbitrary self-types.
-                // Look at `tests/ui/moves/move-fn-self-receiver.rs`.
-                if errors.len() > 1 {
-                    errors.truncate(errors.len() - 1);
+            let mut selcx = SelectionContext::new(self);
+            match selcx.select(&Obligation::new(
+                self.tcx,
+                ObligationCause::dummy(),
+                param_env,
+                ty::TraitRef::new(self.tcx, trait_def_id, [ty]),
+            )) {
+                Ok(Some(selection)) => {
+                    let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(self);
+                    fulfill_cx.register_predicate_obligations(self, selection.nested_obligations());
+                    Some(fulfill_cx.select_all_or_error(self))
                 }
-                Some(errors)
-            } else {
-                None
+                Ok(None) | Err(_) => None,
             }
         })
     }
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
index 2139210b873..f08622816ec 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -11,7 +11,7 @@ use rustc_middle::ty;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 
 use super::eval_ctxt::GenerateProofTree;
-use super::{Certainty, InferCtxtEvalExt};
+use super::{Certainty, Goal, InferCtxtEvalExt};
 
 /// A trait engine using the new trait solver.
 ///
@@ -36,8 +36,28 @@ pub struct FulfillmentCtxt<'tcx> {
 
 impl<'tcx> FulfillmentCtxt<'tcx> {
     pub fn new(infcx: &InferCtxt<'tcx>) -> FulfillmentCtxt<'tcx> {
+        assert!(
+            infcx.next_trait_solver(),
+            "new trait solver fulfillment context created when \
+            infcx is set up for old trait solver"
+        );
         FulfillmentCtxt { obligations: Vec::new(), usable_in_snapshot: infcx.num_open_snapshots() }
     }
+
+    fn inspect_evaluated_obligation(
+        &self,
+        infcx: &InferCtxt<'tcx>,
+        obligation: &PredicateObligation<'tcx>,
+        result: &Result<(bool, Certainty, Vec<Goal<'tcx, ty::Predicate<'tcx>>>), NoSolution>,
+    ) {
+        if let Some(inspector) = infcx.obligation_inspector.get() {
+            let result = match result {
+                Ok((_, c, _)) => Ok(*c),
+                Err(NoSolution) => Err(NoSolution),
+            };
+            (inspector)(infcx, &obligation, result);
+        }
+    }
 }
 
 impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
@@ -61,10 +81,10 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
                         .0
                     {
                         Ok((_, Certainty::Maybe(MaybeCause::Ambiguity), _)) => {
-                            FulfillmentErrorCode::CodeAmbiguity { overflow: false }
+                            FulfillmentErrorCode::Ambiguity { overflow: false }
                         }
                         Ok((_, Certainty::Maybe(MaybeCause::Overflow), _)) => {
-                            FulfillmentErrorCode::CodeAmbiguity { overflow: true }
+                            FulfillmentErrorCode::Ambiguity { overflow: true }
                         }
                         Ok((_, Certainty::Yes, _)) => {
                             bug!("did not expect successful goal when collecting ambiguity errors")
@@ -95,65 +115,66 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
             let mut has_changed = false;
             for obligation in mem::take(&mut self.obligations) {
                 let goal = obligation.clone().into();
-                let (changed, certainty, nested_goals) =
-                    match infcx.evaluate_root_goal(goal, GenerateProofTree::IfEnabled).0 {
-                        Ok(result) => result,
-                        Err(NoSolution) => {
-                            errors.push(FulfillmentError {
-                                obligation: obligation.clone(),
-                                code: match goal.predicate.kind().skip_binder() {
-                                    ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) => {
-                                        FulfillmentErrorCode::CodeProjectionError(
-                                            // FIXME: This could be a `Sorts` if the term is a type
-                                            MismatchedProjectionTypes { err: TypeError::Mismatch },
-                                        )
-                                    }
-                                    ty::PredicateKind::NormalizesTo(..) => {
-                                        FulfillmentErrorCode::CodeProjectionError(
-                                            MismatchedProjectionTypes { err: TypeError::Mismatch },
-                                        )
-                                    }
-                                    ty::PredicateKind::AliasRelate(_, _, _) => {
-                                        FulfillmentErrorCode::CodeProjectionError(
-                                            MismatchedProjectionTypes { err: TypeError::Mismatch },
-                                        )
-                                    }
-                                    ty::PredicateKind::Subtype(pred) => {
-                                        let (a, b) = infcx.instantiate_binder_with_placeholders(
-                                            goal.predicate.kind().rebind((pred.a, pred.b)),
-                                        );
-                                        let expected_found = ExpectedFound::new(true, a, b);
-                                        FulfillmentErrorCode::CodeSubtypeError(
-                                            expected_found,
-                                            TypeError::Sorts(expected_found),
-                                        )
-                                    }
-                                    ty::PredicateKind::Coerce(pred) => {
-                                        let (a, b) = infcx.instantiate_binder_with_placeholders(
-                                            goal.predicate.kind().rebind((pred.a, pred.b)),
-                                        );
-                                        let expected_found = ExpectedFound::new(false, a, b);
-                                        FulfillmentErrorCode::CodeSubtypeError(
-                                            expected_found,
-                                            TypeError::Sorts(expected_found),
-                                        )
-                                    }
-                                    ty::PredicateKind::Clause(_)
-                                    | ty::PredicateKind::ObjectSafe(_)
-                                    | ty::PredicateKind::Ambiguous => {
-                                        FulfillmentErrorCode::CodeSelectionError(
-                                            SelectionError::Unimplemented,
-                                        )
-                                    }
-                                    ty::PredicateKind::ConstEquate(..) => {
-                                        bug!("unexpected goal: {goal:?}")
-                                    }
-                                },
-                                root_obligation: obligation,
-                            });
-                            continue;
-                        }
-                    };
+                let result = infcx.evaluate_root_goal(goal, GenerateProofTree::IfEnabled).0;
+                self.inspect_evaluated_obligation(infcx, &obligation, &result);
+                let (changed, certainty, nested_goals) = match result {
+                    Ok(result) => result,
+                    Err(NoSolution) => {
+                        errors.push(FulfillmentError {
+                            obligation: obligation.clone(),
+                            code: match goal.predicate.kind().skip_binder() {
+                                ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) => {
+                                    FulfillmentErrorCode::ProjectionError(
+                                        // FIXME: This could be a `Sorts` if the term is a type
+                                        MismatchedProjectionTypes { err: TypeError::Mismatch },
+                                    )
+                                }
+                                ty::PredicateKind::NormalizesTo(..) => {
+                                    FulfillmentErrorCode::ProjectionError(
+                                        MismatchedProjectionTypes { err: TypeError::Mismatch },
+                                    )
+                                }
+                                ty::PredicateKind::AliasRelate(_, _, _) => {
+                                    FulfillmentErrorCode::ProjectionError(
+                                        MismatchedProjectionTypes { err: TypeError::Mismatch },
+                                    )
+                                }
+                                ty::PredicateKind::Subtype(pred) => {
+                                    let (a, b) = infcx.instantiate_binder_with_placeholders(
+                                        goal.predicate.kind().rebind((pred.a, pred.b)),
+                                    );
+                                    let expected_found = ExpectedFound::new(true, a, b);
+                                    FulfillmentErrorCode::SubtypeError(
+                                        expected_found,
+                                        TypeError::Sorts(expected_found),
+                                    )
+                                }
+                                ty::PredicateKind::Coerce(pred) => {
+                                    let (a, b) = infcx.instantiate_binder_with_placeholders(
+                                        goal.predicate.kind().rebind((pred.a, pred.b)),
+                                    );
+                                    let expected_found = ExpectedFound::new(false, a, b);
+                                    FulfillmentErrorCode::SubtypeError(
+                                        expected_found,
+                                        TypeError::Sorts(expected_found),
+                                    )
+                                }
+                                ty::PredicateKind::Clause(_)
+                                | ty::PredicateKind::ObjectSafe(_)
+                                | ty::PredicateKind::Ambiguous => {
+                                    FulfillmentErrorCode::SelectionError(
+                                        SelectionError::Unimplemented,
+                                    )
+                                }
+                                ty::PredicateKind::ConstEquate(..) => {
+                                    bug!("unexpected goal: {goal:?}")
+                                }
+                            },
+                            root_obligation: obligation,
+                        });
+                        continue;
+                    }
+                };
                 // Push any nested goals that we get from unifying our canonical response
                 // with our obligation onto the fulfillment context.
                 self.obligations.extend(nested_goals.into_iter().map(|goal| {
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 6c0909d2853..0e33e9cd790 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -859,6 +859,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             && let hir::Node::Expr(lhs) = self.tcx.hir_node(*lhs_hir_id)
             && let hir::Node::Expr(rhs) = self.tcx.hir_node(*rhs_hir_id)
             && let Some(rhs_ty) = typeck_results.expr_ty_opt(rhs)
+            && let trait_pred = predicate.unwrap_or(trait_pred)
+            // Only run this code on binary operators
+            && hir::lang_items::BINARY_OPERATORS
+                .iter()
+                .filter_map(|&op| self.tcx.lang_items().get(op))
+                .any(|op| {
+                    op == trait_pred.skip_binder().trait_ref.def_id
+                })
         {
             // Suggest dereferencing the LHS, RHS, or both terms of a binop if possible
 
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 b970ec7f726..149dcffe333 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
@@ -14,8 +14,8 @@ use crate::traits::specialize::to_pretty_impl_header;
 use crate::traits::NormalizeExt;
 use crate::traits::{
     elaborate, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, Obligation,
-    ObligationCause, ObligationCauseCode, ObligationCtxt, OutputTypeParameterMismatch, Overflow,
-    PredicateObligation, SelectionError, TraitNotObjectSafe,
+    ObligationCause, ObligationCauseCode, ObligationCtxt, Overflow, PredicateObligation,
+    SelectionError, SignatureMismatch, TraitNotObjectSafe,
 };
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
 use rustc_errors::{
@@ -30,7 +30,7 @@ use rustc_hir::{GenericParam, Item, Node};
 use rustc_infer::infer::error_reporting::TypeErrCtxt;
 use rustc_infer::infer::{InferOk, TypeTrace};
 use rustc_middle::traits::select::OverflowError;
-use rustc_middle::traits::{DefiningAnchor, SelectionOutputTypeParameterMismatch};
+use rustc_middle::traits::{DefiningAnchor, SignatureMismatchData};
 use rustc_middle::ty::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::fold::{BottomUpFolder, TypeFolder, TypeSuperFoldable};
@@ -785,14 +785,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
                     ty::PredicateKind::Subtype(predicate) => {
                         // Errors for Subtype predicates show up as
-                        // `FulfillmentErrorCode::CodeSubtypeError`,
+                        // `FulfillmentErrorCode::SubtypeError`,
                         // not selection error.
                         span_bug!(span, "subtype requirement gave wrong error: `{:?}`", predicate)
                     }
 
                     ty::PredicateKind::Coerce(predicate) => {
                         // Errors for Coerce predicates show up as
-                        // `FulfillmentErrorCode::CodeSubtypeError`,
+                        // `FulfillmentErrorCode::SubtypeError`,
                         // not selection error.
                         span_bug!(span, "coerce requirement gave wrong error: `{:?}`", predicate)
                     }
@@ -891,22 +891,22 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 }
             }
 
-            OutputTypeParameterMismatch(box SelectionOutputTypeParameterMismatch {
+            SignatureMismatch(box SignatureMismatchData {
                 found_trait_ref,
                 expected_trait_ref,
                 terr: terr @ TypeError::CyclicTy(_),
-            }) => self.report_type_parameter_mismatch_cyclic_type_error(
+            }) => self.report_cyclic_signature_error(
                 &obligation,
                 found_trait_ref,
                 expected_trait_ref,
                 terr,
             ),
-            OutputTypeParameterMismatch(box SelectionOutputTypeParameterMismatch {
+            SignatureMismatch(box SignatureMismatchData {
                 found_trait_ref,
                 expected_trait_ref,
                 terr: _,
             }) => {
-                match self.report_type_parameter_mismatch_error(
+                match self.report_signature_mismatch_error(
                     &obligation,
                     span,
                     found_trait_ref,
@@ -1492,7 +1492,7 @@ pub(super) trait InferCtxtPrivExt<'tcx> {
         kind: ty::ClosureKind,
     ) -> DiagnosticBuilder<'tcx>;
 
-    fn report_type_parameter_mismatch_cyclic_type_error(
+    fn report_cyclic_signature_error(
         &self,
         obligation: &PredicateObligation<'tcx>,
         found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
@@ -1506,7 +1506,7 @@ pub(super) trait InferCtxtPrivExt<'tcx> {
         def_id: DefId,
     ) -> DiagnosticBuilder<'tcx>;
 
-    fn report_type_parameter_mismatch_error(
+    fn report_signature_mismatch_error(
         &self,
         obligation: &PredicateObligation<'tcx>,
         span: Span,
@@ -1572,23 +1572,23 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         }
 
         match error.code {
-            FulfillmentErrorCode::CodeSelectionError(ref selection_error) => {
+            FulfillmentErrorCode::SelectionError(ref selection_error) => {
                 self.report_selection_error(
                     error.obligation.clone(),
                     &error.root_obligation,
                     selection_error,
                 );
             }
-            FulfillmentErrorCode::CodeProjectionError(ref e) => {
+            FulfillmentErrorCode::ProjectionError(ref e) => {
                 self.report_projection_error(&error.obligation, e);
             }
-            FulfillmentErrorCode::CodeAmbiguity { overflow: false } => {
+            FulfillmentErrorCode::Ambiguity { overflow: false } => {
                 self.maybe_report_ambiguity(&error.obligation);
             }
-            FulfillmentErrorCode::CodeAmbiguity { overflow: true } => {
+            FulfillmentErrorCode::Ambiguity { overflow: true } => {
                 self.report_overflow_no_abort(error.obligation.clone());
             }
-            FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => {
+            FulfillmentErrorCode::SubtypeError(ref expected_found, ref err) => {
                 self.report_mismatched_types(
                     &error.obligation.cause,
                     expected_found.expected,
@@ -1597,7 +1597,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 )
                 .emit();
             }
-            FulfillmentErrorCode::CodeConstEquateError(ref expected_found, ref err) => {
+            FulfillmentErrorCode::ConstEquateError(ref expected_found, ref err) => {
                 let mut diag = self.report_mismatched_consts(
                     &error.obligation.cause,
                     expected_found.expected,
@@ -1622,7 +1622,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 }
                 diag.emit();
             }
-            FulfillmentErrorCode::CodeCycle(ref cycle) => {
+            FulfillmentErrorCode::Cycle(ref cycle) => {
                 self.report_overflow_obligation_cycle(cycle);
             }
         }
@@ -3366,7 +3366,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         self.dcx().create_err(err)
     }
 
-    fn report_type_parameter_mismatch_cyclic_type_error(
+    fn report_cyclic_signature_error(
         &self,
         obligation: &PredicateObligation<'tcx>,
         found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
@@ -3427,7 +3427,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         err
     }
 
-    fn report_type_parameter_mismatch_error(
+    fn report_signature_mismatch_error(
         &self,
         obligation: &PredicateObligation<'tcx>,
         span: Span,
@@ -3446,10 +3446,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         };
 
         let found_did = match *found_trait_ty.kind() {
-            ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) | ty::Coroutine(did, ..) => {
-                Some(did)
-            }
-            ty::Adt(def, _) => Some(def.did()),
+            ty::Closure(did, _) | ty::FnDef(did, _) | ty::Coroutine(did, ..) => Some(did),
             _ => None,
         };
 
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 045d7e444b6..0337672b302 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -18,9 +18,6 @@ use super::const_evaluatable;
 use super::project::{self, ProjectAndUnifyResult};
 use super::select::SelectionContext;
 use super::wf;
-use super::CodeAmbiguity;
-use super::CodeProjectionError;
-use super::CodeSelectionError;
 use super::EvaluationResult;
 use super::PredicateObligation;
 use super::Unimplemented;
@@ -80,6 +77,11 @@ static_assert_size!(PendingPredicateObligation<'_>, 72);
 impl<'tcx> FulfillmentContext<'tcx> {
     /// Creates a new fulfillment context.
     pub(super) fn new(infcx: &InferCtxt<'tcx>) -> FulfillmentContext<'tcx> {
+        assert!(
+            !infcx.next_trait_solver(),
+            "old trait solver fulfillment context created when \
+            infcx is set up for new trait solver"
+        );
         FulfillmentContext {
             predicates: ObligationForest::new(),
             usable_in_snapshot: infcx.num_open_snapshots(),
@@ -135,7 +137,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
         _infcx: &InferCtxt<'tcx>,
     ) -> Vec<FulfillmentError<'tcx>> {
         self.predicates
-            .to_errors(CodeAmbiguity { overflow: false })
+            .to_errors(FulfillmentErrorCode::Ambiguity { overflow: false })
             .into_iter()
             .map(to_fulfillment_error)
             .collect()
@@ -409,7 +411,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
 
                 ty::PredicateKind::ObjectSafe(trait_def_id) => {
                     if !self.selcx.tcx().check_is_object_safe(trait_def_id) {
-                        ProcessResult::Error(CodeSelectionError(Unimplemented))
+                        ProcessResult::Error(FulfillmentErrorCode::SelectionError(Unimplemented))
                     } else {
                         ProcessResult::Changed(vec![])
                     }
@@ -480,7 +482,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                         Ok(Err(err)) => {
                             let expected_found =
                                 ExpectedFound::new(subtype.a_is_expected, subtype.a, subtype.b);
-                            ProcessResult::Error(FulfillmentErrorCode::CodeSubtypeError(
+                            ProcessResult::Error(FulfillmentErrorCode::SubtypeError(
                                 expected_found,
                                 err,
                             ))
@@ -503,7 +505,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                         Ok(Ok(ok)) => ProcessResult::Changed(mk_pending(ok.obligations)),
                         Ok(Err(err)) => {
                             let expected_found = ExpectedFound::new(false, coerce.a, coerce.b);
-                            ProcessResult::Error(FulfillmentErrorCode::CodeSubtypeError(
+                            ProcessResult::Error(FulfillmentErrorCode::SubtypeError(
                                 expected_found,
                                 err,
                             ))
@@ -529,7 +531,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                         Err(
                             e @ NotConstEvaluatable::MentionsParam
                             | e @ NotConstEvaluatable::Error(_),
-                        ) => ProcessResult::Error(CodeSelectionError(
+                        ) => ProcessResult::Error(FulfillmentErrorCode::SelectionError(
                             SelectionError::NotConstEvaluatable(e),
                         )),
                     }
@@ -618,20 +620,22 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                                 Ok(inf_ok) => {
                                     ProcessResult::Changed(mk_pending(inf_ok.into_obligations()))
                                 }
-                                Err(err) => ProcessResult::Error(
-                                    FulfillmentErrorCode::CodeConstEquateError(
+                                Err(err) => {
+                                    ProcessResult::Error(FulfillmentErrorCode::ConstEquateError(
                                         ExpectedFound::new(true, c1, c2),
                                         err,
-                                    ),
-                                ),
+                                    ))
+                                }
                             }
                         }
                         (Err(ErrorHandled::Reported(reported, _)), _)
-                        | (_, Err(ErrorHandled::Reported(reported, _))) => ProcessResult::Error(
-                            CodeSelectionError(SelectionError::NotConstEvaluatable(
-                                NotConstEvaluatable::Error(reported.into()),
-                            )),
-                        ),
+                        | (_, Err(ErrorHandled::Reported(reported, _))) => {
+                            ProcessResult::Error(FulfillmentErrorCode::SelectionError(
+                                SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(
+                                    reported.into(),
+                                )),
+                            ))
+                        }
                         (Err(ErrorHandled::TooGeneric(_)), _)
                         | (_, Err(ErrorHandled::TooGeneric(_))) => {
                             if c1.has_non_region_infer() || c2.has_non_region_infer() {
@@ -639,7 +643,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                             } else {
                                 // Two different constants using generic parameters ~> error.
                                 let expected_found = ExpectedFound::new(true, c1, c2);
-                                ProcessResult::Error(FulfillmentErrorCode::CodeConstEquateError(
+                                ProcessResult::Error(FulfillmentErrorCode::ConstEquateError(
                                     expected_found,
                                     TypeError::ConstMismatch(expected_found),
                                 ))
@@ -654,7 +658,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                         ty,
                     ) {
                         Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())),
-                        Err(_) => ProcessResult::Error(FulfillmentErrorCode::CodeSelectionError(
+                        Err(_) => ProcessResult::Error(FulfillmentErrorCode::SelectionError(
                             SelectionError::Unimplemented,
                         )),
                     }
@@ -677,7 +681,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
             Ok(())
         } else {
             let cycle: Vec<_> = cycle.map(|c| c.obligation.clone()).collect();
-            Err(FulfillmentErrorCode::CodeCycle(cycle))
+            Err(FulfillmentErrorCode::Cycle(cycle))
         }
     }
 }
@@ -732,7 +736,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
             Err(selection_err) => {
                 debug!("selecting trait at depth {} yielded Err", obligation.recursion_depth);
 
-                ProcessResult::Error(CodeSelectionError(selection_err))
+                ProcessResult::Error(FulfillmentErrorCode::SelectionError(selection_err))
             }
         }
     }
@@ -784,7 +788,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
                 project_obligation.with(tcx, project_obligation.predicate),
             ])),
             ProjectAndUnifyResult::MismatchedProjectionTypes(e) => {
-                ProcessResult::Error(CodeProjectionError(e))
+                ProcessResult::Error(FulfillmentErrorCode::ProjectionError(e))
             }
         }
     }
diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs
index 073174127d6..0cd376fcbbd 100644
--- a/compiler/rustc_trait_selection/src/traits/misc.rs
+++ b/compiler/rustc_trait_selection/src/traits/misc.rs
@@ -194,7 +194,7 @@ pub fn all_fields_implement_trait<'tcx>(
                 infcx.implied_bounds_tys(
                     param_env,
                     parent_cause.body_id,
-                    FxIndexSet::from_iter([self_type]),
+                    &FxIndexSet::from_iter([self_type]),
                 ),
             );
             let errors = infcx.resolve_regions(&outlives_env);
diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
index 5b349d576b6..52631d4353b 100644
--- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
@@ -9,123 +9,153 @@ use rustc_span::def_id::LocalDefId;
 
 pub use rustc_middle::traits::query::OutlivesBound;
 
+pub type BoundsCompat<'a, 'tcx: 'a> = impl Iterator<Item = OutlivesBound<'tcx>> + 'a;
 pub type Bounds<'a, 'tcx: 'a> = impl Iterator<Item = OutlivesBound<'tcx>> + 'a;
 pub trait InferCtxtExt<'a, 'tcx> {
-    fn implied_outlives_bounds(
-        &self,
+    /// Do *NOT* call this directly.
+    fn implied_bounds_tys_compat(
+        &'a self,
         param_env: ty::ParamEnv<'tcx>,
         body_id: LocalDefId,
-        ty: Ty<'tcx>,
-    ) -> Vec<OutlivesBound<'tcx>>;
+        tys: &'a FxIndexSet<Ty<'tcx>>,
+        compat: bool,
+    ) -> BoundsCompat<'a, 'tcx>;
 
+    /// If `-Z no-implied-bounds-compat` is set, calls `implied_bounds_tys_compat`
+    /// with `compat` set to `true`, otherwise `false`.
     fn implied_bounds_tys(
         &'a self,
         param_env: ty::ParamEnv<'tcx>,
         body_id: LocalDefId,
-        tys: FxIndexSet<Ty<'tcx>>,
+        tys: &'a FxIndexSet<Ty<'tcx>>,
     ) -> Bounds<'a, 'tcx>;
 }
 
-impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> {
-    /// Implied bounds are region relationships that we deduce
-    /// automatically. The idea is that (e.g.) a caller must check that a
-    /// function's argument types are well-formed immediately before
-    /// calling that fn, and hence the *callee* can assume that its
-    /// argument types are well-formed. This may imply certain relationships
-    /// between generic parameters. For example:
-    /// ```
-    /// fn foo<T>(x: &T) {}
-    /// ```
-    /// can only be called with a `'a` and `T` such that `&'a T` is WF.
-    /// For `&'a T` to be WF, `T: 'a` must hold. So we can assume `T: 'a`.
-    ///
-    /// # Parameters
-    ///
-    /// - `param_env`, the where-clauses in scope
-    /// - `body_id`, the body-id to use when normalizing assoc types.
-    ///   Note that this may cause outlives obligations to be injected
-    ///   into the inference context with this body-id.
-    /// - `ty`, the type that we are supposed to assume is WF.
-    #[instrument(level = "debug", skip(self, param_env, body_id), ret)]
-    fn implied_outlives_bounds(
-        &self,
-        param_env: ty::ParamEnv<'tcx>,
-        body_id: LocalDefId,
-        ty: Ty<'tcx>,
-    ) -> Vec<OutlivesBound<'tcx>> {
-        let ty = self.resolve_vars_if_possible(ty);
-        let ty = OpportunisticRegionResolver::new(self).fold_ty(ty);
+/// Implied bounds are region relationships that we deduce
+/// automatically. The idea is that (e.g.) a caller must check that a
+/// function's argument types are well-formed immediately before
+/// calling that fn, and hence the *callee* can assume that its
+/// argument types are well-formed. This may imply certain relationships
+/// between generic parameters. For example:
+/// ```
+/// fn foo<T>(x: &T) {}
+/// ```
+/// can only be called with a `'a` and `T` such that `&'a T` is WF.
+/// For `&'a T` to be WF, `T: 'a` must hold. So we can assume `T: 'a`.
+///
+/// # Parameters
+///
+/// - `param_env`, the where-clauses in scope
+/// - `body_id`, the body-id to use when normalizing assoc types.
+///   Note that this may cause outlives obligations to be injected
+///   into the inference context with this body-id.
+/// - `ty`, the type that we are supposed to assume is WF.
+#[instrument(level = "debug", skip(infcx, param_env, body_id), ret)]
+fn implied_outlives_bounds<'a, 'tcx>(
+    infcx: &'a InferCtxt<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    body_id: LocalDefId,
+    ty: Ty<'tcx>,
+    compat: bool,
+) -> Vec<OutlivesBound<'tcx>> {
+    let ty = infcx.resolve_vars_if_possible(ty);
+    let ty = OpportunisticRegionResolver::new(infcx).fold_ty(ty);
 
-        // We do not expect existential variables in implied bounds.
-        // We may however encounter unconstrained lifetime variables
-        // in very rare cases.
-        //
-        // See `ui/implied-bounds/implied-bounds-unconstrained-2.rs` for
-        // an example.
-        assert!(!ty.has_non_region_infer());
+    // We do not expect existential variables in implied bounds.
+    // We may however encounter unconstrained lifetime variables
+    // in very rare cases.
+    //
+    // See `ui/implied-bounds/implied-bounds-unconstrained-2.rs` for
+    // an example.
+    assert!(!ty.has_non_region_infer());
 
-        let mut canonical_var_values = OriginalQueryValues::default();
-        let canonical_ty = self.canonicalize_query(param_env.and(ty), &mut canonical_var_values);
-        let Ok(canonical_result) = self.tcx.implied_outlives_bounds(canonical_ty) else {
-            return vec![];
-        };
+    let mut canonical_var_values = OriginalQueryValues::default();
+    let canonical_ty = infcx.canonicalize_query(param_env.and(ty), &mut canonical_var_values);
+    let implied_bounds_result = if compat {
+        infcx.tcx.implied_outlives_bounds_compat(canonical_ty)
+    } else {
+        infcx.tcx.implied_outlives_bounds(canonical_ty)
+    };
+    let Ok(canonical_result) = implied_bounds_result else {
+        return vec![];
+    };
 
-        let mut constraints = QueryRegionConstraints::default();
-        let Ok(InferOk { value: mut bounds, obligations }) = self
-            .instantiate_nll_query_response_and_region_obligations(
-                &ObligationCause::dummy(),
-                param_env,
-                &canonical_var_values,
-                canonical_result,
-                &mut constraints,
-            )
-        else {
-            return vec![];
-        };
-        assert_eq!(&obligations, &[]);
+    let mut constraints = QueryRegionConstraints::default();
+    let Ok(InferOk { value: mut bounds, obligations }) = infcx
+        .instantiate_nll_query_response_and_region_obligations(
+            &ObligationCause::dummy(),
+            param_env,
+            &canonical_var_values,
+            canonical_result,
+            &mut constraints,
+        )
+    else {
+        return vec![];
+    };
+    assert_eq!(&obligations, &[]);
 
-        // Because of #109628, we may have unexpected placeholders. Ignore them!
-        // FIXME(#109628): panic in this case once the issue is fixed.
-        bounds.retain(|bound| !bound.has_placeholders());
+    // Because of #109628, we may have unexpected placeholders. Ignore them!
+    // FIXME(#109628): panic in this case once the issue is fixed.
+    bounds.retain(|bound| !bound.has_placeholders());
 
-        if !constraints.is_empty() {
-            let span = self.tcx.def_span(body_id);
+    if !constraints.is_empty() {
+        let span = infcx.tcx.def_span(body_id);
 
-            debug!(?constraints);
-            if !constraints.member_constraints.is_empty() {
-                span_bug!(span, "{:#?}", constraints.member_constraints);
-            }
+        debug!(?constraints);
+        if !constraints.member_constraints.is_empty() {
+            span_bug!(span, "{:#?}", constraints.member_constraints);
+        }
 
-            // Instantiation may have produced new inference variables and constraints on those
-            // variables. Process these constraints.
-            let ocx = ObligationCtxt::new(self);
-            let cause = ObligationCause::misc(span, body_id);
-            for &constraint in &constraints.outlives {
-                ocx.register_obligation(self.query_outlives_constraint_to_obligation(
-                    constraint,
-                    cause.clone(),
-                    param_env,
-                ));
-            }
+        // Instantiation may have produced new inference variables and constraints on those
+        // variables. Process these constraints.
+        let ocx = ObligationCtxt::new(infcx);
+        let cause = ObligationCause::misc(span, body_id);
+        for &constraint in &constraints.outlives {
+            ocx.register_obligation(infcx.query_outlives_constraint_to_obligation(
+                constraint,
+                cause.clone(),
+                param_env,
+            ));
+        }
 
-            let errors = ocx.select_all_or_error();
-            if !errors.is_empty() {
-                self.dcx().span_delayed_bug(
-                    span,
-                    "implied_outlives_bounds failed to solve obligations from instantiation",
-                );
-            }
-        };
+        let errors = ocx.select_all_or_error();
+        if !errors.is_empty() {
+            infcx.dcx().span_delayed_bug(
+                span,
+                "implied_outlives_bounds failed to solve obligations from instantiation",
+            );
+        }
+    };
 
-        bounds
+    bounds
+}
+
+impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> {
+    fn implied_bounds_tys_compat(
+        &'a self,
+        param_env: ParamEnv<'tcx>,
+        body_id: LocalDefId,
+        tys: &'a FxIndexSet<Ty<'tcx>>,
+        compat: bool,
+    ) -> BoundsCompat<'a, 'tcx> {
+        tys.iter()
+            .flat_map(move |ty| implied_outlives_bounds(self, param_env, body_id, *ty, compat))
     }
 
     fn implied_bounds_tys(
         &'a self,
         param_env: ParamEnv<'tcx>,
         body_id: LocalDefId,
-        tys: FxIndexSet<Ty<'tcx>>,
+        tys: &'a FxIndexSet<Ty<'tcx>>,
     ) -> Bounds<'a, 'tcx> {
-        tys.into_iter().flat_map(move |ty| self.implied_outlives_bounds(param_env, body_id, ty))
+        tys.iter().flat_map(move |ty| {
+            implied_outlives_bounds(
+                self,
+                param_env,
+                body_id,
+                *ty,
+                !self.tcx.sess.opts.unstable_opts.no_implied_bounds_compat,
+            )
+        })
     }
 }
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index dd4e69efe37..abbc2066eac 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -2466,7 +2466,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>(
     debug!(?cache_projection, ?obligation_projection);
 
     match infcx.at(cause, param_env).eq(
-        DefineOpaqueTypes::No,
+        DefineOpaqueTypes::Yes,
         cache_projection,
         obligation_projection,
     ) {
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs
index 152ceeee869..0aaeacb6a23 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs
@@ -63,13 +63,16 @@ fn relate_mir_and_user_ty<'tcx>(
     user_ty: Ty<'tcx>,
 ) -> Result<(), NoSolution> {
     let cause = ObligationCause::dummy_with_span(span);
+    ocx.register_obligation(Obligation::new(
+        ocx.infcx.tcx,
+        cause.clone(),
+        param_env,
+        ty::ClauseKind::WellFormed(user_ty.into()),
+    ));
+
     let user_ty = ocx.normalize(&cause, param_env, user_ty);
     ocx.eq(&cause, param_env, mir_ty, user_ty)?;
 
-    // FIXME(#104764): We should check well-formedness before normalization.
-    let predicate =
-        ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(user_ty.into())));
-    ocx.register_obligation(Obligation::new(ocx.infcx.tcx, cause, param_env, predicate));
     Ok(())
 }
 
@@ -113,31 +116,38 @@ fn relate_mir_and_user_args<'tcx>(
         ocx.register_obligation(Obligation::new(tcx, cause, param_env, instantiated_predicate));
     }
 
+    // Now prove the well-formedness of `def_id` with `substs`.
+    // Note for some items, proving the WF of `ty` is not sufficient because the
+    // well-formedness of an item may depend on the WF of gneneric args not present in the
+    // item's type. Currently this is true for associated consts, e.g.:
+    // ```rust
+    // impl<T> MyTy<T> {
+    //     const CONST: () = { /* arbitrary code that depends on T being WF */ };
+    // }
+    // ```
+    for arg in args {
+        ocx.register_obligation(Obligation::new(
+            tcx,
+            cause.clone(),
+            param_env,
+            ty::ClauseKind::WellFormed(arg),
+        ));
+    }
+
     if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty {
+        ocx.register_obligation(Obligation::new(
+            tcx,
+            cause.clone(),
+            param_env,
+            ty::ClauseKind::WellFormed(self_ty.into()),
+        ));
+
         let self_ty = ocx.normalize(&cause, param_env, self_ty);
         let impl_self_ty = tcx.type_of(impl_def_id).instantiate(tcx, args);
         let impl_self_ty = ocx.normalize(&cause, param_env, impl_self_ty);
 
         ocx.eq(&cause, param_env, self_ty, impl_self_ty)?;
-        let predicate = ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
-            impl_self_ty.into(),
-        )));
-        ocx.register_obligation(Obligation::new(tcx, cause.clone(), param_env, predicate));
     }
 
-    // In addition to proving the predicates, we have to
-    // prove that `ty` is well-formed -- this is because
-    // the WF of `ty` is predicated on the args being
-    // well-formed, and we haven't proven *that*. We don't
-    // want to prove the WF of types from  `args` directly because they
-    // haven't been normalized.
-    //
-    // FIXME(nmatsakis): Well, perhaps we should normalize
-    // them?  This would only be relevant if some input
-    // type were ill-formed but did not appear in `ty`,
-    // which...could happen with normalization...
-    let predicate =
-        ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(ty.into())));
-    ocx.register_obligation(Obligation::new(tcx, cause, param_env, predicate));
     Ok(())
 }
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
index ba6ed298774..83d23597c0c 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
@@ -5,10 +5,11 @@ use crate::traits::ObligationCtxt;
 
 use rustc_infer::infer::canonical::Canonical;
 use rustc_infer::infer::outlives::components::{push_outlives_components, Component};
+use rustc_infer::infer::resolve::OpportunisticRegionResolver;
 use rustc_infer::traits::query::OutlivesBound;
 use rustc_middle::infer::canonical::CanonicalQueryResponse;
 use rustc_middle::traits::ObligationCause;
-use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeFolder, TypeVisitableExt};
 use rustc_span::def_id::CRATE_DEF_ID;
 use rustc_span::DUMMY_SP;
 use smallvec::{smallvec, SmallVec};
@@ -47,14 +48,22 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ImpliedOutlivesBounds<'tcx> {
             param_env.and(ty)
         });
 
-        tcx.implied_outlives_bounds(canonicalized)
+        if tcx.sess.opts.unstable_opts.no_implied_bounds_compat {
+            tcx.implied_outlives_bounds(canonicalized)
+        } else {
+            tcx.implied_outlives_bounds_compat(canonicalized)
+        }
     }
 
     fn perform_locally_with_next_solver(
         ocx: &ObligationCtxt<'_, 'tcx>,
         key: ParamEnvAnd<'tcx, Self>,
     ) -> Result<Self::QueryResponse, NoSolution> {
-        compute_implied_outlives_bounds_inner(ocx, key.param_env, key.value.ty)
+        if ocx.infcx.tcx.sess.opts.unstable_opts.no_implied_bounds_compat {
+            compute_implied_outlives_bounds_inner(ocx, key.param_env, key.value.ty)
+        } else {
+            compute_implied_outlives_bounds_compat_inner(ocx, key.param_env, key.value.ty)
+        }
     }
 }
 
@@ -63,6 +72,85 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>(
     param_env: ty::ParamEnv<'tcx>,
     ty: Ty<'tcx>,
 ) -> Result<Vec<OutlivesBound<'tcx>>, NoSolution> {
+    let normalize_op = |ty| {
+        let ty = ocx.normalize(&ObligationCause::dummy(), param_env, ty);
+        if !ocx.select_all_or_error().is_empty() {
+            return Err(NoSolution);
+        }
+        let ty = ocx.infcx.resolve_vars_if_possible(ty);
+        let ty = OpportunisticRegionResolver::new(&ocx.infcx).fold_ty(ty);
+        Ok(ty)
+    };
+
+    // Sometimes when we ask what it takes for T: WF, we get back that
+    // U: WF is required; in that case, we push U onto this stack and
+    // process it next. Because the resulting predicates aren't always
+    // guaranteed to be a subset of the original type, so we need to store the
+    // WF args we've computed in a set.
+    let mut checked_wf_args = rustc_data_structures::fx::FxHashSet::default();
+    let mut wf_args = vec![ty.into(), normalize_op(ty)?.into()];
+
+    let mut outlives_bounds: Vec<OutlivesBound<'tcx>> = vec![];
+
+    while let Some(arg) = wf_args.pop() {
+        if !checked_wf_args.insert(arg) {
+            continue;
+        }
+
+        // From the full set of obligations, just filter down to the region relationships.
+        for obligation in
+            wf::unnormalized_obligations(ocx.infcx, param_env, arg).into_iter().flatten()
+        {
+            assert!(!obligation.has_escaping_bound_vars());
+            let Some(pred) = obligation.predicate.kind().no_bound_vars() else {
+                continue;
+            };
+            match pred {
+                // FIXME(const_generics): Make sure that `<'a, 'b, const N: &'a &'b u32>` is sound
+                // if we ever support that
+                ty::PredicateKind::Clause(ty::ClauseKind::Trait(..))
+                | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
+                | ty::PredicateKind::Subtype(..)
+                | ty::PredicateKind::Coerce(..)
+                | ty::PredicateKind::Clause(ty::ClauseKind::Projection(..))
+                | ty::PredicateKind::ObjectSafe(..)
+                | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
+                | ty::PredicateKind::ConstEquate(..)
+                | ty::PredicateKind::Ambiguous
+                | ty::PredicateKind::NormalizesTo(..)
+                | ty::PredicateKind::AliasRelate(..) => {}
+
+                // We need to search through *all* WellFormed predicates
+                ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
+                    wf_args.push(arg);
+                }
+
+                // We need to register region relationships
+                ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(
+                    ty::OutlivesPredicate(r_a, r_b),
+                )) => outlives_bounds.push(OutlivesBound::RegionSubRegion(r_b, r_a)),
+
+                ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(
+                    ty_a,
+                    r_b,
+                ))) => {
+                    let ty_a = normalize_op(ty_a)?;
+                    let mut components = smallvec![];
+                    push_outlives_components(ocx.infcx.tcx, ty_a, &mut components);
+                    outlives_bounds.extend(implied_bounds_from_components(r_b, components))
+                }
+            }
+        }
+    }
+
+    Ok(outlives_bounds)
+}
+
+pub fn compute_implied_outlives_bounds_compat_inner<'tcx>(
+    ocx: &ObligationCtxt<'_, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    ty: Ty<'tcx>,
+) -> Result<Vec<OutlivesBound<'tcx>>, NoSolution> {
     let tcx = ocx.infcx.tcx;
 
     // Sometimes when we ask what it takes for T: WF, we get back that
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
index e21ede47f6d..14f14ae6e2e 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
@@ -30,6 +30,23 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> {
             }
         }
 
+        if let ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) =
+            key.value.predicate.kind().skip_binder()
+        {
+            match arg.as_type()?.kind() {
+                ty::Param(_)
+                | ty::Bool
+                | ty::Char
+                | ty::Int(_)
+                | ty::Float(_)
+                | ty::Str
+                | ty::Uint(_) => {
+                    return Some(());
+                }
+                _ => {}
+            }
+        }
+
         None
     }
 
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index e20bb06d777..74f388e53a3 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -11,7 +11,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir::lang_items::LangItem;
 use rustc_infer::infer::BoundRegionConversionTime::HigherRankedType;
 use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
-use rustc_middle::traits::{BuiltinImplSource, SelectionOutputTypeParameterMismatch};
+use rustc_middle::traits::{BuiltinImplSource, SignatureMismatchData};
 use rustc_middle::ty::{
     self, GenericArgs, GenericArgsRef, GenericParamDefKind, ToPolyTraitRef, ToPredicate,
     TraitPredicate, Ty, TyCtxt, TypeVisitableExt,
@@ -26,9 +26,9 @@ use crate::traits::vtable::{
 };
 use crate::traits::{
     BuiltinDerivedObligation, ImplDerivedObligation, ImplDerivedObligationCause, ImplSource,
-    ImplSourceUserDefinedData, Normalized, Obligation, ObligationCause,
-    OutputTypeParameterMismatch, PolyTraitObligation, PredicateObligation, Selection,
-    SelectionError, TraitNotObjectSafe, Unimplemented,
+    ImplSourceUserDefinedData, Normalized, Obligation, ObligationCause, PolyTraitObligation,
+    PredicateObligation, Selection, SelectionError, SignatureMismatch, TraitNotObjectSafe,
+    Unimplemented,
 };
 
 use super::BuiltinImplConditions;
@@ -922,7 +922,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 obligations
             })
             .map_err(|terr| {
-                OutputTypeParameterMismatch(Box::new(SelectionOutputTypeParameterMismatch {
+                SignatureMismatch(Box::new(SignatureMismatchData {
                     expected_trait_ref: obligation_trait_ref,
                     found_trait_ref: expected_trait_ref,
                     terr,
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index 200d022c80c..b37d9714ddd 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -26,7 +26,7 @@ use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt, TypeVisitableExt};
 use rustc_middle::ty::{GenericArgs, GenericArgsRef};
 use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK;
 use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS;
-use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP};
+use rustc_span::{sym, ErrorGuaranteed, Span, DUMMY_SP};
 
 use super::util;
 use super::SelectionContext;
@@ -142,10 +142,30 @@ pub fn translate_args_with_cause<'tcx>(
 pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, DefId)) -> bool {
     // The feature gate should prevent introducing new specializations, but not
     // taking advantage of upstream ones.
+    // If specialization is enabled for this crate then no extra checks are needed.
+    // If it's not, and either of the `impl`s is local to this crate, then this definitely
+    // isn't specializing - unless specialization is enabled for the `impl` span,
+    // e.g. if it comes from an `allow_internal_unstable` macro
     let features = tcx.features();
     let specialization_enabled = features.specialization || features.min_specialization;
-    if !specialization_enabled && (impl1_def_id.is_local() || impl2_def_id.is_local()) {
-        return false;
+    if !specialization_enabled {
+        if impl1_def_id.is_local() {
+            let span = tcx.def_span(impl1_def_id);
+            if !span.allows_unstable(sym::specialization)
+                && !span.allows_unstable(sym::min_specialization)
+            {
+                return false;
+            }
+        }
+
+        if impl2_def_id.is_local() {
+            let span = tcx.def_span(impl2_def_id);
+            if !span.allows_unstable(sym::specialization)
+                && !span.allows_unstable(sym::min_specialization)
+            {
+                return false;
+            }
+        }
     }
 
     // We determine whether there's a subset relationship by:
diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs
index 2cd1c3b502a..f3fae63ecc7 100644
--- a/compiler/rustc_traits/src/codegen.rs
+++ b/compiler/rustc_traits/src/codegen.rs
@@ -63,7 +63,7 @@ pub fn codegen_select_candidate<'tcx>(
         // Cycle errors are the only post-monomorphization errors possible; emit them now so
         // `rustc_ty_utils::resolve_associated_item` doesn't return `None` post-monomorphization.
         for err in errors {
-            if let FulfillmentErrorCode::CodeCycle(cycle) = err.code {
+            if let FulfillmentErrorCode::Cycle(cycle) = err.code {
                 infcx.err_ctxt().report_overflow_obligation_cycle(&cycle);
             }
         }
diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs
index 959838ab348..24e91c263e3 100644
--- a/compiler/rustc_traits/src/implied_outlives_bounds.rs
+++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs
@@ -8,13 +8,29 @@ use rustc_infer::traits::query::OutlivesBound;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_trait_selection::infer::InferCtxtBuilderExt;
-use rustc_trait_selection::traits::query::type_op::implied_outlives_bounds::compute_implied_outlives_bounds_inner;
+use rustc_trait_selection::traits::query::type_op::implied_outlives_bounds::{
+    compute_implied_outlives_bounds_compat_inner, compute_implied_outlives_bounds_inner,
+};
 use rustc_trait_selection::traits::query::{CanonicalTyGoal, NoSolution};
 
 pub(crate) fn provide(p: &mut Providers) {
+    *p = Providers { implied_outlives_bounds_compat, ..*p };
     *p = Providers { implied_outlives_bounds, ..*p };
 }
 
+fn implied_outlives_bounds_compat<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    goal: CanonicalTyGoal<'tcx>,
+) -> Result<
+    &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec<OutlivesBound<'tcx>>>>,
+    NoSolution,
+> {
+    tcx.infer_ctxt().enter_canonical_trait_query(&goal, |ocx, key| {
+        let (param_env, ty) = key.into_parts();
+        compute_implied_outlives_bounds_compat_inner(ocx, param_env, ty)
+    })
+}
+
 fn implied_outlives_bounds<'tcx>(
     tcx: TyCtxt<'tcx>,
     goal: CanonicalTyGoal<'tcx>,
diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs
index b8c71bc96f8..21a016e29d6 100644
--- a/compiler/rustc_traits/src/normalize_projection_ty.rs
+++ b/compiler/rustc_traits/src/normalize_projection_ty.rs
@@ -54,7 +54,7 @@ fn normalize_projection_ty<'tcx>(
                     // that impl vars are constrained by the signature, for example).
                     if !tcx.sess.opts.actually_rustdoc {
                         for error in &errors {
-                            if let FulfillmentErrorCode::CodeCycle(cycle) = &error.code {
+                            if let FulfillmentErrorCode::Cycle(cycle) = &error.code {
                                 ocx.infcx.err_ctxt().report_overflow_obligation_cycle(cycle);
                             }
                         }
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index 6e8293dac31..333aec1d38d 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -83,7 +83,11 @@ fn fn_sig_for_fn_abi<'tcx>(
                 kind: ty::BoundRegionKind::BrEnv,
             };
             let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br);
-            let env_ty = tcx.closure_env_ty(def_id, args, env_region).unwrap();
+            let env_ty = tcx.closure_env_ty(
+                Ty::new_closure(tcx, def_id, args),
+                args.as_closure().kind(),
+                env_region,
+            );
 
             let sig = sig.skip_binder();
             ty::Binder::bind_with_vars(
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index b8351463c55..2fc4bfd4aa3 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -1052,6 +1052,8 @@ fn variant_info_for_coroutine<'tcx>(
     def_id: DefId,
     args: ty::GenericArgsRef<'tcx>,
 ) -> (Vec<VariantInfo>, Option<Size>) {
+    use itertools::Itertools;
+
     let Variants::Multiple { tag, ref tag_encoding, tag_field, .. } = layout.variants else {
         return (vec![], None);
     };
@@ -1064,7 +1066,7 @@ fn variant_info_for_coroutine<'tcx>(
         .as_coroutine()
         .upvar_tys()
         .iter()
-        .zip(upvar_names)
+        .zip_eq(upvar_names)
         .enumerate()
         .map(|(field_idx, (_, name))| {
             let field_layout = layout.field(cx, field_idx);
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index bff93859645..83efbfb855f 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -327,21 +327,21 @@ impl UniverseIndex {
     /// name the region `'a`, but that region was not nameable from
     /// `U` because it was not in scope there.
     pub fn next_universe(self) -> UniverseIndex {
-        UniverseIndex::from_u32(self.private.checked_add(1).unwrap())
+        UniverseIndex::from_u32(self.as_u32().checked_add(1).unwrap())
     }
 
     /// Returns `true` if `self` can name a name from `other` -- in other words,
     /// if the set of names in `self` is a superset of those in
     /// `other` (`self >= other`).
     pub fn can_name(self, other: UniverseIndex) -> bool {
-        self.private >= other.private
+        self >= other
     }
 
     /// Returns `true` if `self` cannot name some names from `other` -- in other
     /// words, if the set of names in `self` is a strict subset of
     /// those in `other` (`self < other`).
     pub fn cannot_name(self, other: UniverseIndex) -> bool {
-        self.private < other.private
+        self < other
     }
 }
 
diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs
index eba2ac57012..b0a08cd9b79 100644
--- a/compiler/stable_mir/src/ty.rs
+++ b/compiler/stable_mir/src/ty.rs
@@ -12,7 +12,7 @@ use std::fmt::{self, Debug, Display, Formatter};
 use std::ops::Range;
 
 #[derive(Copy, Clone, Eq, PartialEq, Hash)]
-pub struct Ty(pub usize);
+pub struct Ty(usize);
 
 impl Debug for Ty {
     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
@@ -138,7 +138,7 @@ impl Const {
 }
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
-pub struct ConstId(pub usize);
+pub struct ConstId(usize);
 
 type Ident = Opaque;