about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLaurențiu Nicola <lnicola@users.noreply.github.com>2024-11-01 12:26:18 +0000
committerGitHub <noreply@github.com>2024-11-01 12:26:18 +0000
commitcf6bc48353ba46fceb43f5efc37858c471d05bb7 (patch)
tree0cff0055f2ed9e9d18df92e2d98f10d7b5359075
parenta5b5b466b0517124e8c5d8610d708aa04a1c4fc7 (diff)
parent9acf57c48e0d55e7b2d07dae2bb4fbfc3fc010dd (diff)
downloadrust-cf6bc48353ba46fceb43f5efc37858c471d05bb7.tar.gz
rust-cf6bc48353ba46fceb43f5efc37858c471d05bb7.zip
Merge pull request #18457 from lnicola/sync-from-rust
minor: Sync from downstream
-rw-r--r--Cargo.lock27
-rw-r--r--compiler/rustc_abi/Cargo.toml4
-rw-r--r--compiler/rustc_abi/src/callconv.rs16
-rw-r--r--compiler/rustc_abi/src/extern_abi/mod.rs (renamed from compiler/rustc_target/src/spec/abi/mod.rs)4
-rw-r--r--compiler/rustc_abi/src/extern_abi/tests.rs (renamed from compiler/rustc_target/src/spec/abi/tests.rs)0
-rw-r--r--compiler/rustc_abi/src/layout.rs108
-rw-r--r--compiler/rustc_abi/src/layout/ty.rs12
-rw-r--r--compiler/rustc_abi/src/lib.rs123
-rw-r--r--compiler/rustc_ast/src/ast.rs2
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs2
-rw-r--r--compiler/rustc_ast/src/token.rs2
-rw-r--r--compiler/rustc_ast/src/visit.rs2
-rw-r--r--compiler/rustc_ast_lowering/src/block.rs5
-rw-r--r--compiler/rustc_ast_lowering/src/delegation.rs5
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs136
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs10
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs340
-rw-r--r--compiler/rustc_ast_lowering/src/lifetime_collector.rs151
-rw-r--r--compiler/rustc_ast_lowering/src/pat.rs70
-rw-r--r--compiler/rustc_ast_lowering/src/path.rs2
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs13
-rw-r--r--compiler/rustc_ast_pretty/Cargo.toml1
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs3
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs9
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs1
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/opaque_suggestions.rs224
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs2
-rw-r--r--compiler/rustc_borrowck/src/lib.rs35
-rw-r--r--compiler/rustc_borrowck/src/nll.rs4
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs4
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs16
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs4
-rw-r--r--compiler/rustc_codegen_cranelift/src/abi/mod.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs28
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs8
-rw-r--r--compiler/rustc_codegen_cranelift/src/discriminant.rs4
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs10
-rw-r--r--compiler/rustc_codegen_cranelift/src/lib.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/value_and_place.rs57
-rw-r--r--compiler/rustc_codegen_cranelift/src/vtable.rs4
-rw-r--r--compiler/rustc_codegen_gcc/src/builder.rs4
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/mod.rs6
-rw-r--r--compiler/rustc_codegen_gcc/src/type_of.rs37
-rw-r--r--compiler/rustc_codegen_llvm/src/abi.rs14
-rw-r--r--compiler/rustc_codegen_llvm/src/allocator.rs12
-rw-r--r--compiler/rustc_codegen_llvm/src/asm.rs103
-rw-r--r--compiler/rustc_codegen_llvm/src/back/lto.rs29
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs25
-rw-r--r--compiler/rustc_codegen_llvm/src/base.rs6
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs27
-rw-r--r--compiler/rustc_codegen_llvm/src/common.rs26
-rw-r--r--compiler/rustc_codegen_llvm/src/consts.rs8
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs289
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs6
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs15
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs48
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs8
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs6
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs10
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs10
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/mod.rs82
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/declare.rs7
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs13
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs122
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/mod.rs79
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs5
-rw-r--r--compiler/rustc_codegen_llvm/src/type_of.rs37
-rw-r--r--compiler/rustc_codegen_ssa/src/back/metadata.rs5
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs10
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/constant.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/debuginfo.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/operand.rs39
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/place.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs18
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/builder.rs4
-rw-r--r--compiler/rustc_const_eval/src/check_consts/check.rs14
-rw-r--r--compiler/rustc_const_eval/src/check_consts/mod.rs7
-rw-r--r--compiler/rustc_const_eval/src/check_consts/ops.rs2
-rw-r--r--compiler/rustc_const_eval/src/check_consts/qualifs.rs10
-rw-r--r--compiler/rustc_const_eval/src/const_eval/dummy_machine.rs2
-rw-r--r--compiler/rustc_const_eval/src/const_eval/eval_queries.rs6
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs2
-rw-r--r--compiler/rustc_const_eval/src/const_eval/valtrees.rs6
-rw-r--r--compiler/rustc_const_eval/src/interpret/call.rs4
-rw-r--r--compiler/rustc_const_eval/src/interpret/cast.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/discriminant.rs8
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs25
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs4
-rw-r--r--compiler/rustc_const_eval/src/interpret/operand.rs58
-rw-r--r--compiler/rustc_const_eval/src/interpret/operator.rs18
-rw-r--r--compiler/rustc_const_eval/src/interpret/place.rs22
-rw-r--r--compiler/rustc_const_eval/src/interpret/stack.rs13
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs29
-rw-r--r--compiler/rustc_const_eval/src/util/check_validity_requirement.rs16
-rw-r--r--compiler/rustc_const_eval/src/util/compare_types.rs22
-rw-r--r--compiler/rustc_const_eval/src/util/mod.rs2
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0801.md51
-rw-r--r--compiler/rustc_error_codes/src/lib.rs1
-rw-r--r--compiler/rustc_errors/Cargo.toml1
-rw-r--r--compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs2
-rw-r--r--compiler/rustc_errors/src/diagnostic_impls.rs2
-rw-r--r--compiler/rustc_errors/src/emitter.rs15
-rw-r--r--compiler/rustc_errors/src/json.rs4
-rw-r--r--compiler/rustc_expand/messages.ftl2
-rw-r--r--compiler/rustc_expand/src/errors.rs2
-rw-r--r--compiler/rustc_expand/src/expand.rs5
-rw-r--r--compiler/rustc_expand/src/mbe/diagnostics.rs13
-rw-r--r--compiler/rustc_expand/src/mbe/macro_parser.rs7
-rw-r--r--compiler/rustc_expand/src/mbe/transcribe.rs3
-rw-r--r--compiler/rustc_feature/src/accepted.rs2
-rw-r--r--compiler/rustc_feature/src/unstable.rs2
-rw-r--r--compiler/rustc_hir/src/hir.rs36
-rw-r--r--compiler/rustc_hir/src/intravisit.rs7
-rw-r--r--compiler/rustc_hir_analysis/Cargo.toml1
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl10
-rw-r--r--compiler/rustc_hir_analysis/src/bounds.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs19
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs26
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/check/dropck.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/check/entry.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsicck.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/check/region.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs69
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/orphan.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs29
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs15
-rw-r--r--compiler/rustc_hir_analysis/src/collect/item_bounds.rs19
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs29
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs367
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs159
-rw-r--r--compiler/rustc_hir_analysis/src/hir_wf_check.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs6
-rw-r--r--compiler/rustc_hir_pretty/Cargo.toml2
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/_match.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/autoderef.rs7
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs17
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs17
-rw-r--r--compiler/rustc_hir_typeck/src/expr_use_visitor.rs13
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/confirm.rs11
-rw-r--r--compiler/rustc_hir_typeck/src/method/mod.rs91
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/op.rs44
-rw-r--r--compiler/rustc_hir_typeck/src/place_op.rs33
-rw-r--r--compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs5
-rw-r--r--compiler/rustc_infer/src/infer/at.rs36
-rw-r--r--compiler/rustc_infer/src/infer/canonical/canonicalizer.rs6
-rw-r--r--compiler/rustc_infer/src/infer/context.rs17
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs99
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types/mod.rs56
-rw-r--r--compiler/rustc_infer/src/infer/relate/generalize.rs11
-rw-r--r--compiler/rustc_interface/src/queries.rs2
-rw-r--r--compiler/rustc_lint/Cargo.toml1
-rw-r--r--compiler/rustc_lint/messages.ftl2
-rw-r--r--compiler/rustc_lint/src/builtin.rs14
-rw-r--r--compiler/rustc_lint/src/context.rs15
-rw-r--r--compiler/rustc_lint/src/for_loops_over_fallibles.rs2
-rw-r--r--compiler/rustc_lint/src/foreign_modules.rs4
-rw-r--r--compiler/rustc_lint/src/if_let_rescope.rs3
-rw-r--r--compiler/rustc_lint/src/impl_trait_overcaptures.rs4
-rw-r--r--compiler/rustc_lint/src/lints.rs4
-rw-r--r--compiler/rustc_lint/src/non_fmt_panic.rs2
-rw-r--r--compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs4
-rw-r--r--compiler/rustc_lint/src/types.rs6
-rw-r--r--compiler/rustc_lint/src/types/literal.rs2
-rw-r--r--compiler/rustc_lint/src/unused.rs2
-rw-r--r--compiler/rustc_lint_defs/Cargo.toml2
-rw-r--r--compiler/rustc_lint_defs/src/lib.rs4
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp14
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp142
-rw-r--r--compiler/rustc_metadata/Cargo.toml2
-rw-r--r--compiler/rustc_metadata/src/locator.rs29
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs5
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs5
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs13
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs5
-rw-r--r--compiler/rustc_middle/src/middle/debugger_visualizer.rs2
-rw-r--r--compiler/rustc_middle/src/middle/resolve_bound_vars.rs4
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs11
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs11
-rw-r--r--compiler/rustc_middle/src/query/erase.rs1
-rw-r--r--compiler/rustc_middle/src/query/mod.rs22
-rw-r--r--compiler/rustc_middle/src/query/on_disk_cache.rs45
-rw-r--r--compiler/rustc_middle/src/query/plumbing.rs2
-rw-r--r--compiler/rustc_middle/src/ty/adjustment.rs21
-rw-r--r--compiler/rustc_middle/src/ty/assoc.rs2
-rw-r--r--compiler/rustc_middle/src/ty/context.rs46
-rw-r--r--compiler/rustc_middle/src/ty/flags.rs2
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs9
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs12
-rw-r--r--compiler/rustc_middle/src/ty/parameterized.rs1
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs8
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs2
-rw-r--r--compiler/rustc_mir_build/Cargo.toml3
-rw-r--r--compiler/rustc_mir_build/src/build/custom/parse/instruction.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_constant.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_place.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs17
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs13
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs25
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs8
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs2
-rw-r--r--compiler/rustc_mir_dataflow/Cargo.toml1
-rw-r--r--compiler/rustc_mir_dataflow/src/drop_flag_effects.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/elaborate_drops.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/graphviz.rs111
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/mod.rs109
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/results.rs (renamed from compiler/rustc_mir_dataflow/src/framework/engine.rs)121
-rw-r--r--compiler/rustc_mir_dataflow/src/lib.rs6
-rw-r--r--compiler/rustc_mir_dataflow/src/rustc_peek.rs15
-rw-r--r--compiler/rustc_mir_dataflow/src/value_analysis.rs420
-rw-r--r--compiler/rustc_mir_transform/Cargo.toml1
-rw-r--r--compiler/rustc_mir_transform/src/coroutine.rs23
-rw-r--r--compiler/rustc_mir_transform/src/dataflow_const_prop.rs351
-rw-r--r--compiler/rustc_mir_transform/src/dead_store_elimination.rs3
-rw-r--r--compiler/rustc_mir_transform/src/dest_prop.rs5
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_drops.rs8
-rw-r--r--compiler/rustc_mir_transform/src/gvn.rs23
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs27
-rw-r--r--compiler/rustc_mir_transform/src/known_panics_lint.rs10
-rw-r--r--compiler/rustc_mir_transform/src/lint.rs6
-rw-r--r--compiler/rustc_mir_transform/src/ref_prop.rs3
-rw-r--r--compiler/rustc_mir_transform/src/remove_uninit_drops.rs4
-rw-r--r--compiler/rustc_mir_transform/src/unreachable_enum_branching.rs4
-rw-r--r--compiler/rustc_mir_transform/src/validate.rs25
-rw-r--r--compiler/rustc_next_trait_solver/src/delegate.rs4
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs14
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/effect_goals.rs11
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs3
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs23
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs17
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs50
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/trait_goals.rs46
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs3
-rw-r--r--compiler/rustc_parse/src/parser/item.rs2
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs2
-rw-r--r--compiler/rustc_passes/Cargo.toml1
-rw-r--r--compiler/rustc_passes/src/check_attr.rs4
-rw-r--r--compiler/rustc_passes/src/dead.rs2
-rw-r--r--compiler/rustc_passes/src/layout_test.rs11
-rw-r--r--compiler/rustc_pattern_analysis/Cargo.toml3
-rw-r--r--compiler/rustc_pattern_analysis/src/rustc.rs2
-rw-r--r--compiler/rustc_pattern_analysis/src/rustc/print.rs2
-rw-r--r--compiler/rustc_privacy/src/lib.rs2
-rw-r--r--compiler/rustc_query_system/src/dep_graph/graph.rs2
-rw-r--r--compiler/rustc_query_system/src/query/job.rs2
-rw-r--r--compiler/rustc_resolve/src/late.rs40
-rw-r--r--compiler/rustc_resolve/src/lib.rs6
-rw-r--r--compiler/rustc_resolve/src/macros.rs2
-rw-r--r--compiler/rustc_session/Cargo.toml1
-rw-r--r--compiler/rustc_session/src/code_stats.rs2
-rw-r--r--compiler/rustc_session/src/config/cfg.rs2
-rw-r--r--compiler/rustc_session/src/filesearch.rs2
-rw-r--r--compiler/rustc_session/src/parse.rs6
-rw-r--r--compiler/rustc_session/src/session.rs5
-rw-r--r--compiler/rustc_smir/src/rustc_internal/mod.rs2
-rw-r--r--compiler/rustc_smir/src/rustc_smir/alloc.rs14
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/abi.rs64
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/mir.rs6
-rw-r--r--compiler/rustc_smir/src/rustc_smir/mod.rs2
-rw-r--r--compiler/rustc_span/src/caching_source_map_view.rs14
-rw-r--r--compiler/rustc_span/src/source_map.rs12
-rw-r--r--compiler/rustc_symbol_mangling/Cargo.toml2
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs2
-rw-r--r--compiler/rustc_target/src/callconv/loongarch.rs18
-rw-r--r--compiler/rustc_target/src/callconv/mips64.rs8
-rw-r--r--compiler/rustc_target/src/callconv/mod.rs29
-rw-r--r--compiler/rustc_target/src/callconv/riscv.rs18
-rw-r--r--compiler/rustc_target/src/callconv/sparc64.rs8
-rw-r--r--compiler/rustc_target/src/callconv/x86.rs18
-rw-r--r--compiler/rustc_target/src/callconv/x86_64.rs14
-rw-r--r--compiler/rustc_target/src/callconv/x86_win64.rs27
-rw-r--r--compiler/rustc_target/src/callconv/xtensa.rs6
-rw-r--r--compiler/rustc_target/src/spec/mod.rs8
-rw-r--r--compiler/rustc_target/src/spec/targets/mipsel_sony_psx.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/sparc64_unknown_linux_gnu.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/sparc64_unknown_netbsd.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/sparc64_unknown_openbsd.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/sparc_unknown_none_elf.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs2
-rw-r--r--compiler/rustc_target/src/spec/tests/tests_impl.rs3
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs5
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs5
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/region.rs16
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs15
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs27
-rw-r--r--compiler/rustc_trait_selection/src/solve/delegate.rs24
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs5
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs16
-rw-r--r--compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs14
-rw-r--r--compiler/rustc_trait_selection/src/traits/effects.rs154
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs48
-rw-r--r--compiler/rustc_trait_selection/src/traits/misc.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs21
-rw-r--r--compiler/rustc_trait_selection/src/traits/normalize.rs33
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs65
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/normalize.rs20
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs11
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs113
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/mod.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/vtable.rs5
-rw-r--r--compiler/rustc_traits/src/codegen.rs4
-rw-r--r--compiler/rustc_traits/src/normalize_erasing_regions.rs4
-rw-r--r--compiler/rustc_transmute/src/layout/tree.rs4
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs14
-rw-r--r--compiler/rustc_ty_utils/src/assoc.rs10
-rw-r--r--compiler/rustc_ty_utils/src/common_traits.rs4
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs4
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs43
-rw-r--r--compiler/rustc_ty_utils/src/layout/invariant.rs48
-rw-r--r--compiler/rustc_ty_utils/src/opaque_types.rs2
-rw-r--r--compiler/rustc_ty_utils/src/structural_match.rs4
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs2
-rw-r--r--compiler/rustc_type_ir/src/canonical.rs4
-rw-r--r--compiler/rustc_type_ir/src/elaborate.rs2
-rw-r--r--compiler/rustc_type_ir/src/infer_ctxt.rs75
-rw-r--r--compiler/rustc_type_ir/src/interner.rs23
-rw-r--r--compiler/rustc_type_ir/src/outlives.rs12
-rw-r--r--compiler/rustc_type_ir/src/predicate.rs55
-rw-r--r--compiler/rustc_type_ir/src/relate/combine.rs18
-rw-r--r--compiler/rustc_type_ir/src/search_graph/mod.rs21
-rw-r--r--compiler/rustc_type_ir/src/solve/mod.rs13
-rw-r--r--config.example.toml9
-rw-r--r--library/Cargo.lock4
-rw-r--r--library/alloc/Cargo.toml2
-rw-r--r--library/alloc/src/boxed.rs1032
-rw-r--r--library/alloc/src/boxed/convert.rs747
-rw-r--r--library/alloc/src/boxed/iter.rs194
-rw-r--r--library/alloc/src/rc.rs28
-rw-r--r--library/alloc/src/sync.rs16
-rw-r--r--library/alloc/tests/arc.rs40
-rw-r--r--library/alloc/tests/boxed.rs38
-rw-r--r--library/alloc/tests/rc.rs38
-rw-r--r--library/core/src/iter/traits/iterator.rs76
-rw-r--r--library/core/src/lib.rs2
-rw-r--r--library/core/src/num/mod.rs4
-rw-r--r--library/core/src/str/mod.rs48
-rw-r--r--library/proc_macro/src/lib.rs4
-rw-r--r--library/proc_macro/src/to_tokens.rs310
-rw-r--r--library/std/Cargo.toml2
-rw-r--r--library/std/src/fs.rs2
-rw-r--r--library/std/src/sys/sync/condvar/xous.rs1
-rw-r--r--library/std/src/sys/sync/mutex/xous.rs1
-rw-r--r--src/bootstrap/src/bin/rustc.rs4
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs9
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs5
-rw-r--r--src/bootstrap/src/core/config/config.rs37
-rw-r--r--src/ci/docker/host-x86_64/mingw-check/Dockerfile3
-rwxr-xr-xsrc/ci/docker/host-x86_64/x86_64-fuchsia/build-fuchsia.sh2
-rw-r--r--src/ci/github-actions/jobs.yml10
-rw-r--r--src/doc/rustc/src/platform-support/aix.md4
-rw-r--r--src/doc/rustc/src/platform-support/apple-darwin.md5
-rw-r--r--src/doc/rustc/src/platform-support/fuchsia.md23
-rwxr-xr-xsrc/etc/htmldocck.py2
-rw-r--r--src/librustdoc/clean/blanket_impl.rs4
-rw-r--r--src/librustdoc/clean/mod.rs8
-rw-r--r--src/librustdoc/doctest/runner.rs4
-rw-r--r--src/librustdoc/doctest/rust.rs14
-rw-r--r--src/librustdoc/html/format.rs5
-rw-r--r--src/librustdoc/html/render/type_layout.rs8
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css2
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/eta_reduction.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/must_use.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/future_not_send.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/lifetimes.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/explicit_into_iter_loop.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_async_fn.rs80
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/no_effect.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_slicing.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/useless_conversion.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs5
-rw-r--r--src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs10
-rw-r--r--src/tools/clippy/tests/ui/issue_4266.stderr2
-rw-r--r--src/tools/compiletest/Cargo.toml1
-rw-r--r--src/tools/compiletest/src/common.rs8
-rw-r--r--src/tools/compiletest/src/directive-list.rs (renamed from src/tools/compiletest/src/command-list.rs)1
-rw-r--r--src/tools/compiletest/src/header.rs144
-rw-r--r--src/tools/compiletest/src/header/tests.rs79
-rw-r--r--src/tools/compiletest/src/lib.rs15
-rw-r--r--src/tools/compiletest/src/runtest.rs78
-rw-r--r--src/tools/compiletest/src/runtest/assembly.rs32
-rw-r--r--src/tools/compiletest/src/tests.rs13
-rw-r--r--src/tools/jsondocck/src/main.rs2
-rw-r--r--src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs7
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs7
-rw-r--r--src/tools/miri/src/helpers.rs8
-rw-r--r--src/tools/miri/src/lib.rs1
-rw-r--r--src/tools/miri/src/operator.rs2
-rw-r--r--src/tools/miri/src/shims/native_lib.rs4
-rw-r--r--src/tools/miri/tests/fail/coroutine-pinned-moved.stderr2
-rw-r--r--src/tools/rust-analyzer/Cargo.lock31
-rw-r--r--src/tools/rust-analyzer/Cargo.toml11
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/layout.rs30
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib/version.rs17
-rw-r--r--src/tools/rust-analyzer/rust-version2
-rw-r--r--src/tools/rust-analyzer/xtask/src/tidy.rs1
-rw-r--r--src/tools/tidy/src/deps.rs4
-rw-r--r--src/tools/tidy/src/issues.txt1
-rw-r--r--tests/assembly/compiletest-self-test/use-minicore-no-run.rs5
-rw-r--r--tests/assembly/riscv-soft-abi-with-float-features.rs11
-rw-r--r--tests/auxiliary/minicore.rs72
-rw-r--r--tests/codegen/clone_as_copy.rs2
-rw-r--r--tests/codegen/compiletest-self-test/minicore-smoke-test.rs20
-rw-r--r--tests/codegen/try_question_mark_nop.rs14
-rw-r--r--tests/crashes/125249.rs8
-rw-r--r--tests/crashes/23707.rs109
-rw-r--r--tests/mir-opt/gvn_clone.rs2
-rw-r--r--tests/mir-opt/gvn_clone.{impl#0}-clone.GVN.diff6
-rw-r--r--tests/mir-opt/gvn_copy_aggregate.rs2
-rw-r--r--tests/mir-opt/pre-codegen/clone_as_copy.rs2
-rw-r--r--tests/mir-opt/pre-codegen/no_inlined_clone.{impl#0}-clone.PreCodegen.after.mir6
-rw-r--r--tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir8
-rw-r--r--tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir30
-rw-r--r--tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir30
-rw-r--r--tests/mir-opt/simplify_aggregate_to_copy_miscompile.foo.GVN.diff72
-rw-r--r--tests/mir-opt/simplify_aggregate_to_copy_miscompile.rs32
-rw-r--r--tests/rustdoc-gui/fields.goml13
-rw-r--r--tests/rustdoc-ui/doctest/auxiliary/extern_macros_2024.rs10
-rw-r--r--tests/rustdoc-ui/doctest/auxiliary/relative-dir-empty-file0
-rw-r--r--tests/rustdoc-ui/doctest/auxiliary/relative-dir.md3
-rw-r--r--tests/rustdoc-ui/doctest/dead-code-2024.rs15
-rw-r--r--tests/rustdoc-ui/doctest/dead-code-2024.stdout29
-rw-r--r--tests/rustdoc-ui/doctest/dead-code.rs15
-rw-r--r--tests/rustdoc-ui/doctest/dead-code.stdout29
-rw-r--r--tests/rustdoc-ui/doctest/doctest-output-include-fail.rs3
-rw-r--r--tests/rustdoc-ui/doctest/doctest-output.edition2015.stdout8
-rw-r--r--tests/rustdoc-ui/doctest/doctest-output.edition2024.stdout8
-rw-r--r--tests/rustdoc-ui/doctest/doctest-output.rs10
-rw-r--r--tests/rustdoc-ui/doctest/doctest-output.stdout8
-rw-r--r--tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.edition2015.stdout24
-rw-r--r--tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.edition2024.stdout6
-rw-r--r--tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.rs18
-rw-r--r--tests/ui/abi/c-zst.aarch64-darwin.stderr (renamed from tests/ui/abi/c-zst.other-linux.stderr)6
-rw-r--r--tests/ui/abi/c-zst.powerpc-linux.stderr6
-rw-r--r--tests/ui/abi/c-zst.rs80
-rw-r--r--tests/ui/abi/c-zst.s390x-linux.stderr6
-rw-r--r--tests/ui/abi/c-zst.sparc64-linux.stderr6
-rw-r--r--tests/ui/abi/c-zst.x86_64-linux.stderr (renamed from tests/ui/abi/c-zst.other.stderr)6
-rw-r--r--tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr6
-rw-r--r--tests/ui/abi/compatibility.rs69
-rw-r--r--tests/ui/abi/debug.stderr24
-rw-r--r--tests/ui/abi/sysv64-zst.stderr4
-rw-r--r--tests/ui/abi/win64-zst.rs23
-rw-r--r--tests/ui/abi/win64-zst.x86_64-linux.stderr (renamed from tests/ui/abi/win64-zst.other.stderr)6
-rw-r--r--tests/ui/abi/win64-zst.x86_64-windows-gnu.stderr (renamed from tests/ui/abi/win64-zst.windows-gnu.stderr)6
-rw-r--r--tests/ui/abi/win64-zst.x86_64-windows-msvc.stderr67
-rw-r--r--tests/ui/array-slice-vec/vec-macro-with-comma-only.rs2
-rw-r--r--tests/ui/array-slice-vec/vec-macro-with-comma-only.stderr2
-rw-r--r--tests/ui/associated-consts/issue-58022.stderr2
-rw-r--r--tests/ui/associated-type-bounds/implied-from-self-where-clause.rs21
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr2
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/impl-trait-in-trait.rs (renamed from tests/crashes/131648.rs)3
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/impl-trait-in-trait.stderr27
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-unsatisfied.stderr2
-rw-r--r--tests/ui/associated-types/defaults-suitability.current.stderr6
-rw-r--r--tests/ui/associated-types/defaults-suitability.next.stderr6
-rw-r--r--tests/ui/associated-types/hr-associated-type-bound-1.stderr2
-rw-r--r--tests/ui/associated-types/hr-associated-type-bound-param-1.stderr2
-rw-r--r--tests/ui/associated-types/hr-associated-type-bound-param-2.stderr2
-rw-r--r--tests/ui/associated-types/hr-associated-type-bound-param-3.stderr2
-rw-r--r--tests/ui/associated-types/hr-associated-type-bound-param-4.stderr2
-rw-r--r--tests/ui/associated-types/hr-associated-type-bound-param-5.stderr4
-rw-r--r--tests/ui/associated-types/issue-38821.stderr36
-rw-r--r--tests/ui/associated-types/issue-43784-associated-type.stderr2
-rw-r--r--tests/ui/associated-types/issue-65774-1.stderr2
-rw-r--r--tests/ui/associated-types/substs-ppaux.normal.stderr2
-rw-r--r--tests/ui/associated-types/substs-ppaux.verbose.stderr2
-rw-r--r--tests/ui/async-await/async-await-let-else.stderr8
-rw-r--r--tests/ui/async-await/async-closures/not-clone-closure.stderr2
-rw-r--r--tests/ui/async-await/async-fn-nonsend.stderr4
-rw-r--r--tests/ui/async-await/async-is-unwindsafe.stderr2
-rw-r--r--tests/ui/async-await/debug-ice-attempted-to-add-with-overflow.stderr2
-rw-r--r--tests/ui/async-await/drop-track-bad-field-in-fru.stderr2
-rw-r--r--tests/ui/async-await/drop-track-field-assign-nonsend.stderr2
-rw-r--r--tests/ui/async-await/field-assign-nonsend.stderr2
-rw-r--r--tests/ui/async-await/in-trait/missing-send-bound.stderr2
-rw-r--r--tests/ui/async-await/issue-101715.stderr2
-rw-r--r--tests/ui/async-await/issue-64130-1-sync.stderr2
-rw-r--r--tests/ui/async-await/issue-64130-2-send.stderr2
-rw-r--r--tests/ui/async-await/issue-64130-3-other.stderr2
-rw-r--r--tests/ui/async-await/issue-64130-non-send-future-diags.stderr2
-rw-r--r--tests/ui/async-await/issue-67252-unnamed-future.stderr2
-rw-r--r--tests/ui/async-await/issue-68112.stderr6
-rw-r--r--tests/ui/async-await/issue-70935-complex-spans.stderr4
-rw-r--r--tests/ui/async-await/issue-71137.stderr2
-rw-r--r--tests/ui/async-await/issue-72590-type-error-sized.stderr2
-rw-r--r--tests/ui/async-await/issues/issue-67893.stderr2
-rw-r--r--tests/ui/async-await/partial-drop-partial-reinit.stderr2
-rw-r--r--tests/ui/async-await/pin-needed-to-poll-2.stderr2
-rw-r--r--tests/ui/async-await/unnecessary-await.stderr8
-rw-r--r--tests/ui/auto-traits/issue-83857-ub.stderr4
-rw-r--r--tests/ui/auto-traits/str-contains-slice-conceptually.stderr2
-rw-r--r--tests/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.stderr2
-rw-r--r--tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr2
-rw-r--r--tests/ui/binop/binary-op-suggest-deref.stderr16
-rw-r--r--tests/ui/block-result/issue-22645.stderr2
-rw-r--r--tests/ui/cast/unsized-union-ice.stderr2
-rw-r--r--tests/ui/check-cfg/well-known-values.stderr6
-rw-r--r--tests/ui/closures/closure-move-sync.stderr2
-rw-r--r--tests/ui/closures/closure-return-type-must-be-sized.stderr18
-rw-r--r--tests/ui/coherence/deep-bad-copy-reason.stderr2
-rw-r--r--tests/ui/compiletest-self-test/minicore-smoke-test.rs20
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.stderr2
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.stderr6
-rw-r--r--tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr4
-rw-r--r--tests/ui/const-generics/generic_const_exprs/issue-85848.stderr2
-rw-r--r--tests/ui/const-generics/issues/issue-67185-2.stderr4
-rw-r--r--tests/ui/const-generics/kind_mismatch.stderr2
-rw-r--r--tests/ui/consts/const-blocks/fn-call-in-non-const.stderr2
-rw-r--r--tests/ui/consts/const-blocks/migrate-fail.stderr4
-rw-r--r--tests/ui/consts/const-blocks/nll-fail.stderr4
-rw-r--r--tests/ui/consts/const-blocks/trait-error.stderr2
-rw-r--r--tests/ui/consts/const-fn-in-vec.stderr4
-rw-r--r--tests/ui/consts/constifconst-call-in-const-position.stderr17
-rw-r--r--tests/ui/coroutine/clone-impl.stderr12
-rw-r--r--tests/ui/coroutine/drop-tracking-parent-expression.stderr6
-rw-r--r--tests/ui/coroutine/drop-yield-twice.stderr2
-rw-r--r--tests/ui/coroutine/issue-105084.stderr2
-rw-r--r--tests/ui/coroutine/issue-68112.stderr4
-rw-r--r--tests/ui/coroutine/not-send-sync.stderr4
-rw-r--r--tests/ui/coroutine/parent-expression.stderr6
-rw-r--r--tests/ui/coroutine/print/coroutine-print-verbose-1.stderr4
-rw-r--r--tests/ui/coroutine/print/coroutine-print-verbose-2.stderr4
-rw-r--r--tests/ui/coroutine/ref-upvar-not-send.stderr4
-rw-r--r--tests/ui/coroutine/resume-arg-outlives-2.rs34
-rw-r--r--tests/ui/coroutine/resume-arg-outlives-2.stderr17
-rw-r--r--tests/ui/coroutine/resume-arg-outlives.rs27
-rw-r--r--tests/ui/coroutine/resume-arg-outlives.stderr20
-rw-r--r--tests/ui/coroutine/unresolved-ct-var.stderr2
-rw-r--r--tests/ui/coroutine/yield-outside-coroutine-issue-78653.stderr2
-rw-r--r--tests/ui/delegation/unsupported.stderr7
-rw-r--r--tests/ui/derives/derives-span-Debug-enum-struct-variant.stderr2
-rw-r--r--tests/ui/derives/derives-span-Debug-enum.stderr2
-rw-r--r--tests/ui/derives/derives-span-Debug-struct.stderr2
-rw-r--r--tests/ui/derives/derives-span-Debug-tuple-struct.stderr2
-rw-r--r--tests/ui/deriving/issue-103157.stderr2
-rw-r--r--tests/ui/drop/drop_order.rs2
-rw-r--r--tests/ui/drop/drop_order_if_let_rescope.rs1
-rw-r--r--tests/ui/drop/if-let-rescope-borrowck-suggestions.rs1
-rw-r--r--tests/ui/drop/if-let-rescope-borrowck-suggestions.stderr12
-rw-r--r--tests/ui/drop/lint-if-let-rescope-gated.edition2021.stderr (renamed from tests/ui/drop/lint-if-let-rescope-gated.with_feature_gate.stderr)0
-rw-r--r--tests/ui/drop/lint-if-let-rescope-gated.rs22
-rw-r--r--tests/ui/drop/lint-if-let-rescope-with-macro.rs1
-rw-r--r--tests/ui/drop/lint-if-let-rescope-with-macro.stderr6
-rw-r--r--tests/ui/drop/lint-if-let-rescope.fixed2
-rw-r--r--tests/ui/drop/lint-if-let-rescope.rs2
-rw-r--r--tests/ui/dropck/const_drop_is_valid.stderr7
-rw-r--r--tests/ui/dst/dst-bad-deep-2.stderr2
-rw-r--r--tests/ui/dst/dst-bad-deep.stderr2
-rw-r--r--tests/ui/editions/edition-keywords-2015-2015-parsing.rs4
-rw-r--r--tests/ui/editions/edition-keywords-2015-2015-parsing.stderr4
-rw-r--r--tests/ui/editions/edition-keywords-2015-2018-parsing.rs4
-rw-r--r--tests/ui/editions/edition-keywords-2015-2018-parsing.stderr4
-rw-r--r--tests/ui/editions/edition-keywords-2018-2015-parsing.rs4
-rw-r--r--tests/ui/editions/edition-keywords-2018-2015-parsing.stderr6
-rw-r--r--tests/ui/editions/edition-keywords-2018-2018-parsing.rs4
-rw-r--r--tests/ui/editions/edition-keywords-2018-2018-parsing.stderr6
-rw-r--r--tests/ui/error-codes/E0277-2.stderr2
-rw-r--r--tests/ui/error-codes/E0277.stderr2
-rw-r--r--tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr28
-rw-r--r--tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr28
-rw-r--r--tests/ui/extern/extern-types-unsized.stderr6
-rw-r--r--tests/ui/fail-simple.rs2
-rw-r--r--tests/ui/fail-simple.stderr2
-rw-r--r--tests/ui/feature-gates/feature-gate-if-let-rescope.rs27
-rw-r--r--tests/ui/feature-gates/feature-gate-if-let-rescope.stderr18
-rw-r--r--tests/ui/feature-gates/feature-gate-offset-of-slice.stderr2
-rw-r--r--tests/ui/feature-gates/feature-gate-trivial_bounds.stderr2
-rw-r--r--tests/ui/fmt/ifmt-unimpl.stderr2
-rw-r--r--tests/ui/for/for-c-in-str.stderr2
-rw-r--r--tests/ui/for/for-loop-bogosity.stderr2
-rw-r--r--tests/ui/function-pointer/unsized-ret.stderr4
-rw-r--r--tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.current.stderr2
-rw-r--r--tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.next.stderr2
-rw-r--r--tests/ui/generic-associated-types/impl_bounds.stderr4
-rw-r--r--tests/ui/generic-associated-types/issue-101020.stderr2
-rw-r--r--tests/ui/generic-associated-types/issue-74824.current.stderr2
-rw-r--r--tests/ui/generic-associated-types/issue-74824.next.stderr2
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89118.stderr6
-rw-r--r--tests/ui/impl-trait/auto-trait-leak2.stderr4
-rw-r--r--tests/ui/impl-trait/closure-in-type.rs (renamed from tests/crashes/126850.rs)3
-rw-r--r--tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.svg2
-rw-r--r--tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr4
-rw-r--r--tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr12
-rw-r--r--tests/ui/impl-trait/in-trait/return-type-notation.rs9
-rw-r--r--tests/ui/impl-trait/in-trait/return-type-notation.stderr27
-rw-r--r--tests/ui/impl-trait/in-trait/shorthand-projection-in-rpitit-bound.rs13
-rw-r--r--tests/ui/impl-trait/in-trait/variance.rs6
-rw-r--r--tests/ui/impl-trait/in-trait/variance.stderr6
-rw-r--r--tests/ui/impl-trait/issue-55872-1.stderr4
-rw-r--r--tests/ui/impl-trait/nested_impl_trait.stderr4
-rw-r--r--tests/ui/impl-trait/precise-capturing/auxiliary/foreign.rs6
-rw-r--r--tests/ui/impl-trait/precise-capturing/bound-modifiers.rs2
-rw-r--r--tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr32
-rw-r--r--tests/ui/impl-trait/precise-capturing/foreign-2021.rs15
-rw-r--r--tests/ui/impl-trait/precise-capturing/foreign-2021.stderr26
-rw-r--r--tests/ui/impl-trait/precise-capturing/migration-note.rs190
-rw-r--r--tests/ui/impl-trait/precise-capturing/migration-note.stderr284
-rw-r--r--tests/ui/indexing/index-help.stderr2
-rw-r--r--tests/ui/indexing/indexing-requires-a-uint.stderr2
-rw-r--r--tests/ui/indexing/point-at-index-for-obligation-failure.stderr2
-rw-r--r--tests/ui/integral-indexing.stderr16
-rw-r--r--tests/ui/interior-mutability/interior-mutability.stderr2
-rw-r--r--tests/ui/intrinsics/safe-intrinsic-mismatch.effects.stderr7
-rw-r--r--tests/ui/issues/issue-21763.stderr2
-rw-r--r--tests/ui/issues/issue-22872.stderr2
-rw-r--r--tests/ui/issues/issue-22874.stderr2
-rw-r--r--tests/ui/issues/issue-37534.rs3
-rw-r--r--tests/ui/issues/issue-37534.stderr13
-rw-r--r--tests/ui/issues/issue-40827.stderr4
-rw-r--r--tests/ui/issues/issue-7364.stderr2
-rw-r--r--tests/ui/iterators/float_iterator_hint.stderr2
-rw-r--r--tests/ui/iterators/integral.stderr24
-rw-r--r--tests/ui/iterators/issue-28098.stderr4
-rw-r--r--tests/ui/iterators/ranges.stderr4
-rw-r--r--tests/ui/iterators/string.stderr4
-rw-r--r--tests/ui/json/json-bom-plus-crlf-multifile.rs2
-rw-r--r--tests/ui/json/json-bom-plus-crlf.rs2
-rw-r--r--tests/ui/json/json-bom-plus-crlf.stderr8
-rw-r--r--tests/ui/kindck/kindck-impl-type-params-2.stderr2
-rw-r--r--tests/ui/kindck/kindck-impl-type-params.stderr8
-rw-r--r--tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr2
-rw-r--r--tests/ui/kindck/kindck-inherited-copy-bound.dyn_compatible_for_dispatch.stderr2
-rw-r--r--tests/ui/kindck/kindck-nonsendable-1.stderr2
-rw-r--r--tests/ui/kindck/kindck-send-object.stderr4
-rw-r--r--tests/ui/kindck/kindck-send-object1.stderr4
-rw-r--r--tests/ui/kindck/kindck-send-object2.stderr4
-rw-r--r--tests/ui/kindck/kindck-send-owned.stderr2
-rw-r--r--tests/ui/layout/debug.stderr20
-rw-r--r--tests/ui/layout/enum-scalar-pair-int-ptr.rs2
-rw-r--r--tests/ui/layout/enum-scalar-pair-int-ptr.stderr2
-rw-r--r--tests/ui/layout/hexagon-enum.stderr10
-rw-r--r--tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr10
-rw-r--r--tests/ui/layout/issue-96185-overaligned-enum.stderr10
-rw-r--r--tests/ui/layout/struct.rs2
-rw-r--r--tests/ui/layout/struct.stderr2
-rw-r--r--tests/ui/layout/thumb-enum.stderr10
-rw-r--r--tests/ui/layout/zero-sized-array-enum-niche.stderr26
-rw-r--r--tests/ui/lexer/lexer-crlf-line-endings-string-literal-doc-comment.rs1
-rw-r--r--tests/ui/lint/cli-lint-override.forbid_warn.stderr3
-rw-r--r--tests/ui/lint/cli-lint-override.force_warn_deny.stderr3
-rw-r--r--tests/ui/lint/cli-lint-override.warn_deny.stderr3
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate.cdylib_.stderr4
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate.dylib_.stderr4
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate.lib_.stderr4
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate.proc_macro_.stderr4
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rlib_.stderr4
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rs15
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate.staticlib_.stderr4
-rw-r--r--tests/ui/macros/assert-trailing-junk.with-generic-asset.stderr4
-rw-r--r--tests/ui/macros/assert-trailing-junk.without-generic-asset.stderr4
-rw-r--r--tests/ui/macros/best-failure.rs2
-rw-r--r--tests/ui/macros/best-failure.stderr2
-rw-r--r--tests/ui/macros/expr_2021_inline_const.edi2021.stderr4
-rw-r--r--tests/ui/macros/expr_2021_inline_const.edi2024.stderr2
-rw-r--r--tests/ui/macros/expr_2021_inline_const.rs4
-rw-r--r--tests/ui/macros/expr_2024_underscore_expr.edi2021.stderr4
-rw-r--r--tests/ui/macros/expr_2024_underscore_expr.edi2024.stderr2
-rw-r--r--tests/ui/macros/expr_2024_underscore_expr.rs4
-rw-r--r--tests/ui/macros/issue-118786.rs2
-rw-r--r--tests/ui/macros/issue-118786.stderr2
-rw-r--r--tests/ui/macros/issue-30007.rs2
-rw-r--r--tests/ui/macros/issue-30007.stderr2
-rw-r--r--tests/ui/macros/issue-54441.rs2
-rw-r--r--tests/ui/macros/issue-54441.stderr2
-rw-r--r--tests/ui/macros/macro-at-most-once-rep-2015.rs14
-rw-r--r--tests/ui/macros/macro-at-most-once-rep-2015.stderr14
-rw-r--r--tests/ui/macros/macro-at-most-once-rep-2018.rs14
-rw-r--r--tests/ui/macros/macro-at-most-once-rep-2018.stderr14
-rw-r--r--tests/ui/macros/macro-context.rs6
-rw-r--r--tests/ui/macros/macro-context.stderr6
-rw-r--r--tests/ui/macros/macro-in-expression-context.fixed2
-rw-r--r--tests/ui/macros/macro-in-expression-context.rs2
-rw-r--r--tests/ui/macros/macro-in-expression-context.stderr2
-rw-r--r--tests/ui/macros/macro-non-lifetime.rs2
-rw-r--r--tests/ui/macros/macro-non-lifetime.stderr2
-rw-r--r--tests/ui/macros/missing-comma.rs10
-rw-r--r--tests/ui/macros/missing-comma.stderr10
-rw-r--r--tests/ui/macros/nonterminal-matching.rs10
-rw-r--r--tests/ui/macros/nonterminal-matching.stderr14
-rw-r--r--tests/ui/macros/not-utf8.rs2
-rw-r--r--tests/ui/macros/not-utf8.stderr2
-rw-r--r--tests/ui/macros/syntax-error-recovery.rs2
-rw-r--r--tests/ui/macros/syntax-error-recovery.stderr2
-rw-r--r--tests/ui/macros/trace_faulty_macros.stderr2
-rw-r--r--tests/ui/mir/clone-canonicalization-miscompile-132353.rs25
-rw-r--r--tests/ui/mir/mir_let_chains_drop_order.rs1
-rw-r--r--tests/ui/modules/issue-107649.stderr2
-rw-r--r--tests/ui/mut/mutable-enum-indirect.stderr2
-rw-r--r--tests/ui/nll/issue-54556-niconii.edition2021.stderr2
-rw-r--r--tests/ui/nll/issue-54556-niconii.rs2
-rw-r--r--tests/ui/no-send-res-ports.stderr2
-rw-r--r--tests/ui/no_send-enum.stderr2
-rw-r--r--tests/ui/no_share-enum.stderr2
-rw-r--r--tests/ui/not-clone-closure.stderr2
-rw-r--r--tests/ui/not-panic/not-panic-safe-2.stderr4
-rw-r--r--tests/ui/not-panic/not-panic-safe-3.stderr4
-rw-r--r--tests/ui/not-panic/not-panic-safe-4.stderr4
-rw-r--r--tests/ui/not-panic/not-panic-safe-5.stderr2
-rw-r--r--tests/ui/not-panic/not-panic-safe-6.stderr4
-rw-r--r--tests/ui/offset-of/offset-of-arg-count.rs2
-rw-r--r--tests/ui/offset-of/offset-of-arg-count.stderr2
-rw-r--r--tests/ui/offset-of/offset-of-dst-field.stderr2
-rw-r--r--tests/ui/offset-of/offset-of-tuple.stderr2
-rw-r--r--tests/ui/on-unimplemented/slice-index.stderr4
-rw-r--r--tests/ui/or-patterns/or-patterns-syntactic-fail-2018.rs4
-rw-r--r--tests/ui/or-patterns/or-patterns-syntactic-fail-2018.stderr4
-rw-r--r--tests/ui/parser/macro/macro-doc-comments-1.rs2
-rw-r--r--tests/ui/parser/macro/macro-doc-comments-1.stderr2
-rw-r--r--tests/ui/parser/macro/macro-doc-comments-2.rs2
-rw-r--r--tests/ui/parser/macro/macro-doc-comments-2.stderr2
-rw-r--r--tests/ui/parser/macro/macro-expand-to-match-arm.rs2
-rw-r--r--tests/ui/parser/macro/macro-expand-to-match-arm.stderr2
-rw-r--r--tests/ui/parser/macro/macro-incomplete-parse.rs4
-rw-r--r--tests/ui/parser/macro/macro-incomplete-parse.stderr4
-rw-r--r--tests/ui/parser/macro/trait-non-item-macros.rs2
-rw-r--r--tests/ui/parser/macro/trait-non-item-macros.stderr2
-rw-r--r--tests/ui/parser/shebang/issue-71471-ignore-tidy.rs2
-rw-r--r--tests/ui/parser/shebang/multiline-attrib.rs1
-rw-r--r--tests/ui/parser/shebang/regular-attrib.rs1
-rw-r--r--tests/ui/parser/shebang/shebang-and-attrib.rs1
-rw-r--r--tests/ui/parser/shebang/shebang-comment.rs1
-rw-r--r--tests/ui/parser/shebang/shebang-doc-comment.rs2
-rw-r--r--tests/ui/parser/shebang/shebang-empty.rs1
-rw-r--r--tests/ui/parser/shebang/shebang-must-start-file.rs2
-rw-r--r--tests/ui/parser/shebang/shebang-space.rs1
-rw-r--r--tests/ui/parser/shebang/sneaky-attrib.rs1
-rw-r--r--tests/ui/parser/shebang/valid-shebang.rs1
-rw-r--r--tests/ui/parser/struct-literal-in-for.stderr2
-rw-r--r--tests/ui/parser/utf16-be-without-bom.rsbin127 -> 162 bytes
-rw-r--r--tests/ui/parser/utf16-be-without-bom.stderr28
-rw-r--r--tests/ui/parser/utf16-le-without-bom.rsbin128 -> 163 bytes
-rw-r--r--tests/ui/parser/utf16-le-without-bom.stderr28
-rw-r--r--tests/ui/proc-macro/attr-invalid-exprs.rs4
-rw-r--r--tests/ui/proc-macro/attr-invalid-exprs.stderr4
-rw-r--r--tests/ui/proc-macro/expand-expr.rs4
-rw-r--r--tests/ui/proc-macro/expand-expr.stderr4
-rw-r--r--tests/ui/range/range-1.stderr2
-rw-r--r--tests/ui/recursion/recursive-requirements.stderr4
-rw-r--r--tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr4
-rw-r--r--tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr4
-rw-r--r--tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr4
-rw-r--r--tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr4
-rw-r--r--tests/ui/repr/repr-c-int-dead-variants.stderr4
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr2
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs2
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr2
-rw-r--r--tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr2
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.rs2
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.stderr2
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/irrefutable-lets.disallowed.stderr20
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/irrefutable-lets.rs20
-rw-r--r--tests/ui/self/arbitrary-self-from-method-substs-ice.rs2
-rw-r--r--tests/ui/self/arbitrary-self-from-method-substs-ice.stderr10
-rw-r--r--tests/ui/self/arbitrary-self-from-method-substs.default.stderr162
-rw-r--r--tests/ui/self/arbitrary-self-from-method-substs.feature.stderr176
-rw-r--r--tests/ui/self/arbitrary-self-from-method-substs.rs94
-rw-r--r--tests/ui/specialization/min_specialization/issue-79224.stderr8
-rw-r--r--tests/ui/statics/unsized_type2.stderr4
-rw-r--r--tests/ui/statics/unsizing-wfcheck-issue-127299.stderr2
-rw-r--r--tests/ui/str/str-idx.stderr4
-rw-r--r--tests/ui/str/str-mut-idx.stderr4
-rw-r--r--tests/ui/suggestions/derive-clone-for-eq.stderr2
-rw-r--r--tests/ui/suggestions/derive-macro-missing-bounds.stderr10
-rw-r--r--tests/ui/suggestions/into-str.stderr2
-rw-r--r--tests/ui/suggestions/issue-71394-no-from-impl.stderr2
-rw-r--r--tests/ui/suggestions/issue-88696.stderr2
-rw-r--r--tests/ui/suggestions/issue-96223.stderr2
-rw-r--r--tests/ui/suggestions/issue-96555.stderr6
-rw-r--r--tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr4
-rw-r--r--tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr4
-rw-r--r--tests/ui/suggestions/path-by-value.stderr2
-rw-r--r--tests/ui/suggestions/path-display.stderr2
-rw-r--r--tests/ui/suggestions/suggest-dereferencing-index.stderr2
-rw-r--r--tests/ui/suggestions/suggest-pin-macro.stderr2
-rw-r--r--tests/ui/suggestions/suggest-remove-refs-1.stderr2
-rw-r--r--tests/ui/suggestions/suggest-remove-refs-2.stderr2
-rw-r--r--tests/ui/suggestions/suggest-remove-refs-3.stderr2
-rw-r--r--tests/ui/suggestions/suggest-remove-refs-4.stderr2
-rw-r--r--tests/ui/suggestions/suggest-remove-refs-5.stderr4
-rw-r--r--tests/ui/sync/mutexguard-sync.stderr2
-rw-r--r--tests/ui/sync/reentrantlockguard-sync.stderr2
-rw-r--r--tests/ui/thir-print/thir-tree-match.stdout46
-rw-r--r--tests/ui/trait-bounds/maybe-bound-generics-deny.rs4
-rw-r--r--tests/ui/trait-bounds/maybe-bound-generics-deny.stderr11
-rw-r--r--tests/ui/trait-bounds/maybe-bound-has-path-args.rs7
-rw-r--r--tests/ui/trait-bounds/maybe-bound-has-path-args.stderr17
-rw-r--r--tests/ui/trait-bounds/maybe-bound-with-assoc.rs12
-rw-r--r--tests/ui/trait-bounds/maybe-bound-with-assoc.stderr21
-rw-r--r--tests/ui/trait-bounds/super-assoc-mismatch.stderr4
-rw-r--r--tests/ui/traits/alias/cross-crate.stderr4
-rw-r--r--tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr2
-rw-r--r--tests/ui/traits/bound/assoc-fn-bound-root-obligation.rs2
-rw-r--r--tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr2
-rw-r--r--tests/ui/traits/const-traits/const-bounds-non-const-trait.stderr7
-rw-r--r--tests/ui/traits/const-traits/const-drop.precise.stderr28
-rw-r--r--tests/ui/traits/const-traits/const-drop.stock.stderr28
-rw-r--r--tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.stderr7
-rw-r--r--tests/ui/traits/const-traits/const_derives/derive-const-use.stderr7
-rw-r--r--tests/ui/traits/const-traits/const_derives/derive-const-with-params.stderr7
-rw-r--r--tests/ui/traits/const-traits/do-not-const-check.rs3
-rw-r--r--tests/ui/traits/const-traits/do-not-const-check.stderr11
-rw-r--r--tests/ui/traits/const-traits/effects/ice-112822-expected-type-for-param.stderr7
-rw-r--r--tests/ui/traits/const-traits/effects/no-explicit-const-params.rs1
-rw-r--r--tests/ui/traits/const-traits/effects/no-explicit-const-params.stderr14
-rw-r--r--tests/ui/traits/const-traits/effects/span-bug-issue-121418.stderr9
-rw-r--r--tests/ui/traits/const-traits/effects/spec-effectvar-ice.stderr7
-rw-r--r--tests/ui/traits/const-traits/effects/trait-fn-const.stderr7
-rw-r--r--tests/ui/traits/const-traits/effects/with-without-next-solver.coherence.stderr7
-rw-r--r--tests/ui/traits/const-traits/effects/with-without-next-solver.rs10
-rw-r--r--tests/ui/traits/const-traits/effects/with-without-next-solver.stock.stderr7
-rw-r--r--tests/ui/traits/const-traits/ice-119717-constant-lifetime.stderr7
-rw-r--r--tests/ui/traits/const-traits/ice-120503-async-const-method.stderr7
-rw-r--r--tests/ui/traits/const-traits/ice-121536-const-method.stderr7
-rw-r--r--tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.stderr7
-rw-r--r--tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.stderr7
-rw-r--r--tests/ui/traits/const-traits/ice-126148-failed-to-normalize.stderr7
-rw-r--r--tests/ui/traits/const-traits/impl-with-default-fn-fail.stderr7
-rw-r--r--tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.stderr7
-rw-r--r--tests/ui/traits/const-traits/specializing-constness.stderr7
-rw-r--r--tests/ui/traits/const-traits/tilde-const-and-const-params.rs2
-rw-r--r--tests/ui/traits/const-traits/tilde-const-and-const-params.stderr20
-rw-r--r--tests/ui/traits/copy-impl-cannot-normalize.stderr2
-rw-r--r--tests/ui/traits/dont-autoderef-ty-with-escaping-var.stderr2
-rw-r--r--tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr2
-rw-r--r--tests/ui/traits/issue-43784-supertrait.stderr2
-rw-r--r--tests/ui/traits/issue-7013.stderr2
-rw-r--r--tests/ui/traits/issue-71036.stderr2
-rw-r--r--tests/ui/traits/issue-71136.stderr2
-rw-r--r--tests/ui/traits/issue-91594.stderr2
-rw-r--r--tests/ui/traits/issue-97576.stderr2
-rw-r--r--tests/ui/traits/negative-impls/negated-auto-traits-error.stderr6
-rw-r--r--tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr2
-rw-r--r--tests/ui/traits/next-solver/builtin-fn-must-return-sized.stderr2
-rw-r--r--tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.with.stderr2
-rw-r--r--tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.without.stderr2
-rw-r--r--tests/ui/traits/next-solver/diagnostics/point-at-failing-nested.stderr2
-rw-r--r--tests/ui/traits/next-solver/diagnostics/where-clause-doesnt-apply.stderr2
-rw-r--r--tests/ui/traits/next-solver/dyn-incompatibility.stderr4
-rw-r--r--tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr2
-rw-r--r--tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr4
-rw-r--r--tests/ui/traits/question-mark-result-err-mismatch.stderr6
-rw-r--r--tests/ui/traits/suggest-dereferences/dont-suggest-unsize-deref.stderr2
-rw-r--r--tests/ui/traits/suggest-dereferences/invalid-suggest-deref-issue-127590.stderr8
-rw-r--r--tests/ui/traits/suggest-dereferences/issue-39029.stderr2
-rw-r--r--tests/ui/traits/suggest-dereferences/root-obligation.stderr2
-rw-r--r--tests/ui/traits/suggest-dereferences/suggest-dereferencing-receiver-argument.stderr2
-rw-r--r--tests/ui/traits/unsend-future.stderr2
-rw-r--r--tests/ui/try-block/try-block-bad-type.stderr2
-rw-r--r--tests/ui/try-trait/bad-interconversion.stderr2
-rw-r--r--tests/ui/try-trait/issue-32709.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/auto-trait-leakage2.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/escaping-bound-var.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/escaping-bound-var.stderr14
-rw-r--r--tests/ui/type-alias-impl-trait/issue-57700.rs21
-rw-r--r--tests/ui/type-alias-impl-trait/issue-57700.stderr8
-rw-r--r--tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/underconstrained_generic.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/variance.rs16
-rw-r--r--tests/ui/type-alias-impl-trait/variance.stderr16
-rw-r--r--tests/ui/type/issue-58355.stderr2
-rw-r--r--tests/ui/type/pattern_types/range_patterns.stderr4
-rw-r--r--tests/ui/typeck/bad-index-due-to-nested.stderr4
-rw-r--r--tests/ui/typeck/issue-90101.stderr2
-rw-r--r--tests/ui/typeck/suggest-similar-impls-for-root-obligation.stderr2
-rw-r--r--tests/ui/typeck/typeck-default-trait-impl-negation-sync.stderr4
-rw-r--r--tests/ui/typeck/typeck-unsafe-always-share.stderr2
-rw-r--r--tests/ui/underscore-ident-matcher.rs2
-rw-r--r--tests/ui/underscore-ident-matcher.stderr2
-rw-r--r--tests/ui/union/projection-as-union-type-error-2.stderr2
-rw-r--r--tests/ui/unsized-locals/issue-50940-with-feature.stderr2
-rw-r--r--tests/ui/unsized-locals/rust-call.stderr2
-rw-r--r--tests/ui/unsized-locals/unsized-exprs.stderr6
-rw-r--r--tests/ui/unsized/unsized-enum2.stderr8
-rw-r--r--tests/ui/utf8-bom.rs1
-rw-r--r--tests/ui/wf/hir-wf-check-erase-regions.stderr6
-rw-r--r--tests/ui/wf/wf-const-type.stderr6
-rw-r--r--tests/ui/wf/wf-static-type.stderr6
-rw-r--r--triagebot.toml7
906 files changed, 8788 insertions, 6525 deletions
diff --git a/Cargo.lock b/Cargo.lock
index f0e035c025e..9fa1daf6546 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -720,6 +720,7 @@ dependencies = [
  "miropt-test-tools",
  "regex",
  "rustfix",
+ "semver",
  "serde",
  "serde_json",
  "tracing",
@@ -3203,9 +3204,11 @@ dependencies = [
  "rand",
  "rand_xoshiro",
  "rustc_data_structures",
+ "rustc_feature",
  "rustc_index",
  "rustc_macros",
  "rustc_serialize",
+ "rustc_span",
  "tracing",
 ]
 
@@ -3301,6 +3304,7 @@ version = "0.0.0"
 dependencies = [
  "itertools",
  "rustc_ast",
+ "rustc_data_structures",
  "rustc_lexer",
  "rustc_span",
  "thin-vec",
@@ -3621,6 +3625,7 @@ version = "0.0.0"
 dependencies = [
  "annotate-snippets 0.11.4",
  "derive_setters",
+ "rustc_abi",
  "rustc_ast",
  "rustc_ast_pretty",
  "rustc_data_structures",
@@ -3718,6 +3723,7 @@ name = "rustc_hir_analysis"
 version = "0.0.0"
 dependencies = [
  "itertools",
+ "rustc_abi",
  "rustc_arena",
  "rustc_ast",
  "rustc_attr",
@@ -3745,11 +3751,11 @@ dependencies = [
 name = "rustc_hir_pretty"
 version = "0.0.0"
 dependencies = [
+ "rustc_abi",
  "rustc_ast",
  "rustc_ast_pretty",
  "rustc_hir",
  "rustc_span",
- "rustc_target",
 ]
 
 [[package]]
@@ -3906,6 +3912,7 @@ dependencies = [
 name = "rustc_lint"
 version = "0.0.0"
 dependencies = [
+ "rustc_abi",
  "rustc_ast",
  "rustc_ast_pretty",
  "rustc_attr",
@@ -3933,6 +3940,7 @@ dependencies = [
 name = "rustc_lint_defs"
 version = "0.0.0"
 dependencies = [
+ "rustc_abi",
  "rustc_ast",
  "rustc_data_structures",
  "rustc_error_messages",
@@ -3940,7 +3948,6 @@ dependencies = [
  "rustc_macros",
  "rustc_serialize",
  "rustc_span",
- "rustc_target",
  "serde",
 ]
 
@@ -3980,6 +3987,7 @@ dependencies = [
  "bitflags 2.6.0",
  "libloading",
  "odht",
+ "rustc_abi",
  "rustc_ast",
  "rustc_attr",
  "rustc_data_structures",
@@ -3998,7 +4006,6 @@ dependencies = [
  "rustc_span",
  "rustc_target",
  "rustc_type_ir",
- "snap",
  "tempfile",
  "tracing",
 ]
@@ -4048,6 +4055,7 @@ version = "0.0.0"
 dependencies = [
  "either",
  "itertools",
+ "rustc_abi",
  "rustc_apfloat",
  "rustc_arena",
  "rustc_ast",
@@ -4063,7 +4071,6 @@ dependencies = [
  "rustc_pattern_analysis",
  "rustc_session",
  "rustc_span",
- "rustc_target",
  "rustc_trait_selection",
  "tracing",
 ]
@@ -4074,6 +4081,7 @@ version = "0.0.0"
 dependencies = [
  "polonius-engine",
  "regex",
+ "rustc_abi",
  "rustc_ast",
  "rustc_data_structures",
  "rustc_errors",
@@ -4095,6 +4103,7 @@ version = "0.0.0"
 dependencies = [
  "either",
  "itertools",
+ "rustc_abi",
  "rustc_arena",
  "rustc_ast",
  "rustc_attr",
@@ -4187,6 +4196,7 @@ dependencies = [
 name = "rustc_passes"
 version = "0.0.0"
 dependencies = [
+ "rustc_abi",
  "rustc_ast",
  "rustc_ast_pretty",
  "rustc_attr",
@@ -4213,6 +4223,7 @@ name = "rustc_pattern_analysis"
 version = "0.0.0"
 dependencies = [
  "rustc-hash 2.0.0",
+ "rustc_abi",
  "rustc_apfloat",
  "rustc_arena",
  "rustc_data_structures",
@@ -4352,6 +4363,7 @@ dependencies = [
  "bitflags 2.6.0",
  "getopts",
  "libc",
+ "rustc_abi",
  "rustc_ast",
  "rustc_data_structures",
  "rustc_errors",
@@ -4415,6 +4427,7 @@ version = "0.0.0"
 dependencies = [
  "punycode",
  "rustc-demangle",
+ "rustc_abi",
  "rustc_data_structures",
  "rustc_errors",
  "rustc_hir",
@@ -4878,12 +4891,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
 
 [[package]]
-name = "snap"
-version = "1.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b"
-
-[[package]]
 name = "socket2"
 version = "0.5.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/compiler/rustc_abi/Cargo.toml b/compiler/rustc_abi/Cargo.toml
index 7448f066d0a..3acd25e5461 100644
--- a/compiler/rustc_abi/Cargo.toml
+++ b/compiler/rustc_abi/Cargo.toml
@@ -9,9 +9,11 @@ bitflags = "2.4.1"
 rand = { version = "0.8.4", default-features = false, optional = true }
 rand_xoshiro = { version = "0.6.0", optional = true }
 rustc_data_structures = { path = "../rustc_data_structures", optional = true  }
+rustc_feature = { path = "../rustc_feature", optional = true }
 rustc_index = { path = "../rustc_index", default-features = false }
 rustc_macros = { path = "../rustc_macros", optional = true }
 rustc_serialize = { path = "../rustc_serialize", optional = true  }
+rustc_span = { path = "../rustc_span", optional = true }
 tracing = "0.1"
 # tidy-alphabetical-end
 
@@ -22,8 +24,10 @@ default = ["nightly", "randomize"]
 # without depending on rustc_data_structures, rustc_macros and rustc_serialize
 nightly = [
     "dep:rustc_data_structures",
+    "dep:rustc_feature",
     "dep:rustc_macros",
     "dep:rustc_serialize",
+    "dep:rustc_span",
     "rustc_index/nightly",
 ]
 randomize = ["dep:rand", "dep:rand_xoshiro", "nightly"]
diff --git a/compiler/rustc_abi/src/callconv.rs b/compiler/rustc_abi/src/callconv.rs
index 872cae59a4e..ee63e46e88c 100644
--- a/compiler/rustc_abi/src/callconv.rs
+++ b/compiler/rustc_abi/src/callconv.rs
@@ -6,9 +6,9 @@ mod abi {
 #[cfg(feature = "nightly")]
 use rustc_macros::HashStable_Generic;
 
-#[cfg(feature = "nightly")]
-use crate::{Abi, FieldsShape, TyAbiInterface, TyAndLayout};
 use crate::{Align, HasDataLayout, Size};
+#[cfg(feature = "nightly")]
+use crate::{BackendRepr, FieldsShape, TyAbiInterface, TyAndLayout};
 
 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
@@ -128,11 +128,11 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
     where
         Ty: TyAbiInterface<'a, C> + Copy,
     {
-        match self.abi {
-            Abi::Uninhabited => Err(Heterogeneous),
+        match self.backend_repr {
+            BackendRepr::Uninhabited => Err(Heterogeneous),
 
             // The primitive for this algorithm.
-            Abi::Scalar(scalar) => {
+            BackendRepr::Scalar(scalar) => {
                 let kind = match scalar.primitive() {
                     abi::Int(..) | abi::Pointer(_) => RegKind::Integer,
                     abi::Float(_) => RegKind::Float,
@@ -140,7 +140,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
                 Ok(HomogeneousAggregate::Homogeneous(Reg { kind, size: self.size }))
             }
 
-            Abi::Vector { .. } => {
+            BackendRepr::Vector { .. } => {
                 assert!(!self.is_zst());
                 Ok(HomogeneousAggregate::Homogeneous(Reg {
                     kind: RegKind::Vector,
@@ -148,7 +148,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
                 }))
             }
 
-            Abi::ScalarPair(..) | Abi::Aggregate { sized: true } => {
+            BackendRepr::ScalarPair(..) | BackendRepr::Memory { sized: true } => {
                 // Helper for computing `homogeneous_aggregate`, allowing a custom
                 // starting offset (used below for handling variants).
                 let from_fields_at =
@@ -246,7 +246,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
                     Ok(result)
                 }
             }
-            Abi::Aggregate { sized: false } => Err(Heterogeneous),
+            BackendRepr::Memory { sized: false } => Err(Heterogeneous),
         }
     }
 }
diff --git a/compiler/rustc_target/src/spec/abi/mod.rs b/compiler/rustc_abi/src/extern_abi/mod.rs
index c2095155afa..f7e41280131 100644
--- a/compiler/rustc_target/src/spec/abi/mod.rs
+++ b/compiler/rustc_abi/src/extern_abi/mod.rs
@@ -7,9 +7,11 @@ use rustc_span::{Span, Symbol};
 #[cfg(test)]
 mod tests;
 
+use ExternAbi as Abi;
+
 #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug)]
 #[derive(HashStable_Generic, Encodable, Decodable)]
-pub enum Abi {
+pub enum ExternAbi {
     // Some of the ABIs come first because every time we add a new ABI, we have to re-bless all the
     // hashing tests. These are used in many places, so giving them stable values reduces test
     // churn. The specific values are meaningless.
diff --git a/compiler/rustc_target/src/spec/abi/tests.rs b/compiler/rustc_abi/src/extern_abi/tests.rs
index 4823058dd69..4823058dd69 100644
--- a/compiler/rustc_target/src/spec/abi/tests.rs
+++ b/compiler/rustc_abi/src/extern_abi/tests.rs
diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs
index 141a15b99a3..e6d66f608da 100644
--- a/compiler/rustc_abi/src/layout.rs
+++ b/compiler/rustc_abi/src/layout.rs
@@ -6,7 +6,7 @@ use rustc_index::Idx;
 use tracing::debug;
 
 use crate::{
-    Abi, AbiAndPrefAlign, Align, FieldsShape, HasDataLayout, IndexSlice, IndexVec, Integer,
+    AbiAndPrefAlign, Align, BackendRepr, FieldsShape, HasDataLayout, IndexSlice, IndexVec, Integer,
     LayoutData, Niche, NonZeroUsize, Primitive, ReprOptions, Scalar, Size, StructKind, TagEncoding,
     Variants, WrappingRange,
 };
@@ -28,7 +28,7 @@ where
     VariantIdx: Idx,
     F: Deref<Target = &'a LayoutData<FieldIdx, VariantIdx>> + fmt::Debug,
 {
-    let uninhabited = fields.iter().any(|f| f.abi.is_uninhabited());
+    let uninhabited = fields.iter().any(|f| f.is_uninhabited());
     // We cannot ignore alignment; that might lead us to entirely discard a variant and
     // produce an enum that is less aligned than it should be!
     let is_1zst = fields.iter().all(|f| f.is_1zst());
@@ -125,7 +125,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
                 offsets: [Size::ZERO, b_offset].into(),
                 memory_index: [0, 1].into(),
             },
-            abi: Abi::ScalarPair(a, b),
+            backend_repr: BackendRepr::ScalarPair(a, b),
             largest_niche,
             align,
             size,
@@ -216,7 +216,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
         LayoutData {
             variants: Variants::Single { index: VariantIdx::new(0) },
             fields: FieldsShape::Primitive,
-            abi: Abi::Uninhabited,
+            backend_repr: BackendRepr::Uninhabited,
             largest_niche: None,
             align: dl.i8_align,
             size: Size::ZERO,
@@ -331,7 +331,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
 
             if let Ok(common) = common_non_zst_abi_and_align {
                 // Discard valid range information and allow undef
-                let field_abi = field.abi.to_union();
+                let field_abi = field.backend_repr.to_union();
 
                 if let Some((common_abi, common_align)) = common {
                     if common_abi != field_abi {
@@ -340,7 +340,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
                     } else {
                         // Fields with the same non-Aggregate ABI should also
                         // have the same alignment
-                        if !matches!(common_abi, Abi::Aggregate { .. }) {
+                        if !matches!(common_abi, BackendRepr::Memory { .. }) {
                             assert_eq!(
                                 common_align, field.align.abi,
                                 "non-Aggregate field with matching ABI but differing alignment"
@@ -369,11 +369,11 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
         // If all non-ZST fields have the same ABI, we may forward that ABI
         // for the union as a whole, unless otherwise inhibited.
         let abi = match common_non_zst_abi_and_align {
-            Err(AbiMismatch) | Ok(None) => Abi::Aggregate { sized: true },
+            Err(AbiMismatch) | Ok(None) => BackendRepr::Memory { sized: true },
             Ok(Some((abi, _))) => {
                 if abi.inherent_align(dl).map(|a| a.abi) != Some(align.abi) {
                     // Mismatched alignment (e.g. union is #[repr(packed)]): disable opt
-                    Abi::Aggregate { sized: true }
+                    BackendRepr::Memory { sized: true }
                 } else {
                     abi
                 }
@@ -387,7 +387,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
         Ok(LayoutData {
             variants: Variants::Single { index: only_variant_idx },
             fields: FieldsShape::Union(union_field_count),
-            abi,
+            backend_repr: abi,
             largest_niche: None,
             align,
             size: size.align_to(align.abi),
@@ -434,23 +434,23 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
                 // Already doesn't have any niches
                 Scalar::Union { .. } => {}
             };
-            match &mut st.abi {
-                Abi::Uninhabited => {}
-                Abi::Scalar(scalar) => hide_niches(scalar),
-                Abi::ScalarPair(a, b) => {
+            match &mut st.backend_repr {
+                BackendRepr::Uninhabited => {}
+                BackendRepr::Scalar(scalar) => hide_niches(scalar),
+                BackendRepr::ScalarPair(a, b) => {
                     hide_niches(a);
                     hide_niches(b);
                 }
-                Abi::Vector { element, count: _ } => hide_niches(element),
-                Abi::Aggregate { sized: _ } => {}
+                BackendRepr::Vector { element, count: _ } => hide_niches(element),
+                BackendRepr::Memory { sized: _ } => {}
             }
             st.largest_niche = None;
             return Ok(st);
         }
 
         let (start, end) = scalar_valid_range;
-        match st.abi {
-            Abi::Scalar(ref mut scalar) | Abi::ScalarPair(ref mut scalar, _) => {
+        match st.backend_repr {
+            BackendRepr::Scalar(ref mut scalar) | BackendRepr::ScalarPair(ref mut scalar, _) => {
                 // Enlarging validity ranges would result in missed
                 // optimizations, *not* wrongly assuming the inner
                 // value is valid. e.g. unions already enlarge validity ranges,
@@ -607,8 +607,8 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
                 }
 
                 // It can't be a Scalar or ScalarPair because the offset isn't 0.
-                if !layout.abi.is_uninhabited() {
-                    layout.abi = Abi::Aggregate { sized: true };
+                if !layout.is_uninhabited() {
+                    layout.backend_repr = BackendRepr::Memory { sized: true };
                 }
                 layout.size += this_offset;
 
@@ -627,26 +627,26 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
             let same_size = size == variant_layouts[largest_variant_index].size;
             let same_align = align == variant_layouts[largest_variant_index].align;
 
-            let abi = if variant_layouts.iter().all(|v| v.abi.is_uninhabited()) {
-                Abi::Uninhabited
+            let abi = if variant_layouts.iter().all(|v| v.is_uninhabited()) {
+                BackendRepr::Uninhabited
             } else if same_size && same_align && others_zst {
-                match variant_layouts[largest_variant_index].abi {
+                match variant_layouts[largest_variant_index].backend_repr {
                     // When the total alignment and size match, we can use the
                     // same ABI as the scalar variant with the reserved niche.
-                    Abi::Scalar(_) => Abi::Scalar(niche_scalar),
-                    Abi::ScalarPair(first, second) => {
+                    BackendRepr::Scalar(_) => BackendRepr::Scalar(niche_scalar),
+                    BackendRepr::ScalarPair(first, second) => {
                         // Only the niche is guaranteed to be initialised,
                         // so use union layouts for the other primitive.
                         if niche_offset == Size::ZERO {
-                            Abi::ScalarPair(niche_scalar, second.to_union())
+                            BackendRepr::ScalarPair(niche_scalar, second.to_union())
                         } else {
-                            Abi::ScalarPair(first.to_union(), niche_scalar)
+                            BackendRepr::ScalarPair(first.to_union(), niche_scalar)
                         }
                     }
-                    _ => Abi::Aggregate { sized: true },
+                    _ => BackendRepr::Memory { sized: true },
                 }
             } else {
-                Abi::Aggregate { sized: true }
+                BackendRepr::Memory { sized: true }
             };
 
             let layout = LayoutData {
@@ -664,7 +664,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
                     offsets: [niche_offset].into(),
                     memory_index: [0].into(),
                 },
-                abi,
+                backend_repr: abi,
                 largest_niche,
                 size,
                 align,
@@ -681,7 +681,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
         let discr_type = repr.discr_type();
         let bits = Integer::from_attr(dl, discr_type).size().bits();
         for (i, mut val) in discriminants {
-            if !repr.c() && variants[i].iter().any(|f| f.abi.is_uninhabited()) {
+            if !repr.c() && variants[i].iter().any(|f| f.is_uninhabited()) {
                 continue;
             }
             if discr_type.is_signed() {
@@ -833,14 +833,14 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
                 end: (max as u128 & tag_mask),
             },
         };
-        let mut abi = Abi::Aggregate { sized: true };
+        let mut abi = BackendRepr::Memory { sized: true };
 
-        if layout_variants.iter().all(|v| v.abi.is_uninhabited()) {
-            abi = Abi::Uninhabited;
+        if layout_variants.iter().all(|v| v.is_uninhabited()) {
+            abi = BackendRepr::Uninhabited;
         } else if tag.size(dl) == size {
             // Make sure we only use scalar layout when the enum is entirely its
             // own tag (i.e. it has no padding nor any non-ZST variant fields).
-            abi = Abi::Scalar(tag);
+            abi = BackendRepr::Scalar(tag);
         } else {
             // Try to use a ScalarPair for all tagged enums.
             // That's possible only if we can find a common primitive type for all variants.
@@ -864,8 +864,8 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
                         break;
                     }
                 };
-                let prim = match field.abi {
-                    Abi::Scalar(scalar) => {
+                let prim = match field.backend_repr {
+                    BackendRepr::Scalar(scalar) => {
                         common_prim_initialized_in_all_variants &=
                             matches!(scalar, Scalar::Initialized { .. });
                         scalar.primitive()
@@ -934,7 +934,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
                 {
                     // We can use `ScalarPair` only when it matches our
                     // already computed layout (including `#[repr(C)]`).
-                    abi = pair.abi;
+                    abi = pair.backend_repr;
                 }
             }
         }
@@ -942,12 +942,14 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
         // If we pick a "clever" (by-value) ABI, we might have to adjust the ABI of the
         // variants to ensure they are consistent. This is because a downcast is
         // semantically a NOP, and thus should not affect layout.
-        if matches!(abi, Abi::Scalar(..) | Abi::ScalarPair(..)) {
+        if matches!(abi, BackendRepr::Scalar(..) | BackendRepr::ScalarPair(..)) {
             for variant in &mut layout_variants {
                 // We only do this for variants with fields; the others are not accessed anyway.
                 // Also do not overwrite any already existing "clever" ABIs.
-                if variant.fields.count() > 0 && matches!(variant.abi, Abi::Aggregate { .. }) {
-                    variant.abi = abi;
+                if variant.fields.count() > 0
+                    && matches!(variant.backend_repr, BackendRepr::Memory { .. })
+                {
+                    variant.backend_repr = abi;
                     // Also need to bump up the size and alignment, so that the entire value fits
                     // in here.
                     variant.size = cmp::max(variant.size, size);
@@ -970,7 +972,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
                 memory_index: [0].into(),
             },
             largest_niche,
-            abi,
+            backend_repr: abi,
             align,
             size,
             max_repr_align,
@@ -1252,7 +1254,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
         }
         let mut layout_of_single_non_zst_field = None;
         let sized = unsized_field.is_none();
-        let mut abi = Abi::Aggregate { sized };
+        let mut abi = BackendRepr::Memory { sized };
 
         let optimize_abi = !repr.inhibit_newtype_abi_optimization();
 
@@ -1270,16 +1272,16 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
                     // Field fills the struct and it has a scalar or scalar pair ABI.
                     if offsets[i].bytes() == 0 && align.abi == field.align.abi && size == field.size
                     {
-                        match field.abi {
+                        match field.backend_repr {
                             // For plain scalars, or vectors of them, we can't unpack
                             // newtypes for `#[repr(C)]`, as that affects C ABIs.
-                            Abi::Scalar(_) | Abi::Vector { .. } if optimize_abi => {
-                                abi = field.abi;
+                            BackendRepr::Scalar(_) | BackendRepr::Vector { .. } if optimize_abi => {
+                                abi = field.backend_repr;
                             }
                             // But scalar pairs are Rust-specific and get
                             // treated as aggregates by C ABIs anyway.
-                            Abi::ScalarPair(..) => {
-                                abi = field.abi;
+                            BackendRepr::ScalarPair(..) => {
+                                abi = field.backend_repr;
                             }
                             _ => {}
                         }
@@ -1288,8 +1290,8 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
 
                 // Two non-ZST fields, and they're both scalars.
                 (Some((i, a)), Some((j, b)), None) => {
-                    match (a.abi, b.abi) {
-                        (Abi::Scalar(a), Abi::Scalar(b)) => {
+                    match (a.backend_repr, b.backend_repr) {
+                        (BackendRepr::Scalar(a), BackendRepr::Scalar(b)) => {
                             // Order by the memory placement, not source order.
                             let ((i, a), (j, b)) = if offsets[i] < offsets[j] {
                                 ((i, a), (j, b))
@@ -1315,7 +1317,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
                             {
                                 // We can use `ScalarPair` only when it matches our
                                 // already computed layout (including `#[repr(C)]`).
-                                abi = pair.abi;
+                                abi = pair.backend_repr;
                             }
                         }
                         _ => {}
@@ -1325,8 +1327,8 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
                 _ => {}
             }
         }
-        if fields.iter().any(|f| f.abi.is_uninhabited()) {
-            abi = Abi::Uninhabited;
+        if fields.iter().any(|f| f.is_uninhabited()) {
+            abi = BackendRepr::Uninhabited;
         }
 
         let unadjusted_abi_align = if repr.transparent() {
@@ -1344,7 +1346,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
         Ok(LayoutData {
             variants: Variants::Single { index: VariantIdx::new(0) },
             fields: FieldsShape::Arbitrary { offsets, memory_index },
-            abi,
+            backend_repr: abi,
             largest_niche,
             align,
             size,
diff --git a/compiler/rustc_abi/src/layout/ty.rs b/compiler/rustc_abi/src/layout/ty.rs
index e029e1426b2..062447ea03f 100644
--- a/compiler/rustc_abi/src/layout/ty.rs
+++ b/compiler/rustc_abi/src/layout/ty.rs
@@ -83,8 +83,8 @@ impl<'a> Layout<'a> {
         &self.0.0.variants
     }
 
-    pub fn abi(self) -> Abi {
-        self.0.0.abi
+    pub fn backend_repr(self) -> BackendRepr {
+        self.0.0.backend_repr
     }
 
     pub fn largest_niche(self) -> Option<Niche> {
@@ -114,7 +114,7 @@ impl<'a> Layout<'a> {
     pub fn is_pointer_like(self, data_layout: &TargetDataLayout) -> bool {
         self.size() == data_layout.pointer_size
             && self.align().abi == data_layout.pointer_align.abi
-            && matches!(self.abi(), Abi::Scalar(Scalar::Initialized { .. }))
+            && matches!(self.backend_repr(), BackendRepr::Scalar(Scalar::Initialized { .. }))
     }
 }
 
@@ -196,9 +196,9 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
         Ty: TyAbiInterface<'a, C>,
         C: HasDataLayout,
     {
-        match self.abi {
-            Abi::Scalar(scalar) => matches!(scalar.primitive(), Float(F32 | F64)),
-            Abi::Aggregate { .. } => {
+        match self.backend_repr {
+            BackendRepr::Scalar(scalar) => matches!(scalar.primitive(), Float(F32 | F64)),
+            BackendRepr::Memory { .. } => {
                 if self.fields.count() == 1 && self.fields.offset(0).bytes() == 0 {
                     self.field(cx, 0).is_single_fp_element(cx)
                 } else {
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index b54efa4bb48..ec758785173 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -1,6 +1,7 @@
 // tidy-alphabetical-start
 #![cfg_attr(feature = "nightly", allow(internal_features))]
 #![cfg_attr(feature = "nightly", doc(rust_logo))]
+#![cfg_attr(feature = "nightly", feature(assert_matches))]
 #![cfg_attr(feature = "nightly", feature(rustc_attrs))]
 #![cfg_attr(feature = "nightly", feature(rustdoc_internals))]
 #![cfg_attr(feature = "nightly", feature(step_trait))]
@@ -28,8 +29,15 @@ mod layout;
 #[cfg(test)]
 mod tests;
 
+#[cfg(feature = "nightly")]
+mod extern_abi;
+
 pub use callconv::{Heterogeneous, HomogeneousAggregate, Reg, RegKind};
 #[cfg(feature = "nightly")]
+pub use extern_abi::{
+    AbiDisabled, AbiUnsupported, ExternAbi, all_names, enabled_names, is_enabled, is_stable, lookup,
+};
+#[cfg(feature = "nightly")]
 pub use layout::{FIRST_VARIANT, FieldIdx, Layout, TyAbiInterface, TyAndLayout, VariantIdx};
 pub use layout::{LayoutCalculator, LayoutCalculatorError};
 
@@ -1344,11 +1352,19 @@ impl AddressSpace {
     pub const DATA: Self = AddressSpace(0);
 }
 
-/// Describes how values of the type are passed by target ABIs,
-/// in terms of categories of C types there are ABI rules for.
+/// The way we represent values to the backend
+///
+/// Previously this was conflated with the "ABI" a type is given, as in the platform-specific ABI.
+/// In reality, this implies little about that, but is mostly used to describe the syntactic form
+/// emitted for the backend, as most backends handle SSA values and blobs of memory differently.
+/// The psABI may need consideration in doing so, but this enum does not constitute a promise for
+/// how the value will be lowered to the calling convention, in itself.
+///
+/// Generally, a codegen backend will prefer to handle smaller values as a scalar or short vector,
+/// and larger values will usually prefer to be represented as memory.
 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
-pub enum Abi {
+pub enum BackendRepr {
     Uninhabited,
     Scalar(Scalar),
     ScalarPair(Scalar, Scalar),
@@ -1356,19 +1372,23 @@ pub enum Abi {
         element: Scalar,
         count: u64,
     },
-    Aggregate {
+    // FIXME: I sometimes use memory, sometimes use an IR aggregate!
+    Memory {
         /// If true, the size is exact, otherwise it's only a lower bound.
         sized: bool,
     },
 }
 
-impl Abi {
+impl BackendRepr {
     /// Returns `true` if the layout corresponds to an unsized type.
     #[inline]
     pub fn is_unsized(&self) -> bool {
         match *self {
-            Abi::Uninhabited | Abi::Scalar(_) | Abi::ScalarPair(..) | Abi::Vector { .. } => false,
-            Abi::Aggregate { sized } => !sized,
+            BackendRepr::Uninhabited
+            | BackendRepr::Scalar(_)
+            | BackendRepr::ScalarPair(..)
+            | BackendRepr::Vector { .. } => false,
+            BackendRepr::Memory { sized } => !sized,
         }
     }
 
@@ -1381,7 +1401,7 @@ impl Abi {
     #[inline]
     pub fn is_signed(&self) -> bool {
         match self {
-            Abi::Scalar(scal) => match scal.primitive() {
+            BackendRepr::Scalar(scal) => match scal.primitive() {
                 Primitive::Int(_, signed) => signed,
                 _ => false,
             },
@@ -1392,61 +1412,67 @@ impl Abi {
     /// Returns `true` if this is an uninhabited type
     #[inline]
     pub fn is_uninhabited(&self) -> bool {
-        matches!(*self, Abi::Uninhabited)
+        matches!(*self, BackendRepr::Uninhabited)
     }
 
     /// Returns `true` if this is a scalar type
     #[inline]
     pub fn is_scalar(&self) -> bool {
-        matches!(*self, Abi::Scalar(_))
+        matches!(*self, BackendRepr::Scalar(_))
     }
 
     /// Returns `true` if this is a bool
     #[inline]
     pub fn is_bool(&self) -> bool {
-        matches!(*self, Abi::Scalar(s) if s.is_bool())
+        matches!(*self, BackendRepr::Scalar(s) if s.is_bool())
     }
 
     /// Returns the fixed alignment of this ABI, if any is mandated.
     pub fn inherent_align<C: HasDataLayout>(&self, cx: &C) -> Option<AbiAndPrefAlign> {
         Some(match *self {
-            Abi::Scalar(s) => s.align(cx),
-            Abi::ScalarPair(s1, s2) => s1.align(cx).max(s2.align(cx)),
-            Abi::Vector { element, count } => {
+            BackendRepr::Scalar(s) => s.align(cx),
+            BackendRepr::ScalarPair(s1, s2) => s1.align(cx).max(s2.align(cx)),
+            BackendRepr::Vector { element, count } => {
                 cx.data_layout().vector_align(element.size(cx) * count)
             }
-            Abi::Uninhabited | Abi::Aggregate { .. } => return None,
+            BackendRepr::Uninhabited | BackendRepr::Memory { .. } => return None,
         })
     }
 
     /// Returns the fixed size of this ABI, if any is mandated.
     pub fn inherent_size<C: HasDataLayout>(&self, cx: &C) -> Option<Size> {
         Some(match *self {
-            Abi::Scalar(s) => {
+            BackendRepr::Scalar(s) => {
                 // No padding in scalars.
                 s.size(cx)
             }
-            Abi::ScalarPair(s1, s2) => {
+            BackendRepr::ScalarPair(s1, s2) => {
                 // May have some padding between the pair.
                 let field2_offset = s1.size(cx).align_to(s2.align(cx).abi);
                 (field2_offset + s2.size(cx)).align_to(self.inherent_align(cx)?.abi)
             }
-            Abi::Vector { element, count } => {
+            BackendRepr::Vector { element, count } => {
                 // No padding in vectors, except possibly for trailing padding
                 // to make the size a multiple of align (e.g. for vectors of size 3).
                 (element.size(cx) * count).align_to(self.inherent_align(cx)?.abi)
             }
-            Abi::Uninhabited | Abi::Aggregate { .. } => return None,
+            BackendRepr::Uninhabited | BackendRepr::Memory { .. } => return None,
         })
     }
 
     /// Discard validity range information and allow undef.
     pub fn to_union(&self) -> Self {
         match *self {
-            Abi::Scalar(s) => Abi::Scalar(s.to_union()),
-            Abi::ScalarPair(s1, s2) => Abi::ScalarPair(s1.to_union(), s2.to_union()),
-            Abi::Vector { element, count } => Abi::Vector { element: element.to_union(), count },
-            Abi::Uninhabited | Abi::Aggregate { .. } => Abi::Aggregate { sized: true },
+            BackendRepr::Scalar(s) => BackendRepr::Scalar(s.to_union()),
+            BackendRepr::ScalarPair(s1, s2) => {
+                BackendRepr::ScalarPair(s1.to_union(), s2.to_union())
+            }
+            BackendRepr::Vector { element, count } => {
+                BackendRepr::Vector { element: element.to_union(), count }
+            }
+            BackendRepr::Uninhabited | BackendRepr::Memory { .. } => {
+                BackendRepr::Memory { sized: true }
+            }
         }
     }
 
@@ -1454,12 +1480,12 @@ impl Abi {
         match (self, other) {
             // Scalar, Vector, ScalarPair have `Scalar` in them where we ignore validity ranges.
             // We do *not* ignore the sign since it matters for some ABIs (e.g. s390x).
-            (Abi::Scalar(l), Abi::Scalar(r)) => l.primitive() == r.primitive(),
+            (BackendRepr::Scalar(l), BackendRepr::Scalar(r)) => l.primitive() == r.primitive(),
             (
-                Abi::Vector { element: element_l, count: count_l },
-                Abi::Vector { element: element_r, count: count_r },
+                BackendRepr::Vector { element: element_l, count: count_l },
+                BackendRepr::Vector { element: element_r, count: count_r },
             ) => element_l.primitive() == element_r.primitive() && count_l == count_r,
-            (Abi::ScalarPair(l1, l2), Abi::ScalarPair(r1, r2)) => {
+            (BackendRepr::ScalarPair(l1, l2), BackendRepr::ScalarPair(r1, r2)) => {
                 l1.primitive() == r1.primitive() && l2.primitive() == r2.primitive()
             }
             // Everything else must be strictly identical.
@@ -1616,14 +1642,14 @@ pub struct LayoutData<FieldIdx: Idx, VariantIdx: Idx> {
     /// must be taken into account.
     pub variants: Variants<FieldIdx, VariantIdx>,
 
-    /// The `abi` defines how this data is passed between functions, and it defines
-    /// value restrictions via `valid_range`.
+    /// The `backend_repr` defines how this data will be represented to the codegen backend,
+    /// and encodes value restrictions via `valid_range`.
     ///
     /// Note that this is entirely orthogonal to the recursive structure defined by
     /// `variants` and `fields`; for example, `ManuallyDrop<Result<isize, isize>>` has
-    /// `Abi::ScalarPair`! So, even with non-`Aggregate` `abi`, `fields` and `variants`
+    /// `IrForm::ScalarPair`! So, even with non-`Memory` `backend_repr`, `fields` and `variants`
     /// have to be taken into account to find all fields of this layout.
-    pub abi: Abi,
+    pub backend_repr: BackendRepr,
 
     /// The leaf scalar with the largest number of invalid values
     /// (i.e. outside of its `valid_range`), if it exists.
@@ -1646,12 +1672,17 @@ pub struct LayoutData<FieldIdx: Idx, VariantIdx: Idx> {
 impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
     /// Returns `true` if this is an aggregate type (including a ScalarPair!)
     pub fn is_aggregate(&self) -> bool {
-        match self.abi {
-            Abi::Uninhabited | Abi::Scalar(_) | Abi::Vector { .. } => false,
-            Abi::ScalarPair(..) | Abi::Aggregate { .. } => true,
+        match self.backend_repr {
+            BackendRepr::Uninhabited | BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => false,
+            BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => true,
         }
     }
 
+    /// Returns `true` if this is an uninhabited type
+    pub fn is_uninhabited(&self) -> bool {
+        self.backend_repr.is_uninhabited()
+    }
+
     pub fn scalar<C: HasDataLayout>(cx: &C, scalar: Scalar) -> Self {
         let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar);
         let size = scalar.size(cx);
@@ -1659,7 +1690,7 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
         LayoutData {
             variants: Variants::Single { index: VariantIdx::new(0) },
             fields: FieldsShape::Primitive,
-            abi: Abi::Scalar(scalar),
+            backend_repr: BackendRepr::Scalar(scalar),
             largest_niche,
             size,
             align,
@@ -1681,7 +1712,7 @@ where
         let LayoutData {
             size,
             align,
-            abi,
+            backend_repr,
             fields,
             largest_niche,
             variants,
@@ -1691,7 +1722,7 @@ where
         f.debug_struct("Layout")
             .field("size", size)
             .field("align", align)
-            .field("abi", abi)
+            .field("abi", backend_repr)
             .field("fields", fields)
             .field("largest_niche", largest_niche)
             .field("variants", variants)
@@ -1727,12 +1758,12 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
     /// Returns `true` if the layout corresponds to an unsized type.
     #[inline]
     pub fn is_unsized(&self) -> bool {
-        self.abi.is_unsized()
+        self.backend_repr.is_unsized()
     }
 
     #[inline]
     pub fn is_sized(&self) -> bool {
-        self.abi.is_sized()
+        self.backend_repr.is_sized()
     }
 
     /// Returns `true` if the type is sized and a 1-ZST (meaning it has size 0 and alignment 1).
@@ -1745,10 +1776,12 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
     /// Note that this does *not* imply that the type is irrelevant for layout! It can still have
     /// non-trivial alignment constraints. You probably want to use `is_1zst` instead.
     pub fn is_zst(&self) -> bool {
-        match self.abi {
-            Abi::Scalar(_) | Abi::ScalarPair(..) | Abi::Vector { .. } => false,
-            Abi::Uninhabited => self.size.bytes() == 0,
-            Abi::Aggregate { sized } => sized && self.size.bytes() == 0,
+        match self.backend_repr {
+            BackendRepr::Scalar(_) | BackendRepr::ScalarPair(..) | BackendRepr::Vector { .. } => {
+                false
+            }
+            BackendRepr::Uninhabited => self.size.bytes() == 0,
+            BackendRepr::Memory { sized } => sized && self.size.bytes() == 0,
         }
     }
 
@@ -1763,8 +1796,8 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
         // 2nd point is quite hard to check though.
         self.size == other.size
             && self.is_sized() == other.is_sized()
-            && self.abi.eq_up_to_validity(&other.abi)
-            && self.abi.is_bool() == other.abi.is_bool()
+            && self.backend_repr.eq_up_to_validity(&other.backend_repr)
+            && self.backend_repr.is_bool() == other.backend_repr.is_bool()
             && self.align.abi == other.align.abi
             && self.max_repr_align == other.max_repr_align
             && self.unadjusted_abi_align == other.unadjusted_abi_align
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 8e4f4c8e71a..ec6ca70ae0a 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -2810,6 +2810,8 @@ pub struct ModSpans {
 /// E.g., `extern { .. }` or `extern "C" { .. }`.
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct ForeignMod {
+    /// Span of the `extern` keyword.
+    pub extern_span: Span,
     /// `unsafe` keyword accepted syntactically for macro DSLs, but not
     /// semantically by Rust.
     pub safety: Safety,
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 2afbd979c30..44bb44cb728 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -525,7 +525,7 @@ pub fn walk_ty<T: MutVisitor>(vis: &mut T, ty: &mut P<Ty>) {
 }
 
 fn walk_foreign_mod<T: MutVisitor>(vis: &mut T, foreign_mod: &mut ForeignMod) {
-    let ForeignMod { safety, abi: _, items } = foreign_mod;
+    let ForeignMod { extern_span: _, safety, abi: _, items } = foreign_mod;
     visit_safety(vis, safety);
     items.flat_map_in_place(|item| vis.flat_map_foreign_item(item));
 }
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index 1d6abbef06c..3b9edef0615 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -368,7 +368,7 @@ impl Clone for TokenKind {
         // a copy. This is faster than the `derive(Clone)` version which has a
         // separate path for every variant.
         match self {
-            Interpolated(nt) => Interpolated(nt.clone()),
+            Interpolated(nt) => Interpolated(Lrc::clone(nt)),
             _ => unsafe { std::ptr::read(self) },
         }
     }
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index eb71ec5f4ec..2f8115441de 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -366,7 +366,7 @@ impl WalkItemKind for ItemKind {
                 }
                 ModKind::Unloaded => {}
             },
-            ItemKind::ForeignMod(ForeignMod { safety: _, abi: _, items }) => {
+            ItemKind::ForeignMod(ForeignMod { extern_span: _, safety: _, abi: _, items }) => {
                 walk_list!(visitor, visit_foreign_item, items);
             }
             ItemKind::GlobalAsm(asm) => try_visit!(visitor.visit_inline_asm(asm)),
diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs
index 9d2b5690c23..20d3ce65fac 100644
--- a/compiler/rustc_ast_lowering/src/block.rs
+++ b/compiler/rustc_ast_lowering/src/block.rs
@@ -10,17 +10,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         b: &Block,
         targeted_by_break: bool,
     ) -> &'hir hir::Block<'hir> {
-        self.arena.alloc(self.lower_block_noalloc(b, targeted_by_break))
+        let hir_id = self.lower_node_id(b.id);
+        self.arena.alloc(self.lower_block_noalloc(hir_id, b, targeted_by_break))
     }
 
     pub(super) fn lower_block_noalloc(
         &mut self,
+        hir_id: hir::HirId,
         b: &Block,
         targeted_by_break: bool,
     ) -> hir::Block<'hir> {
         let (stmts, expr) = self.lower_stmts(&b.stmts);
         let rules = self.lower_block_check_mode(&b.rules);
-        let hir_id = self.lower_node_id(b.id);
         hir::Block { hir_id, stmts, expr, rules, span: self.lower_span(b.span), targeted_by_break }
     }
 
diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs
index 3b85f1737bd..70c94f4019a 100644
--- a/compiler/rustc_ast_lowering/src/delegation.rs
+++ b/compiler/rustc_ast_lowering/src/delegation.rs
@@ -259,10 +259,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         self_param_id: pat_node_id,
                     };
                     self_resolver.visit_block(block);
+                    // Target expr needs to lower `self` path.
+                    this.ident_and_label_to_local_id.insert(pat_node_id, param.pat.hir_id.local_id);
                     this.lower_target_expr(&block)
                 } else {
-                    let pat_hir_id = this.lower_node_id(pat_node_id);
-                    this.generate_arg(pat_hir_id, span)
+                    this.generate_arg(param.pat.hir_id, span)
                 };
                 args.push(arg);
             }
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index a1a16d0ca26..b7cf2d252dc 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -3,6 +3,7 @@ use std::assert_matches::assert_matches;
 use rustc_ast::ptr::P as AstP;
 use rustc_ast::*;
 use rustc_data_structures::stack::ensure_sufficient_stack;
+use rustc_data_structures::sync::Lrc;
 use rustc_hir as hir;
 use rustc_hir::HirId;
 use rustc_hir::def::{DefKind, Res};
@@ -70,8 +71,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 _ => (),
             }
 
-            let hir_id = self.lower_node_id(e.id);
-            self.lower_attrs(hir_id, &e.attrs);
+            let expr_hir_id = self.lower_node_id(e.id);
+            self.lower_attrs(expr_hir_id, &e.attrs);
 
             let kind = match &e.kind {
                 ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),
@@ -143,7 +144,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 ExprKind::IncludedBytes(bytes) => {
                     let lit = self.arena.alloc(respan(
                         self.lower_span(e.span),
-                        LitKind::ByteStr(bytes.clone(), StrStyle::Cooked),
+                        LitKind::ByteStr(Lrc::clone(bytes), StrStyle::Cooked),
                     ));
                     hir::ExprKind::Lit(lit)
                 }
@@ -175,18 +176,25 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 ExprKind::If(cond, then, else_opt) => {
                     self.lower_expr_if(cond, then, else_opt.as_deref())
                 }
-                ExprKind::While(cond, body, opt_label) => self.with_loop_scope(e.id, |this| {
-                    let span = this.mark_span_with_reason(DesugaringKind::WhileLoop, e.span, None);
-                    this.lower_expr_while_in_loop_scope(span, cond, body, *opt_label)
-                }),
-                ExprKind::Loop(body, opt_label, span) => self.with_loop_scope(e.id, |this| {
-                    hir::ExprKind::Loop(
-                        this.lower_block(body, false),
-                        this.lower_label(*opt_label),
-                        hir::LoopSource::Loop,
-                        this.lower_span(*span),
-                    )
-                }),
+                ExprKind::While(cond, body, opt_label) => {
+                    self.with_loop_scope(expr_hir_id, |this| {
+                        let span =
+                            this.mark_span_with_reason(DesugaringKind::WhileLoop, e.span, None);
+                        let opt_label = this.lower_label(*opt_label, e.id, expr_hir_id);
+                        this.lower_expr_while_in_loop_scope(span, cond, body, opt_label)
+                    })
+                }
+                ExprKind::Loop(body, opt_label, span) => {
+                    self.with_loop_scope(expr_hir_id, |this| {
+                        let opt_label = this.lower_label(*opt_label, e.id, expr_hir_id);
+                        hir::ExprKind::Loop(
+                            this.lower_block(body, false),
+                            opt_label,
+                            hir::LoopSource::Loop,
+                            this.lower_span(*span),
+                        )
+                    })
+                }
                 ExprKind::TryBlock(body) => self.lower_expr_try_block(body),
                 ExprKind::Match(expr, arms, kind) => hir::ExprKind::Match(
                     self.lower_expr(expr),
@@ -212,7 +220,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         binder,
                         *capture_clause,
                         e.id,
-                        hir_id,
+                        expr_hir_id,
                         *coroutine_kind,
                         fn_decl,
                         body,
@@ -223,7 +231,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         binder,
                         *capture_clause,
                         e.id,
-                        hir_id,
+                        expr_hir_id,
                         *constness,
                         *movability,
                         fn_decl,
@@ -250,8 +258,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     )
                 }
                 ExprKind::Block(blk, opt_label) => {
-                    let opt_label = self.lower_label(*opt_label);
-                    hir::ExprKind::Block(self.lower_block(blk, opt_label.is_some()), opt_label)
+                    // Different from loops, label of block resolves to block id rather than
+                    // expr node id.
+                    let block_hir_id = self.lower_node_id(blk.id);
+                    let opt_label = self.lower_label(*opt_label, blk.id, block_hir_id);
+                    let hir_block = self.arena.alloc(self.lower_block_noalloc(
+                        block_hir_id,
+                        blk,
+                        opt_label.is_some(),
+                    ));
+                    hir::ExprKind::Block(hir_block, opt_label)
                 }
                 ExprKind::Assign(el, er, span) => self.lower_expr_assign(el, er, *span, e.span),
                 ExprKind::AssignOp(op, el, er) => hir::ExprKind::AssignOp(
@@ -354,7 +370,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 ExprKind::MacCall(_) => panic!("{:?} shouldn't exist here", e.span),
             };
 
-            hir::Expr { hir_id, kind, span: self.lower_span(e.span) }
+            hir::Expr { hir_id: expr_hir_id, kind, span: self.lower_span(e.span) }
         })
     }
 
@@ -504,7 +520,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let if_expr = self.expr(span, if_kind);
         let block = self.block_expr(self.arena.alloc(if_expr));
         let span = self.lower_span(span.with_hi(cond.span.hi()));
-        let opt_label = self.lower_label(opt_label);
         hir::ExprKind::Loop(block, opt_label, hir::LoopSource::While, span)
     }
 
@@ -512,8 +527,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
     /// `try { <stmts>; }` into `{ <stmts>; ::std::ops::Try::from_output(()) }`
     /// and save the block id to use it as a break target for desugaring of the `?` operator.
     fn lower_expr_try_block(&mut self, body: &Block) -> hir::ExprKind<'hir> {
-        self.with_catch_scope(body.id, |this| {
-            let mut block = this.lower_block_noalloc(body, true);
+        let body_hir_id = self.lower_node_id(body.id);
+        self.with_catch_scope(body_hir_id, |this| {
+            let mut block = this.lower_block_noalloc(body_hir_id, body, true);
 
             // Final expression of the block (if present) or `()` with span at the end of block
             let (try_span, tail_expr) = if let Some(expr) = block.expr.take() {
@@ -521,7 +537,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     this.mark_span_with_reason(
                         DesugaringKind::TryBlock,
                         expr.span,
-                        Some(this.allow_try_trait.clone()),
+                        Some(Lrc::clone(&this.allow_try_trait)),
                     ),
                     expr,
                 )
@@ -529,7 +545,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 let try_span = this.mark_span_with_reason(
                     DesugaringKind::TryBlock,
                     this.tcx.sess.source_map().end_point(body.span),
-                    Some(this.allow_try_trait.clone()),
+                    Some(Lrc::clone(&this.allow_try_trait)),
                 );
 
                 (try_span, this.expr_unit(try_span))
@@ -638,7 +654,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 let unstable_span = self.mark_span_with_reason(
                     DesugaringKind::Async,
                     self.lower_span(span),
-                    Some(self.allow_gen_future.clone()),
+                    Some(Lrc::clone(&self.allow_gen_future)),
                 );
                 let resume_ty =
                     self.make_lang_item_qpath(hir::LangItem::ResumeTy, unstable_span, None);
@@ -724,7 +740,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             let unstable_span = self.mark_span_with_reason(
                 DesugaringKind::Async,
                 span,
-                Some(self.allow_gen_future.clone()),
+                Some(Lrc::clone(&self.allow_gen_future)),
             );
             self.lower_attrs(inner_hir_id, &[Attribute {
                 kind: AttrKind::Normal(ptr::P(NormalAttr::from_ident(Ident::new(
@@ -800,13 +816,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
         let features = match await_kind {
             FutureKind::Future => None,
-            FutureKind::AsyncIterator => Some(self.allow_for_await.clone()),
+            FutureKind::AsyncIterator => Some(Lrc::clone(&self.allow_for_await)),
         };
         let span = self.mark_span_with_reason(DesugaringKind::Await, await_kw_span, features);
         let gen_future_span = self.mark_span_with_reason(
             DesugaringKind::Await,
             full_span,
-            Some(self.allow_gen_future.clone()),
+            Some(Lrc::clone(&self.allow_gen_future)),
         );
         let expr_hir_id = expr.hir_id;
 
@@ -869,7 +885,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             let x_expr = self.expr_ident(gen_future_span, x_ident, x_pat_hid);
             let ready_field = self.single_pat_field(gen_future_span, x_pat);
             let ready_pat = self.pat_lang_item_variant(span, hir::LangItem::PollReady, ready_field);
-            let break_x = self.with_loop_scope(loop_node_id, move |this| {
+            let break_x = self.with_loop_scope(loop_hir_id, move |this| {
                 let expr_break =
                     hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr));
                 this.arena.alloc(this.expr(gen_future_span, expr_break))
@@ -1101,8 +1117,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         hir::CoroutineSource::Closure,
                     );
 
-                    let hir_id = this.lower_node_id(coroutine_kind.closure_id());
-                    this.maybe_forward_track_caller(body.span, closure_hir_id, hir_id);
+                    this.maybe_forward_track_caller(body.span, closure_hir_id, expr.hir_id);
 
                     (parameters, expr)
                 });
@@ -1465,8 +1480,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
         )
     }
 
-    fn lower_label(&self, opt_label: Option<Label>) -> Option<Label> {
+    // Record labelled expr's HirId so that we can retrieve it in `lower_jump_destination` without
+    // lowering node id again.
+    fn lower_label(
+        &mut self,
+        opt_label: Option<Label>,
+        dest_id: NodeId,
+        dest_hir_id: hir::HirId,
+    ) -> Option<Label> {
         let label = opt_label?;
+        self.ident_and_label_to_local_id.insert(dest_id, dest_hir_id.local_id);
         Some(Label { ident: self.lower_ident(label.ident) })
     }
 
@@ -1474,17 +1497,20 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let target_id = match destination {
             Some((id, _)) => {
                 if let Some(loop_id) = self.resolver.get_label_res(id) {
-                    Ok(self.lower_node_id(loop_id))
+                    let local_id = self.ident_and_label_to_local_id[&loop_id];
+                    let loop_hir_id = HirId { owner: self.current_hir_id_owner, local_id };
+                    Ok(loop_hir_id)
                 } else {
                     Err(hir::LoopIdError::UnresolvedLabel)
                 }
             }
-            None => self
-                .loop_scope
-                .map(|id| Ok(self.lower_node_id(id)))
-                .unwrap_or(Err(hir::LoopIdError::OutsideLoopScope)),
+            None => {
+                self.loop_scope.map(|id| Ok(id)).unwrap_or(Err(hir::LoopIdError::OutsideLoopScope))
+            }
         };
-        let label = self.lower_label(destination.map(|(_, label)| label));
+        let label = destination
+            .map(|(_, label)| label)
+            .map(|label| Label { ident: self.lower_ident(label.ident) });
         hir::Destination { label, target_id }
     }
 
@@ -1499,14 +1525,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
         }
     }
 
-    fn with_catch_scope<T>(&mut self, catch_id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T {
+    fn with_catch_scope<T>(&mut self, catch_id: hir::HirId, f: impl FnOnce(&mut Self) -> T) -> T {
         let old_scope = self.catch_scope.replace(catch_id);
         let result = f(self);
         self.catch_scope = old_scope;
         result
     }
 
-    fn with_loop_scope<T>(&mut self, loop_id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T {
+    fn with_loop_scope<T>(&mut self, loop_id: hir::HirId, f: impl FnOnce(&mut Self) -> T) -> T {
         // We're no longer in the base loop's condition; we're in another loop.
         let was_in_loop_condition = self.is_in_loop_condition;
         self.is_in_loop_condition = false;
@@ -1658,9 +1684,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let head_span = self.mark_span_with_reason(DesugaringKind::ForLoop, head.span, None);
         let pat_span = self.mark_span_with_reason(DesugaringKind::ForLoop, pat.span, None);
 
+        let loop_hir_id = self.lower_node_id(e.id);
+        let label = self.lower_label(opt_label, e.id, loop_hir_id);
+
         // `None => break`
         let none_arm = {
-            let break_expr = self.with_loop_scope(e.id, |this| this.expr_break_alloc(for_span));
+            let break_expr =
+                self.with_loop_scope(loop_hir_id, |this| this.expr_break_alloc(for_span));
             let pat = self.pat_none(for_span);
             self.arm(pat, break_expr)
         };
@@ -1668,7 +1698,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
         // Some(<pat>) => <body>,
         let some_arm = {
             let some_pat = self.pat_some(pat_span, pat);
-            let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body, false));
+            let body_block =
+                self.with_loop_scope(loop_hir_id, |this| this.lower_block(body, false));
             let body_expr = self.arena.alloc(self.expr_block(body_block));
             self.arm(some_pat, body_expr)
         };
@@ -1722,12 +1753,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
         // `[opt_ident]: loop { ... }`
         let kind = hir::ExprKind::Loop(
             loop_block,
-            self.lower_label(opt_label),
+            label,
             hir::LoopSource::ForLoop,
             self.lower_span(for_span.with_hi(head.span.hi())),
         );
-        let loop_expr =
-            self.arena.alloc(hir::Expr { hir_id: self.lower_node_id(e.id), kind, span: for_span });
+        let loop_expr = self.arena.alloc(hir::Expr { hir_id: loop_hir_id, kind, span: for_span });
 
         // `mut iter => { ... }`
         let iter_arm = self.arm(iter_pat, loop_expr);
@@ -1812,13 +1842,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let unstable_span = self.mark_span_with_reason(
             DesugaringKind::QuestionMark,
             span,
-            Some(self.allow_try_trait.clone()),
+            Some(Lrc::clone(&self.allow_try_trait)),
         );
         let try_span = self.tcx.sess.source_map().end_point(span);
         let try_span = self.mark_span_with_reason(
             DesugaringKind::QuestionMark,
             try_span,
-            Some(self.allow_try_trait.clone()),
+            Some(Lrc::clone(&self.allow_try_trait)),
         );
 
         // `Try::branch(<expr>)`
@@ -1867,8 +1897,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 self.arena.alloc(residual_expr),
                 unstable_span,
             );
-            let ret_expr = if let Some(catch_node) = self.catch_scope {
-                let target_id = Ok(self.lower_node_id(catch_node));
+            let ret_expr = if let Some(catch_id) = self.catch_scope {
+                let target_id = Ok(catch_id);
                 self.arena.alloc(self.expr(
                     try_span,
                     hir::ExprKind::Break(
@@ -1912,7 +1942,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let unstable_span = self.mark_span_with_reason(
             DesugaringKind::YeetExpr,
             span,
-            Some(self.allow_try_trait.clone()),
+            Some(Lrc::clone(&self.allow_try_trait)),
         );
 
         let from_yeet_expr = self.wrap_in_try_constructor(
@@ -1922,8 +1952,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
             yeeted_span,
         );
 
-        if let Some(catch_node) = self.catch_scope {
-            let target_id = Ok(self.lower_node_id(catch_node));
+        if let Some(catch_id) = self.catch_scope {
+            let target_id = Ok(catch_id);
             hir::ExprKind::Break(hir::Destination { label: None, target_id }, Some(from_yeet_expr))
         } else {
             hir::ExprKind::Ret(Some(from_yeet_expr))
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 97fa90d340e..d7245607501 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -154,7 +154,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
     fn lower_item(&mut self, i: &Item) -> &'hir hir::Item<'hir> {
         let mut ident = i.ident;
         let vis_span = self.lower_span(i.vis.span);
-        let hir_id = self.lower_node_id(i.id);
+        let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
         let attrs = self.lower_attrs(hir_id, &i.attrs);
         let kind = self.lower_item_kind(i.span, i.id, hir_id, &mut ident, attrs, vis_span, &i.kind);
         let item = hir::Item {
@@ -604,7 +604,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
     }
 
     fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> {
-        let hir_id = self.lower_node_id(i.id);
+        let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
         let owner_id = hir_id.expect_owner();
         self.lower_attrs(hir_id, &i.attrs);
         let item = hir::ForeignItem {
@@ -728,7 +728,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
     }
 
     fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
-        let hir_id = self.lower_node_id(i.id);
+        let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
         self.lower_attrs(hir_id, &i.attrs);
         let trait_item_def_id = hir_id.expect_owner();
 
@@ -858,7 +858,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         // Since `default impl` is not yet implemented, this is always true in impls.
         let has_value = true;
         let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
-        let hir_id = self.lower_node_id(i.id);
+        let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
         self.lower_attrs(hir_id, &i.attrs);
 
         let (generics, kind) = match &i.kind {
@@ -1086,7 +1086,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             );
 
             // FIXME(async_fn_track_caller): Can this be moved above?
-            let hir_id = this.lower_node_id(coroutine_kind.closure_id());
+            let hir_id = expr.hir_id;
             this.maybe_forward_track_caller(body.span, fn_id, hir_id);
 
             (parameters, expr)
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 34b8137aea8..5a0e9e8aec0 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -40,23 +40,19 @@
 #![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
-use std::collections::hash_map::Entry;
-
 use rustc_ast::node_id::NodeMap;
 use rustc_ast::ptr::P;
 use rustc_ast::{self as ast, *};
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_data_structures::fx::FxIndexSet;
 use rustc_data_structures::sorted_map::SortedMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, StashKey};
 use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
-use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalDefIdMap};
+use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId};
 use rustc_hir::{
-    self as hir, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem, MissingLifetimeKind,
-    ParamName, TraitCandidate,
+    self as hir, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem, ParamName, TraitCandidate,
 };
 use rustc_index::{Idx, IndexSlice, IndexVec};
 use rustc_macros::extension;
@@ -85,7 +81,6 @@ mod expr;
 mod format;
 mod index;
 mod item;
-mod lifetime_collector;
 mod pat;
 mod path;
 
@@ -115,8 +110,8 @@ struct LoweringContext<'a, 'hir> {
     /// outside of an `async fn`.
     current_item: Option<Span>,
 
-    catch_scope: Option<NodeId>,
-    loop_scope: Option<NodeId>,
+    catch_scope: Option<HirId>,
+    loop_scope: Option<HirId>,
     is_in_loop_condition: bool,
     is_in_trait_impl: bool,
     is_in_dyn_type: bool,
@@ -140,7 +135,10 @@ struct LoweringContext<'a, 'hir> {
     impl_trait_defs: Vec<hir::GenericParam<'hir>>,
     impl_trait_bounds: Vec<hir::WherePredicate<'hir>>,
 
-    /// NodeIds that are lowered inside the current HIR owner.
+    /// NodeIds of pattern identifiers and labelled nodes that are lowered inside the current HIR owner.
+    ident_and_label_to_local_id: NodeMap<hir::ItemLocalId>,
+    /// NodeIds that are lowered inside the current HIR owner. Only used for duplicate lowering check.
+    #[cfg(debug_assertions)]
     node_id_to_local_id: NodeMap<hir::ItemLocalId>,
 
     allow_try_trait: Lrc<[Symbol]>,
@@ -148,12 +146,6 @@ struct LoweringContext<'a, 'hir> {
     allow_async_iterator: Lrc<[Symbol]>,
     allow_for_await: Lrc<[Symbol]>,
     allow_async_fn_traits: Lrc<[Symbol]>,
-
-    /// Mapping from generics `def_id`s to TAIT generics `def_id`s.
-    /// For each captured lifetime (e.g., 'a), we create a new lifetime parameter that is a generic
-    /// defined on the TAIT, so we have type Foo<'a1> = ... and we establish a mapping in this
-    /// field from the original parameter 'a to the new parameter 'a1.
-    generics_def_id_map: Vec<LocalDefIdMap<LocalDefId>>,
 }
 
 impl<'a, 'hir> LoweringContext<'a, 'hir> {
@@ -171,6 +163,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             current_hir_id_owner: hir::CRATE_OWNER_ID,
             current_def_id_parent: CRATE_DEF_ID,
             item_local_id_counter: hir::ItemLocalId::ZERO,
+            ident_and_label_to_local_id: Default::default(),
+            #[cfg(debug_assertions)]
             node_id_to_local_id: Default::default(),
             trait_map: Default::default(),
 
@@ -196,7 +190,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             // FIXME(gen_blocks): how does `closure_track_caller`/`async_fn_track_caller`
             // interact with `gen`/`async gen` blocks
             allow_async_iterator: [sym::gen_future, sym::async_iterator].into(),
-            generics_def_id_map: Default::default(),
         }
     }
 
@@ -279,7 +272,7 @@ enum ImplTraitContext {
     /// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually
     /// equivalent to a new opaque type like `type T = impl Debug; fn foo() -> T`.
     ///
-    OpaqueTy { origin: hir::OpaqueTyOrigin },
+    OpaqueTy { origin: hir::OpaqueTyOrigin<LocalDefId> },
     /// `impl Trait` is unstably accepted in this position.
     FeatureGated(ImplTraitPosition, Symbol),
     /// `impl Trait` is not accepted in this position.
@@ -525,54 +518,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
     /// Given the id of some node in the AST, finds the `LocalDefId` associated with it by the name
     /// resolver (if any).
-    fn orig_opt_local_def_id(&self, node: NodeId) -> Option<LocalDefId> {
-        self.resolver.node_id_to_def_id.get(&node).copied()
-    }
-
-    /// Given the id of some node in the AST, finds the `LocalDefId` associated with it by the name
-    /// resolver (if any), after applying any remapping from `get_remapped_def_id`.
-    ///
-    /// For example, in a function like `fn foo<'a>(x: &'a u32)`,
-    /// invoking with the id from the `ast::Lifetime` node found inside
-    /// the `&'a u32` type would return the `LocalDefId` of the
-    /// `'a` parameter declared on `foo`.
-    ///
-    /// This function also applies remapping from `get_remapped_def_id`.
-    /// These are used when synthesizing opaque types from `-> impl Trait` return types and so forth.
-    /// For example, in a function like `fn foo<'a>() -> impl Debug + 'a`,
-    /// we would create an opaque type `type FooReturn<'a1> = impl Debug + 'a1`.
-    /// When lowering the `Debug + 'a` bounds, we add a remapping to map `'a` to `'a1`.
     fn opt_local_def_id(&self, node: NodeId) -> Option<LocalDefId> {
-        self.orig_opt_local_def_id(node).map(|local_def_id| self.get_remapped_def_id(local_def_id))
+        self.resolver.node_id_to_def_id.get(&node).copied()
     }
 
     fn local_def_id(&self, node: NodeId) -> LocalDefId {
         self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{node:?}`"))
     }
 
-    /// Get the previously recorded `to` local def id given the `from` local def id, obtained using
-    /// `generics_def_id_map` field.
-    fn get_remapped_def_id(&self, local_def_id: LocalDefId) -> LocalDefId {
-        // `generics_def_id_map` is a stack of mappings. As we go deeper in impl traits nesting we
-        // push new mappings, so we first need to get the latest (innermost) mappings, hence `iter().rev()`.
-        //
-        // Consider:
-        //
-        // `fn test<'a, 'b>() -> impl Trait<&'a u8, Ty = impl Sized + 'b> {}`
-        //
-        // We would end with a generics_def_id_map like:
-        //
-        // `[[fn#'b -> impl_trait#'b], [fn#'b -> impl_sized#'b]]`
-        //
-        // for the opaque type generated on `impl Sized + 'b`, we want the result to be: impl_sized#'b.
-        // So, if we were trying to find first from the start (outermost) would give the wrong result, impl_trait#'b.
-        self.generics_def_id_map
-            .iter()
-            .rev()
-            .find_map(|map| map.get(&local_def_id).copied())
-            .unwrap_or(local_def_id)
-    }
-
     /// Freshen the `LoweringContext` and ready it to lower a nested item.
     /// The lowered item is registered into `self.children`.
     ///
@@ -588,7 +541,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
         let current_attrs = std::mem::take(&mut self.attrs);
         let current_bodies = std::mem::take(&mut self.bodies);
-        let current_node_ids = std::mem::take(&mut self.node_id_to_local_id);
+        let current_ident_and_label_to_local_id =
+            std::mem::take(&mut self.ident_and_label_to_local_id);
+
+        #[cfg(debug_assertions)]
+        let current_node_id_to_local_id = std::mem::take(&mut self.node_id_to_local_id);
         let current_trait_map = std::mem::take(&mut self.trait_map);
         let current_owner =
             std::mem::replace(&mut self.current_hir_id_owner, hir::OwnerId { def_id });
@@ -602,8 +559,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         // and the caller to refer to some of the subdefinitions' nodes' `LocalDefId`s.
 
         // Always allocate the first `HirId` for the owner itself.
-        let _old = self.node_id_to_local_id.insert(owner, hir::ItemLocalId::ZERO);
-        debug_assert_eq!(_old, None);
+        #[cfg(debug_assertions)]
+        {
+            let _old = self.node_id_to_local_id.insert(owner, hir::ItemLocalId::ZERO);
+            debug_assert_eq!(_old, None);
+        }
 
         let item = self.with_def_id_parent(def_id, f);
         debug_assert_eq!(def_id, item.def_id().def_id);
@@ -614,7 +574,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
         self.attrs = current_attrs;
         self.bodies = current_bodies;
-        self.node_id_to_local_id = current_node_ids;
+        self.ident_and_label_to_local_id = current_ident_and_label_to_local_id;
+
+        #[cfg(debug_assertions)]
+        {
+            self.node_id_to_local_id = current_node_id_to_local_id;
+        }
         self.trait_map = current_trait_map;
         self.current_hir_id_owner = current_owner;
         self.item_local_id_counter = current_local_counter;
@@ -632,27 +597,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         result
     }
 
-    /// Installs the remapping `remap` in scope while `f` is being executed.
-    /// This causes references to the `LocalDefId` keys to be changed to
-    /// refer to the values instead.
-    ///
-    /// The remapping is used when one piece of AST expands to multiple
-    /// pieces of HIR. For example, the function `fn foo<'a>(...) -> impl Debug + 'a`,
-    /// expands to both a function definition (`foo`) and a TAIT for the return value,
-    /// both of which have a lifetime parameter `'a`. The remapping allows us to
-    /// rewrite the `'a` in the return value to refer to the
-    /// `'a` declared on the TAIT, instead of the function.
-    fn with_remapping<R>(
-        &mut self,
-        remap: LocalDefIdMap<LocalDefId>,
-        f: impl FnOnce(&mut Self) -> R,
-    ) -> R {
-        self.generics_def_id_map.push(remap);
-        let res = f(self);
-        self.generics_def_id_map.pop();
-        res
-    }
-
     fn make_owner_info(&mut self, node: hir::OwnerNode<'hir>) -> &'hir hir::OwnerInfo<'hir> {
         let attrs = std::mem::take(&mut self.attrs);
         let mut bodies = std::mem::take(&mut self.bodies);
@@ -680,39 +624,37 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         self.arena.alloc(hir::OwnerInfo { nodes, parenting, attrs, trait_map })
     }
 
-    /// This method allocates a new `HirId` for the given `NodeId` and stores it in
-    /// the `LoweringContext`'s `NodeId => HirId` map.
+    /// This method allocates a new `HirId` for the given `NodeId`.
     /// Take care not to call this method if the resulting `HirId` is then not
     /// actually used in the HIR, as that would trigger an assertion in the
     /// `HirIdValidator` later on, which makes sure that all `NodeId`s got mapped
-    /// properly. Calling the method twice with the same `NodeId` is fine though.
+    /// properly. Calling the method twice with the same `NodeId` is also forbidden.
     #[instrument(level = "debug", skip(self), ret)]
     fn lower_node_id(&mut self, ast_node_id: NodeId) -> HirId {
         assert_ne!(ast_node_id, DUMMY_NODE_ID);
 
-        match self.node_id_to_local_id.entry(ast_node_id) {
-            Entry::Occupied(o) => HirId { owner: self.current_hir_id_owner, local_id: *o.get() },
-            Entry::Vacant(v) => {
-                // Generate a new `HirId`.
-                let owner = self.current_hir_id_owner;
-                let local_id = self.item_local_id_counter;
-                let hir_id = HirId { owner, local_id };
-
-                v.insert(local_id);
-                self.item_local_id_counter.increment_by(1);
+        let owner = self.current_hir_id_owner;
+        let local_id = self.item_local_id_counter;
+        assert_ne!(local_id, hir::ItemLocalId::ZERO);
+        self.item_local_id_counter.increment_by(1);
+        let hir_id = HirId { owner, local_id };
 
-                assert_ne!(local_id, hir::ItemLocalId::ZERO);
-                if let Some(def_id) = self.opt_local_def_id(ast_node_id) {
-                    self.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id)));
-                }
+        if let Some(def_id) = self.opt_local_def_id(ast_node_id) {
+            self.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id)));
+        }
 
-                if let Some(traits) = self.resolver.trait_map.remove(&ast_node_id) {
-                    self.trait_map.insert(hir_id.local_id, traits.into_boxed_slice());
-                }
+        if let Some(traits) = self.resolver.trait_map.remove(&ast_node_id) {
+            self.trait_map.insert(hir_id.local_id, traits.into_boxed_slice());
+        }
 
-                hir_id
-            }
+        // Check whether the same `NodeId` is lowered more than once.
+        #[cfg(debug_assertions)]
+        {
+            let old = self.node_id_to_local_id.insert(ast_node_id, local_id);
+            assert_eq!(old, None);
         }
+
+        hir_id
     }
 
     /// Generate a new `HirId` without a backing `NodeId`.
@@ -729,7 +671,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     fn lower_res(&mut self, res: Res<NodeId>) -> Res {
         let res: Result<Res, ()> = res.apply_id(|id| {
             let owner = self.current_hir_id_owner;
-            let local_id = self.node_id_to_local_id.get(&id).copied().ok_or(())?;
+            let local_id = self.ident_and_label_to_local_id.get(&id).copied().ok_or(())?;
             Ok(HirId { owner, local_id })
         });
         trace!(?res);
@@ -1474,7 +1416,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     fn lower_opaque_impl_trait(
         &mut self,
         span: Span,
-        origin: hir::OpaqueTyOrigin,
+        origin: hir::OpaqueTyOrigin<LocalDefId>,
         opaque_ty_node_id: NodeId,
         bounds: &GenericBounds,
         itctx: ImplTraitContext,
@@ -1486,27 +1428,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         // frequently opened issues show.
         let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None);
 
-        // Whether this opaque always captures lifetimes in scope.
-        // Right now, this is all RPITIT and TAITs, and when `lifetime_capture_rules_2024`
-        // is enabled. We don't check the span of the edition, since this is done
-        // on a per-opaque basis to account for nested opaques.
-        let always_capture_in_scope = match origin {
-            _ if self.tcx.features().lifetime_capture_rules_2024() => true,
-            hir::OpaqueTyOrigin::TyAlias { .. } => true,
-            hir::OpaqueTyOrigin::FnReturn { in_trait_or_impl, .. } => in_trait_or_impl.is_some(),
-            hir::OpaqueTyOrigin::AsyncFn { .. } => {
-                unreachable!("should be using `lower_coroutine_fn_ret_ty`")
-            }
-        };
-        let captured_lifetimes_to_duplicate = lifetime_collector::lifetimes_for_opaque(
-            self.resolver,
-            always_capture_in_scope,
-            opaque_ty_node_id,
-            bounds,
-            span,
-        );
-        debug!(?captured_lifetimes_to_duplicate);
-
         // Feature gate for RPITIT + use<..>
         match origin {
             rustc_hir::OpaqueTyOrigin::FnReturn { in_trait_or_impl: Some(_), .. } => {
@@ -1529,22 +1450,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             _ => {}
         }
 
-        self.lower_opaque_inner(
-            opaque_ty_node_id,
-            origin,
-            captured_lifetimes_to_duplicate,
-            span,
-            opaque_ty_span,
-            |this| this.lower_param_bounds(bounds, itctx),
-        )
+        self.lower_opaque_inner(opaque_ty_node_id, origin, opaque_ty_span, |this| {
+            this.lower_param_bounds(bounds, itctx)
+        })
     }
 
     fn lower_opaque_inner(
         &mut self,
         opaque_ty_node_id: NodeId,
-        origin: hir::OpaqueTyOrigin,
-        captured_lifetimes_to_duplicate: FxIndexSet<Lifetime>,
-        span: Span,
+        origin: hir::OpaqueTyOrigin<LocalDefId>,
         opaque_ty_span: Span,
         lower_item_bounds: impl FnOnce(&mut Self) -> &'hir [hir::GenericBound<'hir>],
     ) -> hir::TyKind<'hir> {
@@ -1552,145 +1466,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let opaque_ty_hir_id = self.lower_node_id(opaque_ty_node_id);
         debug!(?opaque_ty_def_id, ?opaque_ty_hir_id);
 
-        // Map from captured (old) lifetime to synthetic (new) lifetime.
-        // Used to resolve lifetimes in the bounds of the opaque.
-        let mut captured_to_synthesized_mapping = LocalDefIdMap::default();
-        // List of (early-bound) synthetic lifetimes that are owned by the opaque.
-        // This is used to create the `hir::Generics` owned by the opaque.
-        let mut synthesized_lifetime_definitions = vec![];
-        // Pairs of lifetime arg (that resolves to the captured lifetime)
-        // and the def-id of the (early-bound) synthetic lifetime definition.
-        // This is used both to create generics for the `TyKind::OpaqueDef` that
-        // we return, and also as a captured lifetime mapping for RPITITs.
-        let mut synthesized_lifetime_args = vec![];
-
-        for lifetime in captured_lifetimes_to_duplicate {
-            let res = self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error);
-            let (old_def_id, missing_kind) = match res {
-                LifetimeRes::Param { param: old_def_id, binder: _ } => (old_def_id, None),
-
-                LifetimeRes::Fresh { param, kind, .. } => {
-                    debug_assert_eq!(lifetime.ident.name, kw::UnderscoreLifetime);
-                    if let Some(old_def_id) = self.orig_opt_local_def_id(param) {
-                        (old_def_id, Some(kind))
-                    } else {
-                        self.dcx()
-                            .span_delayed_bug(lifetime.ident.span, "no def-id for fresh lifetime");
-                        continue;
-                    }
-                }
-
-                // Opaques do not capture `'static`
-                LifetimeRes::Static { .. } | LifetimeRes::Error => {
-                    continue;
-                }
-
-                res => {
-                    let bug_msg = format!(
-                        "Unexpected lifetime resolution {:?} for {:?} at {:?}",
-                        res, lifetime.ident, lifetime.ident.span
-                    );
-                    span_bug!(lifetime.ident.span, "{}", bug_msg);
-                }
-            };
-
-            if captured_to_synthesized_mapping.get(&old_def_id).is_none() {
-                // Create a new lifetime parameter local to the opaque.
-                let duplicated_lifetime_node_id = self.next_node_id();
-                let duplicated_lifetime_def_id = self.create_def(
-                    opaque_ty_def_id,
-                    duplicated_lifetime_node_id,
-                    lifetime.ident.name,
-                    DefKind::LifetimeParam,
-                    self.lower_span(lifetime.ident.span),
-                );
-                captured_to_synthesized_mapping.insert(old_def_id, duplicated_lifetime_def_id);
-                // FIXME: Instead of doing this, we could move this whole loop
-                // into the `with_hir_id_owner`, then just directly construct
-                // the `hir::GenericParam` here.
-                synthesized_lifetime_definitions.push((
-                    duplicated_lifetime_node_id,
-                    duplicated_lifetime_def_id,
-                    self.lower_ident(lifetime.ident),
-                    missing_kind,
-                ));
-
-                // Now make an arg that we can use for the generic params of the opaque tykind.
-                let id = self.next_node_id();
-                let lifetime_arg = self.new_named_lifetime_with_res(id, lifetime.ident, res);
-                let duplicated_lifetime_def_id = self.local_def_id(duplicated_lifetime_node_id);
-                synthesized_lifetime_args.push((lifetime_arg, duplicated_lifetime_def_id))
-            }
-        }
-
         let opaque_ty_def = self.with_def_id_parent(opaque_ty_def_id, |this| {
-            // Install the remapping from old to new (if any). This makes sure that
-            // any lifetimes that would have resolved to the def-id of captured
-            // lifetimes are remapped to the new *synthetic* lifetimes of the opaque.
-            let bounds = this
-                .with_remapping(captured_to_synthesized_mapping, |this| lower_item_bounds(this));
-
-            let generic_params =
-                this.arena.alloc_from_iter(synthesized_lifetime_definitions.iter().map(
-                    |&(new_node_id, new_def_id, ident, missing_kind)| {
-                        let hir_id = this.lower_node_id(new_node_id);
-                        let (name, kind) = if ident.name == kw::UnderscoreLifetime {
-                            (
-                                hir::ParamName::Fresh,
-                                hir::LifetimeParamKind::Elided(
-                                    missing_kind.unwrap_or(MissingLifetimeKind::Underscore),
-                                ),
-                            )
-                        } else {
-                            (hir::ParamName::Plain(ident), hir::LifetimeParamKind::Explicit)
-                        };
-
-                        hir::GenericParam {
-                            hir_id,
-                            def_id: new_def_id,
-                            name,
-                            span: ident.span,
-                            pure_wrt_drop: false,
-                            kind: hir::GenericParamKind::Lifetime { kind },
-                            colon_span: None,
-                            source: hir::GenericParamSource::Generics,
-                        }
-                    },
-                ));
-            debug!("lower_async_fn_ret_ty: generic_params={:#?}", generic_params);
-
-            let lifetime_mapping = self.arena.alloc_slice(&synthesized_lifetime_args);
-
-            trace!("registering opaque type with id {:#?}", opaque_ty_def_id);
+            let bounds = lower_item_bounds(this);
             let opaque_ty_def = hir::OpaqueTy {
                 hir_id: opaque_ty_hir_id,
                 def_id: opaque_ty_def_id,
-                generics: this.arena.alloc(hir::Generics {
-                    params: generic_params,
-                    predicates: &[],
-                    has_where_clause_predicates: false,
-                    where_clause_span: this.lower_span(span),
-                    span: this.lower_span(span),
-                }),
                 bounds,
                 origin,
-                lifetime_mapping,
                 span: this.lower_span(opaque_ty_span),
             };
             this.arena.alloc(opaque_ty_def)
         });
 
-        let generic_args = self.arena.alloc_from_iter(
-            synthesized_lifetime_args
-                .iter()
-                .map(|(lifetime, _)| hir::GenericArg::Lifetime(*lifetime)),
-        );
-
-        // Create the `Foo<...>` reference itself. Note that the `type
-        // Foo = impl Trait` is, internally, created as a child of the
-        // async fn, so the *type parameters* are inherited. It's
-        // only the lifetime parameters that we must supply.
-        hir::TyKind::OpaqueDef(opaque_ty_def, generic_args)
+        hir::TyKind::OpaqueDef(opaque_ty_def)
     }
 
     fn lower_precise_capturing_args(
@@ -1865,20 +1653,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             CoroutineKind::Async { return_impl_trait_id, .. } => (return_impl_trait_id, None),
             CoroutineKind::Gen { return_impl_trait_id, .. } => (return_impl_trait_id, None),
             CoroutineKind::AsyncGen { return_impl_trait_id, .. } => {
-                (return_impl_trait_id, Some(self.allow_async_iterator.clone()))
+                (return_impl_trait_id, Some(Lrc::clone(&self.allow_async_iterator)))
             }
         };
 
         let opaque_ty_span =
             self.mark_span_with_reason(DesugaringKind::Async, span, allowed_features);
 
-        let captured_lifetimes = self
-            .resolver
-            .extra_lifetime_params(opaque_ty_node_id)
-            .into_iter()
-            .map(|(ident, id, _)| Lifetime { id, ident })
-            .collect();
-
         let in_trait_or_impl = match fn_kind {
             FnDeclKind::Trait => Some(hir::RpitContext::Trait),
             FnDeclKind::Impl => Some(hir::RpitContext::TraitImpl),
@@ -1889,8 +1670,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let opaque_ty_ref = self.lower_opaque_inner(
             opaque_ty_node_id,
             hir::OpaqueTyOrigin::AsyncFn { parent: fn_def_id, in_trait_or_impl },
-            captured_lifetimes,
-            span,
             opaque_ty_span,
             |this| {
                 let bound = this.lower_coroutine_fn_output_type_to_bound(
@@ -1987,10 +1766,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         res: LifetimeRes,
     ) -> &'hir hir::Lifetime {
         let res = match res {
-            LifetimeRes::Param { param, .. } => {
-                let param = self.get_remapped_def_id(param);
-                hir::LifetimeName::Param(param)
-            }
+            LifetimeRes::Param { param, .. } => hir::LifetimeName::Param(param),
             LifetimeRes::Fresh { param, .. } => {
                 let param = self.local_def_id(param);
                 hir::LifetimeName::Param(param)
diff --git a/compiler/rustc_ast_lowering/src/lifetime_collector.rs b/compiler/rustc_ast_lowering/src/lifetime_collector.rs
deleted file mode 100644
index 8d47c856bdd..00000000000
--- a/compiler/rustc_ast_lowering/src/lifetime_collector.rs
+++ /dev/null
@@ -1,151 +0,0 @@
-use rustc_ast::visit::{self, BoundKind, LifetimeCtxt, Visitor};
-use rustc_ast::{
-    GenericBound, GenericBounds, Lifetime, NodeId, PathSegment, PolyTraitRef, Ty, TyKind,
-};
-use rustc_data_structures::fx::FxIndexSet;
-use rustc_hir::def::{DefKind, LifetimeRes, Res};
-use rustc_middle::span_bug;
-use rustc_middle::ty::ResolverAstLowering;
-use rustc_span::Span;
-use rustc_span::symbol::{Ident, kw};
-
-use super::ResolverAstLoweringExt;
-
-struct LifetimeCollectVisitor<'ast> {
-    resolver: &'ast mut ResolverAstLowering,
-    always_capture_in_scope: bool,
-    current_binders: Vec<NodeId>,
-    collected_lifetimes: FxIndexSet<Lifetime>,
-}
-
-impl<'ast> LifetimeCollectVisitor<'ast> {
-    fn new(resolver: &'ast mut ResolverAstLowering, always_capture_in_scope: bool) -> Self {
-        Self {
-            resolver,
-            always_capture_in_scope,
-            current_binders: Vec::new(),
-            collected_lifetimes: FxIndexSet::default(),
-        }
-    }
-
-    fn visit_opaque(&mut self, opaque_ty_node_id: NodeId, bounds: &'ast GenericBounds, span: Span) {
-        // If we're edition 2024 or within a TAIT or RPITIT, *and* there is no
-        // `use<>` statement to override the default capture behavior, then
-        // capture all of the in-scope lifetimes.
-        if (self.always_capture_in_scope || span.at_least_rust_2024())
-            && bounds.iter().all(|bound| !matches!(bound, GenericBound::Use(..)))
-        {
-            for (ident, id, _) in self.resolver.extra_lifetime_params(opaque_ty_node_id) {
-                self.record_lifetime_use(Lifetime { id, ident });
-            }
-        }
-
-        // We also recurse on the bounds to make sure we capture all the lifetimes
-        // mentioned in the bounds. These may disagree with the `use<>` list, in which
-        // case we will error on these later. We will also recurse to visit any
-        // nested opaques, which may *implicitly* capture lifetimes.
-        for bound in bounds {
-            self.visit_param_bound(bound, BoundKind::Bound);
-        }
-    }
-
-    fn record_lifetime_use(&mut self, lifetime: Lifetime) {
-        match self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error) {
-            LifetimeRes::Param { binder, .. } | LifetimeRes::Fresh { binder, .. } => {
-                if !self.current_binders.contains(&binder) {
-                    self.collected_lifetimes.insert(lifetime);
-                }
-            }
-            LifetimeRes::Static { .. } | LifetimeRes::Error => {
-                self.collected_lifetimes.insert(lifetime);
-            }
-            LifetimeRes::Infer => {}
-            res => {
-                let bug_msg = format!(
-                    "Unexpected lifetime resolution {:?} for {:?} at {:?}",
-                    res, lifetime.ident, lifetime.ident.span
-                );
-                span_bug!(lifetime.ident.span, "{}", bug_msg);
-            }
-        }
-    }
-
-    /// This collect lifetimes that are elided, for nodes like `Foo<T>` where there are no explicit
-    /// lifetime nodes. Is equivalent to having "pseudo" nodes introduced for each of the node ids
-    /// in the list start..end.
-    fn record_elided_anchor(&mut self, node_id: NodeId, span: Span) {
-        if let Some(LifetimeRes::ElidedAnchor { start, end }) =
-            self.resolver.get_lifetime_res(node_id)
-        {
-            for i in start..end {
-                let lifetime = Lifetime { id: i, ident: Ident::new(kw::UnderscoreLifetime, span) };
-                self.record_lifetime_use(lifetime);
-            }
-        }
-    }
-}
-
-impl<'ast> Visitor<'ast> for LifetimeCollectVisitor<'ast> {
-    fn visit_lifetime(&mut self, lifetime: &'ast Lifetime, _: LifetimeCtxt) {
-        self.record_lifetime_use(*lifetime);
-    }
-
-    fn visit_path_segment(&mut self, path_segment: &'ast PathSegment) {
-        self.record_elided_anchor(path_segment.id, path_segment.ident.span);
-        visit::walk_path_segment(self, path_segment);
-    }
-
-    fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef) {
-        self.current_binders.push(t.trait_ref.ref_id);
-
-        visit::walk_poly_trait_ref(self, t);
-
-        self.current_binders.pop();
-    }
-
-    fn visit_ty(&mut self, t: &'ast Ty) {
-        match &t.kind {
-            TyKind::Path(None, _) => {
-                // We can sometimes encounter bare trait objects
-                // which are represented in AST as paths.
-                if let Some(partial_res) = self.resolver.get_partial_res(t.id)
-                    && let Some(Res::Def(DefKind::Trait | DefKind::TraitAlias, _)) =
-                        partial_res.full_res()
-                {
-                    self.current_binders.push(t.id);
-                    visit::walk_ty(self, t);
-                    self.current_binders.pop();
-                } else {
-                    visit::walk_ty(self, t);
-                }
-            }
-            TyKind::BareFn(_) => {
-                self.current_binders.push(t.id);
-                visit::walk_ty(self, t);
-                self.current_binders.pop();
-            }
-            TyKind::Ref(None, _) | TyKind::PinnedRef(None, _) => {
-                self.record_elided_anchor(t.id, t.span);
-                visit::walk_ty(self, t);
-            }
-            TyKind::ImplTrait(opaque_ty_node_id, bounds) => {
-                self.visit_opaque(*opaque_ty_node_id, bounds, t.span)
-            }
-            _ => {
-                visit::walk_ty(self, t);
-            }
-        }
-    }
-}
-
-pub(crate) fn lifetimes_for_opaque(
-    resolver: &mut ResolverAstLowering,
-    always_capture_in_scope: bool,
-    opaque_ty_node_id: NodeId,
-    bounds: &GenericBounds,
-    span: Span,
-) -> FxIndexSet<Lifetime> {
-    let mut visitor = LifetimeCollectVisitor::new(resolver, always_capture_in_scope);
-    visitor.visit_opaque(opaque_ty_node_id, bounds, span);
-    visitor.collected_lifetimes
-}
diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs
index 760f84564f1..ace7bfb5c73 100644
--- a/compiler/rustc_ast_lowering/src/pat.rs
+++ b/compiler/rustc_ast_lowering/src/pat.rs
@@ -21,13 +21,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     fn lower_pat_mut(&mut self, mut pattern: &Pat) -> hir::Pat<'hir> {
         ensure_sufficient_stack(|| {
             // loop here to avoid recursion
+            let pat_hir_id = self.lower_node_id(pattern.id);
             let node = loop {
                 match &pattern.kind {
                     PatKind::Wild => break hir::PatKind::Wild,
                     PatKind::Never => break hir::PatKind::Never,
                     PatKind::Ident(binding_mode, ident, sub) => {
                         let lower_sub = |this: &mut Self| sub.as_ref().map(|s| this.lower_pat(s));
-                        break self.lower_pat_ident(pattern, *binding_mode, *ident, lower_sub);
+                        break self.lower_pat_ident(
+                            pattern,
+                            *binding_mode,
+                            *ident,
+                            pat_hir_id,
+                            lower_sub,
+                        );
                     }
                     PatKind::Lit(e) => {
                         break hir::PatKind::Lit(self.lower_expr_within_pat(e, false));
@@ -119,7 +126,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 }
             };
 
-            self.pat_with_node_id_of(pattern, node)
+            self.pat_with_node_id_of(pattern, node, pat_hir_id)
         })
     }
 
@@ -187,10 +194,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let mut prev_rest_span = None;
 
         // Lowers `$bm $ident @ ..` to `$bm $ident @ _`.
-        let lower_rest_sub = |this: &mut Self, pat, &ann, &ident, sub| {
-            let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub));
-            let node = this.lower_pat_ident(pat, ann, ident, lower_sub);
-            this.pat_with_node_id_of(pat, node)
+        let lower_rest_sub = |this: &mut Self, pat: &Pat, &ann, &ident, sub: &Pat| {
+            let sub_hir_id = this.lower_node_id(sub.id);
+            let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub, sub_hir_id));
+            let pat_hir_id = this.lower_node_id(pat.id);
+            let node = this.lower_pat_ident(pat, ann, ident, pat_hir_id, lower_sub);
+            this.pat_with_node_id_of(pat, node, pat_hir_id)
         };
 
         let mut iter = pats.iter();
@@ -200,7 +209,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 // Found a sub-slice pattern `..`. Record, lower it to `_`, and stop here.
                 PatKind::Rest => {
                     prev_rest_span = Some(pat.span);
-                    slice = Some(self.pat_wild_with_node_id_of(pat));
+                    let hir_id = self.lower_node_id(pat.id);
+                    slice = Some(self.pat_wild_with_node_id_of(pat, hir_id));
                     break;
                 }
                 // Found a sub-slice pattern `$binding_mode $ident @ ..`.
@@ -248,19 +258,35 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         p: &Pat,
         annotation: BindingMode,
         ident: Ident,
+        hir_id: hir::HirId,
         lower_sub: impl FnOnce(&mut Self) -> Option<&'hir hir::Pat<'hir>>,
     ) -> hir::PatKind<'hir> {
         match self.resolver.get_partial_res(p.id).map(|d| d.expect_full_res()) {
             // `None` can occur in body-less function signatures
             res @ (None | Some(Res::Local(_))) => {
-                let canonical_id = match res {
-                    Some(Res::Local(id)) => id,
-                    _ => p.id,
+                let binding_id = match res {
+                    Some(Res::Local(id)) => {
+                        // In `Or` patterns like `VariantA(s) | VariantB(s, _)`, multiple identifier patterns
+                        // will be resolved to the same `Res::Local`. Thus they just share a single
+                        // `HirId`.
+                        if id == p.id {
+                            self.ident_and_label_to_local_id.insert(id, hir_id.local_id);
+                            hir_id
+                        } else {
+                            hir::HirId {
+                                owner: self.current_hir_id_owner,
+                                local_id: self.ident_and_label_to_local_id[&id],
+                            }
+                        }
+                    }
+                    _ => {
+                        self.ident_and_label_to_local_id.insert(p.id, hir_id.local_id);
+                        hir_id
+                    }
                 };
-
                 hir::PatKind::Binding(
                     annotation,
-                    self.lower_node_id(canonical_id),
+                    binding_id,
                     self.lower_ident(ident),
                     lower_sub(self),
                 )
@@ -280,18 +306,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         }
     }
 
-    fn pat_wild_with_node_id_of(&mut self, p: &Pat) -> &'hir hir::Pat<'hir> {
-        self.arena.alloc(self.pat_with_node_id_of(p, hir::PatKind::Wild))
+    fn pat_wild_with_node_id_of(&mut self, p: &Pat, hir_id: hir::HirId) -> &'hir hir::Pat<'hir> {
+        self.arena.alloc(self.pat_with_node_id_of(p, hir::PatKind::Wild, hir_id))
     }
 
-    /// Construct a `Pat` with the `HirId` of `p.id` lowered.
-    fn pat_with_node_id_of(&mut self, p: &Pat, kind: hir::PatKind<'hir>) -> hir::Pat<'hir> {
-        hir::Pat {
-            hir_id: self.lower_node_id(p.id),
-            kind,
-            span: self.lower_span(p.span),
-            default_binding_modes: true,
-        }
+    /// Construct a `Pat` with the `HirId` of `p.id` already lowered.
+    fn pat_with_node_id_of(
+        &mut self,
+        p: &Pat,
+        kind: hir::PatKind<'hir>,
+        hir_id: hir::HirId,
+    ) -> hir::Pat<'hir> {
+        hir::Pat { hir_id, kind, span: self.lower_span(p.span), default_binding_modes: true }
     }
 
     /// Emit a friendly error for extra `..` patterns in a tuple/tuple struct/slice pattern.
diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs
index 6a0f03c8b31..133793e26ea 100644
--- a/compiler/rustc_ast_lowering/src/path.rs
+++ b/compiler/rustc_ast_lowering/src/path.rs
@@ -73,7 +73,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let bound_modifier_allowed_features = if let Res::Def(DefKind::Trait, async_def_id) = res
             && self.tcx.async_fn_trait_kind_from_def_id(async_def_id).is_some()
         {
-            Some(self.allow_async_fn_traits.clone())
+            Some(Lrc::clone(&self.allow_async_fn_traits))
         } else {
             None
         };
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 0a4f86d4822..dee48586f34 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -677,9 +677,8 @@ impl<'a> AstValidator<'a> {
                 Self::check_decl_no_pat(&bfty.decl, |span, _, _| {
                     self.dcx().emit_err(errors::PatternFnPointer { span });
                 });
-                if let Extern::Implicit(_) = bfty.ext {
-                    let sig_span = self.sess.source_map().next_point(ty.span.shrink_to_lo());
-                    self.maybe_lint_missing_abi(sig_span, ty.id);
+                if let Extern::Implicit(extern_span) = bfty.ext {
+                    self.maybe_lint_missing_abi(extern_span, ty.id);
                 }
             }
             TyKind::TraitObject(bounds, ..) => {
@@ -953,7 +952,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 walk_list!(self, visit_attribute, &item.attrs);
                 return; // Avoid visiting again.
             }
-            ItemKind::ForeignMod(ForeignMod { abi, safety, .. }) => {
+            ItemKind::ForeignMod(ForeignMod { extern_span, abi, safety, .. }) => {
                 self.with_in_extern_mod(*safety, |this| {
                     let old_item = mem::replace(&mut this.extern_mod, Some(item.span));
                     this.visibility_not_permitted(
@@ -977,7 +976,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                     }
 
                     if abi.is_none() {
-                        this.maybe_lint_missing_abi(item.span, item.id);
+                        this.maybe_lint_missing_abi(*extern_span, item.id);
                     }
                     visit::walk_item(this, item);
                     this.extern_mod = old_item;
@@ -1350,13 +1349,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
         if let FnKind::Fn(
             _,
             _,
-            FnSig { span: sig_span, header: FnHeader { ext: Extern::Implicit(_), .. }, .. },
+            FnSig { header: FnHeader { ext: Extern::Implicit(extern_span), .. }, .. },
             _,
             _,
             _,
         ) = fk
         {
-            self.maybe_lint_missing_abi(*sig_span, id);
+            self.maybe_lint_missing_abi(*extern_span, id);
         }
 
         // Functions without bodies cannot have patterns.
diff --git a/compiler/rustc_ast_pretty/Cargo.toml b/compiler/rustc_ast_pretty/Cargo.toml
index 9ae5c9b3cec..f290fedcd8b 100644
--- a/compiler/rustc_ast_pretty/Cargo.toml
+++ b/compiler/rustc_ast_pretty/Cargo.toml
@@ -7,6 +7,7 @@ edition = "2021"
 # tidy-alphabetical-start
 itertools = "0.12"
 rustc_ast = { path = "../rustc_ast" }
+rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_lexer = { path = "../rustc_lexer" }
 rustc_span = { path = "../rustc_span" }
 thin-vec = "0.2.12"
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index 1e18f0779f0..de9f5187be7 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -21,6 +21,7 @@ use rustc_ast::{
     GenericBound, InlineAsmOperand, InlineAsmOptions, InlineAsmRegOrRegClass,
     InlineAsmTemplatePiece, PatKind, RangeEnd, RangeSyntax, Safety, SelfKind, Term, attr,
 };
+use rustc_data_structures::sync::Lrc;
 use rustc_span::edition::Edition;
 use rustc_span::source_map::{SourceMap, Spanned};
 use rustc_span::symbol::{Ident, IdentPrinter, Symbol, kw, sym};
@@ -105,7 +106,7 @@ fn split_block_comment_into_lines(text: &str, col: CharPos) -> Vec<String> {
 fn gather_comments(sm: &SourceMap, path: FileName, src: String) -> Vec<Comment> {
     let sm = SourceMap::new(sm.path_mapping().clone());
     let source_file = sm.new_source_file(path, src);
-    let text = (*source_file.src.as_ref().unwrap()).clone();
+    let text = Lrc::clone(&(*source_file.src.as_ref().unwrap()));
 
     let text: &str = text.as_str();
     let start_bpos = source_file.start_pos;
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index c687be69b1a..511313cca6f 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -1489,6 +1489,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
             &borrow_msg,
             &value_msg,
         );
+        self.note_due_to_edition_2024_opaque_capture_rules(borrow, &mut err);
 
         borrow_spans.var_path_only_subdiag(&mut err, crate::InitializationRequiringAction::Borrow);
 
@@ -1524,7 +1525,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                 matches!(
                     adj.kind,
                     ty::adjustment::Adjust::Borrow(ty::adjustment::AutoBorrow::Ref(
-                        _,
                         ty::adjustment::AutoBorrowMutability::Not
                             | ty::adjustment::AutoBorrowMutability::Mut {
                                 allow_two_phase_borrow: ty::adjustment::AllowTwoPhase::No
@@ -1561,6 +1561,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
             borrow_span,
             &self.describe_any_place(borrow.borrowed_place.as_ref()),
         );
+        self.note_due_to_edition_2024_opaque_capture_rules(borrow, &mut err);
+
         borrow_spans.var_subdiag(&mut err, Some(borrow.kind), |kind, var_span| {
             use crate::session_diagnostics::CaptureVarCause::*;
             let place = &borrow.borrowed_place;
@@ -1820,6 +1822,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                 unreachable!()
             }
         };
+        self.note_due_to_edition_2024_opaque_capture_rules(issued_borrow, &mut err);
 
         if issued_spans == borrow_spans {
             borrow_spans.var_subdiag(&mut err, Some(gen_borrow_kind), |kind, var_span| {
@@ -2860,7 +2863,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
 
         debug!(?place_desc, ?explanation);
 
-        let err = match (place_desc, explanation) {
+        let mut err = match (place_desc, explanation) {
             // If the outlives constraint comes from inside the closure,
             // for example:
             //
@@ -2939,6 +2942,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                 explanation,
             ),
         };
+        self.note_due_to_edition_2024_opaque_capture_rules(borrow, &mut err);
 
         self.buffer_error(err);
     }
@@ -3777,6 +3781,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         }
 
         let mut err = self.cannot_assign_to_borrowed(span, loan_span, &descr_place);
+        self.note_due_to_edition_2024_opaque_capture_rules(loan, &mut err);
 
         loan_spans.var_subdiag(&mut err, Some(loan.kind), |kind, var_span| {
             use crate::session_diagnostics::CaptureVarCause::*;
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 801c7af2de7..3b600716036 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -48,6 +48,7 @@ mod conflict_errors;
 mod explain_borrow;
 mod move_errors;
 mod mutability_errors;
+mod opaque_suggestions;
 mod region_errors;
 
 pub(crate) use bound_region_errors::{ToUniverseInfo, UniverseInfo};
diff --git a/compiler/rustc_borrowck/src/diagnostics/opaque_suggestions.rs b/compiler/rustc_borrowck/src/diagnostics/opaque_suggestions.rs
new file mode 100644
index 00000000000..bfd7e83501c
--- /dev/null
+++ b/compiler/rustc_borrowck/src/diagnostics/opaque_suggestions.rs
@@ -0,0 +1,224 @@
+#![allow(rustc::diagnostic_outside_of_impl)]
+#![allow(rustc::untranslatable_diagnostic)]
+
+use std::ops::ControlFlow;
+
+use either::Either;
+use rustc_data_structures::fx::FxIndexSet;
+use rustc_errors::{Applicability, Diag};
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_middle::mir::{self, ConstraintCategory, Location};
+use rustc_middle::ty::{
+    self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
+};
+use rustc_span::Symbol;
+
+use crate::MirBorrowckCtxt;
+use crate::borrow_set::BorrowData;
+use crate::consumers::RegionInferenceContext;
+use crate::type_check::Locations;
+
+impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
+    /// Try to note when an opaque is involved in a borrowck error and that
+    /// opaque captures lifetimes due to edition 2024.
+    // FIXME: This code is otherwise somewhat general, and could easily be adapted
+    // to explain why other things overcapture... like async fn and RPITITs.
+    pub(crate) fn note_due_to_edition_2024_opaque_capture_rules(
+        &self,
+        borrow: &BorrowData<'tcx>,
+        diag: &mut Diag<'_>,
+    ) {
+        // We look at all the locals. Why locals? Because it's the best thing
+        // I could think of that's correlated with the *instantiated* higer-ranked
+        // binder for calls, since we don't really store those anywhere else.
+        for ty in self.body.local_decls.iter().map(|local| local.ty) {
+            if !ty.has_opaque_types() {
+                continue;
+            }
+
+            let tcx = self.infcx.tcx;
+            let ControlFlow::Break((opaque_def_id, offending_region_idx, location)) = ty
+                .visit_with(&mut FindOpaqueRegion {
+                    regioncx: &self.regioncx,
+                    tcx,
+                    borrow_region: borrow.region,
+                })
+            else {
+                continue;
+            };
+
+            // If an opaque explicitly captures a lifetime, then no need to point it out.
+            // FIXME: We should be using a better heuristic for `use<>`.
+            if tcx.rendered_precise_capturing_args(opaque_def_id).is_some() {
+                continue;
+            }
+
+            // If one of the opaque's bounds mentions the region, then no need to
+            // point it out, since it would've been captured on edition 2021 as well.
+            //
+            // Also, while we're at it, collect all the lifetimes that the opaque
+            // *does* mention. We'll use that for the `+ use<'a>` suggestion below.
+            let mut visitor = CheckExplicitRegionMentionAndCollectGenerics {
+                tcx,
+                offending_region_idx,
+                seen_opaques: [opaque_def_id].into_iter().collect(),
+                seen_lifetimes: Default::default(),
+            };
+            if tcx
+                .explicit_item_bounds(opaque_def_id)
+                .skip_binder()
+                .visit_with(&mut visitor)
+                .is_break()
+            {
+                continue;
+            }
+
+            // If we successfully located a terminator, then point it out
+            // and provide a suggestion if it's local.
+            match self.body.stmt_at(location) {
+                Either::Right(mir::Terminator { source_info, .. }) => {
+                    diag.span_note(
+                        source_info.span,
+                        "this call may capture more lifetimes than intended, \
+                        because Rust 2024 has adjusted the `impl Trait` lifetime capture rules",
+                    );
+                    let mut seen_generics: Vec<_> =
+                        visitor.seen_lifetimes.iter().map(ToString::to_string).collect();
+                    // Capture all in-scope ty/const params.
+                    seen_generics.extend(
+                        ty::GenericArgs::identity_for_item(tcx, opaque_def_id)
+                            .iter()
+                            .filter(|arg| {
+                                matches!(
+                                    arg.unpack(),
+                                    ty::GenericArgKind::Type(_) | ty::GenericArgKind::Const(_)
+                                )
+                            })
+                            .map(|arg| arg.to_string()),
+                    );
+                    if opaque_def_id.is_local() {
+                        diag.span_suggestion_verbose(
+                            tcx.def_span(opaque_def_id).shrink_to_hi(),
+                            "add a precise capturing bound to avoid overcapturing",
+                            format!(" + use<{}>", seen_generics.join(", ")),
+                            Applicability::MaybeIncorrect,
+                        );
+                    } else {
+                        diag.span_help(
+                            tcx.def_span(opaque_def_id),
+                            format!(
+                                "if you can modify this crate, add a precise \
+                                capturing bound to avoid overcapturing: `+ use<{}>`",
+                                seen_generics.join(", ")
+                            ),
+                        );
+                    }
+                    return;
+                }
+                Either::Left(_) => {}
+            }
+        }
+    }
+}
+
+/// This visitor contains the bulk of the logic for this lint.
+struct FindOpaqueRegion<'a, 'tcx> {
+    tcx: TyCtxt<'tcx>,
+    regioncx: &'a RegionInferenceContext<'tcx>,
+    borrow_region: ty::RegionVid,
+}
+
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for FindOpaqueRegion<'_, 'tcx> {
+    type Result = ControlFlow<(DefId, usize, Location), ()>;
+
+    fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
+        // If we find an opaque in a local ty, then for each of its captured regions,
+        // try to find a path between that captured regions and our borrow region...
+        if let ty::Alias(ty::Opaque, opaque) = *ty.kind()
+            && let hir::OpaqueTyOrigin::FnReturn { parent, in_trait_or_impl: None } =
+                self.tcx.opaque_ty_origin(opaque.def_id)
+        {
+            let variances = self.tcx.variances_of(opaque.def_id);
+            for (idx, (arg, variance)) in std::iter::zip(opaque.args, variances).enumerate() {
+                // Skip uncaptured args.
+                if *variance == ty::Bivariant {
+                    continue;
+                }
+                // We only care about regions.
+                let Some(opaque_region) = arg.as_region() else {
+                    continue;
+                };
+                // Don't try to convert a late-bound region, which shouldn't exist anyways (yet).
+                if opaque_region.is_bound() {
+                    continue;
+                }
+                let opaque_region_vid = self.regioncx.to_region_vid(opaque_region);
+
+                // Find a path between the borrow region and our opaque capture.
+                if let Some((path, _)) =
+                    self.regioncx.find_constraint_paths_between_regions(self.borrow_region, |r| {
+                        r == opaque_region_vid
+                    })
+                {
+                    for constraint in path {
+                        // If we find a call in this path, then check if it defines the opaque.
+                        if let ConstraintCategory::CallArgument(Some(call_ty)) = constraint.category
+                            && let ty::FnDef(call_def_id, _) = *call_ty.kind()
+                            // This function defines the opaque :D
+                            && call_def_id == parent
+                            && let Locations::Single(location) = constraint.locations
+                        {
+                            return ControlFlow::Break((opaque.def_id, idx, location));
+                        }
+                    }
+                }
+            }
+        }
+
+        ty.super_visit_with(self)
+    }
+}
+
+struct CheckExplicitRegionMentionAndCollectGenerics<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    offending_region_idx: usize,
+    seen_opaques: FxIndexSet<DefId>,
+    seen_lifetimes: FxIndexSet<Symbol>,
+}
+
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for CheckExplicitRegionMentionAndCollectGenerics<'tcx> {
+    type Result = ControlFlow<(), ()>;
+
+    fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
+        match *ty.kind() {
+            ty::Alias(ty::Opaque, opaque) => {
+                if self.seen_opaques.insert(opaque.def_id) {
+                    for (bound, _) in self
+                        .tcx
+                        .explicit_item_bounds(opaque.def_id)
+                        .iter_instantiated_copied(self.tcx, opaque.args)
+                    {
+                        bound.visit_with(self)?;
+                    }
+                }
+                ControlFlow::Continue(())
+            }
+            _ => ty.super_visit_with(self),
+        }
+    }
+
+    fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result {
+        match r.kind() {
+            ty::ReEarlyParam(param) => {
+                if param.index as usize == self.offending_region_idx {
+                    ControlFlow::Break(())
+                } else {
+                    self.seen_lifetimes.insert(param.name);
+                    ControlFlow::Continue(())
+                }
+            }
+            _ => ControlFlow::Continue(()),
+        }
+    }
+}
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index b4b8373ac97..6ca7251295d 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -830,7 +830,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
     ///
     /// [`OpaqueDef`]: hir::TyKind::OpaqueDef
     fn get_future_inner_return_ty(&self, hir_ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::Ty<'tcx> {
-        let hir::TyKind::OpaqueDef(opaque_ty, _) = hir_ty.kind else {
+        let hir::TyKind::OpaqueDef(opaque_ty) = hir_ty.kind else {
             span_bug!(
                 hir_ty.span,
                 "lowered return type of async fn is not OpaqueDef: {:?}",
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 698fdafc936..efcee2899c6 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -34,7 +34,7 @@ use rustc_infer::infer::{
 use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::mir::*;
 use rustc_middle::query::Providers;
-use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt};
+use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt, TypingMode};
 use rustc_middle::{bug, span_bug};
 use rustc_mir_dataflow::Analysis;
 use rustc_mir_dataflow::impls::{
@@ -193,9 +193,7 @@ fn do_mir_borrowck<'tcx>(
         .map(|(idx, body)| (idx, MoveData::gather_moves(body, tcx, |_| true)));
 
     let mut flow_inits = MaybeInitializedPlaces::new(tcx, body, &move_data)
-        .into_engine(tcx, body)
-        .pass_name("borrowck")
-        .iterate_to_fixpoint()
+        .iterate_to_fixpoint(tcx, body, Some("borrowck"))
         .into_results_cursor(body);
 
     let locals_are_invalidated_at_exit = tcx.hir().body_owner_kind(def).is_fn_or_closure();
@@ -243,18 +241,21 @@ fn do_mir_borrowck<'tcx>(
     // usage significantly on some benchmarks.
     drop(flow_inits);
 
-    let flow_borrows = Borrows::new(tcx, body, &regioncx, &borrow_set)
-        .into_engine(tcx, body)
-        .pass_name("borrowck")
-        .iterate_to_fixpoint();
-    let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &move_data)
-        .into_engine(tcx, body)
-        .pass_name("borrowck")
-        .iterate_to_fixpoint();
-    let flow_ever_inits = EverInitializedPlaces::new(body, &move_data)
-        .into_engine(tcx, body)
-        .pass_name("borrowck")
-        .iterate_to_fixpoint();
+    let flow_borrows = Borrows::new(tcx, body, &regioncx, &borrow_set).iterate_to_fixpoint(
+        tcx,
+        body,
+        Some("borrowck"),
+    );
+    let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &move_data).iterate_to_fixpoint(
+        tcx,
+        body,
+        Some("borrowck"),
+    );
+    let flow_ever_inits = EverInitializedPlaces::new(body, &move_data).iterate_to_fixpoint(
+        tcx,
+        body,
+        Some("borrowck"),
+    );
 
     let movable_coroutine =
         // The first argument is the coroutine type passed by value
@@ -440,7 +441,7 @@ pub struct BorrowckInferCtxt<'tcx> {
 
 impl<'tcx> BorrowckInferCtxt<'tcx> {
     pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
-        let infcx = tcx.infer_ctxt().with_opaque_type_inference(def_id).build();
+        let infcx = tcx.infer_ctxt().build(TypingMode::analysis_in_body(tcx, def_id));
         BorrowckInferCtxt { infcx, reg_var_to_origin: RefCell::new(Default::default()) }
     }
 
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index 3674053409b..f76603d5679 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -107,13 +107,13 @@ pub(crate) fn compute_regions<'a, 'tcx>(
             param_env,
             body,
             promoted,
-            universal_regions.clone(),
+            Rc::clone(&universal_regions),
             location_table,
             borrow_set,
             &mut all_facts,
             flow_inits,
             move_data,
-            elements.clone(),
+            Rc::clone(&elements),
             upvars,
         );
 
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index e85f529bf0e..d5c2796932e 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -733,7 +733,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         }
 
         // Now take member constraints into account.
-        let member_constraints = self.member_constraints.clone();
+        let member_constraints = Rc::clone(&self.member_constraints);
         for m_c_i in member_constraints.indices(scc_a) {
             self.apply_member_constraint(scc_a, m_c_i, member_constraints.choice_regions(m_c_i));
         }
@@ -1679,7 +1679,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         infcx: &InferCtxt<'tcx>,
         errors_buffer: &mut RegionErrors<'tcx>,
     ) {
-        let member_constraints = self.member_constraints.clone();
+        let member_constraints = Rc::clone(&self.member_constraints);
         for m_c_i in member_constraints.all_indices() {
             debug!(?m_c_i);
             let m_c = &member_constraints[m_c_i];
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index abce98265b3..3a2f5c35c72 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -9,6 +9,7 @@ use rustc_macros::extension;
 use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{
     self, GenericArgKind, GenericArgs, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable,
+    TypingMode,
 };
 use rustc_span::Span;
 use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
@@ -340,14 +341,13 @@ fn check_opaque_type_well_formed<'tcx>(
         parent_def_id = tcx.local_parent(parent_def_id);
     }
 
-    // FIXME(-Znext-solver): We probably should use `&[]` instead of
-    // and prepopulate this `InferCtxt` with known opaque values, rather than
-    // allowing opaque types to be defined and checking them after the fact.
+    // FIXME(#132279): This should eventually use the already defined hidden types
+    // instead. Alternatively we'll entirely remove this function given we also check
+    // the opaque in `check_opaque_meets_bounds` later.
     let infcx = tcx
         .infer_ctxt()
         .with_next_trait_solver(next_trait_solver)
-        .with_opaque_type_inference(parent_def_id)
-        .build();
+        .build(TypingMode::analysis_in_body(tcx, parent_def_id));
     let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
     let identity_args = GenericArgs::identity_for_item(tcx, def_id);
 
@@ -502,7 +502,7 @@ impl<'tcx> LazyOpaqueTyEnv<'tcx> {
         }
 
         let &Self { tcx, def_id, .. } = self;
-        let origin = tcx.opaque_type_origin(def_id);
+        let origin = tcx.local_opaque_ty_origin(def_id);
         let parent = match origin {
             hir::OpaqueTyOrigin::FnReturn { parent, .. }
             | hir::OpaqueTyOrigin::AsyncFn { parent, .. }
@@ -517,7 +517,9 @@ impl<'tcx> LazyOpaqueTyEnv<'tcx> {
             },
         );
 
-        let infcx = tcx.infer_ctxt().build();
+        // FIXME(#132279): It feels wrong to use `non_body_analysis` here given that we're
+        // in a body here.
+        let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
         let ocx = ObligationCtxt::new(&infcx);
 
         let wf_tys = ocx.assumed_wf_types(param_env, parent).unwrap_or_else(|_| {
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index a544d88e832..26919bfd488 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -134,7 +134,7 @@ pub(crate) fn type_check<'a, 'tcx>(
     let mut constraints = MirTypeckRegionConstraints {
         placeholder_indices: PlaceholderIndices::default(),
         placeholder_index_to_region: IndexVec::default(),
-        liveness_constraints: LivenessValues::with_specific_points(elements.clone()),
+        liveness_constraints: LivenessValues::with_specific_points(Rc::clone(&elements)),
         outlives_constraints: OutlivesConstraintSet::default(),
         member_constraints: MemberConstraintSet::default(),
         type_tests: Vec::default(),
@@ -150,7 +150,7 @@ pub(crate) fn type_check<'a, 'tcx>(
         infcx,
         param_env,
         implicit_region_bound,
-        universal_regions.clone(),
+        Rc::clone(&universal_regions),
         &mut constraints,
     );
 
diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
index 892ec3e9585..089b09d06ae 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
@@ -193,7 +193,7 @@ fn make_local_place<'tcx>(
         );
     }
     let place = if is_ssa {
-        if let rustc_target::abi::Abi::ScalarPair(_, _) = layout.abi {
+        if let BackendRepr::ScalarPair(_, _) = layout.backend_repr {
             CPlace::new_var_pair(fx, local, layout)
         } else {
             CPlace::new_var(fx, local, layout)
diff --git a/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs b/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs
index 38c322b5e04..ad0a13dc7e5 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs
@@ -78,19 +78,19 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
     fn get_abi_param(&self, tcx: TyCtxt<'tcx>) -> SmallVec<[AbiParam; 2]> {
         match self.mode {
             PassMode::Ignore => smallvec![],
-            PassMode::Direct(attrs) => match self.layout.abi {
-                Abi::Scalar(scalar) => smallvec![apply_arg_attrs_to_abi_param(
+            PassMode::Direct(attrs) => match self.layout.backend_repr {
+                BackendRepr::Scalar(scalar) => smallvec![apply_arg_attrs_to_abi_param(
                     AbiParam::new(scalar_to_clif_type(tcx, scalar)),
                     attrs
                 )],
-                Abi::Vector { .. } => {
+                BackendRepr::Vector { .. } => {
                     let vector_ty = crate::intrinsics::clif_vector_type(tcx, self.layout);
                     smallvec![AbiParam::new(vector_ty)]
                 }
-                _ => unreachable!("{:?}", self.layout.abi),
+                _ => unreachable!("{:?}", self.layout.backend_repr),
             },
-            PassMode::Pair(attrs_a, attrs_b) => match self.layout.abi {
-                Abi::ScalarPair(a, b) => {
+            PassMode::Pair(attrs_a, attrs_b) => match self.layout.backend_repr {
+                BackendRepr::ScalarPair(a, b) => {
                     let a = scalar_to_clif_type(tcx, a);
                     let b = scalar_to_clif_type(tcx, b);
                     smallvec![
@@ -98,7 +98,7 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
                         apply_arg_attrs_to_abi_param(AbiParam::new(b), attrs_b),
                     ]
                 }
-                _ => unreachable!("{:?}", self.layout.abi),
+                _ => unreachable!("{:?}", self.layout.backend_repr),
             },
             PassMode::Cast { ref cast, pad_i32 } => {
                 assert!(!pad_i32, "padding support not yet implemented");
@@ -130,23 +130,23 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
     fn get_abi_return(&self, tcx: TyCtxt<'tcx>) -> (Option<AbiParam>, Vec<AbiParam>) {
         match self.mode {
             PassMode::Ignore => (None, vec![]),
-            PassMode::Direct(_) => match self.layout.abi {
-                Abi::Scalar(scalar) => {
+            PassMode::Direct(_) => match self.layout.backend_repr {
+                BackendRepr::Scalar(scalar) => {
                     (None, vec![AbiParam::new(scalar_to_clif_type(tcx, scalar))])
                 }
-                Abi::Vector { .. } => {
+                BackendRepr::Vector { .. } => {
                     let vector_ty = crate::intrinsics::clif_vector_type(tcx, self.layout);
                     (None, vec![AbiParam::new(vector_ty)])
                 }
-                _ => unreachable!("{:?}", self.layout.abi),
+                _ => unreachable!("{:?}", self.layout.backend_repr),
             },
-            PassMode::Pair(_, _) => match self.layout.abi {
-                Abi::ScalarPair(a, b) => {
+            PassMode::Pair(_, _) => match self.layout.backend_repr {
+                BackendRepr::ScalarPair(a, b) => {
                     let a = scalar_to_clif_type(tcx, a);
                     let b = scalar_to_clif_type(tcx, b);
                     (None, vec![AbiParam::new(a), AbiParam::new(b)])
                 }
-                _ => unreachable!("{:?}", self.layout.abi),
+                _ => unreachable!("{:?}", self.layout.backend_repr),
             },
             PassMode::Cast { ref cast, .. } => {
                 (None, cast_target_to_abi_params(cast).into_iter().collect())
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index a681e6d9f3c..99e39971b74 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -290,7 +290,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
     let arg_uninhabited = fx
         .mir
         .args_iter()
-        .any(|arg| fx.layout_of(fx.monomorphize(fx.mir.local_decls[arg].ty)).abi.is_uninhabited());
+        .any(|arg| fx.layout_of(fx.monomorphize(fx.mir.local_decls[arg].ty)).is_uninhabited());
     if arg_uninhabited {
         fx.bcx.append_block_params_for_function_params(fx.block_map[START_BLOCK]);
         fx.bcx.switch_to_block(fx.block_map[START_BLOCK]);
@@ -644,9 +644,9 @@ fn codegen_stmt<'tcx>(
                                 _ => unreachable!("un op Neg for {:?}", layout.ty),
                             }
                         }
-                        UnOp::PtrMetadata => match layout.abi {
-                            Abi::Scalar(_) => CValue::zst(dest_layout),
-                            Abi::ScalarPair(_, _) => {
+                        UnOp::PtrMetadata => match layout.backend_repr {
+                            BackendRepr::Scalar(_) => CValue::zst(dest_layout),
+                            BackendRepr::ScalarPair(_, _) => {
                                 CValue::by_val(operand.load_scalar_pair(fx).1, dest_layout)
                             }
                             _ => bug!("Unexpected `PtrToMetadata` operand: {operand:?}"),
diff --git a/compiler/rustc_codegen_cranelift/src/discriminant.rs b/compiler/rustc_codegen_cranelift/src/discriminant.rs
index d462dcd63a9..45794a42665 100644
--- a/compiler/rustc_codegen_cranelift/src/discriminant.rs
+++ b/compiler/rustc_codegen_cranelift/src/discriminant.rs
@@ -14,7 +14,7 @@ pub(crate) fn codegen_set_discriminant<'tcx>(
     variant_index: VariantIdx,
 ) {
     let layout = place.layout();
-    if layout.for_variant(fx, variant_index).abi.is_uninhabited() {
+    if layout.for_variant(fx, variant_index).is_uninhabited() {
         return;
     }
     match layout.variants {
@@ -80,7 +80,7 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
 ) {
     let layout = value.layout();
 
-    if layout.abi.is_uninhabited() {
+    if layout.is_uninhabited() {
         return;
     }
 
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index 35f0ccff3f9..aae6794891d 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -51,8 +51,8 @@ fn report_atomic_type_validation_error<'tcx>(
 }
 
 pub(crate) fn clif_vector_type<'tcx>(tcx: TyCtxt<'tcx>, layout: TyAndLayout<'tcx>) -> Type {
-    let (element, count) = match layout.abi {
-        Abi::Vector { element, count } => (element, count),
+    let (element, count) = match layout.backend_repr {
+        BackendRepr::Vector { element, count } => (element, count),
         _ => unreachable!(),
     };
 
@@ -505,7 +505,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
             let layout = fx.layout_of(generic_args.type_at(0));
             // Note: Can't use is_unsized here as truly unsized types need to take the fixed size
             // branch
-            let meta = if let Abi::ScalarPair(_, _) = ptr.layout().abi {
+            let meta = if let BackendRepr::ScalarPair(_, _) = ptr.layout().backend_repr {
                 Some(ptr.load_scalar_pair(fx).1)
             } else {
                 None
@@ -519,7 +519,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
             let layout = fx.layout_of(generic_args.type_at(0));
             // Note: Can't use is_unsized here as truly unsized types need to take the fixed size
             // branch
-            let meta = if let Abi::ScalarPair(_, _) = ptr.layout().abi {
+            let meta = if let BackendRepr::ScalarPair(_, _) = ptr.layout().backend_repr {
                 Some(ptr.load_scalar_pair(fx).1)
             } else {
                 None
@@ -693,7 +693,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
                     let layout = fx.layout_of(ty);
                     let msg_str = with_no_visible_paths!({
                         with_no_trimmed_paths!({
-                            if layout.abi.is_uninhabited() {
+                            if layout.is_uninhabited() {
                                 // Use this error even for the other intrinsics as it is more precise.
                                 format!("attempted to instantiate uninhabited type `{}`", ty)
                             } else if intrinsic == sym::assert_zero_valid {
diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs
index b6f9ce8fc29..602b1b98200 100644
--- a/compiler/rustc_codegen_cranelift/src/lib.rs
+++ b/compiler/rustc_codegen_cranelift/src/lib.rs
@@ -92,6 +92,7 @@ mod prelude {
         StackSlotData, StackSlotKind, TrapCode, Type, Value, types,
     };
     pub(crate) use cranelift_module::{self, DataDescription, FuncId, Linkage, Module};
+    pub(crate) use rustc_abi::{BackendRepr, FIRST_VARIANT, FieldIdx, Scalar, Size, VariantIdx};
     pub(crate) use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
     pub(crate) use rustc_hir::def_id::{DefId, LOCAL_CRATE};
     pub(crate) use rustc_index::Idx;
@@ -101,7 +102,6 @@ mod prelude {
         self, FloatTy, Instance, InstanceKind, IntTy, ParamEnv, Ty, TyCtxt, UintTy,
     };
     pub(crate) use rustc_span::Span;
-    pub(crate) use rustc_target::abi::{Abi, FIRST_VARIANT, FieldIdx, Scalar, Size, VariantIdx};
 
     pub(crate) use crate::abi::*;
     pub(crate) use crate::base::{codegen_operand, codegen_place};
diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
index fd77502224e..900d7e69714 100644
--- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs
+++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
@@ -131,8 +131,8 @@ impl<'tcx> CValue<'tcx> {
 
         match self.0 {
             CValueInner::ByRef(ptr, None) => {
-                let (a_scalar, b_scalar) = match self.1.abi {
-                    Abi::ScalarPair(a, b) => (a, b),
+                let (a_scalar, b_scalar) = match self.1.backend_repr {
+                    BackendRepr::ScalarPair(a, b) => (a, b),
                     _ => unreachable!("dyn_star_force_data_on_stack({:?})", self),
                 };
                 let b_offset = scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar);
@@ -164,15 +164,15 @@ impl<'tcx> CValue<'tcx> {
         }
     }
 
-    /// Load a value with layout.abi of scalar
+    /// Load a value with layout.backend_repr of scalar
     #[track_caller]
     pub(crate) fn load_scalar(self, fx: &mut FunctionCx<'_, '_, 'tcx>) -> Value {
         let layout = self.1;
         match self.0 {
             CValueInner::ByRef(ptr, None) => {
-                let clif_ty = match layout.abi {
-                    Abi::Scalar(scalar) => scalar_to_clif_type(fx.tcx, scalar),
-                    Abi::Vector { element, count } => scalar_to_clif_type(fx.tcx, element)
+                let clif_ty = match layout.backend_repr {
+                    BackendRepr::Scalar(scalar) => scalar_to_clif_type(fx.tcx, scalar),
+                    BackendRepr::Vector { element, count } => scalar_to_clif_type(fx.tcx, element)
                         .by(u32::try_from(count).unwrap())
                         .unwrap(),
                     _ => unreachable!("{:?}", layout.ty),
@@ -187,14 +187,14 @@ impl<'tcx> CValue<'tcx> {
         }
     }
 
-    /// Load a value pair with layout.abi of scalar pair
+    /// Load a value pair with layout.backend_repr of scalar pair
     #[track_caller]
     pub(crate) fn load_scalar_pair(self, fx: &mut FunctionCx<'_, '_, 'tcx>) -> (Value, Value) {
         let layout = self.1;
         match self.0 {
             CValueInner::ByRef(ptr, None) => {
-                let (a_scalar, b_scalar) = match layout.abi {
-                    Abi::ScalarPair(a, b) => (a, b),
+                let (a_scalar, b_scalar) = match layout.backend_repr {
+                    BackendRepr::ScalarPair(a, b) => (a, b),
                     _ => unreachable!("load_scalar_pair({:?})", self),
                 };
                 let b_offset = scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar);
@@ -222,8 +222,8 @@ impl<'tcx> CValue<'tcx> {
         let layout = self.1;
         match self.0 {
             CValueInner::ByVal(_) => unreachable!(),
-            CValueInner::ByValPair(val1, val2) => match layout.abi {
-                Abi::ScalarPair(_, _) => {
+            CValueInner::ByValPair(val1, val2) => match layout.backend_repr {
+                BackendRepr::ScalarPair(_, _) => {
                     let val = match field.as_u32() {
                         0 => val1,
                         1 => val2,
@@ -232,7 +232,7 @@ impl<'tcx> CValue<'tcx> {
                     let field_layout = layout.field(&*fx, usize::from(field));
                     CValue::by_val(val, field_layout)
                 }
-                _ => unreachable!("value_field for ByValPair with abi {:?}", layout.abi),
+                _ => unreachable!("value_field for ByValPair with abi {:?}", layout.backend_repr),
             },
             CValueInner::ByRef(ptr, None) => {
                 let (field_ptr, field_layout) = codegen_field(fx, ptr, None, layout, field);
@@ -360,7 +360,7 @@ impl<'tcx> CValue<'tcx> {
     pub(crate) fn cast_pointer_to(self, layout: TyAndLayout<'tcx>) -> Self {
         assert!(matches!(self.layout().ty.kind(), ty::Ref(..) | ty::RawPtr(..) | ty::FnPtr(..)));
         assert!(matches!(layout.ty.kind(), ty::Ref(..) | ty::RawPtr(..) | ty::FnPtr(..)));
-        assert_eq!(self.layout().abi, layout.abi);
+        assert_eq!(self.layout().backend_repr, layout.backend_repr);
         CValue(self.0, layout)
     }
 }
@@ -609,8 +609,8 @@ impl<'tcx> CPlace<'tcx> {
         let dst_layout = self.layout();
         match self.inner {
             CPlaceInner::Var(_local, var) => {
-                let data = match from.1.abi {
-                    Abi::Scalar(_) => CValue(from.0, dst_layout).load_scalar(fx),
+                let data = match from.1.backend_repr {
+                    BackendRepr::Scalar(_) => CValue(from.0, dst_layout).load_scalar(fx),
                     _ => {
                         let (ptr, meta) = from.force_stack(fx);
                         assert!(meta.is_none());
@@ -621,8 +621,10 @@ impl<'tcx> CPlace<'tcx> {
                 transmute_scalar(fx, var, data, dst_ty);
             }
             CPlaceInner::VarPair(_local, var1, var2) => {
-                let (data1, data2) = match from.1.abi {
-                    Abi::ScalarPair(_, _) => CValue(from.0, dst_layout).load_scalar_pair(fx),
+                let (data1, data2) = match from.1.backend_repr {
+                    BackendRepr::ScalarPair(_, _) => {
+                        CValue(from.0, dst_layout).load_scalar_pair(fx)
+                    }
                     _ => {
                         let (ptr, meta) = from.force_stack(fx);
                         assert!(meta.is_none());
@@ -635,7 +637,9 @@ impl<'tcx> CPlace<'tcx> {
             }
             CPlaceInner::Addr(_, Some(_)) => bug!("Can't write value to unsized place {:?}", self),
             CPlaceInner::Addr(to_ptr, None) => {
-                if dst_layout.size == Size::ZERO || dst_layout.abi == Abi::Uninhabited {
+                if dst_layout.size == Size::ZERO
+                    || dst_layout.backend_repr == BackendRepr::Uninhabited
+                {
                     return;
                 }
 
@@ -646,23 +650,28 @@ impl<'tcx> CPlace<'tcx> {
                     CValueInner::ByVal(val) => {
                         to_ptr.store(fx, val, flags);
                     }
-                    CValueInner::ByValPair(val1, val2) => match from.layout().abi {
-                        Abi::ScalarPair(a_scalar, b_scalar) => {
+                    CValueInner::ByValPair(val1, val2) => match from.layout().backend_repr {
+                        BackendRepr::ScalarPair(a_scalar, b_scalar) => {
                             let b_offset =
                                 scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar);
                             to_ptr.store(fx, val1, flags);
                             to_ptr.offset(fx, b_offset).store(fx, val2, flags);
                         }
-                        _ => bug!("Non ScalarPair abi {:?} for ByValPair CValue", dst_layout.abi),
+                        _ => {
+                            bug!(
+                                "Non ScalarPair repr {:?} for ByValPair CValue",
+                                dst_layout.backend_repr
+                            )
+                        }
                     },
                     CValueInner::ByRef(from_ptr, None) => {
-                        match from.layout().abi {
-                            Abi::Scalar(_) => {
+                        match from.layout().backend_repr {
+                            BackendRepr::Scalar(_) => {
                                 let val = from.load_scalar(fx);
                                 to_ptr.store(fx, val, flags);
                                 return;
                             }
-                            Abi::ScalarPair(a_scalar, b_scalar) => {
+                            BackendRepr::ScalarPair(a_scalar, b_scalar) => {
                                 let b_offset =
                                     scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar);
                                 let (val1, val2) = from.load_scalar_pair(fx);
diff --git a/compiler/rustc_codegen_cranelift/src/vtable.rs b/compiler/rustc_codegen_cranelift/src/vtable.rs
index 14c607ccad7..82b6178be9d 100644
--- a/compiler/rustc_codegen_cranelift/src/vtable.rs
+++ b/compiler/rustc_codegen_cranelift/src/vtable.rs
@@ -47,7 +47,7 @@ pub(crate) fn get_ptr_and_method_ref<'tcx>(
     idx: usize,
 ) -> (Pointer, Value) {
     let (ptr, vtable) = 'block: {
-        if let Abi::Scalar(_) = arg.layout().abi {
+        if let BackendRepr::Scalar(_) = arg.layout().backend_repr {
             while !arg.layout().ty.is_unsafe_ptr() && !arg.layout().ty.is_ref() {
                 let (idx, _) = arg
                     .layout()
@@ -68,7 +68,7 @@ pub(crate) fn get_ptr_and_method_ref<'tcx>(
             }
         }
 
-        if let Abi::ScalarPair(_, _) = arg.layout().abi {
+        if let BackendRepr::ScalarPair(_, _) = arg.layout().backend_repr {
             let (ptr, vtable) = arg.load_scalar_pair(fx);
             (Pointer::new(ptr), vtable)
         } else {
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index 7c52cba096b..e6ae7cf174d 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -1016,11 +1016,11 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
             OperandValue::Ref(place.val)
         } else if place.layout.is_gcc_immediate() {
             let load = self.load(place.layout.gcc_type(self), place.val.llval, place.val.align);
-            if let abi::Abi::Scalar(ref scalar) = place.layout.abi {
+            if let abi::BackendRepr::Scalar(ref scalar) = place.layout.backend_repr {
                 scalar_load_metadata(self, load, scalar);
             }
             OperandValue::Immediate(self.to_immediate(load, place.layout))
-        } else if let abi::Abi::ScalarPair(ref a, ref b) = place.layout.abi {
+        } else if let abi::BackendRepr::ScalarPair(ref a, ref b) = place.layout.backend_repr {
             let b_offset = a.size(self).align_to(b.align(self).abi);
 
             let mut load = |i, scalar: &abi::Scalar, align| {
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
index 972d6632140..b0298a35cb0 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
@@ -294,13 +294,13 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
             }
 
             sym::raw_eq => {
-                use rustc_target::abi::Abi::*;
+                use rustc_abi::BackendRepr::*;
                 let tp_ty = fn_args.type_at(0);
                 let layout = self.layout_of(tp_ty).layout;
-                let _use_integer_compare = match layout.abi() {
+                let _use_integer_compare = match layout.backend_repr() {
                     Scalar(_) | ScalarPair(_, _) => true,
                     Uninhabited | Vector { .. } => false,
-                    Aggregate { .. } => {
+                    Memory { .. } => {
                         // For rusty ABIs, small aggregates are actually passed
                         // as `RegKind::Integer` (see `FnAbi::adjust_for_abi`),
                         // so we re-use that same threshold here.
diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs
index db874afe1ab..0efdf36da48 100644
--- a/compiler/rustc_codegen_gcc/src/type_of.rs
+++ b/compiler/rustc_codegen_gcc/src/type_of.rs
@@ -3,7 +3,7 @@ use std::fmt::Write;
 use gccjit::{Struct, Type};
 use rustc_abi as abi;
 use rustc_abi::Primitive::*;
-use rustc_abi::{Abi, FieldsShape, Integer, PointeeInfo, Size, Variants};
+use rustc_abi::{BackendRepr, FieldsShape, Integer, PointeeInfo, Size, Variants};
 use rustc_codegen_ssa::traits::{
     BaseTypeCodegenMethods, DerivedTypeCodegenMethods, LayoutTypeCodegenMethods,
 };
@@ -60,9 +60,9 @@ fn uncached_gcc_type<'gcc, 'tcx>(
     layout: TyAndLayout<'tcx>,
     defer: &mut Option<(Struct<'gcc>, TyAndLayout<'tcx>)>,
 ) -> Type<'gcc> {
-    match layout.abi {
-        Abi::Scalar(_) => bug!("handled elsewhere"),
-        Abi::Vector { ref element, count } => {
+    match layout.backend_repr {
+        BackendRepr::Scalar(_) => bug!("handled elsewhere"),
+        BackendRepr::Vector { ref element, count } => {
             let element = layout.scalar_gcc_type_at(cx, element, Size::ZERO);
             let element =
                 // NOTE: gcc doesn't allow pointer types in vectors.
@@ -74,7 +74,7 @@ fn uncached_gcc_type<'gcc, 'tcx>(
                 };
             return cx.context.new_vector_type(element, count);
         }
-        Abi::ScalarPair(..) => {
+        BackendRepr::ScalarPair(..) => {
             return cx.type_struct(
                 &[
                     layout.scalar_pair_element_gcc_type(cx, 0),
@@ -83,7 +83,7 @@ fn uncached_gcc_type<'gcc, 'tcx>(
                 false,
             );
         }
-        Abi::Uninhabited | Abi::Aggregate { .. } => {}
+        BackendRepr::Uninhabited | BackendRepr::Memory { .. } => {}
     }
 
     let name = match *layout.ty.kind() {
@@ -176,16 +176,21 @@ pub trait LayoutGccExt<'tcx> {
 
 impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
     fn is_gcc_immediate(&self) -> bool {
-        match self.abi {
-            Abi::Scalar(_) | Abi::Vector { .. } => true,
-            Abi::ScalarPair(..) | Abi::Uninhabited | Abi::Aggregate { .. } => false,
+        match self.backend_repr {
+            BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => true,
+            BackendRepr::ScalarPair(..) | BackendRepr::Uninhabited | BackendRepr::Memory { .. } => {
+                false
+            }
         }
     }
 
     fn is_gcc_scalar_pair(&self) -> bool {
-        match self.abi {
-            Abi::ScalarPair(..) => true,
-            Abi::Uninhabited | Abi::Scalar(_) | Abi::Vector { .. } | Abi::Aggregate { .. } => false,
+        match self.backend_repr {
+            BackendRepr::ScalarPair(..) => true,
+            BackendRepr::Uninhabited
+            | BackendRepr::Scalar(_)
+            | BackendRepr::Vector { .. }
+            | BackendRepr::Memory { .. } => false,
         }
     }
 
@@ -205,7 +210,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
         // This must produce the same result for `repr(transparent)` wrappers as for the inner type!
         // In other words, this should generally not look at the type at all, but only at the
         // layout.
-        if let Abi::Scalar(ref scalar) = self.abi {
+        if let BackendRepr::Scalar(ref scalar) = self.backend_repr {
             // Use a different cache for scalars because pointers to DSTs
             // can be either wide or thin (data pointers of wide pointers).
             if let Some(&ty) = cx.scalar_types.borrow().get(&self.ty) {
@@ -261,7 +266,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
     }
 
     fn immediate_gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> {
-        if let Abi::Scalar(ref scalar) = self.abi {
+        if let BackendRepr::Scalar(ref scalar) = self.backend_repr {
             if scalar.is_bool() {
                 return cx.type_i1();
             }
@@ -299,8 +304,8 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
         // This must produce the same result for `repr(transparent)` wrappers as for the inner type!
         // In other words, this should generally not look at the type at all, but only at the
         // layout.
-        let (a, b) = match self.abi {
-            Abi::ScalarPair(ref a, ref b) => (a, b),
+        let (a, b) = match self.backend_repr {
+            BackendRepr::ScalarPair(ref a, ref b) => (a, b),
             _ => bug!("TyAndLayout::scalar_pair_element_llty({:?}): not applicable", self),
         };
         let scalar = [a, b][index];
diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs
index 2fe5ed32daa..855ca010611 100644
--- a/compiler/rustc_codegen_llvm/src/abi.rs
+++ b/compiler/rustc_codegen_llvm/src/abi.rs
@@ -415,7 +415,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
         instance: Option<ty::Instance<'tcx>>,
     ) {
         let mut func_attrs = SmallVec::<[_; 3]>::new();
-        if self.ret.layout.abi.is_uninhabited() {
+        if self.ret.layout.is_uninhabited() {
             func_attrs.push(llvm::AttributeKind::NoReturn.create_attr(cx.llcx));
         }
         if !self.can_unwind {
@@ -458,7 +458,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
         match &self.ret.mode {
             PassMode::Direct(attrs) => {
                 attrs.apply_attrs_to_llfn(llvm::AttributePlace::ReturnValue, cx, llfn);
-                if let abi::Abi::Scalar(scalar) = self.ret.layout.abi {
+                if let abi::BackendRepr::Scalar(scalar) = self.ret.layout.backend_repr {
                     apply_range_attr(llvm::AttributePlace::ReturnValue, scalar);
                 }
             }
@@ -495,7 +495,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
                 }
                 PassMode::Direct(attrs) => {
                     let i = apply(attrs);
-                    if let abi::Abi::Scalar(scalar) = arg.layout.abi {
+                    if let abi::BackendRepr::Scalar(scalar) = arg.layout.backend_repr {
                         apply_range_attr(llvm::AttributePlace::Argument(i), scalar);
                     }
                 }
@@ -510,7 +510,9 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
                 PassMode::Pair(a, b) => {
                     let i = apply(a);
                     let ii = apply(b);
-                    if let abi::Abi::ScalarPair(scalar_a, scalar_b) = arg.layout.abi {
+                    if let abi::BackendRepr::ScalarPair(scalar_a, scalar_b) =
+                        arg.layout.backend_repr
+                    {
                         apply_range_attr(llvm::AttributePlace::Argument(i), scalar_a);
                         apply_range_attr(llvm::AttributePlace::Argument(ii), scalar_b);
                     }
@@ -532,7 +534,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
 
     fn apply_attrs_callsite(&self, bx: &mut Builder<'_, 'll, 'tcx>, callsite: &'ll Value) {
         let mut func_attrs = SmallVec::<[_; 2]>::new();
-        if self.ret.layout.abi.is_uninhabited() {
+        if self.ret.layout.is_uninhabited() {
             func_attrs.push(llvm::AttributeKind::NoReturn.create_attr(bx.cx.llcx));
         }
         if !self.can_unwind {
@@ -570,7 +572,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
         }
         if bx.cx.sess().opts.optimize != config::OptLevel::No
                 && llvm_util::get_version() < (19, 0, 0)
-                && let abi::Abi::Scalar(scalar) = self.ret.layout.abi
+                && let abi::BackendRepr::Scalar(scalar) = self.ret.layout.backend_repr
                 && matches!(scalar.primitive(), Int(..))
                 // If the value is a boolean, the range is 0..2 and that ultimately
                 // become 0..0 when the type becomes i1, which would be rejected
diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs
index 55ee6dcdf87..149ded28356 100644
--- a/compiler/rustc_codegen_llvm/src/allocator.rs
+++ b/compiler/rustc_codegen_llvm/src/allocator.rs
@@ -7,6 +7,7 @@ use rustc_middle::bug;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::config::{DebugInfo, OomStrategy};
 
+use crate::common::AsCCharPtr;
 use crate::llvm::{self, Context, False, Module, True, Type};
 use crate::{ModuleLlvm, attributes, debuginfo};
 
@@ -76,14 +77,14 @@ pub(crate) unsafe fn codegen(
     unsafe {
         // __rust_alloc_error_handler_should_panic
         let name = OomStrategy::SYMBOL;
-        let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_ptr().cast(), name.len(), i8);
+        let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_c_char_ptr(), name.len(), i8);
         llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility()));
         let val = tcx.sess.opts.unstable_opts.oom.should_panic();
         let llval = llvm::LLVMConstInt(i8, val as u64, False);
         llvm::LLVMSetInitializer(ll_g, llval);
 
         let name = NO_ALLOC_SHIM_IS_UNSTABLE;
-        let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_ptr().cast(), name.len(), i8);
+        let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_c_char_ptr(), name.len(), i8);
         llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility()));
         let llval = llvm::LLVMConstInt(i8, 0, False);
         llvm::LLVMSetInitializer(ll_g, llval);
@@ -115,7 +116,7 @@ fn create_wrapper_function(
         );
         let llfn = llvm::LLVMRustGetOrInsertFunction(
             llmod,
-            from_name.as_ptr().cast(),
+            from_name.as_c_char_ptr(),
             from_name.len(),
             ty,
         );
@@ -137,7 +138,7 @@ fn create_wrapper_function(
         }
 
         let callee =
-            llvm::LLVMRustGetOrInsertFunction(llmod, to_name.as_ptr().cast(), to_name.len(), ty);
+            llvm::LLVMRustGetOrInsertFunction(llmod, to_name.as_c_char_ptr(), to_name.len(), ty);
         if let Some(no_return) = no_return {
             // -> ! DIFlagNoReturn
             attributes::apply_to_llfn(callee, llvm::AttributePlace::Function, &[no_return]);
@@ -153,7 +154,7 @@ fn create_wrapper_function(
             .enumerate()
             .map(|(i, _)| llvm::LLVMGetParam(llfn, i as c_uint))
             .collect::<Vec<_>>();
-        let ret = llvm::LLVMRustBuildCall(
+        let ret = llvm::LLVMBuildCallWithOperandBundles(
             llbuilder,
             ty,
             callee,
@@ -161,6 +162,7 @@ fn create_wrapper_function(
             args.len() as c_uint,
             [].as_ptr(),
             0 as c_uint,
+            c"".as_ptr(),
         );
         llvm::LLVMSetTailCall(ret, True);
         if output.is_some() {
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs
index d1d7d0cf4ce..53758967552 100644
--- a/compiler/rustc_codegen_llvm/src/asm.rs
+++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -15,7 +15,7 @@ use smallvec::SmallVec;
 use tracing::debug;
 
 use crate::builder::Builder;
-use crate::common::Funclet;
+use crate::common::{AsCCharPtr, Funclet};
 use crate::context::CodegenCx;
 use crate::type_::Type;
 use crate::type_of::LayoutLlvmExt;
@@ -420,7 +420,7 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
         unsafe {
             llvm::LLVMAppendModuleInlineAsm(
                 self.llmod,
-                template_str.as_ptr().cast(),
+                template_str.as_c_char_ptr(),
                 template_str.len(),
             );
         }
@@ -458,14 +458,14 @@ pub(crate) fn inline_asm_call<'ll>(
     let fty = bx.cx.type_func(&argtys, output);
     unsafe {
         // Ask LLVM to verify that the constraints are well-formed.
-        let constraints_ok = llvm::LLVMRustInlineAsmVerify(fty, cons.as_ptr().cast(), cons.len());
+        let constraints_ok = llvm::LLVMRustInlineAsmVerify(fty, cons.as_c_char_ptr(), cons.len());
         debug!("constraint verification result: {:?}", constraints_ok);
         if constraints_ok {
             let v = llvm::LLVMRustInlineAsm(
                 fty,
-                asm.as_ptr().cast(),
+                asm.as_c_char_ptr(),
                 asm.len(),
-                cons.as_ptr().cast(),
+                cons.as_c_char_ptr(),
                 cons.len(),
                 volatile,
                 alignstack,
@@ -880,8 +880,8 @@ fn llvm_fixup_input<'ll, 'tcx>(
 ) -> &'ll Value {
     use InlineAsmRegClass::*;
     let dl = &bx.tcx.data_layout;
-    match (reg, layout.abi) {
-        (AArch64(AArch64InlineAsmRegClass::vreg), Abi::Scalar(s)) => {
+    match (reg, layout.backend_repr) {
+        (AArch64(AArch64InlineAsmRegClass::vreg), BackendRepr::Scalar(s)) => {
             if let Primitive::Int(Integer::I8, _) = s.primitive() {
                 let vec_ty = bx.cx.type_vector(bx.cx.type_i8(), 8);
                 bx.insert_element(bx.const_undef(vec_ty), value, bx.const_i32(0))
@@ -889,7 +889,7 @@ fn llvm_fixup_input<'ll, 'tcx>(
                 value
             }
         }
-        (AArch64(AArch64InlineAsmRegClass::vreg_low16), Abi::Scalar(s))
+        (AArch64(AArch64InlineAsmRegClass::vreg_low16), BackendRepr::Scalar(s))
             if s.primitive() != Primitive::Float(Float::F128) =>
         {
             let elem_ty = llvm_asm_scalar_type(bx.cx, s);
@@ -902,7 +902,7 @@ fn llvm_fixup_input<'ll, 'tcx>(
             }
             bx.insert_element(bx.const_undef(vec_ty), value, bx.const_i32(0))
         }
-        (AArch64(AArch64InlineAsmRegClass::vreg_low16), Abi::Vector { element, count })
+        (AArch64(AArch64InlineAsmRegClass::vreg_low16), BackendRepr::Vector { element, count })
             if layout.size.bytes() == 8 =>
         {
             let elem_ty = llvm_asm_scalar_type(bx.cx, element);
@@ -910,14 +910,14 @@ fn llvm_fixup_input<'ll, 'tcx>(
             let indices: Vec<_> = (0..count * 2).map(|x| bx.const_i32(x as i32)).collect();
             bx.shuffle_vector(value, bx.const_undef(vec_ty), bx.const_vector(&indices))
         }
-        (X86(X86InlineAsmRegClass::reg_abcd), Abi::Scalar(s))
+        (X86(X86InlineAsmRegClass::reg_abcd), BackendRepr::Scalar(s))
             if s.primitive() == Primitive::Float(Float::F64) =>
         {
             bx.bitcast(value, bx.cx.type_i64())
         }
         (
             X86(X86InlineAsmRegClass::xmm_reg | X86InlineAsmRegClass::zmm_reg),
-            Abi::Vector { .. },
+            BackendRepr::Vector { .. },
         ) if layout.size.bytes() == 64 => bx.bitcast(value, bx.cx.type_vector(bx.cx.type_f64(), 8)),
         (
             X86(
@@ -925,7 +925,7 @@ fn llvm_fixup_input<'ll, 'tcx>(
                 | X86InlineAsmRegClass::ymm_reg
                 | X86InlineAsmRegClass::zmm_reg,
             ),
-            Abi::Scalar(s),
+            BackendRepr::Scalar(s),
         ) if bx.sess().asm_arch == Some(InlineAsmArch::X86)
             && s.primitive() == Primitive::Float(Float::F128) =>
         {
@@ -937,7 +937,7 @@ fn llvm_fixup_input<'ll, 'tcx>(
                 | X86InlineAsmRegClass::ymm_reg
                 | X86InlineAsmRegClass::zmm_reg,
             ),
-            Abi::Scalar(s),
+            BackendRepr::Scalar(s),
         ) if s.primitive() == Primitive::Float(Float::F16) => {
             let value = bx.insert_element(
                 bx.const_undef(bx.type_vector(bx.type_f16(), 8)),
@@ -952,11 +952,14 @@ fn llvm_fixup_input<'ll, 'tcx>(
                 | X86InlineAsmRegClass::ymm_reg
                 | X86InlineAsmRegClass::zmm_reg,
             ),
-            Abi::Vector { element, count: count @ (8 | 16) },
+            BackendRepr::Vector { element, count: count @ (8 | 16) },
         ) if element.primitive() == Primitive::Float(Float::F16) => {
             bx.bitcast(value, bx.type_vector(bx.type_i16(), count))
         }
-        (Arm(ArmInlineAsmRegClass::sreg | ArmInlineAsmRegClass::sreg_low16), Abi::Scalar(s)) => {
+        (
+            Arm(ArmInlineAsmRegClass::sreg | ArmInlineAsmRegClass::sreg_low16),
+            BackendRepr::Scalar(s),
+        ) => {
             if let Primitive::Int(Integer::I32, _) = s.primitive() {
                 bx.bitcast(value, bx.cx.type_f32())
             } else {
@@ -969,7 +972,7 @@ fn llvm_fixup_input<'ll, 'tcx>(
                 | ArmInlineAsmRegClass::dreg_low8
                 | ArmInlineAsmRegClass::dreg_low16,
             ),
-            Abi::Scalar(s),
+            BackendRepr::Scalar(s),
         ) => {
             if let Primitive::Int(Integer::I64, _) = s.primitive() {
                 bx.bitcast(value, bx.cx.type_f64())
@@ -986,11 +989,11 @@ fn llvm_fixup_input<'ll, 'tcx>(
                 | ArmInlineAsmRegClass::qreg_low4
                 | ArmInlineAsmRegClass::qreg_low8,
             ),
-            Abi::Vector { element, count: count @ (4 | 8) },
+            BackendRepr::Vector { element, count: count @ (4 | 8) },
         ) if element.primitive() == Primitive::Float(Float::F16) => {
             bx.bitcast(value, bx.type_vector(bx.type_i16(), count))
         }
-        (Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => {
+        (Mips(MipsInlineAsmRegClass::reg), BackendRepr::Scalar(s)) => {
             match s.primitive() {
                 // MIPS only supports register-length arithmetics.
                 Primitive::Int(Integer::I8 | Integer::I16, _) => bx.zext(value, bx.cx.type_i32()),
@@ -999,7 +1002,7 @@ fn llvm_fixup_input<'ll, 'tcx>(
                 _ => value,
             }
         }
-        (RiscV(RiscVInlineAsmRegClass::freg), Abi::Scalar(s))
+        (RiscV(RiscVInlineAsmRegClass::freg), BackendRepr::Scalar(s))
             if s.primitive() == Primitive::Float(Float::F16)
                 && !any_target_feature_enabled(bx, instance, &[sym::zfhmin, sym::zfh]) =>
         {
@@ -1022,15 +1025,15 @@ fn llvm_fixup_output<'ll, 'tcx>(
     instance: Instance<'_>,
 ) -> &'ll Value {
     use InlineAsmRegClass::*;
-    match (reg, layout.abi) {
-        (AArch64(AArch64InlineAsmRegClass::vreg), Abi::Scalar(s)) => {
+    match (reg, layout.backend_repr) {
+        (AArch64(AArch64InlineAsmRegClass::vreg), BackendRepr::Scalar(s)) => {
             if let Primitive::Int(Integer::I8, _) = s.primitive() {
                 bx.extract_element(value, bx.const_i32(0))
             } else {
                 value
             }
         }
-        (AArch64(AArch64InlineAsmRegClass::vreg_low16), Abi::Scalar(s))
+        (AArch64(AArch64InlineAsmRegClass::vreg_low16), BackendRepr::Scalar(s))
             if s.primitive() != Primitive::Float(Float::F128) =>
         {
             value = bx.extract_element(value, bx.const_i32(0));
@@ -1039,7 +1042,7 @@ fn llvm_fixup_output<'ll, 'tcx>(
             }
             value
         }
-        (AArch64(AArch64InlineAsmRegClass::vreg_low16), Abi::Vector { element, count })
+        (AArch64(AArch64InlineAsmRegClass::vreg_low16), BackendRepr::Vector { element, count })
             if layout.size.bytes() == 8 =>
         {
             let elem_ty = llvm_asm_scalar_type(bx.cx, element);
@@ -1047,14 +1050,14 @@ fn llvm_fixup_output<'ll, 'tcx>(
             let indices: Vec<_> = (0..count).map(|x| bx.const_i32(x as i32)).collect();
             bx.shuffle_vector(value, bx.const_undef(vec_ty), bx.const_vector(&indices))
         }
-        (X86(X86InlineAsmRegClass::reg_abcd), Abi::Scalar(s))
+        (X86(X86InlineAsmRegClass::reg_abcd), BackendRepr::Scalar(s))
             if s.primitive() == Primitive::Float(Float::F64) =>
         {
             bx.bitcast(value, bx.cx.type_f64())
         }
         (
             X86(X86InlineAsmRegClass::xmm_reg | X86InlineAsmRegClass::zmm_reg),
-            Abi::Vector { .. },
+            BackendRepr::Vector { .. },
         ) if layout.size.bytes() == 64 => bx.bitcast(value, layout.llvm_type(bx.cx)),
         (
             X86(
@@ -1062,7 +1065,7 @@ fn llvm_fixup_output<'ll, 'tcx>(
                 | X86InlineAsmRegClass::ymm_reg
                 | X86InlineAsmRegClass::zmm_reg,
             ),
-            Abi::Scalar(s),
+            BackendRepr::Scalar(s),
         ) if bx.sess().asm_arch == Some(InlineAsmArch::X86)
             && s.primitive() == Primitive::Float(Float::F128) =>
         {
@@ -1074,7 +1077,7 @@ fn llvm_fixup_output<'ll, 'tcx>(
                 | X86InlineAsmRegClass::ymm_reg
                 | X86InlineAsmRegClass::zmm_reg,
             ),
-            Abi::Scalar(s),
+            BackendRepr::Scalar(s),
         ) if s.primitive() == Primitive::Float(Float::F16) => {
             let value = bx.bitcast(value, bx.type_vector(bx.type_f16(), 8));
             bx.extract_element(value, bx.const_usize(0))
@@ -1085,11 +1088,14 @@ fn llvm_fixup_output<'ll, 'tcx>(
                 | X86InlineAsmRegClass::ymm_reg
                 | X86InlineAsmRegClass::zmm_reg,
             ),
-            Abi::Vector { element, count: count @ (8 | 16) },
+            BackendRepr::Vector { element, count: count @ (8 | 16) },
         ) if element.primitive() == Primitive::Float(Float::F16) => {
             bx.bitcast(value, bx.type_vector(bx.type_f16(), count))
         }
-        (Arm(ArmInlineAsmRegClass::sreg | ArmInlineAsmRegClass::sreg_low16), Abi::Scalar(s)) => {
+        (
+            Arm(ArmInlineAsmRegClass::sreg | ArmInlineAsmRegClass::sreg_low16),
+            BackendRepr::Scalar(s),
+        ) => {
             if let Primitive::Int(Integer::I32, _) = s.primitive() {
                 bx.bitcast(value, bx.cx.type_i32())
             } else {
@@ -1102,7 +1108,7 @@ fn llvm_fixup_output<'ll, 'tcx>(
                 | ArmInlineAsmRegClass::dreg_low8
                 | ArmInlineAsmRegClass::dreg_low16,
             ),
-            Abi::Scalar(s),
+            BackendRepr::Scalar(s),
         ) => {
             if let Primitive::Int(Integer::I64, _) = s.primitive() {
                 bx.bitcast(value, bx.cx.type_i64())
@@ -1119,11 +1125,11 @@ fn llvm_fixup_output<'ll, 'tcx>(
                 | ArmInlineAsmRegClass::qreg_low4
                 | ArmInlineAsmRegClass::qreg_low8,
             ),
-            Abi::Vector { element, count: count @ (4 | 8) },
+            BackendRepr::Vector { element, count: count @ (4 | 8) },
         ) if element.primitive() == Primitive::Float(Float::F16) => {
             bx.bitcast(value, bx.type_vector(bx.type_f16(), count))
         }
-        (Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => {
+        (Mips(MipsInlineAsmRegClass::reg), BackendRepr::Scalar(s)) => {
             match s.primitive() {
                 // MIPS only supports register-length arithmetics.
                 Primitive::Int(Integer::I8, _) => bx.trunc(value, bx.cx.type_i8()),
@@ -1133,7 +1139,7 @@ fn llvm_fixup_output<'ll, 'tcx>(
                 _ => value,
             }
         }
-        (RiscV(RiscVInlineAsmRegClass::freg), Abi::Scalar(s))
+        (RiscV(RiscVInlineAsmRegClass::freg), BackendRepr::Scalar(s))
             if s.primitive() == Primitive::Float(Float::F16)
                 && !any_target_feature_enabled(bx, instance, &[sym::zfhmin, sym::zfh]) =>
         {
@@ -1153,35 +1159,35 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
     instance: Instance<'_>,
 ) -> &'ll Type {
     use InlineAsmRegClass::*;
-    match (reg, layout.abi) {
-        (AArch64(AArch64InlineAsmRegClass::vreg), Abi::Scalar(s)) => {
+    match (reg, layout.backend_repr) {
+        (AArch64(AArch64InlineAsmRegClass::vreg), BackendRepr::Scalar(s)) => {
             if let Primitive::Int(Integer::I8, _) = s.primitive() {
                 cx.type_vector(cx.type_i8(), 8)
             } else {
                 layout.llvm_type(cx)
             }
         }
-        (AArch64(AArch64InlineAsmRegClass::vreg_low16), Abi::Scalar(s))
+        (AArch64(AArch64InlineAsmRegClass::vreg_low16), BackendRepr::Scalar(s))
             if s.primitive() != Primitive::Float(Float::F128) =>
         {
             let elem_ty = llvm_asm_scalar_type(cx, s);
             let count = 16 / layout.size.bytes();
             cx.type_vector(elem_ty, count)
         }
-        (AArch64(AArch64InlineAsmRegClass::vreg_low16), Abi::Vector { element, count })
+        (AArch64(AArch64InlineAsmRegClass::vreg_low16), BackendRepr::Vector { element, count })
             if layout.size.bytes() == 8 =>
         {
             let elem_ty = llvm_asm_scalar_type(cx, element);
             cx.type_vector(elem_ty, count * 2)
         }
-        (X86(X86InlineAsmRegClass::reg_abcd), Abi::Scalar(s))
+        (X86(X86InlineAsmRegClass::reg_abcd), BackendRepr::Scalar(s))
             if s.primitive() == Primitive::Float(Float::F64) =>
         {
             cx.type_i64()
         }
         (
             X86(X86InlineAsmRegClass::xmm_reg | X86InlineAsmRegClass::zmm_reg),
-            Abi::Vector { .. },
+            BackendRepr::Vector { .. },
         ) if layout.size.bytes() == 64 => cx.type_vector(cx.type_f64(), 8),
         (
             X86(
@@ -1189,7 +1195,7 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
                 | X86InlineAsmRegClass::ymm_reg
                 | X86InlineAsmRegClass::zmm_reg,
             ),
-            Abi::Scalar(s),
+            BackendRepr::Scalar(s),
         ) if cx.sess().asm_arch == Some(InlineAsmArch::X86)
             && s.primitive() == Primitive::Float(Float::F128) =>
         {
@@ -1201,7 +1207,7 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
                 | X86InlineAsmRegClass::ymm_reg
                 | X86InlineAsmRegClass::zmm_reg,
             ),
-            Abi::Scalar(s),
+            BackendRepr::Scalar(s),
         ) if s.primitive() == Primitive::Float(Float::F16) => cx.type_vector(cx.type_i16(), 8),
         (
             X86(
@@ -1209,11 +1215,14 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
                 | X86InlineAsmRegClass::ymm_reg
                 | X86InlineAsmRegClass::zmm_reg,
             ),
-            Abi::Vector { element, count: count @ (8 | 16) },
+            BackendRepr::Vector { element, count: count @ (8 | 16) },
         ) if element.primitive() == Primitive::Float(Float::F16) => {
             cx.type_vector(cx.type_i16(), count)
         }
-        (Arm(ArmInlineAsmRegClass::sreg | ArmInlineAsmRegClass::sreg_low16), Abi::Scalar(s)) => {
+        (
+            Arm(ArmInlineAsmRegClass::sreg | ArmInlineAsmRegClass::sreg_low16),
+            BackendRepr::Scalar(s),
+        ) => {
             if let Primitive::Int(Integer::I32, _) = s.primitive() {
                 cx.type_f32()
             } else {
@@ -1226,7 +1235,7 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
                 | ArmInlineAsmRegClass::dreg_low8
                 | ArmInlineAsmRegClass::dreg_low16,
             ),
-            Abi::Scalar(s),
+            BackendRepr::Scalar(s),
         ) => {
             if let Primitive::Int(Integer::I64, _) = s.primitive() {
                 cx.type_f64()
@@ -1243,11 +1252,11 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
                 | ArmInlineAsmRegClass::qreg_low4
                 | ArmInlineAsmRegClass::qreg_low8,
             ),
-            Abi::Vector { element, count: count @ (4 | 8) },
+            BackendRepr::Vector { element, count: count @ (4 | 8) },
         ) if element.primitive() == Primitive::Float(Float::F16) => {
             cx.type_vector(cx.type_i16(), count)
         }
-        (Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => {
+        (Mips(MipsInlineAsmRegClass::reg), BackendRepr::Scalar(s)) => {
             match s.primitive() {
                 // MIPS only supports register-length arithmetics.
                 Primitive::Int(Integer::I8 | Integer::I16, _) => cx.type_i32(),
@@ -1256,7 +1265,7 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
                 _ => layout.llvm_type(cx),
             }
         }
-        (RiscV(RiscVInlineAsmRegClass::freg), Abi::Scalar(s))
+        (RiscV(RiscVInlineAsmRegClass::freg), BackendRepr::Scalar(s))
             if s.primitive() == Primitive::Float(Float::F16)
                 && !any_target_feature_enabled(cx, instance, &[sym::zfhmin, sym::zfh]) =>
         {
diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs
index 1f7a923dd2c..48beb9be2b2 100644
--- a/compiler/rustc_codegen_llvm/src/back/lto.rs
+++ b/compiler/rustc_codegen_llvm/src/back/lto.rs
@@ -165,13 +165,14 @@ fn get_bitcode_slice_from_object_data<'a>(
     // We drop the "__LLVM," prefix here because on Apple platforms there's a notion of "segment
     // name" which in the public API for sections gets treated as part of the section name, but
     // internally in MachOObjectFile.cpp gets treated separately.
-    let section_name = bitcode_section_name(cgcx).trim_start_matches("__LLVM,");
+    let section_name = bitcode_section_name(cgcx).to_str().unwrap().trim_start_matches("__LLVM,");
     let mut len = 0;
     let data = unsafe {
         llvm::LLVMRustGetSliceFromObjectDataByName(
             obj.as_ptr(),
             obj.len(),
             section_name.as_ptr(),
+            section_name.len(),
             &mut len,
         )
     };
@@ -502,9 +503,9 @@ fn thin_lto(
         // upstream...
         let data = llvm::LLVMRustCreateThinLTOData(
             thin_modules.as_ptr(),
-            thin_modules.len() as u32,
+            thin_modules.len(),
             symbols_below_threshold.as_ptr(),
-            symbols_below_threshold.len() as u32,
+            symbols_below_threshold.len(),
         )
         .ok_or_else(|| write::llvm_err(dcx, LlvmError::PrepareThinLtoContext))?;
 
@@ -569,7 +570,7 @@ fn thin_lto(
 
             info!(" - {}: re-compiled", module_name);
             opt_jobs.push(LtoModuleCodegen::Thin(ThinModule {
-                shared: shared.clone(),
+                shared: Arc::clone(&shared),
                 idx: module_index,
             }));
         }
@@ -601,23 +602,9 @@ pub(crate) fn run_pass_manager(
     // This code is based off the code found in llvm's LTO code generator:
     //      llvm/lib/LTO/LTOCodeGenerator.cpp
     debug!("running the pass manager");
-    unsafe {
-        if !llvm::LLVMRustHasModuleFlag(
-            module.module_llvm.llmod(),
-            "LTOPostLink".as_ptr().cast(),
-            11,
-        ) {
-            llvm::LLVMRustAddModuleFlagU32(
-                module.module_llvm.llmod(),
-                llvm::LLVMModFlagBehavior::Error,
-                c"LTOPostLink".as_ptr(),
-                1,
-            );
-        }
-        let opt_stage = if thin { llvm::OptStage::ThinLTO } else { llvm::OptStage::FatLTO };
-        let opt_level = config.opt_level.unwrap_or(config::OptLevel::No);
-        write::llvm_optimize(cgcx, dcx, module, config, opt_level, opt_stage)?;
-    }
+    let opt_stage = if thin { llvm::OptStage::ThinLTO } else { llvm::OptStage::FatLTO };
+    let opt_level = config.opt_level.unwrap_or(config::OptLevel::No);
+    unsafe { write::llvm_optimize(cgcx, dcx, module, config, opt_level, opt_stage) }?;
     debug!("lto done");
     Ok(())
 }
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index bf77fc56d08..bfa9e8b82a0 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -1,4 +1,4 @@
-use std::ffi::CString;
+use std::ffi::{CStr, CString};
 use std::io::{self, Write};
 use std::path::{Path, PathBuf};
 use std::sync::Arc;
@@ -34,6 +34,7 @@ use crate::back::owned_target_machine::OwnedTargetMachine;
 use crate::back::profiling::{
     LlvmSelfProfiler, selfprofile_after_pass_callback, selfprofile_before_pass_callback,
 };
+use crate::common::AsCCharPtr;
 use crate::errors::{
     CopyBitcode, FromLlvmDiag, FromLlvmOptimizationDiag, LlvmError, UnknownCompression,
     WithLlvmError, WriteBytecode,
@@ -596,9 +597,9 @@ pub(crate) unsafe fn llvm_optimize(
             llvm_selfprofiler,
             selfprofile_before_pass_callback,
             selfprofile_after_pass_callback,
-            extra_passes.as_ptr().cast(),
+            extra_passes.as_c_char_ptr(),
             extra_passes.len(),
-            llvm_plugins.as_ptr().cast(),
+            llvm_plugins.as_c_char_ptr(),
             llvm_plugins.len(),
         )
     };
@@ -957,14 +958,13 @@ fn target_is_aix(cgcx: &CodegenContext<LlvmCodegenBackend>) -> bool {
     cgcx.opts.target_triple.triple().contains("-aix")
 }
 
-//FIXME use c string literals here too
-pub(crate) fn bitcode_section_name(cgcx: &CodegenContext<LlvmCodegenBackend>) -> &'static str {
+pub(crate) fn bitcode_section_name(cgcx: &CodegenContext<LlvmCodegenBackend>) -> &'static CStr {
     if target_is_apple(cgcx) {
-        "__LLVM,__bitcode\0"
+        c"__LLVM,__bitcode"
     } else if target_is_aix(cgcx) {
-        ".ipa\0"
+        c".ipa"
     } else {
-        ".llvmbc\0"
+        c".llvmbc"
     }
 }
 
@@ -1041,8 +1041,7 @@ unsafe fn embed_bitcode(
             );
             llvm::LLVMSetInitializer(llglobal, llconst);
 
-            let section = bitcode_section_name(cgcx);
-            llvm::LLVMSetSection(llglobal, section.as_ptr().cast());
+            llvm::set_section(llglobal, bitcode_section_name(cgcx));
             llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage);
             llvm::LLVMSetGlobalConstant(llglobal, llvm::True);
 
@@ -1060,15 +1059,15 @@ unsafe fn embed_bitcode(
             } else {
                 c".llvmcmd"
             };
-            llvm::LLVMSetSection(llglobal, section.as_ptr());
+            llvm::set_section(llglobal, section);
             llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage);
         } else {
             // We need custom section flags, so emit module-level inline assembly.
             let section_flags = if cgcx.is_pe_coff { "n" } else { "e" };
             let asm = create_section_with_flags_asm(".llvmbc", section_flags, bitcode);
-            llvm::LLVMAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len());
+            llvm::LLVMAppendModuleInlineAsm(llmod, asm.as_c_char_ptr(), asm.len());
             let asm = create_section_with_flags_asm(".llvmcmd", section_flags, cmdline.as_bytes());
-            llvm::LLVMAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len());
+            llvm::LLVMAppendModuleInlineAsm(llmod, asm.as_c_char_ptr(), asm.len());
         }
     }
 }
diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs
index 0ba8d82406a..32793894794 100644
--- a/compiler/rustc_codegen_llvm/src/base.rs
+++ b/compiler/rustc_codegen_llvm/src/base.rs
@@ -145,10 +145,8 @@ pub(crate) fn compile_codegen_unit(
 
 pub(crate) fn set_link_section(llval: &Value, attrs: &CodegenFnAttrs) {
     let Some(sect) = attrs.link_section else { return };
-    unsafe {
-        let buf = SmallCStr::new(sect.as_str());
-        llvm::LLVMSetSection(llval, buf.as_ptr());
-    }
+    let buf = SmallCStr::new(sect.as_str());
+    llvm::set_section(llval, &buf);
 }
 
 pub(crate) fn linkage_to_llvm(linkage: Linkage) -> llvm::Linkage {
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 8702532c36e..15883c91053 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -239,7 +239,6 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
 
         let args = self.check_call("invoke", llty, llfn, args);
         let funclet_bundle = funclet.map(|funclet| funclet.bundle());
-        let funclet_bundle = funclet_bundle.as_ref().map(|b| &*b.raw);
         let mut bundles: SmallVec<[_; 2]> = SmallVec::new();
         if let Some(funclet_bundle) = funclet_bundle {
             bundles.push(funclet_bundle);
@@ -250,13 +249,12 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
 
         // Emit KCFI operand bundle
         let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, instance, llfn);
-        let kcfi_bundle = kcfi_bundle.as_ref().map(|b| &*b.raw);
-        if let Some(kcfi_bundle) = kcfi_bundle {
+        if let Some(kcfi_bundle) = kcfi_bundle.as_deref() {
             bundles.push(kcfi_bundle);
         }
 
         let invoke = unsafe {
-            llvm::LLVMRustBuildInvoke(
+            llvm::LLVMBuildInvokeWithOperandBundles(
                 self.llbuilder,
                 llty,
                 llfn,
@@ -545,13 +543,13 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
             }
             let llval = const_llval.unwrap_or_else(|| {
                 let load = self.load(llty, place.val.llval, place.val.align);
-                if let abi::Abi::Scalar(scalar) = place.layout.abi {
+                if let abi::BackendRepr::Scalar(scalar) = place.layout.backend_repr {
                     scalar_load_metadata(self, load, scalar, place.layout, Size::ZERO);
                 }
                 load
             });
             OperandValue::Immediate(self.to_immediate(llval, place.layout))
-        } else if let abi::Abi::ScalarPair(a, b) = place.layout.abi {
+        } else if let abi::BackendRepr::ScalarPair(a, b) = place.layout.backend_repr {
             let b_offset = a.size(self).align_to(b.align(self).abi);
 
             let mut load = |i, scalar: abi::Scalar, layout, align, offset| {
@@ -1179,7 +1177,6 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
 
         let args = self.check_call("call", llty, llfn, args);
         let funclet_bundle = funclet.map(|funclet| funclet.bundle());
-        let funclet_bundle = funclet_bundle.as_ref().map(|b| &*b.raw);
         let mut bundles: SmallVec<[_; 2]> = SmallVec::new();
         if let Some(funclet_bundle) = funclet_bundle {
             bundles.push(funclet_bundle);
@@ -1190,13 +1187,12 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
 
         // Emit KCFI operand bundle
         let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, instance, llfn);
-        let kcfi_bundle = kcfi_bundle.as_ref().map(|b| &*b.raw);
-        if let Some(kcfi_bundle) = kcfi_bundle {
+        if let Some(kcfi_bundle) = kcfi_bundle.as_deref() {
             bundles.push(kcfi_bundle);
         }
 
         let call = unsafe {
-            llvm::LLVMRustBuildCall(
+            llvm::LLVMBuildCallWithOperandBundles(
                 self.llbuilder,
                 llty,
                 llfn,
@@ -1204,6 +1200,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
                 args.len() as c_uint,
                 bundles.as_ptr(),
                 bundles.len() as c_uint,
+                c"".as_ptr(),
             )
         };
         if let Some(fn_abi) = fn_abi {
@@ -1509,7 +1506,6 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
 
         let args = self.check_call("callbr", llty, llfn, args);
         let funclet_bundle = funclet.map(|funclet| funclet.bundle());
-        let funclet_bundle = funclet_bundle.as_ref().map(|b| &*b.raw);
         let mut bundles: SmallVec<[_; 2]> = SmallVec::new();
         if let Some(funclet_bundle) = funclet_bundle {
             bundles.push(funclet_bundle);
@@ -1520,13 +1516,12 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
 
         // Emit KCFI operand bundle
         let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, instance, llfn);
-        let kcfi_bundle = kcfi_bundle.as_ref().map(|b| &*b.raw);
-        if let Some(kcfi_bundle) = kcfi_bundle {
+        if let Some(kcfi_bundle) = kcfi_bundle.as_deref() {
             bundles.push(kcfi_bundle);
         }
 
         let callbr = unsafe {
-            llvm::LLVMRustBuildCallBr(
+            llvm::LLVMBuildCallBr(
                 self.llbuilder,
                 llty,
                 llfn,
@@ -1601,7 +1596,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
         fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
         instance: Option<Instance<'tcx>>,
         llfn: &'ll Value,
-    ) -> Option<llvm::OperandBundleDef<'ll>> {
+    ) -> Option<llvm::OperandBundleOwned<'ll>> {
         let is_indirect_call = unsafe { llvm::LLVMRustIsNonGVFunctionPointerTy(llfn) };
         let kcfi_bundle = if self.tcx.sess.is_sanitizer_kcfi_enabled()
             && let Some(fn_abi) = fn_abi
@@ -1627,7 +1622,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
                 kcfi::typeid_for_fnabi(self.tcx, fn_abi, options)
             };
 
-            Some(llvm::OperandBundleDef::new("kcfi", &[self.const_u32(kcfi_typeid)]))
+            Some(llvm::OperandBundleOwned::new("kcfi", &[self.const_u32(kcfi_typeid)]))
         } else {
             None
         };
diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs
index ff47eb944dd..8852dec7d9f 100644
--- a/compiler/rustc_codegen_llvm/src/common.rs
+++ b/compiler/rustc_codegen_llvm/src/common.rs
@@ -17,7 +17,7 @@ use tracing::debug;
 
 use crate::consts::const_alloc_to_llvm;
 pub(crate) use crate::context::CodegenCx;
-use crate::llvm::{self, BasicBlock, Bool, ConstantInt, False, Metadata, OperandBundleDef, True};
+use crate::llvm::{self, BasicBlock, Bool, ConstantInt, False, Metadata, True};
 use crate::type_::Type;
 use crate::value::Value;
 
@@ -63,19 +63,19 @@ use crate::value::Value;
 /// the `OperandBundleDef` value created for MSVC landing pads.
 pub(crate) struct Funclet<'ll> {
     cleanuppad: &'ll Value,
-    operand: OperandBundleDef<'ll>,
+    operand: llvm::OperandBundleOwned<'ll>,
 }
 
 impl<'ll> Funclet<'ll> {
     pub(crate) fn new(cleanuppad: &'ll Value) -> Self {
-        Funclet { cleanuppad, operand: OperandBundleDef::new("funclet", &[cleanuppad]) }
+        Funclet { cleanuppad, operand: llvm::OperandBundleOwned::new("funclet", &[cleanuppad]) }
     }
 
     pub(crate) fn cleanuppad(&self) -> &'ll Value {
         self.cleanuppad
     }
 
-    pub(crate) fn bundle(&self) -> &OperandBundleDef<'ll> {
+    pub(crate) fn bundle(&self) -> &llvm::OperandBundle<'ll> {
         &self.operand
     }
 }
@@ -392,3 +392,21 @@ pub(crate) fn get_dllimport<'tcx>(
     tcx.native_library(id)
         .and_then(|lib| lib.dll_imports.iter().find(|di| di.name.as_str() == name))
 }
+
+/// Extension trait for explicit casts to `*const c_char`.
+pub(crate) trait AsCCharPtr {
+    /// Equivalent to `self.as_ptr().cast()`, but only casts to `*const c_char`.
+    fn as_c_char_ptr(&self) -> *const c_char;
+}
+
+impl AsCCharPtr for str {
+    fn as_c_char_ptr(&self) -> *const c_char {
+        self.as_ptr().cast()
+    }
+}
+
+impl AsCCharPtr for [u8] {
+    fn as_c_char_ptr(&self) -> *const c_char {
+        self.as_ptr().cast()
+    }
+}
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index 1e3abcfd1af..21d996ef460 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -19,7 +19,7 @@ use rustc_target::abi::{
 };
 use tracing::{debug, instrument, trace};
 
-use crate::common::CodegenCx;
+use crate::common::{AsCCharPtr, CodegenCx};
 use crate::errors::{
     InvalidMinimumAlignmentNotPowerOfTwo, InvalidMinimumAlignmentTooLarge, SymbolAlreadyDefined,
 };
@@ -400,7 +400,7 @@ impl<'ll> CodegenCx<'ll, '_> {
 
                 let new_g = llvm::LLVMRustGetOrInsertGlobal(
                     self.llmod,
-                    name.as_ptr().cast(),
+                    name.as_c_char_ptr(),
                     name.len(),
                     val_llty,
                 );
@@ -451,7 +451,7 @@ impl<'ll> CodegenCx<'ll, '_> {
                 if let Some(section) = attrs.link_section {
                     let section = llvm::LLVMMDStringInContext2(
                         self.llcx,
-                        section.as_str().as_ptr().cast(),
+                        section.as_str().as_c_char_ptr(),
                         section.as_str().len(),
                     );
                     assert!(alloc.provenance().ptrs().is_empty());
@@ -462,7 +462,7 @@ impl<'ll> CodegenCx<'ll, '_> {
                     let bytes =
                         alloc.inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.len());
                     let alloc =
-                        llvm::LLVMMDStringInContext2(self.llcx, bytes.as_ptr().cast(), bytes.len());
+                        llvm::LLVMMDStringInContext2(self.llcx, bytes.as_c_char_ptr(), bytes.len());
                     let data = [section, alloc];
                     let meta = llvm::LLVMMDNodeInContext2(self.llcx, data.as_ptr(), data.len());
                     let val = llvm::LLVMMetadataAsValue(self.llcx, meta);
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 067028a16ff..13428b109d9 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -29,6 +29,7 @@ use smallvec::SmallVec;
 
 use crate::back::write::to_llvm_code_model;
 use crate::callee::get_fn;
+use crate::common::AsCCharPtr;
 use crate::debuginfo::metadata::apply_vcall_visibility_metadata;
 use crate::llvm::{Metadata, MetadataType};
 use crate::type_::Type;
@@ -147,6 +148,11 @@ pub(crate) unsafe fn create_module<'ll>(
             target_data_layout =
                 target_data_layout.replace("-p270:32:32-p271:32:32-p272:64:64", "");
         }
+        if sess.target.arch.starts_with("sparc") {
+            // LLVM 20 updates the sparc layout to correctly align 128 bit integers to 128 bit.
+            // See https://github.com/llvm/llvm-project/pull/106951
+            target_data_layout = target_data_layout.replace("-i128:128", "");
+        }
     }
 
     // Ensure the data-layout values hardcoded remain the defaults.
@@ -209,133 +215,111 @@ pub(crate) unsafe fn create_module<'ll>(
     // If skipping the PLT is enabled, we need to add some module metadata
     // to ensure intrinsic calls don't use it.
     if !sess.needs_plt() {
-        let avoid_plt = c"RtLibUseGOT".as_ptr();
-        unsafe {
-            llvm::LLVMRustAddModuleFlagU32(llmod, llvm::LLVMModFlagBehavior::Warning, avoid_plt, 1);
-        }
+        llvm::add_module_flag_u32(llmod, llvm::ModuleFlagMergeBehavior::Warning, "RtLibUseGOT", 1);
     }
 
     // Enable canonical jump tables if CFI is enabled. (See https://reviews.llvm.org/D65629.)
     if sess.is_sanitizer_cfi_canonical_jump_tables_enabled() && sess.is_sanitizer_cfi_enabled() {
-        let canonical_jump_tables = c"CFI Canonical Jump Tables".as_ptr();
-        unsafe {
-            llvm::LLVMRustAddModuleFlagU32(
-                llmod,
-                llvm::LLVMModFlagBehavior::Override,
-                canonical_jump_tables,
-                1,
-            );
-        }
+        llvm::add_module_flag_u32(
+            llmod,
+            llvm::ModuleFlagMergeBehavior::Override,
+            "CFI Canonical Jump Tables",
+            1,
+        );
     }
 
     // If we're normalizing integers with CFI, ensure LLVM generated functions do the same.
     // See https://github.com/llvm/llvm-project/pull/104826
     if sess.is_sanitizer_cfi_normalize_integers_enabled() {
-        let cfi_normalize_integers = c"cfi-normalize-integers".as_ptr().cast();
-        unsafe {
-            llvm::LLVMRustAddModuleFlagU32(
-                llmod,
-                llvm::LLVMModFlagBehavior::Override,
-                cfi_normalize_integers,
-                1,
-            );
-        }
+        llvm::add_module_flag_u32(
+            llmod,
+            llvm::ModuleFlagMergeBehavior::Override,
+            "cfi-normalize-integers",
+            1,
+        );
     }
 
     // Enable LTO unit splitting if specified or if CFI is enabled. (See
     // https://reviews.llvm.org/D53891.)
     if sess.is_split_lto_unit_enabled() || sess.is_sanitizer_cfi_enabled() {
-        let enable_split_lto_unit = c"EnableSplitLTOUnit".as_ptr();
-        unsafe {
-            llvm::LLVMRustAddModuleFlagU32(
-                llmod,
-                llvm::LLVMModFlagBehavior::Override,
-                enable_split_lto_unit,
-                1,
-            );
-        }
+        llvm::add_module_flag_u32(
+            llmod,
+            llvm::ModuleFlagMergeBehavior::Override,
+            "EnableSplitLTOUnit",
+            1,
+        );
     }
 
     // Add "kcfi" module flag if KCFI is enabled. (See https://reviews.llvm.org/D119296.)
     if sess.is_sanitizer_kcfi_enabled() {
-        let kcfi = c"kcfi".as_ptr();
-        unsafe {
-            llvm::LLVMRustAddModuleFlagU32(llmod, llvm::LLVMModFlagBehavior::Override, kcfi, 1);
-        }
+        llvm::add_module_flag_u32(llmod, llvm::ModuleFlagMergeBehavior::Override, "kcfi", 1);
 
         // Add "kcfi-offset" module flag with -Z patchable-function-entry (See
         // https://reviews.llvm.org/D141172).
         let pfe =
             PatchableFunctionEntry::from_config(sess.opts.unstable_opts.patchable_function_entry);
         if pfe.prefix() > 0 {
-            let kcfi_offset = c"kcfi-offset".as_ptr().cast();
-            unsafe {
-                llvm::LLVMRustAddModuleFlagU32(
-                    llmod,
-                    llvm::LLVMModFlagBehavior::Override,
-                    kcfi_offset,
-                    pfe.prefix().into(),
-                );
-            }
+            llvm::add_module_flag_u32(
+                llmod,
+                llvm::ModuleFlagMergeBehavior::Override,
+                "kcfi-offset",
+                pfe.prefix().into(),
+            );
         }
     }
 
     // Control Flow Guard is currently only supported by the MSVC linker on Windows.
     if sess.target.is_like_msvc {
-        unsafe {
-            match sess.opts.cg.control_flow_guard {
-                CFGuard::Disabled => {}
-                CFGuard::NoChecks => {
-                    // Set `cfguard=1` module flag to emit metadata only.
-                    llvm::LLVMRustAddModuleFlagU32(
-                        llmod,
-                        llvm::LLVMModFlagBehavior::Warning,
-                        c"cfguard".as_ptr() as *const _,
-                        1,
-                    )
-                }
-                CFGuard::Checks => {
-                    // Set `cfguard=2` module flag to emit metadata and checks.
-                    llvm::LLVMRustAddModuleFlagU32(
-                        llmod,
-                        llvm::LLVMModFlagBehavior::Warning,
-                        c"cfguard".as_ptr() as *const _,
-                        2,
-                    )
-                }
+        match sess.opts.cg.control_flow_guard {
+            CFGuard::Disabled => {}
+            CFGuard::NoChecks => {
+                // Set `cfguard=1` module flag to emit metadata only.
+                llvm::add_module_flag_u32(
+                    llmod,
+                    llvm::ModuleFlagMergeBehavior::Warning,
+                    "cfguard",
+                    1,
+                );
+            }
+            CFGuard::Checks => {
+                // Set `cfguard=2` module flag to emit metadata and checks.
+                llvm::add_module_flag_u32(
+                    llmod,
+                    llvm::ModuleFlagMergeBehavior::Warning,
+                    "cfguard",
+                    2,
+                );
             }
         }
     }
 
     if let Some(BranchProtection { bti, pac_ret }) = sess.opts.unstable_opts.branch_protection {
         if sess.target.arch == "aarch64" {
-            unsafe {
-                llvm::LLVMRustAddModuleFlagU32(
-                    llmod,
-                    llvm::LLVMModFlagBehavior::Min,
-                    c"branch-target-enforcement".as_ptr(),
-                    bti.into(),
-                );
-                llvm::LLVMRustAddModuleFlagU32(
-                    llmod,
-                    llvm::LLVMModFlagBehavior::Min,
-                    c"sign-return-address".as_ptr(),
-                    pac_ret.is_some().into(),
-                );
-                let pac_opts = pac_ret.unwrap_or(PacRet { leaf: false, key: PAuthKey::A });
-                llvm::LLVMRustAddModuleFlagU32(
-                    llmod,
-                    llvm::LLVMModFlagBehavior::Min,
-                    c"sign-return-address-all".as_ptr(),
-                    pac_opts.leaf.into(),
-                );
-                llvm::LLVMRustAddModuleFlagU32(
-                    llmod,
-                    llvm::LLVMModFlagBehavior::Min,
-                    c"sign-return-address-with-bkey".as_ptr(),
-                    u32::from(pac_opts.key == PAuthKey::B),
-                );
-            }
+            llvm::add_module_flag_u32(
+                llmod,
+                llvm::ModuleFlagMergeBehavior::Min,
+                "branch-target-enforcement",
+                bti.into(),
+            );
+            llvm::add_module_flag_u32(
+                llmod,
+                llvm::ModuleFlagMergeBehavior::Min,
+                "sign-return-address",
+                pac_ret.is_some().into(),
+            );
+            let pac_opts = pac_ret.unwrap_or(PacRet { leaf: false, key: PAuthKey::A });
+            llvm::add_module_flag_u32(
+                llmod,
+                llvm::ModuleFlagMergeBehavior::Min,
+                "sign-return-address-all",
+                pac_opts.leaf.into(),
+            );
+            llvm::add_module_flag_u32(
+                llmod,
+                llvm::ModuleFlagMergeBehavior::Min,
+                "sign-return-address-with-bkey",
+                u32::from(pac_opts.key == PAuthKey::B),
+            );
         } else {
             bug!(
                 "branch-protection used on non-AArch64 target; \
@@ -346,59 +330,46 @@ pub(crate) unsafe fn create_module<'ll>(
 
     // Pass on the control-flow protection flags to LLVM (equivalent to `-fcf-protection` in Clang).
     if let CFProtection::Branch | CFProtection::Full = sess.opts.unstable_opts.cf_protection {
-        unsafe {
-            llvm::LLVMRustAddModuleFlagU32(
-                llmod,
-                llvm::LLVMModFlagBehavior::Override,
-                c"cf-protection-branch".as_ptr(),
-                1,
-            );
-        }
+        llvm::add_module_flag_u32(
+            llmod,
+            llvm::ModuleFlagMergeBehavior::Override,
+            "cf-protection-branch",
+            1,
+        );
     }
     if let CFProtection::Return | CFProtection::Full = sess.opts.unstable_opts.cf_protection {
-        unsafe {
-            llvm::LLVMRustAddModuleFlagU32(
-                llmod,
-                llvm::LLVMModFlagBehavior::Override,
-                c"cf-protection-return".as_ptr(),
-                1,
-            );
-        }
+        llvm::add_module_flag_u32(
+            llmod,
+            llvm::ModuleFlagMergeBehavior::Override,
+            "cf-protection-return",
+            1,
+        );
     }
 
     if sess.opts.unstable_opts.virtual_function_elimination {
-        unsafe {
-            llvm::LLVMRustAddModuleFlagU32(
-                llmod,
-                llvm::LLVMModFlagBehavior::Error,
-                c"Virtual Function Elim".as_ptr(),
-                1,
-            );
-        }
+        llvm::add_module_flag_u32(
+            llmod,
+            llvm::ModuleFlagMergeBehavior::Error,
+            "Virtual Function Elim",
+            1,
+        );
     }
 
     // Set module flag to enable Windows EHCont Guard (/guard:ehcont).
     if sess.opts.unstable_opts.ehcont_guard {
-        unsafe {
-            llvm::LLVMRustAddModuleFlagU32(
-                llmod,
-                llvm::LLVMModFlagBehavior::Warning,
-                c"ehcontguard".as_ptr() as *const _,
-                1,
-            )
-        }
+        llvm::add_module_flag_u32(llmod, llvm::ModuleFlagMergeBehavior::Warning, "ehcontguard", 1);
     }
 
     match sess.opts.unstable_opts.function_return {
         FunctionReturn::Keep => {}
-        FunctionReturn::ThunkExtern => unsafe {
-            llvm::LLVMRustAddModuleFlagU32(
+        FunctionReturn::ThunkExtern => {
+            llvm::add_module_flag_u32(
                 llmod,
-                llvm::LLVMModFlagBehavior::Override,
-                c"function_return_thunk_extern".as_ptr(),
+                llvm::ModuleFlagMergeBehavior::Override,
+                "function_return_thunk_extern",
                 1,
-            )
-        },
+            );
+        }
     }
 
     match (sess.opts.unstable_opts.small_data_threshold, sess.target.small_data_threshold_support())
@@ -406,15 +377,12 @@ pub(crate) unsafe fn create_module<'ll>(
         // Set up the small-data optimization limit for architectures that use
         // an LLVM module flag to control this.
         (Some(threshold), SmallDataThresholdSupport::LlvmModuleFlag(flag)) => {
-            let flag = SmallCStr::new(flag.as_ref());
-            unsafe {
-                llvm::LLVMRustAddModuleFlagU32(
-                    llmod,
-                    llvm::LLVMModFlagBehavior::Error,
-                    flag.as_c_str().as_ptr(),
-                    threshold as u32,
-                )
-            }
+            llvm::add_module_flag_u32(
+                llmod,
+                llvm::ModuleFlagMergeBehavior::Error,
+                &flag,
+                threshold as u32,
+            );
         }
         _ => (),
     };
@@ -429,7 +397,7 @@ pub(crate) unsafe fn create_module<'ll>(
     let name_metadata = unsafe {
         llvm::LLVMMDStringInContext2(
             llcx,
-            rustc_producer.as_ptr().cast(),
+            rustc_producer.as_c_char_ptr(),
             rustc_producer.as_bytes().len(),
         )
     };
@@ -448,33 +416,29 @@ pub(crate) unsafe fn create_module<'ll>(
     // If llvm_abiname is empty, emit nothing.
     let llvm_abiname = &sess.target.options.llvm_abiname;
     if matches!(sess.target.arch.as_ref(), "riscv32" | "riscv64") && !llvm_abiname.is_empty() {
-        unsafe {
-            llvm::LLVMRustAddModuleFlagString(
-                llmod,
-                llvm::LLVMModFlagBehavior::Error,
-                c"target-abi".as_ptr(),
-                llvm_abiname.as_ptr().cast(),
-                llvm_abiname.len(),
-            );
-        }
+        llvm::add_module_flag_str(
+            llmod,
+            llvm::ModuleFlagMergeBehavior::Error,
+            "target-abi",
+            llvm_abiname,
+        );
     }
 
     // Add module flags specified via -Z llvm_module_flag
-    for (key, value, behavior) in &sess.opts.unstable_opts.llvm_module_flag {
-        let key = format!("{key}\0");
-        let behavior = match behavior.as_str() {
-            "error" => llvm::LLVMModFlagBehavior::Error,
-            "warning" => llvm::LLVMModFlagBehavior::Warning,
-            "require" => llvm::LLVMModFlagBehavior::Require,
-            "override" => llvm::LLVMModFlagBehavior::Override,
-            "append" => llvm::LLVMModFlagBehavior::Append,
-            "appendunique" => llvm::LLVMModFlagBehavior::AppendUnique,
-            "max" => llvm::LLVMModFlagBehavior::Max,
-            "min" => llvm::LLVMModFlagBehavior::Min,
+    for (key, value, merge_behavior) in &sess.opts.unstable_opts.llvm_module_flag {
+        let merge_behavior = match merge_behavior.as_str() {
+            "error" => llvm::ModuleFlagMergeBehavior::Error,
+            "warning" => llvm::ModuleFlagMergeBehavior::Warning,
+            "require" => llvm::ModuleFlagMergeBehavior::Require,
+            "override" => llvm::ModuleFlagMergeBehavior::Override,
+            "append" => llvm::ModuleFlagMergeBehavior::Append,
+            "appendunique" => llvm::ModuleFlagMergeBehavior::AppendUnique,
+            "max" => llvm::ModuleFlagMergeBehavior::Max,
+            "min" => llvm::ModuleFlagMergeBehavior::Min,
             // We already checked this during option parsing
             _ => unreachable!(),
         };
-        unsafe { llvm::LLVMRustAddModuleFlagU32(llmod, behavior, key.as_ptr().cast(), *value) }
+        llvm::add_module_flag_u32(llmod, merge_behavior, key, *value);
     }
 
     llmod
@@ -595,6 +559,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
 
     /// Extra state that is only available when coverage instrumentation is enabled.
     #[inline]
+    #[track_caller]
     pub(crate) fn coverage_cx(&self) -> &coverageinfo::CrateCoverageContext<'ll, 'tcx> {
         self.coverage_cx.as_ref().expect("only called when coverage instrumentation is enabled")
     }
@@ -606,7 +571,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
             let g = llvm::LLVMAddGlobal(self.llmod, self.val_ty(array), name.as_ptr());
             llvm::LLVMSetInitializer(g, array);
             llvm::set_linkage(g, llvm::Linkage::AppendingLinkage);
-            llvm::LLVMSetSection(g, c"llvm.metadata".as_ptr());
+            llvm::set_section(g, c"llvm.metadata");
         }
     }
 }
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
index 8edd788ee36..f6378199fe2 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
@@ -54,7 +54,11 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) {
         add_unused_functions(cx);
     }
 
-    let function_coverage_map = cx.coverage_cx().take_function_coverage_map();
+    // FIXME(#132395): Can this be none even when coverage is enabled?
+    let function_coverage_map = match cx.coverage_cx {
+        Some(ref cx) => cx.take_function_coverage_map(),
+        None => return,
+    };
     if function_coverage_map.is_empty() {
         // This module has no functions with coverage instrumentation
         return;
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
index c6b2a623ea6..e4ff50816b9 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
@@ -14,7 +14,7 @@ use rustc_target::abi::Size;
 use tracing::{debug, instrument};
 
 use crate::builder::Builder;
-use crate::common::CodegenCx;
+use crate::common::{AsCCharPtr, CodegenCx};
 use crate::coverageinfo::map_data::FunctionCoverageCollector;
 use crate::llvm;
 
@@ -152,7 +152,12 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
             return;
         };
 
-        let mut coverage_map = bx.coverage_cx().function_coverage_map.borrow_mut();
+        // FIXME(#132395): Unwrapping `coverage_cx` here has led to ICEs in the
+        // wild, so keep this early-return until we understand why.
+        let mut coverage_map = match bx.coverage_cx {
+            Some(ref cx) => cx.function_coverage_map.borrow_mut(),
+            None => return,
+        };
         let func_coverage = coverage_map
             .entry(instance)
             .or_insert_with(|| FunctionCoverageCollector::new(instance, function_coverage_info));
@@ -236,7 +241,7 @@ fn create_pgo_func_name_var<'ll, 'tcx>(
     unsafe {
         llvm::LLVMRustCoverageCreatePGOFuncNameVar(
             llfn,
-            mangled_fn_name.as_ptr().cast(),
+            mangled_fn_name.as_c_char_ptr(),
             mangled_fn_name.len(),
         )
     }
@@ -248,7 +253,7 @@ pub(crate) fn write_filenames_section_to_buffer<'a>(
 ) {
     let (pointers, lengths) = filenames
         .into_iter()
-        .map(|s: &str| (s.as_ptr().cast(), s.len()))
+        .map(|s: &str| (s.as_c_char_ptr(), s.len()))
         .unzip::<_, _, Vec<_>, Vec<_>>();
 
     unsafe {
@@ -291,7 +296,7 @@ pub(crate) fn write_mapping_to_buffer(
 }
 
 pub(crate) fn hash_bytes(bytes: &[u8]) -> u64 {
-    unsafe { llvm::LLVMRustCoverageHashByteArray(bytes.as_ptr().cast(), bytes.len()) }
+    unsafe { llvm::LLVMRustCoverageHashByteArray(bytes.as_c_char_ptr(), bytes.len()) }
 }
 
 pub(crate) fn mapping_version() -> u32 {
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
index 7947c9c8c8e..aef8642f199 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
@@ -72,7 +72,7 @@ pub(crate) fn get_or_insert_gdb_debug_scripts_section_global<'ll>(
             let section_var = cx
                 .define_global(section_var_name, llvm_type)
                 .unwrap_or_else(|| bug!("symbol `{}` is already defined", section_var_name));
-            llvm::LLVMSetSection(section_var, c".debug_gdb_scripts".as_ptr());
+            llvm::set_section(section_var, c".debug_gdb_scripts");
             llvm::LLVMSetInitializer(section_var, cx.const_bytes(section_contents));
             llvm::LLVMSetGlobalConstant(section_var, llvm::True);
             llvm::LLVMSetUnnamedAddress(section_var, llvm::UnnamedAddr::Global);
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 15d441a986d..9064cfaeb29 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -32,7 +32,7 @@ use super::type_names::{compute_debuginfo_type_name, compute_debuginfo_vtable_na
 use super::utils::{
     DIB, create_DIArray, debug_context, get_namespace_for_item, is_node_local_to_unit,
 };
-use crate::common::CodegenCx;
+use crate::common::{AsCCharPtr, CodegenCx};
 use crate::debuginfo::metadata::type_map::build_type_with_children;
 use crate::debuginfo::utils::{WidePtrKind, wide_pointer_kind};
 use crate::llvm::debuginfo::{
@@ -190,7 +190,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
                     data_layout.pointer_size.bits(),
                     data_layout.pointer_align.abi.bits() as u32,
                     0, // Ignore DWARF address space.
-                    ptr_type_debuginfo_name.as_ptr().cast(),
+                    ptr_type_debuginfo_name.as_c_char_ptr(),
                     ptr_type_debuginfo_name.len(),
                 )
             };
@@ -348,7 +348,7 @@ fn build_subroutine_type_di_node<'ll, 'tcx>(
             size,
             align,
             0, // Ignore DWARF address space.
-            name.as_ptr().cast(),
+            name.as_c_char_ptr(),
             name.len(),
         )
     };
@@ -518,7 +518,7 @@ fn recursion_marker_type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> &'ll D
             let name = "<recur_type>";
             llvm::LLVMRustDIBuilderCreateBasicType(
                 DIB(cx),
-                name.as_ptr().cast(),
+                name.as_c_char_ptr(),
                 name.len(),
                 cx.tcx.data_layout.pointer_size.bits(),
                 DW_ATE_unsigned,
@@ -640,14 +640,14 @@ pub(crate) fn file_metadata<'ll>(cx: &CodegenCx<'ll, '_>, source_file: &SourceFi
         unsafe {
             llvm::LLVMRustDIBuilderCreateFile(
                 DIB(cx),
-                file_name.as_ptr().cast(),
+                file_name.as_c_char_ptr(),
                 file_name.len(),
-                directory.as_ptr().cast(),
+                directory.as_c_char_ptr(),
                 directory.len(),
                 hash_kind,
-                hash_value.as_ptr().cast(),
+                hash_value.as_c_char_ptr(),
                 hash_value.len(),
-                source.map_or(ptr::null(), |x| x.as_ptr().cast()),
+                source.map_or(ptr::null(), |x| x.as_c_char_ptr()),
                 source.map_or(0, |x| x.len()),
             )
         }
@@ -662,12 +662,12 @@ fn unknown_file_metadata<'ll>(cx: &CodegenCx<'ll, '_>) -> &'ll DIFile {
 
         llvm::LLVMRustDIBuilderCreateFile(
             DIB(cx),
-            file_name.as_ptr().cast(),
+            file_name.as_c_char_ptr(),
             file_name.len(),
-            directory.as_ptr().cast(),
+            directory.as_c_char_ptr(),
             directory.len(),
             llvm::ChecksumKind::None,
-            hash_value.as_ptr().cast(),
+            hash_value.as_c_char_ptr(),
             hash_value.len(),
             ptr::null(),
             0,
@@ -788,7 +788,7 @@ fn build_basic_type_di_node<'ll, 'tcx>(
     let ty_di_node = unsafe {
         llvm::LLVMRustDIBuilderCreateBasicType(
             DIB(cx),
-            name.as_ptr().cast(),
+            name.as_c_char_ptr(),
             name.len(),
             cx.size_of(t).bits(),
             encoding,
@@ -810,7 +810,7 @@ fn build_basic_type_di_node<'ll, 'tcx>(
         llvm::LLVMRustDIBuilderCreateTypedef(
             DIB(cx),
             ty_di_node,
-            typedef_name.as_ptr().cast(),
+            typedef_name.as_c_char_ptr(),
             typedef_name.len(),
             unknown_file_metadata(cx),
             0,
@@ -861,7 +861,7 @@ fn build_param_type_di_node<'ll, 'tcx>(
         di_node: unsafe {
             llvm::LLVMRustDIBuilderCreateBasicType(
                 DIB(cx),
-                name.as_ptr().cast(),
+                name.as_c_char_ptr(),
                 name.len(),
                 Size::ZERO.bits(),
                 DW_ATE_unsigned,
@@ -948,9 +948,9 @@ pub(crate) fn build_compile_unit_di_node<'ll, 'tcx>(
     unsafe {
         let compile_unit_file = llvm::LLVMRustDIBuilderCreateFile(
             debug_context.builder,
-            name_in_debuginfo.as_ptr().cast(),
+            name_in_debuginfo.as_c_char_ptr(),
             name_in_debuginfo.len(),
-            work_dir.as_ptr().cast(),
+            work_dir.as_c_char_ptr(),
             work_dir.len(),
             llvm::ChecksumKind::None,
             ptr::null(),
@@ -963,7 +963,7 @@ pub(crate) fn build_compile_unit_di_node<'ll, 'tcx>(
             debug_context.builder,
             DW_LANG_RUST,
             compile_unit_file,
-            producer.as_ptr().cast(),
+            producer.as_c_char_ptr(),
             producer.len(),
             tcx.sess.opts.optimize != config::OptLevel::No,
             c"".as_ptr(),
@@ -971,7 +971,7 @@ pub(crate) fn build_compile_unit_di_node<'ll, 'tcx>(
             // NB: this doesn't actually have any perceptible effect, it seems. LLVM will instead
             // put the path supplied to `MCSplitDwarfFile` into the debug info of the final
             // output(s).
-            split_name.as_ptr().cast(),
+            split_name.as_c_char_ptr(),
             split_name.len(),
             kind,
             0,
@@ -1022,7 +1022,7 @@ fn build_field_di_node<'ll, 'tcx>(
         llvm::LLVMRustDIBuilderCreateMemberType(
             DIB(cx),
             owner,
-            name.as_ptr().cast(),
+            name.as_c_char_ptr(),
             name.len(),
             unknown_file_metadata(cx),
             UNKNOWN_LINE_NUMBER,
@@ -1306,7 +1306,7 @@ fn build_generic_type_param_di_nodes<'ll, 'tcx>(
                             llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
                                 DIB(cx),
                                 None,
-                                name.as_ptr().cast(),
+                                name.as_c_char_ptr(),
                                 name.len(),
                                 actual_type_di_node,
                             )
@@ -1382,9 +1382,9 @@ pub(crate) fn build_global_var_di_node<'ll>(
         llvm::LLVMRustDIBuilderCreateStaticVariable(
             DIB(cx),
             Some(var_scope),
-            var_name.as_ptr().cast(),
+            var_name.as_c_char_ptr(),
             var_name.len(),
-            linkage_name.as_ptr().cast(),
+            linkage_name.as_c_char_ptr(),
             linkage_name.len(),
             file_metadata,
             line_number,
@@ -1602,9 +1602,9 @@ pub(crate) fn create_vtable_di_node<'ll, 'tcx>(
         llvm::LLVMRustDIBuilderCreateStaticVariable(
             DIB(cx),
             NO_SCOPE_METADATA,
-            vtable_name.as_ptr().cast(),
+            vtable_name.as_c_char_ptr(),
             vtable_name.len(),
-            linkage_name.as_ptr().cast(),
+            linkage_name.as_c_char_ptr(),
             linkage_name.len(),
             unknown_file_metadata(cx),
             UNKNOWN_LINE_NUMBER,
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
index 966788cf32f..5385d3a9212 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
@@ -11,7 +11,7 @@ use rustc_middle::ty::{self, AdtDef, CoroutineArgs, CoroutineArgsExt, Ty};
 use rustc_target::abi::{Align, Endian, Size, TagEncoding, VariantIdx, Variants};
 use smallvec::smallvec;
 
-use crate::common::CodegenCx;
+use crate::common::{AsCCharPtr, CodegenCx};
 use crate::debuginfo::metadata::enums::DiscrResult;
 use crate::debuginfo::metadata::type_map::{self, Stub, UniqueTypeId};
 use crate::debuginfo::metadata::{
@@ -359,7 +359,7 @@ fn build_single_variant_union_fields<'ll, 'tcx>(
             llvm::LLVMRustDIBuilderCreateStaticMemberType(
                 DIB(cx),
                 enum_type_di_node,
-                TAG_FIELD_NAME.as_ptr().cast(),
+                TAG_FIELD_NAME.as_c_char_ptr(),
                 TAG_FIELD_NAME.len(),
                 unknown_file_metadata(cx),
                 UNKNOWN_LINE_NUMBER,
@@ -537,7 +537,7 @@ fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>(
                     llvm::LLVMRustDIBuilderCreateStaticMemberType(
                         DIB(cx),
                         wrapper_struct_type_di_node,
-                        name.as_ptr().cast(),
+                        name.as_c_char_ptr(),
                         name.len(),
                         unknown_file_metadata(cx),
                         UNKNOWN_LINE_NUMBER,
@@ -785,7 +785,7 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>(
             llvm::LLVMRustDIBuilderCreateMemberType(
                 DIB(cx),
                 enum_type_di_node,
-                field_name.as_ptr().cast(),
+                field_name.as_c_char_ptr(),
                 field_name.len(),
                 file_di_node,
                 line_number,
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
index fe1634146ff..4c848027b55 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
@@ -13,7 +13,7 @@ use rustc_target::abi::{FieldIdx, TagEncoding, VariantIdx, Variants};
 
 use super::type_map::{DINodeCreationResult, UniqueTypeId};
 use super::{SmallVec, size_and_align_of};
-use crate::common::CodegenCx;
+use crate::common::{AsCCharPtr, CodegenCx};
 use crate::debuginfo::metadata::type_map::{self, Stub};
 use crate::debuginfo::metadata::{
     UNKNOWN_LINE_NUMBER, build_field_di_node, build_generic_type_param_di_nodes, type_di_node,
@@ -106,7 +106,7 @@ fn build_enumeration_type_di_node<'ll, 'tcx>(
             let value = [value as u64, (value >> 64) as u64];
             Some(llvm::LLVMRustDIBuilderCreateEnumerator(
                 DIB(cx),
-                name.as_ptr().cast(),
+                name.as_c_char_ptr(),
                 name.len(),
                 value.as_ptr(),
                 size.bits() as libc::c_uint,
@@ -119,7 +119,7 @@ fn build_enumeration_type_di_node<'ll, 'tcx>(
         llvm::LLVMRustDIBuilderCreateEnumerationType(
             DIB(cx),
             containing_scope,
-            type_name.as_ptr().cast(),
+            type_name.as_c_char_ptr(),
             type_name.len(),
             unknown_file_metadata(cx),
             UNKNOWN_LINE_NUMBER,
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
index 5e7dbdd921a..b7400c5aeb2 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
@@ -10,7 +10,7 @@ use rustc_middle::ty::{self};
 use rustc_target::abi::{Size, TagEncoding, VariantIdx, Variants};
 use smallvec::smallvec;
 
-use crate::common::CodegenCx;
+use crate::common::{AsCCharPtr, CodegenCx};
 use crate::debuginfo::metadata::type_map::{self, Stub, StubInfo, UniqueTypeId};
 use crate::debuginfo::metadata::{
     DINodeCreationResult, NO_GENERICS, SmallVec, UNKNOWN_LINE_NUMBER, file_metadata,
@@ -244,7 +244,7 @@ fn build_enum_variant_part_di_node<'ll, 'tcx>(
             llvm::LLVMRustDIBuilderCreateVariantPart(
                 DIB(cx),
                 enum_type_di_node,
-                variant_part_name.as_ptr().cast(),
+                variant_part_name.as_c_char_ptr(),
                 variant_part_name.len(),
                 unknown_file_metadata(cx),
                 UNKNOWN_LINE_NUMBER,
@@ -253,7 +253,7 @@ fn build_enum_variant_part_di_node<'ll, 'tcx>(
                 DIFlags::FlagZero,
                 tag_member_di_node,
                 create_DIArray(DIB(cx), &[]),
-                variant_part_unique_type_id_str.as_ptr().cast(),
+                variant_part_unique_type_id_str.as_c_char_ptr(),
                 variant_part_unique_type_id_str.len(),
             )
         },
@@ -327,7 +327,7 @@ fn build_discr_member_di_node<'ll, 'tcx>(
                 Some(llvm::LLVMRustDIBuilderCreateMemberType(
                     DIB(cx),
                     containing_scope,
-                    tag_name.as_ptr().cast(),
+                    tag_name.as_c_char_ptr(),
                     tag_name.len(),
                     unknown_file_metadata(cx),
                     UNKNOWN_LINE_NUMBER,
@@ -399,7 +399,7 @@ fn build_enum_variant_member_di_node<'ll, 'tcx>(
         llvm::LLVMRustDIBuilderCreateVariantMemberType(
             DIB(cx),
             variant_part_di_node,
-            variant_member_info.variant_name.as_ptr().cast(),
+            variant_member_info.variant_name.as_c_char_ptr(),
             variant_member_info.variant_name.len(),
             file_di_node,
             line_number,
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs
index 714e3c0b145..d050dc9b406 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs
@@ -9,7 +9,7 @@ use rustc_middle::ty::{ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt};
 use rustc_target::abi::{Align, Size, VariantIdx};
 
 use super::{SmallVec, UNKNOWN_LINE_NUMBER, unknown_file_metadata};
-use crate::common::CodegenCx;
+use crate::common::{AsCCharPtr, CodegenCx};
 use crate::debuginfo::utils::{DIB, create_DIArray, debug_context};
 use crate::llvm::debuginfo::{DIFlags, DIScope, DIType};
 use crate::llvm::{self};
@@ -191,7 +191,7 @@ pub(super) fn stub<'ll, 'tcx>(
                 llvm::LLVMRustDIBuilderCreateStructType(
                     DIB(cx),
                     containing_scope,
-                    name.as_ptr().cast(),
+                    name.as_c_char_ptr(),
                     name.len(),
                     unknown_file_metadata(cx),
                     UNKNOWN_LINE_NUMBER,
@@ -202,7 +202,7 @@ pub(super) fn stub<'ll, 'tcx>(
                     empty_array,
                     0,
                     vtable_holder,
-                    unique_type_id_str.as_ptr().cast(),
+                    unique_type_id_str.as_c_char_ptr(),
                     unique_type_id_str.len(),
                 )
             }
@@ -211,7 +211,7 @@ pub(super) fn stub<'ll, 'tcx>(
             llvm::LLVMRustDIBuilderCreateUnionType(
                 DIB(cx),
                 containing_scope,
-                name.as_ptr().cast(),
+                name.as_c_char_ptr(),
                 name.len(),
                 unknown_file_metadata(cx),
                 UNKNOWN_LINE_NUMBER,
@@ -220,7 +220,7 @@ pub(super) fn stub<'ll, 'tcx>(
                 flags,
                 Some(empty_array),
                 0,
-                unique_type_id_str.as_ptr().cast(),
+                unique_type_id_str.as_c_char_ptr(),
                 unique_type_id_str.len(),
             )
         },
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index 3de4ca77e7d..72e723aa849 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -31,7 +31,7 @@ use self::namespace::mangled_name_of_instance;
 use self::utils::{DIB, create_DIArray, is_node_local_to_unit};
 use crate::abi::FnAbi;
 use crate::builder::Builder;
-use crate::common::CodegenCx;
+use crate::common::{AsCCharPtr, CodegenCx};
 use crate::llvm;
 use crate::llvm::debuginfo::{
     DIArray, DIBuilder, DIFile, DIFlags, DILexicalBlock, DILocation, DISPFlags, DIScope, DIType,
@@ -91,45 +91,39 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> {
     }
 
     pub(crate) fn finalize(&self, sess: &Session) {
-        unsafe {
-            llvm::LLVMRustDIBuilderFinalize(self.builder);
-
-            if !sess.target.is_like_msvc {
-                // Debuginfo generation in LLVM by default uses a higher
-                // version of dwarf than macOS currently understands. We can
-                // instruct LLVM to emit an older version of dwarf, however,
-                // for macOS to understand. For more info see #11352
-                // This can be overridden using --llvm-opts -dwarf-version,N.
-                // Android has the same issue (#22398)
-                let dwarf_version = sess
-                    .opts
-                    .unstable_opts
-                    .dwarf_version
-                    .unwrap_or(sess.target.default_dwarf_version);
-                llvm::LLVMRustAddModuleFlagU32(
-                    self.llmod,
-                    llvm::LLVMModFlagBehavior::Warning,
-                    c"Dwarf Version".as_ptr(),
-                    dwarf_version,
-                );
-            } else {
-                // Indicate that we want CodeView debug information on MSVC
-                llvm::LLVMRustAddModuleFlagU32(
-                    self.llmod,
-                    llvm::LLVMModFlagBehavior::Warning,
-                    c"CodeView".as_ptr(),
-                    1,
-                )
-            }
-
-            // Prevent bitcode readers from deleting the debug info.
-            llvm::LLVMRustAddModuleFlagU32(
+        unsafe { llvm::LLVMRustDIBuilderFinalize(self.builder) };
+        if !sess.target.is_like_msvc {
+            // Debuginfo generation in LLVM by default uses a higher
+            // version of dwarf than macOS currently understands. We can
+            // instruct LLVM to emit an older version of dwarf, however,
+            // for macOS to understand. For more info see #11352
+            // This can be overridden using --llvm-opts -dwarf-version,N.
+            // Android has the same issue (#22398)
+            let dwarf_version =
+                sess.opts.unstable_opts.dwarf_version.unwrap_or(sess.target.default_dwarf_version);
+            llvm::add_module_flag_u32(
                 self.llmod,
-                llvm::LLVMModFlagBehavior::Warning,
-                c"Debug Info Version".as_ptr(),
-                llvm::LLVMRustDebugMetadataVersion(),
+                llvm::ModuleFlagMergeBehavior::Warning,
+                "Dwarf Version",
+                dwarf_version,
+            );
+        } else {
+            // Indicate that we want CodeView debug information on MSVC
+            llvm::add_module_flag_u32(
+                self.llmod,
+                llvm::ModuleFlagMergeBehavior::Warning,
+                "CodeView",
+                1,
             );
         }
+
+        // Prevent bitcode readers from deleting the debug info.
+        llvm::add_module_flag_u32(
+            self.llmod,
+            llvm::ModuleFlagMergeBehavior::Warning,
+            "Debug Info Version",
+            unsafe { llvm::LLVMRustDebugMetadataVersion() },
+        );
     }
 }
 
@@ -364,7 +358,7 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
 
         let mut flags = DIFlags::FlagPrototyped;
 
-        if fn_abi.ret.layout.abi.is_uninhabited() {
+        if fn_abi.ret.layout.is_uninhabited() {
             flags |= DIFlags::FlagNoReturn;
         }
 
@@ -389,9 +383,9 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
             llvm::LLVMRustDIBuilderCreateMethod(
                 DIB(self),
                 containing_scope,
-                name.as_ptr().cast(),
+                name.as_c_char_ptr(),
                 name.len(),
-                linkage_name.as_ptr().cast(),
+                linkage_name.as_c_char_ptr(),
                 linkage_name.len(),
                 file_metadata,
                 loc.line,
@@ -406,9 +400,9 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
             llvm::LLVMRustDIBuilderCreateFunction(
                 DIB(self),
                 containing_scope,
-                name.as_ptr().cast(),
+                name.as_c_char_ptr(),
                 name.len(),
-                linkage_name.as_ptr().cast(),
+                linkage_name.as_c_char_ptr(),
                 linkage_name.len(),
                 file_metadata,
                 loc.line,
@@ -494,7 +488,7 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
                                 Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
                                     DIB(cx),
                                     None,
-                                    name.as_ptr().cast(),
+                                    name.as_c_char_ptr(),
                                     name.len(),
                                     actual_type_metadata,
                                 ))
@@ -635,7 +629,7 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
                 DIB(self),
                 dwarf_tag,
                 scope_metadata,
-                name.as_ptr().cast(),
+                name.as_c_char_ptr(),
                 name.len(),
                 file_metadata,
                 loc.line,
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs b/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs
index 3578755aae0..33d9bc23890 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs
@@ -5,7 +5,7 @@ use rustc_hir::def_id::DefId;
 use rustc_middle::ty::{self, Instance};
 
 use super::utils::{DIB, debug_context};
-use crate::common::CodegenCx;
+use crate::common::{AsCCharPtr, CodegenCx};
 use crate::llvm;
 use crate::llvm::debuginfo::DIScope;
 
@@ -36,7 +36,7 @@ pub(crate) fn item_namespace<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'l
         llvm::LLVMRustDIBuilderCreateNameSpace(
             DIB(cx),
             parent_scope,
-            namespace_name_string.as_ptr().cast(),
+            namespace_name_string.as_c_char_ptr(),
             namespace_name_string.len(),
             false, // ExportSymbols (only relevant for C++ anonymous namespaces)
         )
diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs
index 33258cb46fa..d338c848754 100644
--- a/compiler/rustc_codegen_llvm/src/declare.rs
+++ b/compiler/rustc_codegen_llvm/src/declare.rs
@@ -20,6 +20,7 @@ use smallvec::SmallVec;
 use tracing::debug;
 
 use crate::abi::{FnAbi, FnAbiLlvmExt};
+use crate::common::AsCCharPtr;
 use crate::context::CodegenCx;
 use crate::llvm::AttributePlace::Function;
 use crate::llvm::Visibility;
@@ -41,7 +42,7 @@ fn declare_raw_fn<'ll>(
 ) -> &'ll Value {
     debug!("declare_raw_fn(name={:?}, ty={:?})", name, ty);
     let llfn = unsafe {
-        llvm::LLVMRustGetOrInsertFunction(cx.llmod, name.as_ptr().cast(), name.len(), ty)
+        llvm::LLVMRustGetOrInsertFunction(cx.llmod, name.as_c_char_ptr(), name.len(), ty)
     };
 
     llvm::SetFunctionCallConv(llfn, callconv);
@@ -68,7 +69,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
     /// return its Value instead.
     pub(crate) fn declare_global(&self, name: &str, ty: &'ll Type) -> &'ll Value {
         debug!("declare_global(name={:?})", name);
-        unsafe { llvm::LLVMRustGetOrInsertGlobal(self.llmod, name.as_ptr().cast(), name.len(), ty) }
+        unsafe { llvm::LLVMRustGetOrInsertGlobal(self.llmod, name.as_c_char_ptr(), name.len(), ty) }
     }
 
     /// Declare a C ABI function.
@@ -209,7 +210,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
     /// Gets declared value by name.
     pub(crate) fn get_declared_value(&self, name: &str) -> Option<&'ll Value> {
         debug!("get_declared_value(name={:?})", name);
-        unsafe { llvm::LLVMRustGetNamedValue(self.llmod, name.as_ptr().cast(), name.len()) }
+        unsafe { llvm::LLVMRustGetNamedValue(self.llmod, name.as_c_char_ptr(), name.len()) }
     }
 
     /// Gets defined or externally defined (AvailableExternally linkage) value by
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index d04b5257619..c77e00aed9a 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -258,8 +258,8 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
                 self.call_intrinsic("llvm.va_copy", &[args[0].immediate(), args[1].immediate()])
             }
             sym::va_arg => {
-                match fn_abi.ret.layout.abi {
-                    abi::Abi::Scalar(scalar) => {
+                match fn_abi.ret.layout.backend_repr {
+                    abi::BackendRepr::Scalar(scalar) => {
                         match scalar.primitive() {
                             Primitive::Int(..) => {
                                 if self.cx().size_of(ret_ty).bytes() < 4 {
@@ -436,13 +436,13 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
             }
 
             sym::raw_eq => {
-                use abi::Abi::*;
+                use abi::BackendRepr::*;
                 let tp_ty = fn_args.type_at(0);
                 let layout = self.layout_of(tp_ty).layout;
-                let use_integer_compare = match layout.abi() {
+                let use_integer_compare = match layout.backend_repr() {
                     Scalar(_) | ScalarPair(_, _) => true,
                     Uninhabited | Vector { .. } => false,
-                    Aggregate { .. } => {
+                    Memory { .. } => {
                         // For rusty ABIs, small aggregates are actually passed
                         // as `RegKind::Integer` (see `FnAbi::adjust_for_abi`),
                         // so we re-use that same threshold here.
@@ -549,7 +549,8 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
                 }
 
                 let llret_ty = if ret_ty.is_simd()
-                    && let abi::Abi::Aggregate { .. } = self.layout_of(ret_ty).layout.abi
+                    && let abi::BackendRepr::Memory { .. } =
+                        self.layout_of(ret_ty).layout.backend_repr
                 {
                     let (size, elem_ty) = ret_ty.simd_size_and_type(self.tcx());
                     let elem_ll_ty = match elem_ty.kind() {
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index acc66076833..8fc586d2c8f 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -3,6 +3,7 @@
 
 use std::fmt::Debug;
 use std::marker::PhantomData;
+use std::ptr;
 
 use libc::{c_char, c_int, c_uint, c_ulonglong, c_void, size_t};
 use rustc_macros::TryFromU32;
@@ -85,7 +86,7 @@ pub enum LLVMMachineType {
     ARM = 0x01c0,
 }
 
-/// LLVM's Module::ModFlagBehavior, defined in llvm/include/llvm/IR/Module.h.
+/// Must match the layout of `LLVMRustModuleFlagMergeBehavior`.
 ///
 /// When merging modules (e.g. during LTO), their metadata flags are combined. Conflicts are
 /// resolved according to the merge behaviors specified here. Flags differing only in merge
@@ -93,9 +94,13 @@ pub enum LLVMMachineType {
 ///
 /// In order for Rust-C LTO to work, we must specify behaviors compatible with Clang. Notably,
 /// 'Error' and 'Warning' cannot be mixed for a given flag.
+///
+/// There is a stable LLVM-C version of this enum (`LLVMModuleFlagBehavior`),
+/// but as of LLVM 19 it does not support all of the enum values in the unstable
+/// C++ API.
 #[derive(Copy, Clone, PartialEq)]
 #[repr(C)]
-pub enum LLVMModFlagBehavior {
+pub enum ModuleFlagMergeBehavior {
     Error = 1,
     Warning = 2,
     Require = 3,
@@ -704,8 +709,9 @@ unsafe extern "C" {
 }
 #[repr(C)]
 pub struct RustArchiveMember<'a>(InvariantOpaque<'a>);
+/// Opaque pointee of `LLVMOperandBundleRef`.
 #[repr(C)]
-pub struct OperandBundleDef<'a>(InvariantOpaque<'a>);
+pub(crate) struct OperandBundle<'a>(InvariantOpaque<'a>);
 #[repr(C)]
 pub struct Linker<'a>(InvariantOpaque<'a>);
 
@@ -1534,6 +1540,50 @@ unsafe extern "C" {
 
     pub fn LLVMGetOrInsertComdat(M: &Module, Name: *const c_char) -> &Comdat;
     pub fn LLVMSetComdat(V: &Value, C: &Comdat);
+
+    pub(crate) fn LLVMCreateOperandBundle(
+        Tag: *const c_char,
+        TagLen: size_t,
+        Args: *const &'_ Value,
+        NumArgs: c_uint,
+    ) -> *mut OperandBundle<'_>;
+    pub(crate) fn LLVMDisposeOperandBundle(Bundle: ptr::NonNull<OperandBundle<'_>>);
+
+    pub(crate) fn LLVMBuildCallWithOperandBundles<'a>(
+        B: &Builder<'a>,
+        Ty: &'a Type,
+        Fn: &'a Value,
+        Args: *const &'a Value,
+        NumArgs: c_uint,
+        Bundles: *const &OperandBundle<'a>,
+        NumBundles: c_uint,
+        Name: *const c_char,
+    ) -> &'a Value;
+    pub(crate) fn LLVMBuildInvokeWithOperandBundles<'a>(
+        B: &Builder<'a>,
+        Ty: &'a Type,
+        Fn: &'a Value,
+        Args: *const &'a Value,
+        NumArgs: c_uint,
+        Then: &'a BasicBlock,
+        Catch: &'a BasicBlock,
+        Bundles: *const &OperandBundle<'a>,
+        NumBundles: c_uint,
+        Name: *const c_char,
+    ) -> &'a Value;
+    pub(crate) fn LLVMBuildCallBr<'a>(
+        B: &Builder<'a>,
+        Ty: &'a Type,
+        Fn: &'a Value,
+        DefaultDest: &'a BasicBlock,
+        IndirectDests: *const &'a BasicBlock,
+        NumIndirectDests: c_uint,
+        Args: *const &'a Value,
+        NumArgs: c_uint,
+        Bundles: *const &OperandBundle<'a>,
+        NumBundles: c_uint,
+        Name: *const c_char,
+    ) -> &'a Value;
 }
 
 #[link(name = "llvm-wrapper", kind = "static")]
@@ -1619,47 +1669,11 @@ unsafe extern "C" {
         AttrsLen: size_t,
     );
 
-    pub fn LLVMRustBuildInvoke<'a>(
-        B: &Builder<'a>,
-        Ty: &'a Type,
-        Fn: &'a Value,
-        Args: *const &'a Value,
-        NumArgs: c_uint,
-        Then: &'a BasicBlock,
-        Catch: &'a BasicBlock,
-        OpBundles: *const &OperandBundleDef<'a>,
-        NumOpBundles: c_uint,
-        Name: *const c_char,
-    ) -> &'a Value;
-
-    pub fn LLVMRustBuildCallBr<'a>(
-        B: &Builder<'a>,
-        Ty: &'a Type,
-        Fn: &'a Value,
-        DefaultDest: &'a BasicBlock,
-        IndirectDests: *const &'a BasicBlock,
-        NumIndirectDests: c_uint,
-        Args: *const &'a Value,
-        NumArgs: c_uint,
-        OpBundles: *const &OperandBundleDef<'a>,
-        NumOpBundles: c_uint,
-        Name: *const c_char,
-    ) -> &'a Value;
-
     pub fn LLVMRustSetFastMath(Instr: &Value);
     pub fn LLVMRustSetAlgebraicMath(Instr: &Value);
     pub fn LLVMRustSetAllowReassoc(Instr: &Value);
 
     // Miscellaneous instructions
-    pub fn LLVMRustBuildCall<'a>(
-        B: &Builder<'a>,
-        Ty: &'a Type,
-        Fn: &'a Value,
-        Args: *const &'a Value,
-        NumArgs: c_uint,
-        OpBundles: *const &OperandBundleDef<'a>,
-        NumOpBundles: c_uint,
-    ) -> &'a Value;
     pub fn LLVMRustBuildMemCpy<'a>(
         B: &Builder<'a>,
         Dst: &'a Value,
@@ -1829,21 +1843,21 @@ unsafe extern "C" {
     /// "compatible" means depends on the merge behaviors involved.
     pub fn LLVMRustAddModuleFlagU32(
         M: &Module,
-        merge_behavior: LLVMModFlagBehavior,
-        name: *const c_char,
-        value: u32,
+        MergeBehavior: ModuleFlagMergeBehavior,
+        Name: *const c_char,
+        NameLen: size_t,
+        Value: u32,
     );
 
     pub fn LLVMRustAddModuleFlagString(
         M: &Module,
-        merge_behavior: LLVMModFlagBehavior,
-        name: *const c_char,
-        value: *const c_char,
-        value_len: size_t,
+        MergeBehavior: ModuleFlagMergeBehavior,
+        Name: *const c_char,
+        NameLen: size_t,
+        Value: *const c_char,
+        ValueLen: size_t,
     );
 
-    pub fn LLVMRustHasModuleFlag(M: &Module, name: *const c_char, len: size_t) -> bool;
-
     pub fn LLVMRustDIBuilderCreate(M: &Module) -> &mut DIBuilder<'_>;
 
     pub fn LLVMRustDIBuilderDispose<'a>(Builder: &'a mut DIBuilder<'a>);
@@ -2353,13 +2367,6 @@ unsafe extern "C" {
 
     pub fn LLVMRustSetDataLayoutFromTargetMachine<'a>(M: &'a Module, TM: &'a TargetMachine);
 
-    pub fn LLVMRustBuildOperandBundleDef(
-        Name: *const c_char,
-        Inputs: *const &'_ Value,
-        NumInputs: c_uint,
-    ) -> &mut OperandBundleDef<'_>;
-    pub fn LLVMRustFreeOperandBundleDef<'a>(Bundle: &'a mut OperandBundleDef<'a>);
-
     pub fn LLVMRustPositionBuilderAtStart<'a>(B: &Builder<'a>, BB: &'a BasicBlock);
 
     pub fn LLVMRustSetModulePICLevel(M: &Module);
@@ -2385,9 +2392,9 @@ unsafe extern "C" {
     pub fn LLVMRustThinLTOBufferThinLinkDataLen(M: &ThinLTOBuffer) -> size_t;
     pub fn LLVMRustCreateThinLTOData(
         Modules: *const ThinLTOModule,
-        NumModules: c_uint,
+        NumModules: size_t,
         PreservedSymbols: *const *const c_char,
-        PreservedSymbolsLen: c_uint,
+        PreservedSymbolsLen: size_t,
     ) -> Option<&'static mut ThinLTOData>;
     pub fn LLVMRustPrepareThinLTORename(
         Data: &ThinLTOData,
@@ -2412,6 +2419,7 @@ unsafe extern "C" {
         data: *const u8,
         len: usize,
         name: *const u8,
+        name_len: usize,
         out_len: &mut usize,
     ) -> *const u8;
 
diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs
index 6aac2eea81d..00a5cd3b859 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs
@@ -2,11 +2,12 @@
 
 use std::cell::RefCell;
 use std::ffi::{CStr, CString};
+use std::ops::Deref;
+use std::ptr;
 use std::str::FromStr;
 use std::string::FromUtf8Error;
 
 use libc::c_uint;
-use rustc_data_structures::small_c_str::SmallCStr;
 use rustc_llvm::RustString;
 use rustc_target::abi::{Align, Size, WrappingRange};
 
@@ -17,13 +18,13 @@ pub use self::IntPredicate::*;
 pub use self::Linkage::*;
 pub use self::MetadataType::*;
 pub use self::RealPredicate::*;
+pub use self::ffi::*;
+use crate::common::AsCCharPtr;
 
 pub mod archive_ro;
 pub mod diagnostic;
 mod ffi;
 
-pub use self::ffi::*;
-
 impl LLVMRustResult {
     pub fn into_result(self) -> Result<(), ()> {
         match self {
@@ -53,9 +54,9 @@ pub fn CreateAttrStringValue<'ll>(llcx: &'ll Context, attr: &str, value: &str) -
     unsafe {
         LLVMCreateStringAttribute(
             llcx,
-            attr.as_ptr().cast(),
+            attr.as_c_char_ptr(),
             attr.len().try_into().unwrap(),
-            value.as_ptr().cast(),
+            value.as_c_char_ptr(),
             value.len().try_into().unwrap(),
         )
     }
@@ -65,7 +66,7 @@ pub fn CreateAttrString<'ll>(llcx: &'ll Context, attr: &str) -> &'ll Attribute {
     unsafe {
         LLVMCreateStringAttribute(
             llcx,
-            attr.as_ptr().cast(),
+            attr.as_c_char_ptr(),
             attr.len().try_into().unwrap(),
             std::ptr::null(),
             0,
@@ -294,7 +295,7 @@ pub fn get_value_name(value: &Value) -> &[u8] {
 /// Safe wrapper for `LLVMSetValueName2` from a byte slice
 pub fn set_value_name(value: &Value, name: &[u8]) {
     unsafe {
-        let data = name.as_ptr().cast();
+        let data = name.as_c_char_ptr();
         LLVMSetValueName2(value, data, name.len());
     }
 }
@@ -331,24 +332,68 @@ pub fn last_error() -> Option<String> {
     }
 }
 
-pub struct OperandBundleDef<'a> {
-    pub raw: &'a mut ffi::OperandBundleDef<'a>,
+/// Owns an [`OperandBundle`], and will dispose of it when dropped.
+pub(crate) struct OperandBundleOwned<'a> {
+    raw: ptr::NonNull<OperandBundle<'a>>,
 }
 
-impl<'a> OperandBundleDef<'a> {
-    pub fn new(name: &str, vals: &[&'a Value]) -> Self {
-        let name = SmallCStr::new(name);
-        let def = unsafe {
-            LLVMRustBuildOperandBundleDef(name.as_ptr(), vals.as_ptr(), vals.len() as c_uint)
+impl<'a> OperandBundleOwned<'a> {
+    pub(crate) fn new(name: &str, vals: &[&'a Value]) -> Self {
+        let raw = unsafe {
+            LLVMCreateOperandBundle(
+                name.as_c_char_ptr(),
+                name.len(),
+                vals.as_ptr(),
+                vals.len() as c_uint,
+            )
         };
-        OperandBundleDef { raw: def }
+        OperandBundleOwned { raw: ptr::NonNull::new(raw).unwrap() }
     }
 }
 
-impl Drop for OperandBundleDef<'_> {
+impl Drop for OperandBundleOwned<'_> {
     fn drop(&mut self) {
         unsafe {
-            LLVMRustFreeOperandBundleDef(&mut *(self.raw as *mut _));
+            LLVMDisposeOperandBundle(self.raw);
         }
     }
 }
+
+impl<'a> Deref for OperandBundleOwned<'a> {
+    type Target = OperandBundle<'a>;
+
+    fn deref(&self) -> &Self::Target {
+        // SAFETY: The returned reference is opaque and can only used for FFI.
+        // It is valid for as long as `&self` is.
+        unsafe { self.raw.as_ref() }
+    }
+}
+
+pub(crate) fn add_module_flag_u32(
+    module: &Module,
+    merge_behavior: ModuleFlagMergeBehavior,
+    key: &str,
+    value: u32,
+) {
+    unsafe {
+        LLVMRustAddModuleFlagU32(module, merge_behavior, key.as_c_char_ptr(), key.len(), value);
+    }
+}
+
+pub(crate) fn add_module_flag_str(
+    module: &Module,
+    merge_behavior: ModuleFlagMergeBehavior,
+    key: &str,
+    value: &str,
+) {
+    unsafe {
+        LLVMRustAddModuleFlagString(
+            module,
+            merge_behavior,
+            key.as_c_char_ptr(),
+            key.len(),
+            value.as_c_char_ptr(),
+            value.len(),
+        );
+    }
+}
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index aa38c02289d..9adb1299b3d 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -698,12 +698,9 @@ fn backend_feature_name<'a>(sess: &Session, s: &'a str) -> Option<&'a str> {
     let feature = s
         .strip_prefix(&['+', '-'][..])
         .unwrap_or_else(|| sess.dcx().emit_fatal(InvalidTargetFeaturePrefix { feature: s }));
-    if s.is_empty() {
-        return None;
-    }
     // Rustc-specific feature requests like `+crt-static` or `-crt-static`
     // are not passed down to LLVM.
-    if RUSTC_SPECIFIC_FEATURES.contains(&feature) {
+    if s.is_empty() || RUSTC_SPECIFIC_FEATURES.contains(&feature) {
         return None;
     }
     Some(feature)
diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs
index 6be4c3f034f..2b05e24a7ba 100644
--- a/compiler/rustc_codegen_llvm/src/type_of.rs
+++ b/compiler/rustc_codegen_llvm/src/type_of.rs
@@ -1,7 +1,7 @@
 use std::fmt::Write;
 
 use rustc_abi::Primitive::{Float, Int, Pointer};
-use rustc_abi::{Abi, Align, FieldsShape, Scalar, Size, Variants};
+use rustc_abi::{Align, BackendRepr, FieldsShape, Scalar, Size, Variants};
 use rustc_codegen_ssa::traits::*;
 use rustc_middle::bug;
 use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
@@ -17,13 +17,13 @@ fn uncached_llvm_type<'a, 'tcx>(
     layout: TyAndLayout<'tcx>,
     defer: &mut Option<(&'a Type, TyAndLayout<'tcx>)>,
 ) -> &'a Type {
-    match layout.abi {
-        Abi::Scalar(_) => bug!("handled elsewhere"),
-        Abi::Vector { element, count } => {
+    match layout.backend_repr {
+        BackendRepr::Scalar(_) => bug!("handled elsewhere"),
+        BackendRepr::Vector { element, count } => {
             let element = layout.scalar_llvm_type_at(cx, element);
             return cx.type_vector(element, count);
         }
-        Abi::Uninhabited | Abi::Aggregate { .. } | Abi::ScalarPair(..) => {}
+        BackendRepr::Uninhabited | BackendRepr::Memory { .. } | BackendRepr::ScalarPair(..) => {}
     }
 
     let name = match layout.ty.kind() {
@@ -170,16 +170,21 @@ pub(crate) trait LayoutLlvmExt<'tcx> {
 
 impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
     fn is_llvm_immediate(&self) -> bool {
-        match self.abi {
-            Abi::Scalar(_) | Abi::Vector { .. } => true,
-            Abi::ScalarPair(..) | Abi::Uninhabited | Abi::Aggregate { .. } => false,
+        match self.backend_repr {
+            BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => true,
+            BackendRepr::ScalarPair(..) | BackendRepr::Uninhabited | BackendRepr::Memory { .. } => {
+                false
+            }
         }
     }
 
     fn is_llvm_scalar_pair(&self) -> bool {
-        match self.abi {
-            Abi::ScalarPair(..) => true,
-            Abi::Uninhabited | Abi::Scalar(_) | Abi::Vector { .. } | Abi::Aggregate { .. } => false,
+        match self.backend_repr {
+            BackendRepr::ScalarPair(..) => true,
+            BackendRepr::Uninhabited
+            | BackendRepr::Scalar(_)
+            | BackendRepr::Vector { .. }
+            | BackendRepr::Memory { .. } => false,
         }
     }
 
@@ -198,7 +203,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
         // This must produce the same result for `repr(transparent)` wrappers as for the inner type!
         // In other words, this should generally not look at the type at all, but only at the
         // layout.
-        if let Abi::Scalar(scalar) = self.abi {
+        if let BackendRepr::Scalar(scalar) = self.backend_repr {
             // Use a different cache for scalars because pointers to DSTs
             // can be either wide or thin (data pointers of wide pointers).
             if let Some(&llty) = cx.scalar_lltypes.borrow().get(&self.ty) {
@@ -248,13 +253,13 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
     }
 
     fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type {
-        match self.abi {
-            Abi::Scalar(scalar) => {
+        match self.backend_repr {
+            BackendRepr::Scalar(scalar) => {
                 if scalar.is_bool() {
                     return cx.type_i1();
                 }
             }
-            Abi::ScalarPair(..) => {
+            BackendRepr::ScalarPair(..) => {
                 // An immediate pair always contains just the two elements, without any padding
                 // filler, as it should never be stored to memory.
                 return cx.type_struct(
@@ -287,7 +292,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
         // This must produce the same result for `repr(transparent)` wrappers as for the inner type!
         // In other words, this should generally not look at the type at all, but only at the
         // layout.
-        let Abi::ScalarPair(a, b) = self.abi else {
+        let BackendRepr::ScalarPair(a, b) = self.backend_repr else {
             bug!("TyAndLayout::scalar_pair_element_llty({:?}): not applicable", self);
         };
         let scalar = [a, b][index];
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index 8857fda1e97..796acb6796f 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -322,10 +322,11 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
             // Set the appropriate flag based on ABI
             // This needs to match LLVM `RISCVELFStreamer.cpp`
             match &*sess.target.llvm_abiname {
-                "" | "ilp32" | "lp64" => (),
+                "ilp32" | "lp64" => (),
                 "ilp32f" | "lp64f" => e_flags |= elf::EF_RISCV_FLOAT_ABI_SINGLE,
                 "ilp32d" | "lp64d" => e_flags |= elf::EF_RISCV_FLOAT_ABI_DOUBLE,
-                "ilp32e" => e_flags |= elf::EF_RISCV_RVE,
+                // Note that the `lp64e` is still unstable as it's not (yet) part of the ELF psABI.
+                "ilp32e" | "lp64e" => e_flags |= elf::EF_RISCV_RVE,
                 _ => bug!("unknown RISC-V ABI name"),
             }
 
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index e3d11cfaf4f..8445d16befb 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -514,7 +514,7 @@ pub(crate) fn start_async_codegen<B: ExtraBackendMethods>(
             future: Some(coordinator_thread),
             phantom: PhantomData,
         },
-        output_filenames: tcx.output_filenames(()).clone(),
+        output_filenames: Arc::clone(tcx.output_filenames(())),
     }
 }
 
@@ -1203,7 +1203,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
         coordinator_send,
         expanded_args: tcx.sess.expanded_args.clone(),
         diag_emitter: shared_emitter.clone(),
-        output_filenames: tcx.output_filenames(()).clone(),
+        output_filenames: Arc::clone(tcx.output_filenames(())),
         regular_module_config: regular_config,
         metadata_module_config: metadata_config,
         allocator_module_config: allocator_config,
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index a726ee73aaa..cb4c9c078b1 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -7,7 +7,7 @@ use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, AllocatorKind, global_fn_n
 use rustc_attr as attr;
 use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
 use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
-use rustc_data_structures::sync::par_map;
+use rustc_data_structures::sync::{Lrc, par_map};
 use rustc_data_structures::unord::UnordMap;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_hir::lang_items::LangItem;
@@ -21,7 +21,7 @@ use rustc_middle::mir::BinOp;
 use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem};
 use rustc_middle::query::Providers;
 use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
-use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
+use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypingMode};
 use rustc_session::Session;
 use rustc_session::config::{self, CrateType, EntryFnType, OptLevel, OutputType};
 use rustc_span::symbol::sym;
@@ -119,7 +119,7 @@ pub fn validate_trivial_unsize<'tcx>(
 ) -> bool {
     match (source_data.principal(), target_data.principal()) {
         (Some(hr_source_principal), Some(hr_target_principal)) => {
-            let infcx = tcx.infer_ctxt().build();
+            let infcx = tcx.infer_ctxt().build(TypingMode::PostAnalysis);
             let universe = infcx.universe();
             let ocx = ObligationCtxt::new(&infcx);
             infcx.enter_forall(hr_target_principal, |target_principal| {
@@ -923,7 +923,7 @@ impl CrateInfo {
             crate_name: UnordMap::with_capacity(n_crates),
             used_crates,
             used_crate_source: UnordMap::with_capacity(n_crates),
-            dependency_formats: tcx.dependency_formats(()).clone(),
+            dependency_formats: Lrc::clone(tcx.dependency_formats(())),
             windows_subsystem,
             natvis_debugger_visualizers: Default::default(),
         };
@@ -936,7 +936,7 @@ impl CrateInfo {
             info.crate_name.insert(cnum, tcx.crate_name(cnum));
 
             let used_crate_source = tcx.used_crate_source(cnum);
-            info.used_crate_source.insert(cnum, used_crate_source.clone());
+            info.used_crate_source.insert(cnum, Lrc::clone(used_crate_source));
             if tcx.is_profiler_runtime(cnum) {
                 info.profiler_runtime = Some(cnum);
             }
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index e3553dc03e1..283740fa664 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -438,7 +438,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 _ => bug!("C-variadic function must have a `VaList` place"),
             }
         }
-        if self.fn_abi.ret.layout.abi.is_uninhabited() {
+        if self.fn_abi.ret.layout.is_uninhabited() {
             // Functions with uninhabited return values are marked `noreturn`,
             // so we should make sure that we never actually do.
             // We play it safe by using a well-defined `abort`, but we could go for immediate UB
@@ -774,7 +774,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             Some(if do_panic {
                 let msg_str = with_no_visible_paths!({
                     with_no_trimmed_paths!({
-                        if layout.abi.is_uninhabited() {
+                        if layout.is_uninhabited() {
                             // Use this error even for the other intrinsics as it is more precise.
                             format!("attempted to instantiate uninhabited type `{ty}`")
                         } else if requirement == ValidityRequirement::Zero {
@@ -1532,7 +1532,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 // the load would just produce `OperandValue::Ref` instead
                 // of the `OperandValue::Immediate` we need for the call.
                 llval = bx.load(bx.backend_type(arg.layout), llval, align);
-                if let abi::Abi::Scalar(scalar) = arg.layout.abi {
+                if let abi::BackendRepr::Scalar(scalar) = arg.layout.backend_repr {
                     if scalar.is_bool() {
                         bx.range_metadata(llval, WrappingRange { start: 0, end: 1 });
                     }
diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs
index 15f45b226f5..54b9c9cc89f 100644
--- a/compiler/rustc_codegen_ssa/src/mir/constant.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs
@@ -1,8 +1,8 @@
+use rustc_abi::BackendRepr;
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::ty::layout::HasTyCtxt;
 use rustc_middle::ty::{self, Ty};
 use rustc_middle::{bug, mir, span_bug};
-use rustc_target::abi::Abi;
 
 use super::FunctionCx;
 use crate::errors;
@@ -86,7 +86,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     .map(|field| {
                         if let Some(prim) = field.try_to_scalar() {
                             let layout = bx.layout_of(field_ty);
-                            let Abi::Scalar(scalar) = layout.abi else {
+                            let BackendRepr::Scalar(scalar) = layout.backend_repr else {
                                 bug!("from_const: invalid ByVal layout: {:#?}", layout);
                             };
                             bx.scalar_to_backend(prim, scalar, bx.immediate_backend_type(layout))
diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
index 146f55f95c2..21d20475408 100644
--- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
@@ -2,6 +2,7 @@ use std::collections::hash_map::Entry;
 use std::marker::PhantomData;
 use std::ops::Range;
 
+use rustc_abi::{BackendRepr, FieldIdx, FieldsShape, Size, VariantIdx};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_index::IndexVec;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
@@ -11,7 +12,6 @@ use rustc_middle::{bug, mir, ty};
 use rustc_session::config::DebugInfo;
 use rustc_span::symbol::{Symbol, kw};
 use rustc_span::{BytePos, Span, hygiene};
-use rustc_target::abi::{Abi, FieldIdx, FieldsShape, Size, VariantIdx};
 
 use super::operand::{OperandRef, OperandValue};
 use super::place::{PlaceRef, PlaceValue};
@@ -510,7 +510,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         // be marked as a `LocalVariable` for MSVC debuggers to visualize
                         // their data correctly. (See #81894 & #88625)
                         let var_ty_layout = self.cx.layout_of(var_ty);
-                        if let Abi::ScalarPair(_, _) = var_ty_layout.abi {
+                        if let BackendRepr::ScalarPair(_, _) = var_ty_layout.backend_repr {
                             VariableKind::LocalVariable
                         } else {
                             VariableKind::ArgumentVariable(arg_index)
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index 88ceff327d0..19101ec2d1b 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -4,7 +4,7 @@ use std::fmt;
 use arrayvec::ArrayVec;
 use either::Either;
 use rustc_abi as abi;
-use rustc_abi::{Abi, Align, Size};
+use rustc_abi::{Align, BackendRepr, Size};
 use rustc_middle::bug;
 use rustc_middle::mir::interpret::{Pointer, Scalar, alloc_range};
 use rustc_middle::mir::{self, ConstValue};
@@ -163,7 +163,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
 
         let val = match val {
             ConstValue::Scalar(x) => {
-                let Abi::Scalar(scalar) = layout.abi else {
+                let BackendRepr::Scalar(scalar) = layout.backend_repr else {
                     bug!("from_const: invalid ByVal layout: {:#?}", layout);
                 };
                 let llval = bx.scalar_to_backend(x, scalar, bx.immediate_backend_type(layout));
@@ -171,7 +171,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
             }
             ConstValue::ZeroSized => return OperandRef::zero_sized(layout),
             ConstValue::Slice { data, meta } => {
-                let Abi::ScalarPair(a_scalar, _) = layout.abi else {
+                let BackendRepr::ScalarPair(a_scalar, _) = layout.backend_repr else {
                     bug!("from_const: invalid ScalarPair layout: {:#?}", layout);
                 };
                 let a = Scalar::from_pointer(
@@ -221,14 +221,14 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
         // case where some of the bytes are initialized and others are not. So, we need an extra
         // check that walks over the type of `mplace` to make sure it is truly correct to treat this
         // like a `Scalar` (or `ScalarPair`).
-        match layout.abi {
-            Abi::Scalar(s @ abi::Scalar::Initialized { .. }) => {
+        match layout.backend_repr {
+            BackendRepr::Scalar(s @ abi::Scalar::Initialized { .. }) => {
                 let size = s.size(bx);
                 assert_eq!(size, layout.size, "abi::Scalar size does not match layout size");
                 let val = read_scalar(offset, size, s, bx.immediate_backend_type(layout));
                 OperandRef { val: OperandValue::Immediate(val), layout }
             }
-            Abi::ScalarPair(
+            BackendRepr::ScalarPair(
                 a @ abi::Scalar::Initialized { .. },
                 b @ abi::Scalar::Initialized { .. },
             ) => {
@@ -322,7 +322,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
         llval: V,
         layout: TyAndLayout<'tcx>,
     ) -> Self {
-        let val = if let Abi::ScalarPair(..) = layout.abi {
+        let val = if let BackendRepr::ScalarPair(..) = layout.backend_repr {
             debug!("Operand::from_immediate_or_packed_pair: unpacking {:?} @ {:?}", llval, layout);
 
             // Deconstruct the immediate aggregate.
@@ -343,7 +343,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
         let field = self.layout.field(bx.cx(), i);
         let offset = self.layout.fields.offset(i);
 
-        let mut val = match (self.val, self.layout.abi) {
+        let mut val = match (self.val, self.layout.backend_repr) {
             // If the field is ZST, it has no data.
             _ if field.is_zst() => OperandValue::ZeroSized,
 
@@ -356,7 +356,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
             }
 
             // Extract a scalar component from a pair.
-            (OperandValue::Pair(a_llval, b_llval), Abi::ScalarPair(a, b)) => {
+            (OperandValue::Pair(a_llval, b_llval), BackendRepr::ScalarPair(a, b)) => {
                 if offset.bytes() == 0 {
                     assert_eq!(field.size, a.size(bx.cx()));
                     OperandValue::Immediate(a_llval)
@@ -368,30 +368,30 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
             }
 
             // `#[repr(simd)]` types are also immediate.
-            (OperandValue::Immediate(llval), Abi::Vector { .. }) => {
+            (OperandValue::Immediate(llval), BackendRepr::Vector { .. }) => {
                 OperandValue::Immediate(bx.extract_element(llval, bx.cx().const_usize(i as u64)))
             }
 
             _ => bug!("OperandRef::extract_field({:?}): not applicable", self),
         };
 
-        match (&mut val, field.abi) {
+        match (&mut val, field.backend_repr) {
             (OperandValue::ZeroSized, _) => {}
             (
                 OperandValue::Immediate(llval),
-                Abi::Scalar(_) | Abi::ScalarPair(..) | Abi::Vector { .. },
+                BackendRepr::Scalar(_) | BackendRepr::ScalarPair(..) | BackendRepr::Vector { .. },
             ) => {
                 // Bools in union fields needs to be truncated.
                 *llval = bx.to_immediate(*llval, field);
             }
-            (OperandValue::Pair(a, b), Abi::ScalarPair(a_abi, b_abi)) => {
+            (OperandValue::Pair(a, b), BackendRepr::ScalarPair(a_abi, b_abi)) => {
                 // Bools in union fields needs to be truncated.
                 *a = bx.to_immediate_scalar(*a, a_abi);
                 *b = bx.to_immediate_scalar(*b, b_abi);
             }
             // Newtype vector of array, e.g. #[repr(simd)] struct S([i32; 4]);
-            (OperandValue::Immediate(llval), Abi::Aggregate { sized: true }) => {
-                assert_matches!(self.layout.abi, Abi::Vector { .. });
+            (OperandValue::Immediate(llval), BackendRepr::Memory { sized: true }) => {
+                assert_matches!(self.layout.backend_repr, BackendRepr::Vector { .. });
 
                 let llfield_ty = bx.cx().backend_type(field);
 
@@ -400,7 +400,10 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
                 bx.store(*llval, llptr, field.align.abi);
                 *llval = bx.load(llfield_ty, llptr, field.align.abi);
             }
-            (OperandValue::Immediate(_), Abi::Uninhabited | Abi::Aggregate { sized: false }) => {
+            (
+                OperandValue::Immediate(_),
+                BackendRepr::Uninhabited | BackendRepr::Memory { sized: false },
+            ) => {
                 bug!()
             }
             (OperandValue::Pair(..), _) => bug!(),
@@ -494,7 +497,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
                 bx.store_with_flags(val, dest.val.llval, dest.val.align, flags);
             }
             OperandValue::Pair(a, b) => {
-                let Abi::ScalarPair(a_scalar, b_scalar) = dest.layout.abi else {
+                let BackendRepr::ScalarPair(a_scalar, b_scalar) = dest.layout.backend_repr else {
                     bug!("store_with_flags: invalid ScalarPair layout: {:#?}", dest.layout);
                 };
                 let b_offset = a_scalar.size(bx).align_to(b_scalar.align(bx).abi);
@@ -645,7 +648,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     // However, some SIMD types do not actually use the vector ABI
                     // (in particular, packed SIMD types do not). Ensure we exclude those.
                     let layout = bx.layout_of(constant_ty);
-                    if let Abi::Vector { .. } = layout.abi {
+                    if let BackendRepr::Vector { .. } = layout.backend_repr {
                         let (llval, ty) = self.immediate_const_vector(bx, constant);
                         return OperandRef {
                             val: OperandValue::Immediate(llval),
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index a7d5541481a..15c8e534461 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -55,7 +55,7 @@ impl<V: CodegenObject> PlaceValue<V> {
     /// Creates a `PlaceRef` to this location with the given type.
     pub fn with_type<'tcx>(self, layout: TyAndLayout<'tcx>) -> PlaceRef<'tcx, V> {
         assert!(
-            layout.is_unsized() || layout.abi.is_uninhabited() || self.llextra.is_none(),
+            layout.is_unsized() || layout.is_uninhabited() || self.llextra.is_none(),
             "Had pointer metadata {:?} for sized type {layout:?}",
             self.llextra,
         );
@@ -239,7 +239,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
         let dl = &bx.tcx().data_layout;
         let cast_to_layout = bx.cx().layout_of(cast_to);
         let cast_to = bx.cx().immediate_backend_type(cast_to_layout);
-        if self.layout.abi.is_uninhabited() {
+        if self.layout.is_uninhabited() {
             return bx.cx().const_poison(cast_to);
         }
         let (tag_scalar, tag_encoding, tag_field) = match self.layout.variants {
@@ -358,7 +358,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
         bx: &mut Bx,
         variant_index: VariantIdx,
     ) {
-        if self.layout.for_variant(bx.cx(), variant_index).abi.is_uninhabited() {
+        if self.layout.for_variant(bx.cx(), variant_index).is_uninhabited() {
             // We play it safe by using a well-defined `abort`, but we could go for immediate UB
             // if that turns out to be helpful.
             bx.abort();
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index 82fea4c58e1..86cf0f9614d 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -203,10 +203,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     ) -> Option<OperandValue<Bx::Value>> {
         // Check for transmutes that are always UB.
         if operand.layout.size != cast.size
-            || operand.layout.abi.is_uninhabited()
-            || cast.abi.is_uninhabited()
+            || operand.layout.is_uninhabited()
+            || cast.is_uninhabited()
         {
-            if !operand.layout.abi.is_uninhabited() {
+            if !operand.layout.is_uninhabited() {
                 // Since this is known statically and the input could have existed
                 // without already having hit UB, might as well trap for it.
                 bx.abort();
@@ -555,7 +555,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
                         assert!(bx.cx().is_backend_immediate(cast));
                         let to_backend_ty = bx.cx().immediate_backend_type(cast);
-                        if operand.layout.abi.is_uninhabited() {
+                        if operand.layout.is_uninhabited() {
                             let val = OperandValue::Immediate(bx.cx().const_poison(to_backend_ty));
                             return OperandRef { val, layout: cast };
                         }
@@ -1136,17 +1136,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             OperandValueKind::ZeroSized
         } else if self.cx.is_backend_immediate(layout) {
             assert!(!self.cx.is_backend_scalar_pair(layout));
-            OperandValueKind::Immediate(match layout.abi {
-                abi::Abi::Scalar(s) => s,
-                abi::Abi::Vector { element, .. } => element,
+            OperandValueKind::Immediate(match layout.backend_repr {
+                abi::BackendRepr::Scalar(s) => s,
+                abi::BackendRepr::Vector { element, .. } => element,
                 x => span_bug!(self.mir.span, "Couldn't translate {x:?} as backend immediate"),
             })
         } else if self.cx.is_backend_scalar_pair(layout) {
-            let abi::Abi::ScalarPair(s1, s2) = layout.abi else {
+            let abi::BackendRepr::ScalarPair(s1, s2) = layout.backend_repr else {
                 span_bug!(
                     self.mir.span,
                     "Couldn't translate {:?} as backend scalar pair",
-                    layout.abi,
+                    layout.backend_repr,
                 );
             };
             OperandValueKind::Pair(s1, s2)
diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs
index 50a51714146..768a0439ab5 100644
--- a/compiler/rustc_codegen_ssa/src/traits/builder.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs
@@ -1,13 +1,13 @@
 use std::assert_matches::assert_matches;
 use std::ops::Deref;
 
+use rustc_abi::{Align, BackendRepr, Scalar, Size, WrappingRange};
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
 use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout};
 use rustc_middle::ty::{Instance, Ty};
 use rustc_session::config::OptLevel;
 use rustc_span::Span;
 use rustc_target::abi::call::FnAbi;
-use rustc_target::abi::{Abi, Align, Scalar, Size, WrappingRange};
 
 use super::abi::AbiBuilderMethods;
 use super::asm::AsmBuilderMethods;
@@ -162,7 +162,7 @@ pub trait BuilderMethods<'a, 'tcx>:
 
     fn from_immediate(&mut self, val: Self::Value) -> Self::Value;
     fn to_immediate(&mut self, val: Self::Value, layout: TyAndLayout<'_>) -> Self::Value {
-        if let Abi::Scalar(scalar) = layout.abi {
+        if let BackendRepr::Scalar(scalar) = layout.backend_repr {
             self.to_immediate_scalar(val, scalar)
         } else {
             val
diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs
index 004fb12419f..b6c227638a1 100644
--- a/compiler/rustc_const_eval/src/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/check_consts/check.rs
@@ -64,8 +64,7 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> {
             let ConstCx { tcx, body, .. } = *ccx;
 
             FlowSensitiveAnalysis::new(NeedsDrop, ccx)
-                .into_engine(tcx, body)
-                .iterate_to_fixpoint()
+                .iterate_to_fixpoint(tcx, body, None)
                 .into_results_cursor(body)
         });
 
@@ -94,8 +93,7 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> {
             let ConstCx { tcx, body, .. } = *ccx;
 
             FlowSensitiveAnalysis::new(NeedsNonConstDrop, ccx)
-                .into_engine(tcx, body)
-                .iterate_to_fixpoint()
+                .iterate_to_fixpoint(tcx, body, None)
                 .into_results_cursor(body)
         });
 
@@ -124,8 +122,7 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> {
             let ConstCx { tcx, body, .. } = *ccx;
 
             FlowSensitiveAnalysis::new(HasMutInterior, ccx)
-                .into_engine(tcx, body)
-                .iterate_to_fixpoint()
+                .iterate_to_fixpoint(tcx, body, None)
                 .into_results_cursor(body)
         });
 
@@ -240,8 +237,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
                 let always_live_locals = &always_storage_live_locals(&ccx.body);
                 let mut maybe_storage_live =
                     MaybeStorageLive::new(Cow::Borrowed(always_live_locals))
-                        .into_engine(ccx.tcx, &ccx.body)
-                        .iterate_to_fixpoint()
+                        .iterate_to_fixpoint(ccx.tcx, &ccx.body, None)
                         .into_results_cursor(&ccx.body);
 
                 // And then check all `Return` in the MIR, and if a local is "maybe live" at a
@@ -593,7 +589,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                 // Typeck only does a "non-const" check since it operates on HIR and cannot distinguish
                 // which path expressions are getting called on and which path expressions are only used
                 // as function pointers. This is required for correctness.
-                let infcx = tcx.infer_ctxt().build();
+                let infcx = tcx.infer_ctxt().build(body.typing_mode(tcx));
                 let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
 
                 let predicates = tcx.predicates_of(callee).instantiate(tcx, fn_args);
diff --git a/compiler/rustc_const_eval/src/check_consts/mod.rs b/compiler/rustc_const_eval/src/check_consts/mod.rs
index 56da6791847..dcdaafaecc2 100644
--- a/compiler/rustc_const_eval/src/check_consts/mod.rs
+++ b/compiler/rustc_const_eval/src/check_consts/mod.rs
@@ -32,14 +32,7 @@ impl<'mir, 'tcx> ConstCx<'mir, 'tcx> {
     pub fn new(tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>) -> Self {
         let def_id = body.source.def_id().expect_local();
         let param_env = tcx.param_env(def_id);
-        Self::new_with_param_env(tcx, body, param_env)
-    }
 
-    pub fn new_with_param_env(
-        tcx: TyCtxt<'tcx>,
-        body: &'mir mir::Body<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-    ) -> Self {
         let const_kind = tcx.hir().body_const_context(body.source.def_id().expect_local());
         ConstCx { body, tcx, param_env, const_kind }
     }
diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs
index 3ac06ae6491..961a27ae9ba 100644
--- a/compiler/rustc_const_eval/src/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/check_consts/ops.rs
@@ -116,7 +116,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
                     let obligation =
                         Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref);
 
-                    let infcx = tcx.infer_ctxt().build();
+                    let infcx = tcx.infer_ctxt().build(body.typing_mode(tcx));
                     let mut selcx = SelectionContext::new(&infcx);
                     let implsrc = selcx.select(&obligation);
 
diff --git a/compiler/rustc_const_eval/src/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs
index 547030a1854..e8637ba45cf 100644
--- a/compiler/rustc_const_eval/src/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs
@@ -114,11 +114,11 @@ impl Qualif for HasMutInterior {
             ty::TraitRef::new(cx.tcx, freeze_def_id, [ty::GenericArg::from(ty)]),
         );
 
-        let infcx = cx
-            .tcx
-            .infer_ctxt()
-            .with_opaque_type_inference(cx.body.source.def_id().expect_local())
-            .build();
+        // FIXME(#132279): This should eventually use the already defined hidden types.
+        let infcx = cx.tcx.infer_ctxt().build(ty::TypingMode::analysis_in_body(
+            cx.tcx,
+            cx.body.source.def_id().expect_local(),
+        ));
         let ocx = ObligationCtxt::new(&infcx);
         ocx.register_obligation(obligation);
         let errors = ocx.select_all_or_error();
diff --git a/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs b/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs
index 743924faa21..bc2661c4fc7 100644
--- a/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs
@@ -131,7 +131,7 @@ impl<'tcx> interpret::Machine<'tcx> for DummyMachine {
         interp_ok(match bin_op {
             Eq | Ne | Lt | Le | Gt | Ge => {
                 // Types can differ, e.g. fn ptrs with different `for`.
-                assert_eq!(left.layout.abi, right.layout.abi);
+                assert_eq!(left.layout.backend_repr, right.layout.backend_repr);
                 let size = ecx.pointer_size();
                 // Just compare the bits. ScalarPairs are compared lexicographically.
                 // We thus always compare pairs and simply fill scalars up with 0.
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 7319c251bbd..81b9d73b952 100644
--- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -1,6 +1,7 @@
 use std::sync::atomic::Ordering::Relaxed;
 
 use either::{Left, Right};
+use rustc_abi::{self as abi, BackendRepr};
 use rustc_hir::def::DefKind;
 use rustc_middle::bug;
 use rustc_middle::mir::interpret::{AllocId, ErrorHandled, InterpErrorInfo};
@@ -12,7 +13,6 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::{DUMMY_SP, Span};
-use rustc_target::abi::{self, Abi};
 use tracing::{debug, instrument, trace};
 
 use super::{CanAccessMutGlobal, CompileTimeInterpCx, CompileTimeMachine};
@@ -174,8 +174,8 @@ pub(super) fn op_to_const<'tcx>(
     // type (it's used throughout the compiler and having it work just on literals is not enough)
     // and we want it to be fast (i.e., don't go to an `Allocation` and reconstruct the `Scalar`
     // from its byte-serialized form).
-    let force_as_immediate = match op.layout.abi {
-        Abi::Scalar(abi::Scalar::Initialized { .. }) => true,
+    let force_as_immediate = match op.layout.backend_repr {
+        BackendRepr::Scalar(abi::Scalar::Initialized { .. }) => true,
         // We don't *force* `ConstValue::Slice` for `ScalarPair`. This has the advantage that if the
         // input `op` is a place, then turning it into a `ConstValue` and back into a `OpTy` will
         // not have to generate any duplicate allocations (we preserve the original `AllocId` in
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index d54c5b750f0..5f0bc8539ee 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -395,7 +395,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
 
     #[inline(always)]
     fn enforce_validity(ecx: &InterpCx<'tcx, Self>, layout: TyAndLayout<'tcx>) -> bool {
-        ecx.tcx.sess.opts.unstable_opts.extra_const_ub_checks || layout.abi.is_uninhabited()
+        ecx.tcx.sess.opts.unstable_opts.extra_const_ub_checks || layout.is_uninhabited()
     }
 
     fn load_mir(
diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
index 9e80e666ba9..ea88b2ed22e 100644
--- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs
+++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
@@ -1,10 +1,10 @@
+use rustc_abi::{BackendRepr, VariantIdx};
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId};
 use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout};
 use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
 use rustc_middle::{bug, mir};
 use rustc_span::DUMMY_SP;
-use rustc_target::abi::{Abi, VariantIdx};
 use tracing::{debug, instrument, trace};
 
 use super::eval_queries::{mk_eval_cx_to_read_const_val, op_to_const};
@@ -117,7 +117,7 @@ fn const_to_valtree_inner<'tcx>(
             let val = ecx.read_immediate(place).unwrap();
             // We could allow wide raw pointers where both sides are integers in the future,
             // but for now we reject them.
-            if matches!(val.layout.abi, Abi::ScalarPair(..)) {
+            if matches!(val.layout.backend_repr, BackendRepr::ScalarPair(..)) {
                 return Err(ValTreeCreationError::NonSupportedType(ty));
             }
             let val = val.to_scalar();
@@ -311,7 +311,7 @@ pub fn valtree_to_const_value<'tcx>(
                 // Fast path to avoid some allocations.
                 return mir::ConstValue::ZeroSized;
             }
-            if layout.abi.is_scalar()
+            if layout.backend_repr.is_scalar()
                 && (matches!(ty.kind(), ty::Tuple(_))
                     || matches!(ty.kind(), ty::Adt(def, _) if def.is_struct()))
             {
diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs
index 85d99900c6c..1915bf75c95 100644
--- a/compiler/rustc_const_eval/src/interpret/call.rs
+++ b/compiler/rustc_const_eval/src/interpret/call.rs
@@ -172,8 +172,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         // must be compatible. So we just accept everything with Pointer ABI as compatible,
         // even if this will accept some code that is not stably guaranteed to work.
         // This also handles function pointers.
-        let thin_pointer = |layout: TyAndLayout<'tcx>| match layout.abi {
-            abi::Abi::Scalar(s) => match s.primitive() {
+        let thin_pointer = |layout: TyAndLayout<'tcx>| match layout.backend_repr {
+            abi::BackendRepr::Scalar(s) => match s.primitive() {
                 abi::Primitive::Pointer(addr_space) => Some(addr_space),
                 _ => None,
             },
diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs
index 64b15611316..60d5e904bd9 100644
--- a/compiler/rustc_const_eval/src/interpret/cast.rs
+++ b/compiler/rustc_const_eval/src/interpret/cast.rs
@@ -274,7 +274,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         cast_ty: Ty<'tcx>,
     ) -> InterpResult<'tcx, Scalar<M::Provenance>> {
         // Let's make sure v is sign-extended *if* it has a signed type.
-        let signed = src_layout.abi.is_signed(); // Also asserts that abi is `Scalar`.
+        let signed = src_layout.backend_repr.is_signed(); // Also asserts that abi is `Scalar`.
 
         let v = match src_layout.ty.kind() {
             Uint(_) | RawPtr(..) | FnPtr(..) => scalar.to_uint(src_layout.size)?,
diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs
index 81e0b1e12ca..bb4ac9556ea 100644
--- a/compiler/rustc_const_eval/src/interpret/discriminant.rs
+++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs
@@ -27,7 +27,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         // discriminant, so we cannot do anything here.
         // When evaluating we will always error before even getting here, but ConstProp 'executes'
         // dead code, so we cannot ICE here.
-        if dest.layout().for_variant(self, variant_index).abi.is_uninhabited() {
+        if dest.layout().for_variant(self, variant_index).is_uninhabited() {
             throw_ub!(UninhabitedEnumVariantWritten(variant_index))
         }
 
@@ -86,7 +86,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                     // For consistency with `write_discriminant`, and to make sure that
                     // `project_downcast` cannot fail due to strange layouts, we declare immediate UB
                     // for uninhabited variants.
-                    if op.layout().for_variant(self, index).abi.is_uninhabited() {
+                    if op.layout().for_variant(self, index).is_uninhabited() {
                         throw_ub!(UninhabitedEnumVariantRead(index))
                     }
                 }
@@ -112,7 +112,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         // Read tag and sanity-check `tag_layout`.
         let tag_val = self.read_immediate(&self.project_field(op, tag_field)?)?;
         assert_eq!(tag_layout.size, tag_val.layout.size);
-        assert_eq!(tag_layout.abi.is_signed(), tag_val.layout.abi.is_signed());
+        assert_eq!(tag_layout.backend_repr.is_signed(), tag_val.layout.backend_repr.is_signed());
         trace!("tag value: {}", tag_val);
 
         // Figure out which discriminant and variant this corresponds to.
@@ -203,7 +203,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         // Reading the discriminant of an uninhabited variant is UB. This is the basis for the
         // `uninhabited_enum_branching` MIR pass. It also ensures consistency with
         // `write_discriminant`.
-        if op.layout().for_variant(self, index).abi.is_uninhabited() {
+        if op.layout().for_variant(self, index).is_uninhabited() {
             throw_ub!(UninhabitedEnumVariantRead(index))
         }
         interp_ok(index)
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index a1c773a4b80..9043bd3e28e 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -3,13 +3,15 @@ use rustc_errors::DiagCtxtHandle;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::infer::at::ToTrace;
-use rustc_infer::traits::ObligationCause;
+use rustc_infer::traits::{ObligationCause, Reveal};
 use rustc_middle::mir::interpret::{ErrorHandled, InvalidMetaKind, ReportedErrorInfo};
 use rustc_middle::query::TyCtxtAt;
 use rustc_middle::ty::layout::{
     self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, TyAndLayout,
 };
-use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt, TypeFoldable, Variance};
+use rustc_middle::ty::{
+    self, GenericArgsRef, ParamEnv, Ty, TyCtxt, TypeFoldable, TypingMode, Variance,
+};
 use rustc_middle::{mir, span_bug};
 use rustc_session::Limit;
 use rustc_span::Span;
@@ -114,6 +116,7 @@ impl<'tcx, M: Machine<'tcx>> FnAbiOfHelpers<'tcx> for InterpCx<'tcx, M> {
 /// This test should be symmetric, as it is primarily about layout compatibility.
 pub(super) fn mir_assign_valid_types<'tcx>(
     tcx: TyCtxt<'tcx>,
+    typing_mode: TypingMode<'tcx>,
     param_env: ParamEnv<'tcx>,
     src: TyAndLayout<'tcx>,
     dest: TyAndLayout<'tcx>,
@@ -122,7 +125,7 @@ pub(super) fn mir_assign_valid_types<'tcx>(
     // all normal lifetimes are erased, higher-ranked types with their
     // late-bound lifetimes are still around and can lead to type
     // differences.
-    if util::relate_types(tcx, param_env, Variance::Covariant, src.ty, dest.ty) {
+    if util::relate_types(tcx, typing_mode, param_env, Variance::Covariant, src.ty, dest.ty) {
         // Make sure the layout is equal, too -- just to be safe. Miri really
         // needs layout equality. For performance reason we skip this check when
         // the types are equal. Equal types *can* have different layouts when
@@ -142,6 +145,7 @@ pub(super) fn mir_assign_valid_types<'tcx>(
 #[cfg_attr(not(debug_assertions), inline(always))]
 pub(super) fn from_known_layout<'tcx>(
     tcx: TyCtxtAt<'tcx>,
+    typing_mode: TypingMode<'tcx>,
     param_env: ParamEnv<'tcx>,
     known_layout: Option<TyAndLayout<'tcx>>,
     compute: impl FnOnce() -> InterpResult<'tcx, TyAndLayout<'tcx>>,
@@ -151,7 +155,13 @@ pub(super) fn from_known_layout<'tcx>(
         Some(known_layout) => {
             if cfg!(debug_assertions) {
                 let check_layout = compute()?;
-                if !mir_assign_valid_types(tcx.tcx, param_env, check_layout, known_layout) {
+                if !mir_assign_valid_types(
+                    tcx.tcx,
+                    typing_mode,
+                    param_env,
+                    check_layout,
+                    known_layout,
+                ) {
                     span_bug!(
                         tcx.span,
                         "expected type differs from actual type.\nexpected: {}\nactual: {}",
@@ -201,6 +211,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         }
     }
 
+    pub fn typing_mode(&self) -> TypingMode<'tcx> {
+        debug_assert_eq!(self.param_env.reveal(), Reveal::All);
+        TypingMode::PostAnalysis
+    }
+
     /// Returns the span of the currently executed statement/terminator.
     /// This is the span typically used for error reporting.
     #[inline(always)]
@@ -325,7 +340,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             return true;
         }
         // Slow path: spin up an inference context to check if these traits are sufficiently equal.
-        let infcx = self.tcx.infer_ctxt().build();
+        let infcx = self.tcx.infer_ctxt().build(self.typing_mode());
         let ocx = ObligationCtxt::new(&infcx);
         let cause = ObligationCause::dummy_with_span(self.cur_span());
         // equate the two trait refs after normalization
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index 4e603f57c56..80e14ee887c 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -364,7 +364,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                     let msg = match requirement {
                         // For *all* intrinsics we first check `is_uninhabited` to give a more specific
                         // error message.
-                        _ if layout.abi.is_uninhabited() => format!(
+                        _ if layout.is_uninhabited() => format!(
                             "aborted execution: attempted to instantiate uninhabited type `{ty}`"
                         ),
                         ValidityRequirement::Inhabited => bug!("handled earlier"),
@@ -563,7 +563,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             self.binary_op(mir_op.wrapping_to_overflowing().unwrap(), l, r)?.to_scalar_pair();
         interp_ok(if overflowed.to_bool()? {
             let size = l.layout.size;
-            if l.layout.abi.is_signed() {
+            if l.layout.backend_repr.is_signed() {
                 // For signed ints the saturated value depends on the sign of the first
                 // term since the sign of the second term can be inferred from this and
                 // the fact that the operation has overflowed (if either is 0 no
diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs
index cd5e2aeca85..a130ae89bcb 100644
--- a/compiler/rustc_const_eval/src/interpret/operand.rs
+++ b/compiler/rustc_const_eval/src/interpret/operand.rs
@@ -5,7 +5,7 @@ use std::assert_matches::assert_matches;
 
 use either::{Either, Left, Right};
 use rustc_abi as abi;
-use rustc_abi::{Abi, HasDataLayout, Size};
+use rustc_abi::{BackendRepr, HasDataLayout, Size};
 use rustc_hir::def::Namespace;
 use rustc_middle::mir::interpret::ScalarSizeMismatch;
 use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutOf, TyAndLayout};
@@ -114,9 +114,9 @@ impl<Prov: Provenance> Immediate<Prov> {
     }
 
     /// Assert that this immediate is a valid value for the given ABI.
-    pub fn assert_matches_abi(self, abi: Abi, msg: &str, cx: &impl HasDataLayout) {
+    pub fn assert_matches_abi(self, abi: BackendRepr, msg: &str, cx: &impl HasDataLayout) {
         match (self, abi) {
-            (Immediate::Scalar(scalar), Abi::Scalar(s)) => {
+            (Immediate::Scalar(scalar), BackendRepr::Scalar(s)) => {
                 assert_eq!(scalar.size(), s.size(cx), "{msg}: scalar value has wrong size");
                 if !matches!(s.primitive(), abi::Primitive::Pointer(..)) {
                     // This is not a pointer, it should not carry provenance.
@@ -126,7 +126,7 @@ impl<Prov: Provenance> Immediate<Prov> {
                     );
                 }
             }
-            (Immediate::ScalarPair(a_val, b_val), Abi::ScalarPair(a, b)) => {
+            (Immediate::ScalarPair(a_val, b_val), BackendRepr::ScalarPair(a, b)) => {
                 assert_eq!(
                     a_val.size(),
                     a.size(cx),
@@ -244,7 +244,7 @@ impl<'tcx, Prov: Provenance> std::ops::Deref for ImmTy<'tcx, Prov> {
 impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
     #[inline]
     pub fn from_scalar(val: Scalar<Prov>, layout: TyAndLayout<'tcx>) -> Self {
-        debug_assert!(layout.abi.is_scalar(), "`ImmTy::from_scalar` on non-scalar layout");
+        debug_assert!(layout.backend_repr.is_scalar(), "`ImmTy::from_scalar` on non-scalar layout");
         debug_assert_eq!(val.size(), layout.size);
         ImmTy { imm: val.into(), layout }
     }
@@ -252,7 +252,7 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
     #[inline]
     pub fn from_scalar_pair(a: Scalar<Prov>, b: Scalar<Prov>, layout: TyAndLayout<'tcx>) -> Self {
         debug_assert!(
-            matches!(layout.abi, Abi::ScalarPair(..)),
+            matches!(layout.backend_repr, BackendRepr::ScalarPair(..)),
             "`ImmTy::from_scalar_pair` on non-scalar-pair layout"
         );
         let imm = Immediate::ScalarPair(a, b);
@@ -263,9 +263,9 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
     pub fn from_immediate(imm: Immediate<Prov>, layout: TyAndLayout<'tcx>) -> Self {
         // Without a `cx` we cannot call `assert_matches_abi`.
         debug_assert!(
-            match (imm, layout.abi) {
-                (Immediate::Scalar(..), Abi::Scalar(..)) => true,
-                (Immediate::ScalarPair(..), Abi::ScalarPair(..)) => true,
+            match (imm, layout.backend_repr) {
+                (Immediate::Scalar(..), BackendRepr::Scalar(..)) => true,
+                (Immediate::ScalarPair(..), BackendRepr::ScalarPair(..)) => true,
                 (Immediate::Uninit, _) if layout.is_sized() => true,
                 _ => false,
             },
@@ -356,7 +356,11 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
     fn offset_(&self, offset: Size, layout: TyAndLayout<'tcx>, cx: &impl HasDataLayout) -> Self {
         // Verify that the input matches its type.
         if cfg!(debug_assertions) {
-            self.assert_matches_abi(self.layout.abi, "invalid input to Immediate::offset", cx);
+            self.assert_matches_abi(
+                self.layout.backend_repr,
+                "invalid input to Immediate::offset",
+                cx,
+            );
         }
         // `ImmTy` have already been checked to be in-bounds, so we can just check directly if this
         // remains in-bounds. This cannot actually be violated since projections are type-checked
@@ -370,19 +374,19 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
         );
         // This makes several assumptions about what layouts we will encounter; we match what
         // codegen does as good as we can (see `extract_field` in `rustc_codegen_ssa/src/mir/operand.rs`).
-        let inner_val: Immediate<_> = match (**self, self.layout.abi) {
+        let inner_val: Immediate<_> = match (**self, self.layout.backend_repr) {
             // If the entire value is uninit, then so is the field (can happen in ConstProp).
             (Immediate::Uninit, _) => Immediate::Uninit,
             // If the field is uninhabited, we can forget the data (can happen in ConstProp).
             // `enum S { A(!), B, C }` is an example of an enum with Scalar layout that
             // has an `Uninhabited` variant, which means this case is possible.
-            _ if layout.abi.is_uninhabited() => Immediate::Uninit,
+            _ if layout.is_uninhabited() => Immediate::Uninit,
             // the field contains no information, can be left uninit
             // (Scalar/ScalarPair can contain even aligned ZST, not just 1-ZST)
             _ if layout.is_zst() => Immediate::Uninit,
             // some fieldless enum variants can have non-zero size but still `Aggregate` ABI... try
             // to detect those here and also give them no data
-            _ if matches!(layout.abi, Abi::Aggregate { .. })
+            _ if matches!(layout.backend_repr, BackendRepr::Memory { .. })
                 && matches!(layout.variants, abi::Variants::Single { .. })
                 && matches!(&layout.fields, abi::FieldsShape::Arbitrary { offsets, .. } if offsets.len() == 0) =>
             {
@@ -394,7 +398,7 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
                 **self
             }
             // extract fields from types with `ScalarPair` ABI
-            (Immediate::ScalarPair(a_val, b_val), Abi::ScalarPair(a, b)) => {
+            (Immediate::ScalarPair(a_val, b_val), BackendRepr::ScalarPair(a, b)) => {
                 Immediate::from(if offset.bytes() == 0 {
                     a_val
                 } else {
@@ -411,7 +415,11 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
             ),
         };
         // Ensure the new layout matches the new value.
-        inner_val.assert_matches_abi(layout.abi, "invalid field type in Immediate::offset", cx);
+        inner_val.assert_matches_abi(
+            layout.backend_repr,
+            "invalid field type in Immediate::offset",
+            cx,
+        );
 
         ImmTy::from_immediate(inner_val, layout)
     }
@@ -567,8 +575,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         // case where some of the bytes are initialized and others are not. So, we need an extra
         // check that walks over the type of `mplace` to make sure it is truly correct to treat this
         // like a `Scalar` (or `ScalarPair`).
-        interp_ok(match mplace.layout.abi {
-            Abi::Scalar(abi::Scalar::Initialized { value: s, .. }) => {
+        interp_ok(match mplace.layout.backend_repr {
+            BackendRepr::Scalar(abi::Scalar::Initialized { value: s, .. }) => {
                 let size = s.size(self);
                 assert_eq!(size, mplace.layout.size, "abi::Scalar size does not match layout size");
                 let scalar = alloc.read_scalar(
@@ -577,7 +585,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 )?;
                 Some(ImmTy::from_scalar(scalar, mplace.layout))
             }
-            Abi::ScalarPair(
+            BackendRepr::ScalarPair(
                 abi::Scalar::Initialized { value: a, .. },
                 abi::Scalar::Initialized { value: b, .. },
             ) => {
@@ -637,9 +645,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         op: &impl Projectable<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
         if !matches!(
-            op.layout().abi,
-            Abi::Scalar(abi::Scalar::Initialized { .. })
-                | Abi::ScalarPair(abi::Scalar::Initialized { .. }, abi::Scalar::Initialized { .. })
+            op.layout().backend_repr,
+            BackendRepr::Scalar(abi::Scalar::Initialized { .. })
+                | BackendRepr::ScalarPair(
+                    abi::Scalar::Initialized { .. },
+                    abi::Scalar::Initialized { .. }
+                )
         ) {
             span_bug!(self.cur_span(), "primitive read not possible for type: {}", op.layout().ty);
         }
@@ -762,6 +773,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 )?;
             if !mir_assign_valid_types(
                 *self.tcx,
+                self.typing_mode(),
                 self.param_env,
                 self.layout_of(normalized_place_ty)?,
                 op.layout,
@@ -821,7 +833,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             })
         };
         let layout =
-            from_known_layout(self.tcx, self.param_env, layout, || self.layout_of(ty).into())?;
+            from_known_layout(self.tcx, self.typing_mode(), self.param_env, layout, || {
+                self.layout_of(ty).into()
+            })?;
         let imm = match val_val {
             mir::ConstValue::Indirect { alloc_id, offset } => {
                 // This is const data, no mutation allowed.
diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs
index b28ac68ac54..cf280e0c1ae 100644
--- a/compiler/rustc_const_eval/src/interpret/operator.rs
+++ b/compiler/rustc_const_eval/src/interpret/operator.rs
@@ -114,7 +114,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             let l_bits = left.layout.size.bits();
             // Compute the equivalent shift modulo `size` that is in the range `0..size`. (This is
             // the one MIR operator that does *not* directly map to a single LLVM operation.)
-            let (shift_amount, overflow) = if right.layout.abi.is_signed() {
+            let (shift_amount, overflow) = if right.layout.backend_repr.is_signed() {
                 let shift_amount = r_signed();
                 let rem = shift_amount.rem_euclid(l_bits.into());
                 // `rem` is guaranteed positive, so the `unwrap` cannot fail
@@ -126,7 +126,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             };
             let shift_amount = u32::try_from(shift_amount).unwrap(); // we brought this in the range `0..size` so this will always fit
             // Compute the shifted result.
-            let result = if left.layout.abi.is_signed() {
+            let result = if left.layout.backend_repr.is_signed() {
                 let l = l_signed();
                 let result = match bin_op {
                     Shl | ShlUnchecked => l.checked_shl(shift_amount).unwrap(),
@@ -147,7 +147,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             if overflow && let Some(intrinsic) = throw_ub_on_overflow {
                 throw_ub!(ShiftOverflow {
                     intrinsic,
-                    shift_amount: if right.layout.abi.is_signed() {
+                    shift_amount: if right.layout.backend_repr.is_signed() {
                         Either::Right(r_signed())
                     } else {
                         Either::Left(r_unsigned())
@@ -171,7 +171,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         let size = left.layout.size;
 
         // Operations that need special treatment for signed integers
-        if left.layout.abi.is_signed() {
+        if left.layout.backend_repr.is_signed() {
             let op: Option<fn(&i128, &i128) -> bool> = match bin_op {
                 Lt => Some(i128::lt),
                 Le => Some(i128::le),
@@ -250,7 +250,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             BitXor => ImmTy::from_uint(l ^ r, left.layout),
 
             _ => {
-                assert!(!left.layout.abi.is_signed());
+                assert!(!left.layout.backend_repr.is_signed());
                 let op: fn(u128, u128) -> (u128, bool) = match bin_op {
                     Add | AddUnchecked | AddWithOverflow => u128::overflowing_add,
                     Sub | SubUnchecked | SubWithOverflow => u128::overflowing_sub,
@@ -315,7 +315,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 let ptr = left.to_scalar().to_pointer(self)?;
                 let pointee_ty = left.layout.ty.builtin_deref(true).unwrap();
                 let pointee_layout = self.layout_of(pointee_ty)?;
-                assert!(pointee_layout.abi.is_sized());
+                assert!(pointee_layout.is_sized());
 
                 // The size always fits in `i64` as it can be at most `isize::MAX`.
                 let pointee_size = i64::try_from(pointee_layout.size.bytes()).unwrap();
@@ -332,7 +332,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 }
 
                 let offset_bytes = val.to_target_isize(self)?;
-                if !right.layout.abi.is_signed() && offset_bytes < 0 {
+                if !right.layout.backend_repr.is_signed() && offset_bytes < 0 {
                     // We were supposed to do an unsigned offset but the result is negative -- this
                     // can only mean that the cast wrapped around.
                     throw_ub!(PointerArithOverflow)
@@ -518,14 +518,14 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
 
         interp_ok(match null_op {
             SizeOf => {
-                if !layout.abi.is_sized() {
+                if !layout.is_sized() {
                     span_bug!(self.cur_span(), "unsized type for `NullaryOp::SizeOf`");
                 }
                 let val = layout.size.bytes();
                 ImmTy::from_uint(val, usize_layout())
             }
             AlignOf => {
-                if !layout.abi.is_sized() {
+                if !layout.is_sized() {
                     span_bug!(self.cur_span(), "unsized type for `NullaryOp::AlignOf`");
                 }
                 let val = layout.align.abi.bytes();
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs
index 81b926a1b65..cc8d1db6cfb 100644
--- a/compiler/rustc_const_eval/src/interpret/place.rs
+++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -5,11 +5,11 @@
 use std::assert_matches::assert_matches;
 
 use either::{Either, Left, Right};
+use rustc_abi::{Align, BackendRepr, HasDataLayout, Size};
 use rustc_ast::Mutability;
 use rustc_middle::ty::Ty;
 use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
 use rustc_middle::{bug, mir, span_bug};
-use rustc_target::abi::{Abi, Align, HasDataLayout, Size};
 use tracing::{instrument, trace};
 
 use super::{
@@ -540,6 +540,7 @@ where
                 )?;
             if !mir_assign_valid_types(
                 *self.tcx,
+                self.typing_mode(),
                 self.param_env,
                 self.layout_of(normalized_place_ty)?,
                 place.layout,
@@ -659,7 +660,7 @@ where
                 // Unfortunately this is too expensive to do in release builds.
                 if cfg!(debug_assertions) {
                     src.assert_matches_abi(
-                        local_layout.abi,
+                        local_layout.backend_repr,
                         "invalid immediate for given destination place",
                         self,
                     );
@@ -683,7 +684,11 @@ where
     ) -> InterpResult<'tcx> {
         // We use the sizes from `value` below.
         // Ensure that matches the type of the place it is written to.
-        value.assert_matches_abi(layout.abi, "invalid immediate for given destination place", self);
+        value.assert_matches_abi(
+            layout.backend_repr,
+            "invalid immediate for given destination place",
+            self,
+        );
         // Note that it is really important that the type here is the right one, and matches the
         // type things are read at. In case `value` is a `ScalarPair`, we don't do any magic here
         // to handle padding properly, which is only correct if we never look at this data with the
@@ -700,7 +705,7 @@ where
                 alloc.write_scalar(alloc_range(Size::ZERO, scalar.size()), scalar)
             }
             Immediate::ScalarPair(a_val, b_val) => {
-                let Abi::ScalarPair(a, b) = layout.abi else {
+                let BackendRepr::ScalarPair(a, b) = layout.backend_repr else {
                     span_bug!(
                         self.cur_span(),
                         "write_immediate_to_mplace: invalid ScalarPair layout: {:#?}",
@@ -866,8 +871,13 @@ where
     ) -> InterpResult<'tcx> {
         // We do NOT compare the types for equality, because well-typed code can
         // actually "transmute" `&mut T` to `&T` in an assignment without a cast.
-        let layout_compat =
-            mir_assign_valid_types(*self.tcx, self.param_env, src.layout(), dest.layout());
+        let layout_compat = mir_assign_valid_types(
+            *self.tcx,
+            self.typing_mode(),
+            self.param_env,
+            src.layout(),
+            dest.layout(),
+        );
         if !allow_transmute && !layout_compat {
             span_bug!(
                 self.cur_span(),
diff --git a/compiler/rustc_const_eval/src/interpret/stack.rs b/compiler/rustc_const_eval/src/interpret/stack.rs
index 3bc9f46aea0..50c0446b3cd 100644
--- a/compiler/rustc_const_eval/src/interpret/stack.rs
+++ b/compiler/rustc_const_eval/src/interpret/stack.rs
@@ -596,12 +596,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             return interp_ok(layout);
         }
 
-        let layout = from_known_layout(self.tcx, self.param_env, layout, || {
-            let local_ty = frame.body.local_decls[local].ty;
-            let local_ty =
-                self.instantiate_from_frame_and_normalize_erasing_regions(frame, local_ty)?;
-            self.layout_of(local_ty).into()
-        })?;
+        let layout =
+            from_known_layout(self.tcx, self.typing_mode(), self.param_env, layout, || {
+                let local_ty = frame.body.local_decls[local].ty;
+                let local_ty =
+                    self.instantiate_from_frame_and_normalize_erasing_regions(frame, local_ty)?;
+                self.layout_of(local_ty).into()
+            })?;
 
         // Layouts of locals are requested a lot, so we cache them.
         state.layout.set(Some(layout));
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index b6120ce82fe..cd2c1ef3613 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -11,6 +11,10 @@ use std::num::NonZero;
 
 use either::{Left, Right};
 use hir::def::DefKind;
+use rustc_abi::{
+    BackendRepr, FieldIdx, FieldsShape, Scalar as ScalarAbi, Size, VariantIdx, Variants,
+    WrappingRange,
+};
 use rustc_ast::Mutability;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
@@ -23,9 +27,6 @@ use rustc_middle::mir::interpret::{
 use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout};
 use rustc_middle::ty::{self, Ty};
 use rustc_span::symbol::{Symbol, sym};
-use rustc_target::abi::{
-    Abi, FieldIdx, FieldsShape, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange,
-};
 use tracing::trace;
 
 use super::machine::AllocMap;
@@ -422,7 +423,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
         // Reset provenance: ensure slice tail metadata does not preserve provenance,
         // and ensure all pointers do not preserve partial provenance.
         if self.reset_provenance_and_padding {
-            if matches!(imm.layout.abi, Abi::Scalar(..)) {
+            if matches!(imm.layout.backend_repr, BackendRepr::Scalar(..)) {
                 // A thin pointer. If it has provenance, we don't have to do anything.
                 // If it does not, ensure we clear the provenance in memory.
                 if matches!(imm.to_scalar(), Scalar::Int(..)) {
@@ -542,7 +543,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
             throw_validation_failure!(self.path, NullPtr { ptr_kind })
         }
         // Do not allow references to uninhabited types.
-        if place.layout.abi.is_uninhabited() {
+        if place.layout.is_uninhabited() {
             let ty = place.layout.ty;
             throw_validation_failure!(self.path, PtrToUninhabited { ptr_kind, ty })
         }
@@ -867,7 +868,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
     /// Add the entire given place to the "data" range of this visit.
     fn add_data_range_place(&mut self, place: &PlaceTy<'tcx, M::Provenance>) {
         // Only sized places can be added this way.
-        debug_assert!(place.layout.abi.is_sized());
+        debug_assert!(place.layout.is_sized());
         if let Some(data_bytes) = self.data_bytes.as_mut() {
             let offset = Self::data_range_offset(self.ecx, place);
             data_bytes.add_range(offset, place.layout.size);
@@ -945,7 +946,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
         layout: TyAndLayout<'tcx>,
     ) -> Cow<'e, RangeSet> {
         assert!(layout.ty.is_union());
-        assert!(layout.abi.is_sized(), "there are no unsized unions");
+        assert!(layout.is_sized(), "there are no unsized unions");
         let layout_cx = LayoutCx::new(*ecx.tcx, ecx.param_env);
         return M::cached_union_data_range(ecx, layout.ty, || {
             let mut out = RangeSet(Vec::new());
@@ -981,7 +982,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
                     let elem = layout.field(cx, 0);
 
                     // Fast-path for large arrays of simple types that do not contain any padding.
-                    if elem.abi.is_scalar() {
+                    if elem.backend_repr.is_scalar() {
                         out.add_range(base_offset, elem.size * count);
                     } else {
                         for idx in 0..count {
@@ -1299,19 +1300,19 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
         // FIXME: We could avoid some redundant checks here. For newtypes wrapping
         // scalars, we do the same check on every "level" (e.g., first we check
         // MyNewtype and then the scalar in there).
-        match val.layout.abi {
-            Abi::Uninhabited => {
+        match val.layout.backend_repr {
+            BackendRepr::Uninhabited => {
                 let ty = val.layout.ty;
                 throw_validation_failure!(self.path, UninhabitedVal { ty });
             }
-            Abi::Scalar(scalar_layout) => {
+            BackendRepr::Scalar(scalar_layout) => {
                 if !scalar_layout.is_uninit_valid() {
                     // There is something to check here.
                     let scalar = self.read_scalar(val, ExpectedKind::InitScalar)?;
                     self.visit_scalar(scalar, scalar_layout)?;
                 }
             }
-            Abi::ScalarPair(a_layout, b_layout) => {
+            BackendRepr::ScalarPair(a_layout, b_layout) => {
                 // We can only proceed if *both* scalars need to be initialized.
                 // FIXME: find a way to also check ScalarPair when one side can be uninit but
                 // the other must be init.
@@ -1322,12 +1323,12 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
                     self.visit_scalar(b, b_layout)?;
                 }
             }
-            Abi::Vector { .. } => {
+            BackendRepr::Vector { .. } => {
                 // No checks here, we assume layout computation gets this right.
                 // (This is harder to check since Miri does not represent these as `Immediate`. We
                 // also cannot use field projections since this might be a newtype around a vector.)
             }
-            Abi::Aggregate { .. } => {
+            BackendRepr::Memory { .. } => {
                 // Nothing to do.
             }
         }
diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
index 649179d5b1e..f743525f359 100644
--- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
+++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
@@ -1,9 +1,9 @@
+use rustc_abi::{BackendRepr, FieldsShape, Scalar, Variants};
 use rustc_middle::bug;
 use rustc_middle::ty::layout::{
     HasTyCtxt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, ValidityRequirement,
 };
 use rustc_middle::ty::{ParamEnvAnd, Ty, TyCtxt};
-use rustc_target::abi::{Abi, FieldsShape, Scalar, Variants};
 
 use crate::const_eval::{CanAccessMutGlobal, CheckAlignment, CompileTimeMachine};
 use crate::interpret::{InterpCx, MemoryKind};
@@ -29,7 +29,7 @@ pub fn check_validity_requirement<'tcx>(
 
     // There is nothing strict or lax about inhabitedness.
     if kind == ValidityRequirement::Inhabited {
-        return Ok(!layout.abi.is_uninhabited());
+        return Ok(!layout.is_uninhabited());
     }
 
     let layout_cx = LayoutCx::new(tcx, param_env_and_ty.param_env);
@@ -111,12 +111,12 @@ fn check_validity_requirement_lax<'tcx>(
     };
 
     // Check the ABI.
-    let valid = match this.abi {
-        Abi::Uninhabited => false, // definitely UB
-        Abi::Scalar(s) => scalar_allows_raw_init(s),
-        Abi::ScalarPair(s1, s2) => scalar_allows_raw_init(s1) && scalar_allows_raw_init(s2),
-        Abi::Vector { element: s, count } => count == 0 || scalar_allows_raw_init(s),
-        Abi::Aggregate { .. } => true, // Fields are checked below.
+    let valid = match this.backend_repr {
+        BackendRepr::Uninhabited => false, // definitely UB
+        BackendRepr::Scalar(s) => scalar_allows_raw_init(s),
+        BackendRepr::ScalarPair(s1, s2) => scalar_allows_raw_init(s1) && scalar_allows_raw_init(s2),
+        BackendRepr::Vector { element: s, count } => count == 0 || scalar_allows_raw_init(s),
+        BackendRepr::Memory { .. } => true, // Fields are checked below.
     };
     if !valid {
         // This is definitely not okay.
diff --git a/compiler/rustc_const_eval/src/util/compare_types.rs b/compiler/rustc_const_eval/src/util/compare_types.rs
index 3ea54146fc7..0cf27d30c36 100644
--- a/compiler/rustc_const_eval/src/util/compare_types.rs
+++ b/compiler/rustc_const_eval/src/util/compare_types.rs
@@ -5,27 +5,18 @@
 
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::traits::ObligationCause;
-use rustc_middle::ty::{ParamEnv, Ty, TyCtxt, Variance};
+use rustc_middle::ty::{ParamEnv, Ty, TyCtxt, TypingMode, Variance};
 use rustc_trait_selection::traits::ObligationCtxt;
 
-/// Returns whether the two types are equal up to subtyping.
-///
-/// This is used in case we don't know the expected subtyping direction
-/// and still want to check whether anything is broken.
-pub fn is_equal_up_to_subtyping<'tcx>(
+/// Returns whether `src` is a subtype of `dest`, i.e. `src <: dest`.
+pub fn sub_types<'tcx>(
     tcx: TyCtxt<'tcx>,
+    typing_mode: TypingMode<'tcx>,
     param_env: ParamEnv<'tcx>,
     src: Ty<'tcx>,
     dest: Ty<'tcx>,
 ) -> bool {
-    // Fast path.
-    if src == dest {
-        return true;
-    }
-
-    // Check for subtyping in either direction.
-    relate_types(tcx, param_env, Variance::Covariant, src, dest)
-        || relate_types(tcx, param_env, Variance::Covariant, dest, src)
+    relate_types(tcx, typing_mode, param_env, Variance::Covariant, src, dest)
 }
 
 /// Returns whether `src` is a subtype of `dest`, i.e. `src <: dest`.
@@ -35,6 +26,7 @@ pub fn is_equal_up_to_subtyping<'tcx>(
 /// because we want to check for type equality.
 pub fn relate_types<'tcx>(
     tcx: TyCtxt<'tcx>,
+    typing_mode: TypingMode<'tcx>,
     param_env: ParamEnv<'tcx>,
     variance: Variance,
     src: Ty<'tcx>,
@@ -45,7 +37,7 @@ pub fn relate_types<'tcx>(
     }
 
     let mut builder = tcx.infer_ctxt().ignoring_regions();
-    let infcx = builder.build();
+    let infcx = builder.build(typing_mode);
     let ocx = ObligationCtxt::new(&infcx);
     let cause = ObligationCause::dummy();
     let src = ocx.normalize(&cause, param_env, src);
diff --git a/compiler/rustc_const_eval/src/util/mod.rs b/compiler/rustc_const_eval/src/util/mod.rs
index 66a1addfb52..25a9dbb2c11 100644
--- a/compiler/rustc_const_eval/src/util/mod.rs
+++ b/compiler/rustc_const_eval/src/util/mod.rs
@@ -8,7 +8,7 @@ mod type_name;
 
 pub use self::alignment::{is_disaligned, is_within_packed};
 pub use self::check_validity_requirement::check_validity_requirement;
-pub use self::compare_types::{is_equal_up_to_subtyping, relate_types};
+pub use self::compare_types::{relate_types, sub_types};
 pub use self::type_name::type_name;
 
 /// Classify whether an operator is "left-homogeneous", i.e., the LHS has the
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index a59dea557bb..e2585c02388 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -1395,7 +1395,7 @@ pub fn install_ice_hook(
     }
 
     let using_internal_features = Arc::new(std::sync::atomic::AtomicBool::default());
-    let using_internal_features_hook = using_internal_features.clone();
+    let using_internal_features_hook = Arc::clone(&using_internal_features);
     panic::update_hook(Box::new(
         move |default_hook: &(dyn Fn(&PanicHookInfo<'_>) + Send + Sync + 'static),
               info: &PanicHookInfo<'_>| {
diff --git a/compiler/rustc_error_codes/src/error_codes/E0801.md b/compiler/rustc_error_codes/src/error_codes/E0801.md
new file mode 100644
index 00000000000..c89feb9b308
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0801.md
@@ -0,0 +1,51 @@
+The `self` parameter in a method has an invalid generic "receiver type".
+
+Erroneous code example:
+
+```compile_fail,E0801
+struct Foo;
+
+impl Foo {
+    fn foo<R: std::ops::Deref<Target=Self>>(self: R) {}
+}
+```
+
+or alternatively,
+
+```compile_fail,E0801
+struct Foo;
+
+impl Foo {
+    fn foo(self: impl std::ops::Deref<Target=Self>) {}
+}
+```
+
+Methods take a special first parameter, termed `self`. It's normal to
+use `self`, `&self` or `&mut self`, which are syntactic sugar for
+`self: Self`, `self: &Self`, and `self: &mut Self` respectively.
+But it's also possible to use more sophisticated types of `self`
+parameter, for instance `std::rc::Rc<Self>`. The set of allowable
+`Self` types is extensible using the nightly feature
+[Arbitrary self types][AST].
+This will extend the valid set of `Self` types to anything which implements
+`std::ops::Deref<Target=Self>`, for example `Rc<Self>`, `Box<Self>`, or
+your own smart pointers that do the same.
+
+However, even with that feature, the `self` type must be concrete.
+Generic `self` types are not permitted. Specifically, a `self` type will
+be rejected if it is a type parameter defined on the method.
+
+These are OK:
+
+```
+struct Foo;
+
+impl Foo {
+    fn foo(self) {}
+    fn foo2(self: std::rc::Rc<Self>) {} // or some other similar
+        // smart pointer if you enable arbitrary self types and
+        // the pointer implements Deref<Target=Self>
+}
+```
+
+[AST]: https://doc.rust-lang.org/unstable-book/language-features/arbitrary-self-types.html
diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs
index 27a34d6003d..29f3277d399 100644
--- a/compiler/rustc_error_codes/src/lib.rs
+++ b/compiler/rustc_error_codes/src/lib.rs
@@ -540,6 +540,7 @@ E0797: 0797,
 E0798: 0798,
 E0799: 0799,
 E0800: 0800,
+E0801: 0801,
         );
     )
 }
diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml
index 00eaf4d5a86..41ebe4ae267 100644
--- a/compiler/rustc_errors/Cargo.toml
+++ b/compiler/rustc_errors/Cargo.toml
@@ -7,6 +7,7 @@ edition = "2021"
 # tidy-alphabetical-start
 annotate-snippets = "0.11"
 derive_setters = "0.1.6"
+rustc_abi = { path = "../rustc_abi" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
 rustc_data_structures = { path = "../rustc_data_structures" }
diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
index 335432c9cfe..b4a651b10b1 100644
--- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
+++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
@@ -173,7 +173,7 @@ impl AnnotateSnippetEmitter {
                             source_map.ensure_source_file_source_present(&file);
                             (
                                 format!("{}", source_map.filename_for_diagnostics(&file.name)),
-                                source_string(file.clone(), &line),
+                                source_string(Lrc::clone(&file), &line),
                                 line.line_index,
                                 line.annotations,
                             )
diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs
index 19529f06ef1..09a608dda7b 100644
--- a/compiler/rustc_errors/src/diagnostic_impls.rs
+++ b/compiler/rustc_errors/src/diagnostic_impls.rs
@@ -5,12 +5,12 @@ use std::num::ParseIntError;
 use std::path::{Path, PathBuf};
 use std::process::ExitStatus;
 
+use rustc_abi::TargetDataLayoutErrors;
 use rustc_ast_pretty::pprust;
 use rustc_macros::Subdiagnostic;
 use rustc_span::Span;
 use rustc_span::edition::Edition;
 use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent, Symbol};
-use rustc_target::abi::TargetDataLayoutErrors;
 use rustc_target::spec::{PanicStrategy, SplitDebuginfo, StackProtector, TargetTriple};
 use rustc_type_ir::{ClosureKind, FloatTy};
 use {rustc_ast as ast, rustc_hir as hir};
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 0ccc71ae06c..6552cf224ea 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -1555,7 +1555,7 @@ impl HumanEmitter {
                 // Get the left-side margin to remove it
                 let mut whitespace_margin = usize::MAX;
                 for line_idx in 0..annotated_file.lines.len() {
-                    let file = annotated_file.file.clone();
+                    let file = Lrc::clone(&annotated_file.file);
                     let line = &annotated_file.lines[line_idx];
                     if let Some(source_string) =
                         line.line_index.checked_sub(1).and_then(|l| file.get_line(l))
@@ -1646,7 +1646,7 @@ impl HumanEmitter {
 
                     let depths = self.render_source_line(
                         &mut buffer,
-                        annotated_file.file.clone(),
+                        Lrc::clone(&annotated_file.file),
                         &annotated_file.lines[line_idx],
                         width_offset,
                         code_offset,
@@ -2529,7 +2529,12 @@ impl FileWithAnnotatedLines {
                 //  | |      |
                 //  | |______foo
                 //  |        baz
-                add_annotation_to_file(&mut output, file.clone(), ann.line_start, ann.as_start());
+                add_annotation_to_file(
+                    &mut output,
+                    Lrc::clone(&file),
+                    ann.line_start,
+                    ann.as_start(),
+                );
                 // 4 is the minimum vertical length of a multiline span when presented: two lines
                 // of code and two lines of underline. This is not true for the special case where
                 // the beginning doesn't have an underline, but the current logic seems to be
@@ -2545,11 +2550,11 @@ impl FileWithAnnotatedLines {
                     .unwrap_or(ann.line_start);
                 for line in ann.line_start + 1..until {
                     // Every `|` that joins the beginning of the span (`___^`) to the end (`|__^`).
-                    add_annotation_to_file(&mut output, file.clone(), line, ann.as_line());
+                    add_annotation_to_file(&mut output, Lrc::clone(&file), line, ann.as_line());
                 }
                 let line_end = ann.line_end - 1;
                 if middle < line_end {
-                    add_annotation_to_file(&mut output, file.clone(), line_end, ann.as_line());
+                    add_annotation_to_file(&mut output, Lrc::clone(&file), line_end, ann.as_line());
                 }
             } else {
                 end_ann.annotation_type = AnnotationType::Singleline;
diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs
index 1534e256520..91e2b9996cd 100644
--- a/compiler/rustc_errors/src/json.rs
+++ b/compiler/rustc_errors/src/json.rs
@@ -367,9 +367,9 @@ impl Diagnostic {
             ColorConfig::Always | ColorConfig::Auto => dst = Box::new(termcolor::Ansi::new(dst)),
             ColorConfig::Never => {}
         }
-        HumanEmitter::new(dst, je.fallback_bundle.clone())
+        HumanEmitter::new(dst, Lrc::clone(&je.fallback_bundle))
             .short_message(short)
-            .sm(Some(je.sm.clone()))
+            .sm(Some(Lrc::clone(&je.sm)))
             .fluent_bundle(je.fluent_bundle.clone())
             .diagnostic_width(je.diagnostic_width)
             .macro_backtrace(je.macro_backtrace)
diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl
index fcf3352bfc5..f26c7c1ba0b 100644
--- a/compiler/rustc_expand/messages.ftl
+++ b/compiler/rustc_expand/messages.ftl
@@ -74,7 +74,7 @@ expand_helper_attribute_name_invalid =
     `{$name}` cannot be a name of derive helper attribute
 
 expand_incomplete_parse =
-    macro expansion ignores token `{$token}` and any following
+    macro expansion ignores {$descr} and any tokens following
     .label = caused by the macro expansion here
     .note = the usage of `{$macro_path}!` is likely invalid in {$kind_name} context
     .suggestion_add_semi = you might be missing a semicolon here
diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs
index 5682c574552..7bd7c305539 100644
--- a/compiler/rustc_expand/src/errors.rs
+++ b/compiler/rustc_expand/src/errors.rs
@@ -275,7 +275,7 @@ pub(crate) struct UnsupportedKeyValue {
 pub(crate) struct IncompleteParse<'a> {
     #[primary_span]
     pub span: Span,
-    pub token: Cow<'a, str>,
+    pub descr: String,
     #[label]
     pub label_span: Span,
     pub macro_path: &'a ast::Path,
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 5ffafcaa542..04ac7891023 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -21,6 +21,7 @@ use rustc_errors::PResult;
 use rustc_feature::Features;
 use rustc_parse::parser::{
     AttemptLocalParseRecovery, CommaRecoveryMode, ForceCollect, Parser, RecoverColon, RecoverComma,
+    token_descr,
 };
 use rustc_parse::validate_attr;
 use rustc_session::lint::BuiltinLintDiag;
@@ -1013,7 +1014,7 @@ pub(crate) fn ensure_complete_parse<'a>(
     span: Span,
 ) {
     if parser.token != token::Eof {
-        let token = pprust::token_to_string(&parser.token);
+        let descr = token_descr(&parser.token);
         // Avoid emitting backtrace info twice.
         let def_site_span = parser.token.span.with_ctxt(SyntaxContext::root());
 
@@ -1029,7 +1030,7 @@ pub(crate) fn ensure_complete_parse<'a>(
 
         parser.dcx().emit_err(IncompleteParse {
             span: def_site_span,
-            token,
+            descr,
             label_span: span,
             macro_path,
             kind_name,
diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs
index 103bbb05e7f..ffcce1e52f6 100644
--- a/compiler/rustc_expand/src/mbe/diagnostics.rs
+++ b/compiler/rustc_expand/src/mbe/diagnostics.rs
@@ -2,10 +2,9 @@ use std::borrow::Cow;
 
 use rustc_ast::token::{self, Token, TokenKind};
 use rustc_ast::tokenstream::TokenStream;
-use rustc_ast_pretty::pprust;
 use rustc_errors::{Applicability, Diag, DiagCtxtHandle, DiagMessage};
 use rustc_macros::Subdiagnostic;
-use rustc_parse::parser::{Parser, Recovery};
+use rustc_parse::parser::{Parser, Recovery, token_descr};
 use rustc_session::parse::ParseSess;
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::Ident;
@@ -336,17 +335,11 @@ pub(super) fn annotate_doc_comment(err: &mut Diag<'_>, sm: &SourceMap, span: Spa
 /// other tokens, this is "unexpected token...".
 pub(super) fn parse_failure_msg(tok: &Token, expected_token: Option<&Token>) -> Cow<'static, str> {
     if let Some(expected_token) = expected_token {
-        Cow::from(format!(
-            "expected `{}`, found `{}`",
-            pprust::token_to_string(expected_token),
-            pprust::token_to_string(tok),
-        ))
+        Cow::from(format!("expected {}, found {}", token_descr(expected_token), token_descr(tok)))
     } else {
         match tok.kind {
             token::Eof => Cow::from("unexpected end of macro invocation"),
-            _ => {
-                Cow::from(format!("no rules expected the token `{}`", pprust::token_to_string(tok)))
-            }
+            _ => Cow::from(format!("no rules expected {}", token_descr(tok))),
         }
     }
 }
diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs
index 3903203da3d..2a8dddc1e00 100644
--- a/compiler/rustc_expand/src/mbe/macro_parser.rs
+++ b/compiler/rustc_expand/src/mbe/macro_parser.rs
@@ -78,11 +78,10 @@ use std::rc::Rc;
 pub(crate) use NamedMatch::*;
 pub(crate) use ParseResult::*;
 use rustc_ast::token::{self, DocComment, NonterminalKind, Token};
-use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::ErrorGuaranteed;
 use rustc_lint_defs::pluralize;
-use rustc_parse::parser::{ParseNtResult, Parser};
+use rustc_parse::parser::{ParseNtResult, Parser, token_descr};
 use rustc_span::Span;
 use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent};
 
@@ -150,7 +149,7 @@ impl Display for MatcherLoc {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         match self {
             MatcherLoc::Token { token } | MatcherLoc::SequenceSep { separator: token } => {
-                write!(f, "`{}`", pprust::token_to_string(token))
+                write!(f, "{}", token_descr(token))
             }
             MatcherLoc::MetaVarDecl { bind, kind, .. } => {
                 write!(f, "meta-variable `${bind}")?;
@@ -622,7 +621,7 @@ impl TtParser {
         // possible next positions into `next_mps`. After some post-processing, the contents of
         // `next_mps` replenish `cur_mps` and we start over again.
         self.cur_mps.clear();
-        self.cur_mps.push(MatcherPos { idx: 0, matches: self.empty_matches.clone() });
+        self.cur_mps.push(MatcherPos { idx: 0, matches: Rc::clone(&self.empty_matches) });
 
         loop {
             self.next_mps.clear();
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index 34811ca2b35..b77d02e630a 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -5,6 +5,7 @@ use rustc_ast::mut_visit::{self, MutVisitor};
 use rustc_ast::token::{self, Delimiter, IdentIsRaw, Lit, LitKind, Nonterminal, Token, TokenKind};
 use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
 use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::sync::Lrc;
 use rustc_errors::{Diag, DiagCtxtHandle, PResult, pluralize};
 use rustc_parse::lexer::nfc_normalize;
 use rustc_parse::parser::ParseNtResult;
@@ -293,7 +294,7 @@ pub(super) fn transcribe<'a>(
                             // `Delimiter::Invisible` to maintain parsing priorities.
                             // `Interpolated` is currently used for such groups in rustc parser.
                             marker.visit_span(&mut sp);
-                            TokenTree::token_alone(token::Interpolated(nt.clone()), sp)
+                            TokenTree::token_alone(token::Interpolated(Lrc::clone(nt)), sp)
                         }
                         MatchedSeq(..) => {
                             // We were unable to descend far enough. This is an error.
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index ac922f184dd..e910415c345 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -224,6 +224,8 @@ declare_features! (
     (accepted, i128_type, "1.26.0", Some(35118)),
     /// Allows the use of `if let` expressions.
     (accepted, if_let, "1.0.0", None),
+    /// Rescoping temporaries in `if let` to align with Rust 2024.
+    (accepted, if_let_rescope, "CURRENT_RUSTC_VERSION", Some(124085)),
     /// Allows top level or-patterns (`p | q`) in `if let` and `while let`.
     (accepted, if_while_or_patterns, "1.33.0", Some(48215)),
     /// Allows lifetime elision in `impl` headers. For example:
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 93047d420ad..a99d9048886 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -505,8 +505,6 @@ declare_features! (
     (unstable, half_open_range_patterns_in_slices, "1.66.0", Some(67264)),
     /// Allows `if let` guard in match arms.
     (unstable, if_let_guard, "1.47.0", Some(51114)),
-    /// Rescoping temporaries in `if let` to align with Rust 2024.
-    (unstable, if_let_rescope, "1.83.0", Some(124085)),
     /// Allows `impl Trait` to be used inside associated types (RFC 2515).
     (unstable, impl_trait_in_assoc_type, "1.70.0", Some(63063)),
     /// Allows `impl Trait` as output type in `Fn` traits in return position of functions.
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 1c268c8bbe0..fa76f8652ea 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2627,7 +2627,6 @@ impl<'hir> Ty<'hir> {
             }
             TyKind::Tup(tys) => tys.iter().any(Self::is_suggestable_infer_ty),
             TyKind::Ptr(mut_ty) | TyKind::Ref(_, mut_ty) => mut_ty.ty.is_suggestable_infer_ty(),
-            TyKind::OpaqueDef(_, generic_args) => are_suggestable_generic_args(generic_args),
             TyKind::Path(QPath::TypeRelative(ty, segment)) => {
                 ty.is_suggestable_infer_ty() || are_suggestable_generic_args(segment.args().args)
             }
@@ -2746,19 +2745,8 @@ pub struct BareFnTy<'hir> {
 pub struct OpaqueTy<'hir> {
     pub hir_id: HirId,
     pub def_id: LocalDefId,
-    pub generics: &'hir Generics<'hir>,
     pub bounds: GenericBounds<'hir>,
-    pub origin: OpaqueTyOrigin,
-    /// Return-position impl traits (and async futures) must "reify" any late-bound
-    /// lifetimes that are captured from the function signature they originate from.
-    ///
-    /// This is done by generating a new early-bound lifetime parameter local to the
-    /// opaque which is instantiated in the function signature with the late-bound
-    /// lifetime.
-    ///
-    /// This mapping associated a captured lifetime (first parameter) with the new
-    /// early-bound lifetime that was generated for the opaque.
-    pub lifetime_mapping: &'hir [(&'hir Lifetime, LocalDefId)],
+    pub origin: OpaqueTyOrigin<LocalDefId>,
     pub span: Span,
 }
 
@@ -2796,33 +2784,35 @@ pub struct PreciseCapturingNonLifetimeArg {
     pub res: Res,
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+#[derive(HashStable_Generic, Encodable, Decodable)]
 pub enum RpitContext {
     Trait,
     TraitImpl,
 }
 
 /// From whence the opaque type came.
-#[derive(Copy, Clone, PartialEq, Eq, Debug, HashStable_Generic)]
-pub enum OpaqueTyOrigin {
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+#[derive(HashStable_Generic, Encodable, Decodable)]
+pub enum OpaqueTyOrigin<D> {
     /// `-> impl Trait`
     FnReturn {
         /// The defining function.
-        parent: LocalDefId,
+        parent: D,
         // Whether this is an RPITIT (return position impl trait in trait)
         in_trait_or_impl: Option<RpitContext>,
     },
     /// `async fn`
     AsyncFn {
         /// The defining function.
-        parent: LocalDefId,
+        parent: D,
         // Whether this is an AFIT (async fn in trait)
         in_trait_or_impl: Option<RpitContext>,
     },
     /// type aliases: `type Foo = impl Trait;`
     TyAlias {
         /// The type alias or associated type parent of the TAIT/ATPIT
-        parent: LocalDefId,
+        parent: D,
         /// associated types in impl blocks for traits.
         in_assoc_ty: bool,
     },
@@ -2861,12 +2851,7 @@ pub enum TyKind<'hir> {
     /// Type parameters may be stored in each `PathSegment`.
     Path(QPath<'hir>),
     /// An opaque type definition itself. This is only used for `impl Trait`.
-    ///
-    /// The generic argument list contains the lifetimes (and in the future
-    /// possibly parameters) that are actually bound on the `impl Trait`.
-    ///
-    /// The last parameter specifies whether this opaque appears in a trait definition.
-    OpaqueDef(&'hir OpaqueTy<'hir>, &'hir [GenericArg<'hir>]),
+    OpaqueDef(&'hir OpaqueTy<'hir>),
     /// A trait object type `Bound1 + Bound2 + Bound3`
     /// where `Bound` is a trait or a lifetime.
     TraitObject(&'hir [PolyTraitRef<'hir>], &'hir Lifetime, TraitObjectSyntax),
@@ -3991,7 +3976,6 @@ impl<'hir> Node<'hir> {
             | Node::TraitItem(TraitItem { generics, .. })
             | Node::ImplItem(ImplItem { generics, .. }) => Some(generics),
             Node::Item(item) => item.kind.generics(),
-            Node::OpaqueTy(opaque) => Some(opaque.generics),
             _ => None,
         }
     }
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 322f8e2a517..a453af3f7fd 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -896,9 +896,8 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Resul
         TyKind::Path(ref qpath) => {
             try_visit!(visitor.visit_qpath(qpath, typ.hir_id, typ.span));
         }
-        TyKind::OpaqueDef(opaque, lifetimes) => {
+        TyKind::OpaqueDef(opaque) => {
             try_visit!(visitor.visit_opaque_ty(opaque));
-            walk_list!(visitor, visit_generic_arg, lifetimes);
         }
         TyKind::Array(ref ty, ref length) => {
             try_visit!(visitor.visit_ty(ty));
@@ -1188,10 +1187,8 @@ pub fn walk_poly_trait_ref<'v, V: Visitor<'v>>(
 }
 
 pub fn walk_opaque_ty<'v, V: Visitor<'v>>(visitor: &mut V, opaque: &'v OpaqueTy<'v>) -> V::Result {
-    let &OpaqueTy { hir_id, def_id: _, generics, bounds, origin: _, lifetime_mapping: _, span: _ } =
-        opaque;
+    let &OpaqueTy { hir_id, def_id: _, bounds, origin: _, span: _ } = opaque;
     try_visit!(visitor.visit_id(hir_id));
-    try_visit!(walk_generics(visitor, generics));
     walk_list!(visitor, visit_param_bound, bounds);
     V::Result::output()
 }
diff --git a/compiler/rustc_hir_analysis/Cargo.toml b/compiler/rustc_hir_analysis/Cargo.toml
index 04ca7f123d3..3c8887f08bc 100644
--- a/compiler/rustc_hir_analysis/Cargo.toml
+++ b/compiler/rustc_hir_analysis/Cargo.toml
@@ -10,6 +10,7 @@ doctest = false
 [dependencies]
 # tidy-alphabetical-start
 itertools = "0.12"
+rustc_abi = { path = "../rustc_abi" }
 rustc_arena = { path = "../rustc_arena" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_attr = { path = "../rustc_attr" }
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 507297ce162..38b11aa4017 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -149,10 +149,6 @@ hir_analysis_drop_impl_reservation = reservation `Drop` impls are not supported
 hir_analysis_duplicate_precise_capture = cannot capture parameter `{$name}` twice
     .label = parameter captured again here
 
-hir_analysis_effects_without_next_solver = using `#![feature(effects)]` without enabling next trait solver globally
-    .note = the next trait solver must be enabled globally for the effects feature to work correctly
-    .help = use `-Znext-solver` to enable
-
 hir_analysis_empty_specialization = specialization impl does not specialize any associated items
     .note = impl is a specialization of this impl
 
@@ -238,6 +234,12 @@ hir_analysis_inherent_ty_outside_relevant = cannot define inherent `impl` for a
     .help = consider moving this inherent impl into the crate defining the type if possible
     .span_help = alternatively add `#[rustc_allow_incoherent_impl]` to the relevant impl items
 
+hir_analysis_invalid_generic_receiver_ty = invalid generic `self` parameter type: `{$receiver_ty}`
+    .note = type of `self` must not be a method generic parameter type
+
+hir_analysis_invalid_generic_receiver_ty_help =
+    use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
 hir_analysis_invalid_receiver_ty = invalid `self` parameter type: `{$receiver_ty}`
     .note = type of `self` must be `Self` or a type that dereferences to it
 
diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs
index 09ddc6ca9de..9b02651a8bd 100644
--- a/compiler/rustc_hir_analysis/src/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/bounds.rs
@@ -84,11 +84,11 @@ impl<'tcx> Bounds<'tcx> {
         &mut self,
         tcx: TyCtxt<'tcx>,
         bound_trait_ref: ty::PolyTraitRef<'tcx>,
-        host: ty::HostPolarity,
+        constness: ty::BoundConstness,
         span: Span,
     ) {
         if tcx.is_const_trait(bound_trait_ref.def_id()) {
-            self.clauses.push((bound_trait_ref.to_host_effect_clause(tcx, host), span));
+            self.clauses.push((bound_trait_ref.to_host_effect_clause(tcx, constness), span));
         } else {
             tcx.dcx().span_delayed_bug(span, "tried to lower {host:?} bound for non-const trait");
         }
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 97f3f1c8ef2..476814c261e 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -1,6 +1,7 @@
 use std::cell::LazyCell;
 use std::ops::ControlFlow;
 
+use rustc_abi::FieldIdx;
 use rustc_data_structures::unord::{UnordMap, UnordSet};
 use rustc_errors::MultiSpan;
 use rustc_errors::codes::*;
@@ -23,13 +24,13 @@ use rustc_middle::ty::{
     TypeVisitableExt,
 };
 use rustc_session::lint::builtin::UNINHABITED_STATIC;
-use rustc_target::abi::FieldIdx;
 use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::error_reporting::traits::on_unimplemented::OnUnimplementedDirective;
 use rustc_trait_selection::traits;
 use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
 use rustc_type_ir::fold::TypeFoldable;
 use tracing::{debug, instrument};
+use ty::TypingMode;
 use {rustc_attr as attr, rustc_hir as hir};
 
 use super::compare_impl_item::{check_type_bounds, compare_impl_method, compare_impl_ty};
@@ -172,7 +173,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
             return;
         }
     };
-    if layout.abi.is_uninhabited() {
+    if layout.is_uninhabited() {
         tcx.node_span_lint(
             UNINHABITED_STATIC,
             tcx.local_def_id_to_hir_id(def_id),
@@ -267,7 +268,7 @@ fn check_opaque_meets_bounds<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: LocalDefId,
     span: Span,
-    origin: &hir::OpaqueTyOrigin,
+    origin: &hir::OpaqueTyOrigin<LocalDefId>,
 ) -> Result<(), ErrorGuaranteed> {
     let defining_use_anchor = match *origin {
         hir::OpaqueTyOrigin::FnReturn { parent, .. }
@@ -276,7 +277,8 @@ fn check_opaque_meets_bounds<'tcx>(
     };
     let param_env = tcx.param_env(defining_use_anchor);
 
-    let infcx = tcx.infer_ctxt().with_opaque_type_inference(defining_use_anchor).build();
+    // FIXME(#132279): This should eventually use the already defined hidden types.
+    let infcx = tcx.infer_ctxt().build(TypingMode::analysis_in_body(tcx, defining_use_anchor));
     let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
 
     let args = match *origin {
@@ -675,7 +677,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
         DefKind::OpaqueTy => {
             check_opaque_precise_captures(tcx, def_id);
 
-            let origin = tcx.opaque_type_origin(def_id);
+            let origin = tcx.local_opaque_ty_origin(def_id);
             if let hir::OpaqueTyOrigin::FnReturn { parent: fn_def_id, .. }
             | hir::OpaqueTyOrigin::AsyncFn { parent: fn_def_id, .. } = origin
                 && let hir::Node::TraitItem(trait_item) = tcx.hir_node_by_def_id(fn_def_id)
@@ -819,8 +821,7 @@ pub(super) fn check_specialization_validity<'tcx>(
     let result = opt_result.unwrap_or(Ok(()));
 
     if let Err(parent_impl) = result {
-        // FIXME(effects) the associated type from effects could be specialized
-        if !tcx.is_impl_trait_in_trait(impl_item) && !tcx.is_effects_desugared_assoc_ty(impl_item) {
+        if !tcx.is_impl_trait_in_trait(impl_item) {
             report_forbidden_specialization(tcx, impl_item, parent_impl);
         } else {
             tcx.dcx().delayed_bug(format!("parent item: {parent_impl:?} not marked as default"));
@@ -1675,8 +1676,8 @@ pub(super) fn check_coroutine_obligations(
         // typeck writeback gives us predicates with their regions erased.
         // As borrowck already has checked lifetimes, we do not need to do it again.
         .ignoring_regions()
-        .with_opaque_type_inference(def_id)
-        .build();
+        // FIXME(#132279): This should eventually use the already defined hidden types.
+        .build(TypingMode::analysis_in_body(tcx, def_id));
 
     let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
     for (predicate, cause) in &typeck_results.coroutine_stalled_predicates {
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 9de96b7ba77..0b7d3f8b085 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -17,7 +17,7 @@ use rustc_middle::ty::fold::BottomUpFolder;
 use rustc_middle::ty::util::ExplicitSelf;
 use rustc_middle::ty::{
     self, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, TypeFolder,
-    TypeSuperFoldable, TypeVisitableExt, Upcast,
+    TypeSuperFoldable, TypeVisitableExt, TypingMode, Upcast,
 };
 use rustc_middle::{bug, span_bug};
 use rustc_span::Span;
@@ -218,7 +218,7 @@ fn compare_method_predicate_entailment<'tcx>(
                     tcx.const_conditions(trait_m.def_id).instantiate_own(tcx, trait_to_impl_args),
                 )
                 .map(|(trait_ref, _)| {
-                    trait_ref.to_host_effect_clause(tcx, ty::HostPolarity::Maybe)
+                    trait_ref.to_host_effect_clause(tcx, ty::BoundConstness::Maybe)
                 }),
         );
     }
@@ -228,7 +228,7 @@ fn compare_method_predicate_entailment<'tcx>(
     let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
     debug!(caller_bounds=?param_env.caller_bounds());
 
-    let infcx = &tcx.infer_ctxt().build();
+    let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
     let ocx = ObligationCtxt::new_with_diagnostics(infcx);
 
     // Create obligations for each predicate declared by the impl
@@ -272,7 +272,7 @@ fn compare_method_predicate_entailment<'tcx>(
                 tcx,
                 cause,
                 param_env,
-                const_condition.to_host_effect_clause(tcx, ty::HostPolarity::Maybe),
+                const_condition.to_host_effect_clause(tcx, ty::BoundConstness::Maybe),
             ));
         }
     }
@@ -516,7 +516,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
         ObligationCause::misc(tcx.def_span(impl_m_def_id), impl_m_def_id),
     );
 
-    let infcx = &tcx.infer_ctxt().build();
+    let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
     let ocx = ObligationCtxt::new_with_diagnostics(infcx);
 
     // Normalize the impl signature with fresh variables for lifetime inference.
@@ -1196,7 +1196,7 @@ fn compare_self_type<'tcx>(
         let self_arg_ty = tcx.fn_sig(method.def_id).instantiate_identity().input(0);
         let param_env = ty::ParamEnv::reveal_all();
 
-        let infcx = tcx.infer_ctxt().build();
+        let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
         let self_arg_ty = tcx.liberate_late_bound_regions(method.def_id, self_arg_ty);
         let can_eq_self = |ty| infcx.can_eq(param_env, untransformed_self_ty, ty);
         match ExplicitSelf::determine(self_arg_ty, can_eq_self) {
@@ -1801,7 +1801,7 @@ fn compare_const_predicate_entailment<'tcx>(
         ObligationCause::misc(impl_ct_span, impl_ct_def_id),
     );
 
-    let infcx = tcx.infer_ctxt().build();
+    let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
     let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
 
     let impl_ct_own_bounds = impl_ct_predicates.instantiate_own_identity();
@@ -1942,7 +1942,7 @@ fn compare_type_predicate_entailment<'tcx>(
                     tcx.const_conditions(trait_ty.def_id).instantiate_own(tcx, trait_to_impl_args),
                 )
                 .map(|(trait_ref, _)| {
-                    trait_ref.to_host_effect_clause(tcx, ty::HostPolarity::Maybe)
+                    trait_ref.to_host_effect_clause(tcx, ty::BoundConstness::Maybe)
                 }),
         );
     }
@@ -1951,7 +1951,7 @@ fn compare_type_predicate_entailment<'tcx>(
     let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
     debug!(caller_bounds=?param_env.caller_bounds());
 
-    let infcx = tcx.infer_ctxt().build();
+    let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
     let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
 
     for (predicate, span) in impl_ty_own_bounds {
@@ -1985,7 +1985,7 @@ fn compare_type_predicate_entailment<'tcx>(
                 tcx,
                 cause,
                 param_env,
-                const_condition.to_host_effect_clause(tcx, ty::HostPolarity::Maybe),
+                const_condition.to_host_effect_clause(tcx, ty::BoundConstness::Maybe),
             ));
         }
     }
@@ -2036,13 +2036,13 @@ pub(super) fn check_type_bounds<'tcx>(
     let impl_ty_args = GenericArgs::identity_for_item(tcx, impl_ty.def_id);
     let rebased_args = impl_ty_args.rebase_onto(tcx, container_id, impl_trait_ref.args);
 
-    let infcx = tcx.infer_ctxt().build();
+    let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
     let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
 
     // A synthetic impl Trait for RPITIT desugaring or assoc type for effects desugaring has no HIR,
     // which we currently use to get the span for an impl's associated type. Instead, for these,
     // use the def_span for the synthesized  associated type.
-    let impl_ty_span = if impl_ty.is_impl_trait_in_trait() || impl_ty.is_effects_desugaring {
+    let impl_ty_span = if impl_ty.is_impl_trait_in_trait() {
         tcx.def_span(impl_ty_def_id)
     } else {
         match tcx.hir_node_by_def_id(impl_ty_def_id) {
@@ -2091,7 +2091,7 @@ pub(super) fn check_type_bounds<'tcx>(
                         tcx,
                         mk_cause(span),
                         param_env,
-                        c.to_host_effect_clause(tcx, ty::HostPolarity::Maybe),
+                        c.to_host_effect_clause(tcx, ty::BoundConstness::Maybe),
                     )
                 }),
         );
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 2d6b9813271..646c104f1f5 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
@@ -8,7 +8,7 @@ use rustc_middle::span_bug;
 use rustc_middle::traits::{ObligationCause, Reveal};
 use rustc_middle::ty::{
     self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperVisitable, TypeVisitable,
-    TypeVisitableExt, TypeVisitor,
+    TypeVisitableExt, TypeVisitor, TypingMode,
 };
 use rustc_span::Span;
 use rustc_trait_selection::regions::InferCtxtRegionExt;
@@ -132,7 +132,7 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
     let param_env = ty::ParamEnv::new(tcx.mk_clauses_from_iter(hybrid_preds), Reveal::UserFacing);
     let param_env = normalize_param_env_or_error(tcx, param_env, ObligationCause::dummy());
 
-    let ref infcx = tcx.infer_ctxt().build();
+    let ref infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
     let ocx = ObligationCtxt::new(infcx);
 
     // Normalize the bounds. This has two purposes:
diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs
index 97a29b32c01..1c9bbe627fb 100644
--- a/compiler/rustc_hir_analysis/src/check/dropck.rs
+++ b/compiler/rustc_hir_analysis/src/check/dropck.rs
@@ -9,7 +9,7 @@ use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
 use rustc_infer::traits::{ObligationCause, ObligationCauseCode};
 use rustc_middle::ty::util::CheckRegions;
-use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt};
+use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypingMode};
 use rustc_trait_selection::regions::InferCtxtRegionExt;
 use rustc_trait_selection::traits::{self, ObligationCtxt};
 
@@ -124,7 +124,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
     adt_def_id: LocalDefId,
     adt_to_impl_args: GenericArgsRef<'tcx>,
 ) -> Result<(), ErrorGuaranteed> {
-    let infcx = tcx.infer_ctxt().build();
+    let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
     let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
 
     let impl_span = tcx.def_span(drop_impl_def_id.to_def_id());
diff --git a/compiler/rustc_hir_analysis/src/check/entry.rs b/compiler/rustc_hir_analysis/src/check/entry.rs
index 7da2cd93d4e..0beb1f98d56 100644
--- a/compiler/rustc_hir_analysis/src/check/entry.rs
+++ b/compiler/rustc_hir_analysis/src/check/entry.rs
@@ -4,7 +4,7 @@ use rustc_hir as hir;
 use rustc_hir::Node;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::span_bug;
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypingMode};
 use rustc_session::config::EntryFnType;
 use rustc_span::Span;
 use rustc_span::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
@@ -128,7 +128,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
             tcx.dcx().emit_err(errors::MainFunctionReturnTypeGeneric { span: return_ty_span });
             return;
         };
-        let infcx = tcx.infer_ctxt().build();
+        let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
         let cause = traits::ObligationCause::new(
             return_ty_span,
             main_diagnostics_def_id,
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
index bbff00cd3b3..e95669c9d40 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
@@ -1,5 +1,6 @@
 use std::assert_matches::debug_assert_matches;
 
+use rustc_abi::FieldIdx;
 use rustc_ast::InlineAsmTemplatePiece;
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir::{self as hir, LangItem};
@@ -8,7 +9,6 @@ use rustc_middle::ty::{self, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintT
 use rustc_session::lint;
 use rustc_span::Symbol;
 use rustc_span::def_id::LocalDefId;
-use rustc_target::abi::FieldIdx;
 use rustc_target::asm::{
     InlineAsmReg, InlineAsmRegClass, InlineAsmRegOrRegClass, InlineAsmType, ModifierInfo,
 };
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 58210aaa066..e9eea36a0e6 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -74,6 +74,7 @@ pub mod wfcheck;
 use std::num::NonZero;
 
 pub use check::{check_abi, check_abi_fn_ptr};
+use rustc_abi::VariantIdx;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_errors::{Diag, ErrorGuaranteed, pluralize, struct_span_code_err};
 use rustc_hir::def_id::{DefId, LocalDefId};
@@ -84,13 +85,12 @@ use rustc_infer::infer::{self, TyCtxtInferExt as _};
 use rustc_infer::traits::ObligationCause;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
-use rustc_middle::ty::{self, GenericArgs, GenericArgsRef, Ty, TyCtxt};
+use rustc_middle::ty::{self, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypingMode};
 use rustc_middle::{bug, span_bug};
 use rustc_session::parse::feature_err;
 use rustc_span::def_id::CRATE_DEF_ID;
 use rustc_span::symbol::{Ident, kw, sym};
 use rustc_span::{BytePos, DUMMY_SP, Span, Symbol};
-use rustc_target::abi::VariantIdx;
 use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::error_reporting::infer::ObligationCauseExt as _;
@@ -530,7 +530,7 @@ fn suggestion_signature<'tcx>(
             let ty = tcx.type_of(assoc.def_id).instantiate_identity();
             let val = tcx
                 .infer_ctxt()
-                .build()
+                .build(TypingMode::non_body_analysis())
                 .err_ctxt()
                 .ty_kind_suggestion(tcx.param_env(assoc.def_id), ty)
                 .unwrap_or_else(|| "value".to_string());
@@ -620,7 +620,7 @@ pub fn check_function_signature<'tcx>(
 
     let param_env = ty::ParamEnv::empty();
 
-    let infcx = &tcx.infer_ctxt().build();
+    let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
     let ocx = ObligationCtxt::new_with_diagnostics(infcx);
 
     let actual_sig = tcx.fn_sig(fn_id).instantiate_identity();
diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs
index bfa088fdefc..679f6ccb816 100644
--- a/compiler/rustc_hir_analysis/src/check/region.rs
+++ b/compiler/rustc_hir_analysis/src/check/region.rs
@@ -464,8 +464,7 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
 
         hir::ExprKind::If(cond, then, Some(otherwise)) => {
             let expr_cx = visitor.cx;
-            let data = if expr.span.at_least_rust_2024() && visitor.tcx.features().if_let_rescope()
-            {
+            let data = if expr.span.at_least_rust_2024() {
                 ScopeData::IfThenRescope
             } else {
                 ScopeData::IfThen
@@ -480,8 +479,7 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
 
         hir::ExprKind::If(cond, then, None) => {
             let expr_cx = visitor.cx;
-            let data = if expr.span.at_least_rust_2024() && visitor.tcx.features().if_let_rescope()
-            {
+            let data = if expr.span.at_least_rust_2024() {
                 ScopeData::IfThenRescope
             } else {
                 ScopeData::IfThen
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 499e42d31c9..d01c3784ade 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -17,7 +17,7 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::trait_def::TraitSpecializationKind;
 use rustc_middle::ty::{
     self, AdtKind, GenericArgKind, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFoldable,
-    TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, Upcast,
+    TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Upcast,
 };
 use rustc_middle::{bug, span_bug};
 use rustc_session::parse::feature_err;
@@ -106,7 +106,7 @@ where
     F: for<'a> FnOnce(&WfCheckingCtxt<'a, 'tcx>) -> Result<(), ErrorGuaranteed>,
 {
     let param_env = tcx.param_env(body_def_id);
-    let infcx = &tcx.infer_ctxt().build();
+    let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
     let ocx = ObligationCtxt::new_with_diagnostics(infcx);
 
     let mut wfcx = WfCheckingCtxt { ocx, span, body_def_id, param_env };
@@ -765,7 +765,7 @@ fn test_region_obligations<'tcx>(
     // Unfortunately, we have to use a new `InferCtxt` each call, because
     // region constraints get added and solved there and we need to test each
     // call individually.
-    let infcx = tcx.infer_ctxt().build();
+    let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
 
     add_constraints(&infcx);
 
@@ -904,7 +904,6 @@ fn check_impl_item<'tcx>(
         hir::ImplItemKind::Type(ty) if ty.span != DUMMY_SP => (None, ty.span),
         _ => (None, impl_item.span),
     };
-
     check_associated_item(tcx, impl_item.owner_id.def_id, span, method_sig)
 }
 
@@ -1389,7 +1388,7 @@ fn check_impl<'tcx>(
                                 ObligationCauseCode::WellFormed(None),
                             ),
                             wfcx.param_env,
-                            bound.to_host_effect_clause(tcx, ty::HostPolarity::Maybe),
+                            bound.to_host_effect_clause(tcx, ty::BoundConstness::Maybe),
                         ))
                     }
                 }
@@ -1725,8 +1724,11 @@ fn check_method_receiver<'tcx>(
     } else {
         None
     };
+    let generics = tcx.generics_of(method.def_id);
 
-    if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, arbitrary_self_types_level) {
+    let receiver_validity =
+        receiver_is_valid(wfcx, span, receiver_ty, self_ty, arbitrary_self_types_level, generics);
+    if let Err(receiver_validity_err) = receiver_validity {
         return Err(match arbitrary_self_types_level {
             // Wherever possible, emit a message advising folks that the features
             // `arbitrary_self_types` or `arbitrary_self_types_pointers` might
@@ -1737,7 +1739,9 @@ fn check_method_receiver<'tcx>(
                 receiver_ty,
                 self_ty,
                 Some(ArbitrarySelfTypesLevel::Basic),
-            ) =>
+                generics,
+            )
+            .is_ok() =>
             {
                 // Report error; would have worked with `arbitrary_self_types`.
                 feature_err(
@@ -1759,7 +1763,9 @@ fn check_method_receiver<'tcx>(
                     receiver_ty,
                     self_ty,
                     Some(ArbitrarySelfTypesLevel::WithPointers),
-                ) =>
+                    generics,
+                )
+                .is_ok() =>
             {
                 // Report error; would have worked with `arbitrary_self_types_pointers`.
                 feature_err(
@@ -1777,13 +1783,45 @@ fn check_method_receiver<'tcx>(
             _ =>
             // Report error; would not have worked with `arbitrary_self_types[_pointers]`.
             {
-                tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty })
+                match receiver_validity_err {
+                    ReceiverValidityError::DoesNotDeref => {
+                        tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty })
+                    }
+                    ReceiverValidityError::MethodGenericParamUsed => {
+                        tcx.dcx().emit_err(errors::InvalidGenericReceiverTy { span, receiver_ty })
+                    }
+                }
             }
         });
     }
     Ok(())
 }
 
+/// Error cases which may be returned from `receiver_is_valid`. These error
+/// cases are generated in this function as they may be unearthed as we explore
+/// the `autoderef` chain, but they're converted to diagnostics in the caller.
+enum ReceiverValidityError {
+    /// The self type does not get to the receiver type by following the
+    /// autoderef chain.
+    DoesNotDeref,
+    /// A type was found which is a method type parameter, and that's not allowed.
+    MethodGenericParamUsed,
+}
+
+/// Confirms that a type is not a type parameter referring to one of the
+/// method's type params.
+fn confirm_type_is_not_a_method_generic_param(
+    ty: Ty<'_>,
+    method_generics: &ty::Generics,
+) -> Result<(), ReceiverValidityError> {
+    if let ty::Param(param) = ty.kind() {
+        if (param.index as usize) >= method_generics.parent_count {
+            return Err(ReceiverValidityError::MethodGenericParamUsed);
+        }
+    }
+    Ok(())
+}
+
 /// Returns whether `receiver_ty` would be considered a valid receiver type for `self_ty`. If
 /// `arbitrary_self_types` is enabled, `receiver_ty` must transitively deref to `self_ty`, possibly
 /// through a `*const/mut T` raw pointer if  `arbitrary_self_types_pointers` is also enabled.
@@ -1799,7 +1837,8 @@ fn receiver_is_valid<'tcx>(
     receiver_ty: Ty<'tcx>,
     self_ty: Ty<'tcx>,
     arbitrary_self_types_enabled: Option<ArbitrarySelfTypesLevel>,
-) -> bool {
+    method_generics: &ty::Generics,
+) -> Result<(), ReceiverValidityError> {
     let infcx = wfcx.infcx;
     let tcx = wfcx.tcx();
     let cause =
@@ -1811,9 +1850,11 @@ fn receiver_is_valid<'tcx>(
         ocx.eq(&cause, wfcx.param_env, self_ty, receiver_ty)?;
         if ocx.select_all_or_error().is_empty() { Ok(()) } else { Err(NoSolution) }
     }) {
-        return true;
+        return Ok(());
     }
 
+    confirm_type_is_not_a_method_generic_param(receiver_ty, method_generics)?;
+
     let mut autoderef = Autoderef::new(infcx, wfcx.param_env, wfcx.body_def_id, span, receiver_ty);
 
     // The `arbitrary_self_types_pointers` feature allows raw pointer receivers like `self: *const Self`.
@@ -1830,6 +1871,8 @@ fn receiver_is_valid<'tcx>(
             potential_self_ty, self_ty
         );
 
+        confirm_type_is_not_a_method_generic_param(potential_self_ty, method_generics)?;
+
         // Check if the self type unifies. If it does, then commit the result
         // since it may have region side-effects.
         if let Ok(()) = wfcx.infcx.commit_if_ok(|_| {
@@ -1838,7 +1881,7 @@ fn receiver_is_valid<'tcx>(
             if ocx.select_all_or_error().is_empty() { Ok(()) } else { Err(NoSolution) }
         }) {
             wfcx.register_obligations(autoderef.into_obligations());
-            return true;
+            return Ok(());
         }
 
         // Without `feature(arbitrary_self_types)`, we require that each step in the
@@ -1865,7 +1908,7 @@ fn receiver_is_valid<'tcx>(
     }
 
     debug!("receiver_is_valid: type `{:?}` does not deref to `{:?}`", receiver_ty, self_ty);
-    false
+    Err(ReceiverValidityError::DoesNotDeref)
 }
 
 fn receiver_is_implemented<'tcx>(
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index b4f6b5a9dd2..5ff52376837 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -15,7 +15,9 @@ use rustc_infer::infer::{self, RegionResolutionError, TyCtxtInferExt};
 use rustc_infer::traits::Obligation;
 use rustc_middle::ty::adjustment::CoerceUnsizedInfo;
 use rustc_middle::ty::print::PrintTraitRefExt as _;
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, suggest_constraining_type_params};
+use rustc_middle::ty::{
+    self, Ty, TyCtxt, TypeVisitableExt, TypingMode, suggest_constraining_type_params,
+};
 use rustc_span::{DUMMY_SP, Span};
 use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::traits::misc::{
@@ -213,7 +215,7 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
 
     let param_env = tcx.param_env(impl_did);
 
-    let infcx = tcx.infer_ctxt().build();
+    let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
     let cause = ObligationCause::misc(span, impl_did);
 
     // Later parts of the compiler rely on all DispatchFromDyn types to be ABI-compatible with raw
@@ -354,7 +356,7 @@ pub(crate) fn coerce_unsized_info<'tcx>(
 
     debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (free)", source, target);
 
-    let infcx = tcx.infer_ctxt().build();
+    let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
     let cause = ObligationCause::misc(span, impl_did);
     let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>,
                        mt_b: ty::TypeAndMut<'tcx>,
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index 04770469132..8a1a887766c 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -7,7 +7,7 @@ use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_lint_defs::builtin::UNCOVERED_PARAM_IN_PROJECTION;
 use rustc_middle::ty::{
     self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable,
-    TypeVisitable, TypeVisitableExt, TypeVisitor,
+    TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode,
 };
 use rustc_middle::{bug, span_bug};
 use rustc_span::def_id::{DefId, LocalDefId};
@@ -302,7 +302,7 @@ fn orphan_check<'tcx>(
     }
 
     // (1)  Instantiate all generic params with fresh inference vars.
-    let infcx = tcx.infer_ctxt().intercrate(true).build();
+    let infcx = tcx.infer_ctxt().build(TypingMode::Coherence);
     let cause = traits::ObligationCause::dummy();
     let args = infcx.fresh_args_for_item(cause.span, impl_def_id.to_def_id());
     let trait_ref = trait_ref.instantiate(tcx, args);
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 3add801cf56..3f6198dbd31 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -34,7 +34,7 @@ use rustc_infer::traits::ObligationCause;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::util::{Discr, IntTypeExt};
-use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, Ty, TyCtxt};
+use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, Ty, TyCtxt, TypingMode};
 use rustc_middle::{bug, span_bug};
 use rustc_span::symbol::{Ident, Symbol, kw, sym};
 use rustc_span::{DUMMY_SP, Span};
@@ -86,7 +86,7 @@ pub fn provide(providers: &mut Providers) {
         impl_trait_header,
         coroutine_kind,
         coroutine_for_closure,
-        is_type_alias_impl_trait,
+        opaque_ty_origin,
         rendered_precise_capturing_args,
         ..*providers
     };
@@ -1302,7 +1302,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
     }
 }
 
-#[instrument(level = "debug", skip(tcx))]
+#[instrument(level = "debug", skip(tcx), ret)]
 fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFnSig<'_>> {
     use rustc_hir::Node::*;
     use rustc_hir::*;
@@ -1438,9 +1438,11 @@ fn infer_return_ty_for_fn_sig<'tcx>(
                     Applicability::MachineApplicable,
                 );
                 recovered_ret_ty = Some(suggestable_ret_ty);
-            } else if let Some(sugg) =
-                suggest_impl_trait(&tcx.infer_ctxt().build(), tcx.param_env(def_id), ret_ty)
-            {
+            } else if let Some(sugg) = suggest_impl_trait(
+                &tcx.infer_ctxt().build(TypingMode::non_body_analysis()),
+                tcx.param_env(def_id),
+                ret_ty,
+            ) {
                 diag.span_suggestion(
                     ty.span,
                     "replace with an appropriate return type",
@@ -1757,9 +1759,18 @@ fn coroutine_for_closure(tcx: TyCtxt<'_>, def_id: LocalDefId) -> DefId {
     def_id.to_def_id()
 }
 
-fn is_type_alias_impl_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool {
-    let opaque = tcx.hir().expect_opaque_ty(def_id);
-    matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias { .. })
+fn opaque_ty_origin<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> hir::OpaqueTyOrigin<DefId> {
+    match tcx.hir_node_by_def_id(def_id).expect_opaque_ty().origin {
+        hir::OpaqueTyOrigin::FnReturn { parent, in_trait_or_impl } => {
+            hir::OpaqueTyOrigin::FnReturn { parent: parent.to_def_id(), in_trait_or_impl }
+        }
+        hir::OpaqueTyOrigin::AsyncFn { parent, in_trait_or_impl } => {
+            hir::OpaqueTyOrigin::AsyncFn { parent: parent.to_def_id(), in_trait_or_impl }
+        }
+        hir::OpaqueTyOrigin::TyAlias { parent, in_assoc_ty } => {
+            hir::OpaqueTyOrigin::TyAlias { parent: parent.to_def_id(), in_assoc_ty }
+        }
+    }
 }
 
 fn rendered_precise_capturing_args<'tcx>(
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index 3eec0e12665..c31bff28fd3 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -426,6 +426,21 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
         });
     }
 
+    if let Node::OpaqueTy(&hir::OpaqueTy { .. }) = node {
+        assert!(own_params.is_empty());
+
+        let lifetimes = tcx.opaque_captured_lifetimes(def_id);
+        debug!(?lifetimes);
+
+        own_params.extend(lifetimes.iter().map(|&(_, param)| ty::GenericParamDef {
+            name: tcx.item_name(param.to_def_id()),
+            index: next_index(),
+            def_id: param.to_def_id(),
+            pure_wrt_drop: false,
+            kind: ty::GenericParamDefKind::Lifetime,
+        }))
+    }
+
     let param_def_id_to_index =
         own_params.iter().map(|param| (param.def_id, param.index)).collect();
 
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index b2ad42be6c7..da779a16569 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -367,20 +367,8 @@ pub(super) fn explicit_item_bounds_with_filter(
         // a projection self type.
         Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
             let opaque_ty = tcx.hir_node_by_def_id(opaque_def_id.expect_local()).expect_opaque_ty();
-            let item_ty = Ty::new_projection_from_args(
-                tcx,
-                def_id.to_def_id(),
-                ty::GenericArgs::identity_for_item(tcx, def_id),
-            );
-            let bounds = opaque_type_bounds(
-                tcx,
-                opaque_def_id.expect_local(),
-                opaque_ty.bounds,
-                item_ty,
-                opaque_ty.span,
-                filter,
-            );
-            assert_only_contains_predicates_from(filter, bounds, item_ty);
+            let bounds =
+                associated_type_bounds(tcx, def_id, opaque_ty.bounds, opaque_ty.span, filter);
             return ty::EarlyBinder::bind(bounds);
         }
         Some(ty::ImplTraitInTraitData::Impl { .. }) => span_bug!(
@@ -391,9 +379,6 @@ pub(super) fn explicit_item_bounds_with_filter(
     }
 
     let bounds = match tcx.hir_node_by_def_id(def_id) {
-        _ if tcx.is_effects_desugared_assoc_ty(def_id.to_def_id()) => {
-            associated_type_bounds(tcx, def_id, &[], tcx.def_span(def_id), filter)
-        }
         hir::Node::TraitItem(hir::TraitItem {
             kind: hir::TraitItemKind::Type(bounds, _),
             span,
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 644ff0c667c..efe84e0006f 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -329,13 +329,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
     // We create bi-directional Outlives predicates between the original
     // and the duplicated parameter, to ensure that they do not get out of sync.
     if let Node::OpaqueTy(..) = node {
-        let opaque_ty_node = tcx.parent_hir_node(hir_id);
-        let Node::Ty(&hir::Ty { kind: TyKind::OpaqueDef(_, lifetimes), .. }) = opaque_ty_node
-        else {
-            bug!("unexpected {opaque_ty_node:?}")
-        };
-        debug!(?lifetimes);
-
         compute_bidirectional_outlives_predicates(tcx, &generics.own_params, &mut predicates);
         debug!(?predicates);
     }
@@ -716,7 +709,7 @@ pub(super) fn assert_only_contains_predicates_from<'tcx>(
                 match clause.kind().skip_binder() {
                     ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
                         trait_ref: _,
-                        host: ty::HostPolarity::Maybe,
+                        constness: ty::BoundConstness::Maybe,
                     }) => {}
                     _ => {
                         bug!(
@@ -732,8 +725,8 @@ pub(super) fn assert_only_contains_predicates_from<'tcx>(
                 match clause.kind().skip_binder() {
                     ty::ClauseKind::HostEffect(pred) => {
                         assert_eq!(
-                            pred.host,
-                            ty::HostPolarity::Maybe,
+                            pred.constness,
+                            ty::BoundConstness::Maybe,
                             "expected `~const` predicate when computing `{filter:?}` \
                             implied bounds: {clause:?}",
                         );
@@ -764,6 +757,16 @@ pub(super) fn type_param_predicates<'tcx>(
     tcx: TyCtxt<'tcx>,
     (item_def_id, def_id, assoc_name): (LocalDefId, LocalDefId, Ident),
 ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
+    match tcx.opt_rpitit_info(item_def_id.to_def_id()) {
+        Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
+            return tcx.type_param_predicates((opaque_def_id.expect_local(), def_id, assoc_name));
+        }
+        Some(ty::ImplTraitInTraitData::Impl { .. }) => {
+            unreachable!("should not be lowering bounds on RPITIT in impl")
+        }
+        None => {}
+    }
+
     use rustc_hir::*;
     use rustc_middle::ty::Ty;
 
@@ -943,7 +946,7 @@ pub(super) fn const_conditions<'tcx>(
         bounds.push_const_bound(
             tcx,
             ty::Binder::dummy(ty::TraitRef::identity(tcx, def_id.to_def_id())),
-            ty::HostPolarity::Maybe,
+            ty::BoundConstness::Maybe,
             DUMMY_SP,
         );
 
@@ -963,7 +966,7 @@ pub(super) fn const_conditions<'tcx>(
                 clause.kind().map_bound(|clause| match clause {
                     ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
                         trait_ref,
-                        host: ty::HostPolarity::Maybe,
+                        constness: ty::BoundConstness::Maybe,
                     }) => trait_ref,
                     _ => bug!("converted {clause:?}"),
                 }),
@@ -1001,7 +1004,7 @@ pub(super) fn implied_const_bounds<'tcx>(
                 clause.kind().map_bound(|clause| match clause {
                     ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
                         trait_ref,
-                        host: ty::HostPolarity::Maybe,
+                        constness: ty::BoundConstness::Maybe,
                     }) => trait_ref,
                     _ => bug!("converted {clause:?}"),
                 }),
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index f7daef3e80c..9483439ae4e 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -6,12 +6,14 @@
 //! the types in HIR to identify late-bound lifetimes and assign their Debruijn indices. This file
 //! is also responsible for assigning their semantics to implicit lifetimes in trait objects.
 
-use core::ops::ControlFlow;
+use std::cell::RefCell;
 use std::fmt;
+use std::ops::ControlFlow;
 
 use rustc_ast::visit::walk_list;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_data_structures::sorted_map::SortedMap;
+use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit::{self, Visitor};
@@ -25,7 +27,7 @@ use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, TyCtxt, TypeSuperVisitable, TypeVisitor};
 use rustc_middle::{bug, span_bug};
 use rustc_span::Span;
-use rustc_span::def_id::{DefId, LocalDefId};
+use rustc_span::def_id::{DefId, LocalDefId, LocalDefIdMap};
 use rustc_span::symbol::{Ident, sym};
 use tracing::{debug, debug_span, instrument};
 
@@ -80,6 +82,9 @@ struct NamedVarMap {
     // - trait refs
     // - bound types (like `T` in `for<'a> T<'a>: Foo`)
     late_bound_vars: ItemLocalMap<Vec<ty::BoundVariableKind>>,
+
+    // List captured variables for each opaque type.
+    opaque_captured_lifetimes: LocalDefIdMap<Vec<(ResolvedArg, LocalDefId)>>,
 }
 
 struct BoundVarContext<'a, 'tcx> {
@@ -147,6 +152,23 @@ enum Scope<'a> {
         s: ScopeRef<'a>,
     },
 
+    /// Remap lifetimes that appear in opaque types to fresh lifetime parameters. Given:
+    /// `fn foo<'a>() -> impl MyTrait<'a> { ... }`
+    ///
+    /// HIR tells us that `'a` refer to the lifetime bound on `foo`.
+    /// However, typeck and borrowck for opaques work based on using a new generic type.
+    /// `type MyAnonTy<'b> = impl MyTrait<'b>;`
+    ///
+    /// This scope collects the mapping `'a -> 'b`.
+    Opaque {
+        /// The opaque type we are traversing.
+        def_id: LocalDefId,
+        /// Mapping from each captured lifetime `'a` to the duplicate generic parameter `'b`.
+        captures: &'a RefCell<FxIndexMap<ResolvedArg, LocalDefId>>,
+
+        s: ScopeRef<'a>,
+    },
+
     /// Disallows capturing late-bound vars from parent scopes.
     ///
     /// This is necessary for something like `for<T> [(); { /* references T */ }]:`,
@@ -192,6 +214,12 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
                 .field("where_bound_origin", where_bound_origin)
                 .field("s", &"..")
                 .finish(),
+            Scope::Opaque { captures, def_id, s: _ } => f
+                .debug_struct("Opaque")
+                .field("def_id", def_id)
+                .field("captures", &captures.borrow())
+                .field("s", &"..")
+                .finish(),
             Scope::Body { id, s: _ } => {
                 f.debug_struct("Body").field("id", id).field("s", &"..").finish()
             }
@@ -226,6 +254,12 @@ pub(crate) fn provide(providers: &mut Providers) {
         is_late_bound_map,
         object_lifetime_default,
         late_bound_vars_map: |tcx, id| &tcx.resolve_bound_vars(id).late_bound_vars,
+        opaque_captured_lifetimes: |tcx, id| {
+            &tcx.resolve_bound_vars(tcx.local_def_id_to_hir_id(id).owner)
+                .opaque_captured_lifetimes
+                .get(&id)
+                .map_or(&[][..], |x| &x[..])
+        },
 
         ..*providers
     };
@@ -236,8 +270,11 @@ pub(crate) fn provide(providers: &mut Providers) {
 /// `named_variable_map`, `is_late_bound_map`, etc.
 #[instrument(level = "debug", skip(tcx))]
 fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBoundVars {
-    let mut named_variable_map =
-        NamedVarMap { defs: Default::default(), late_bound_vars: Default::default() };
+    let mut named_variable_map = NamedVarMap {
+        defs: Default::default(),
+        late_bound_vars: Default::default(),
+        opaque_captured_lifetimes: Default::default(),
+    };
     let mut visitor = BoundVarContext {
         tcx,
         map: &mut named_variable_map,
@@ -264,13 +301,16 @@ fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBou
 
     let defs = named_variable_map.defs.into_sorted_stable_ord();
     let late_bound_vars = named_variable_map.late_bound_vars.into_sorted_stable_ord();
+    let opaque_captured_lifetimes = named_variable_map.opaque_captured_lifetimes;
     let rl = ResolveBoundVars {
         defs: SortedMap::from_presorted_elements(defs),
         late_bound_vars: SortedMap::from_presorted_elements(late_bound_vars),
+        opaque_captured_lifetimes,
     };
 
     debug!(?rl.defs);
     debug!(?rl.late_bound_vars);
+    debug!(?rl.opaque_captured_lifetimes);
     rl
 }
 
@@ -306,6 +346,26 @@ fn generic_param_def_as_bound_arg(param: &ty::GenericParamDef) -> ty::BoundVaria
     }
 }
 
+/// Whether this opaque always captures lifetimes in scope.
+/// Right now, this is all RPITIT and TAITs, and when `lifetime_capture_rules_2024`
+/// is enabled. We don't check the span of the edition, since this is done
+/// on a per-opaque basis to account for nested opaques.
+fn opaque_captures_all_in_scope_lifetimes<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    opaque: &'tcx hir::OpaqueTy<'tcx>,
+) -> bool {
+    match opaque.origin {
+        // if the opaque has the `use<...>` syntax, the user is telling us that they only want
+        // to account for those lifetimes, so do not try to be clever.
+        _ if opaque.bounds.iter().any(|bound| matches!(bound, hir::GenericBound::Use(..))) => false,
+        hir::OpaqueTyOrigin::AsyncFn { .. } | hir::OpaqueTyOrigin::TyAlias { .. } => true,
+        _ if tcx.features().lifetime_capture_rules_2024() || opaque.span.at_least_rust_2024() => {
+            true
+        }
+        hir::OpaqueTyOrigin::FnReturn { in_trait_or_impl, .. } => in_trait_or_impl.is_some(),
+    }
+}
+
 impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
     /// Returns the binders in scope and the type of `Binder` that should be created for a poly trait ref.
     fn poly_trait_ref_binder_info(&mut self) -> (Vec<ty::BoundVariableKind>, BinderScopeType) {
@@ -317,7 +377,9 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                     break (vec![], BinderScopeType::Normal);
                 }
 
-                Scope::ObjectLifetimeDefault { s, .. } | Scope::LateBoundary { s, .. } => {
+                Scope::Opaque { s, .. }
+                | Scope::ObjectLifetimeDefault { s, .. }
+                | Scope::LateBoundary { s, .. } => {
                     scope = s;
                 }
 
@@ -488,29 +550,85 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
         }
     }
 
+    /// Resolve the lifetimes inside the opaque type, and save them into
+    /// `opaque_captured_lifetimes`.
+    ///
+    /// This method has special handling for opaques that capture all lifetimes,
+    /// like async desugaring.
     #[instrument(level = "debug", skip(self))]
     fn visit_opaque_ty(&mut self, opaque: &'tcx rustc_hir::OpaqueTy<'tcx>) {
-        // We want to start our early-bound indices at the end of the parent scope,
-        // not including any parent `impl Trait`s.
-        let mut bound_vars = FxIndexMap::default();
-        debug!(?opaque.generics.params);
-        for param in opaque.generics.params {
-            let arg = ResolvedArg::early(param);
-            bound_vars.insert(param.def_id, arg);
+        let captures = RefCell::new(FxIndexMap::default());
+
+        let capture_all_in_scope_lifetimes =
+            opaque_captures_all_in_scope_lifetimes(self.tcx, opaque);
+        if capture_all_in_scope_lifetimes {
+            let lifetime_ident = |def_id: LocalDefId| {
+                let name = self.tcx.item_name(def_id.to_def_id());
+                let span = self.tcx.def_span(def_id);
+                Ident::new(name, span)
+            };
+
+            // We list scopes outwards, this causes us to see lifetime parameters in reverse
+            // declaration order. In order to make it consistent with what `generics_of` might
+            // give, we will reverse the IndexMap after early captures.
+            let mut scope = self.scope;
+            let mut opaque_capture_scopes = vec![(opaque.def_id, &captures)];
+            loop {
+                match *scope {
+                    Scope::Binder { ref bound_vars, s, .. } => {
+                        for (&original_lifetime, &def) in bound_vars.iter().rev() {
+                            if let DefKind::LifetimeParam = self.tcx.def_kind(original_lifetime) {
+                                let ident = lifetime_ident(original_lifetime);
+                                self.remap_opaque_captures(&opaque_capture_scopes, def, ident);
+                            }
+                        }
+                        scope = s;
+                    }
+
+                    Scope::Root { mut opt_parent_item } => {
+                        while let Some(parent_item) = opt_parent_item {
+                            let parent_generics = self.tcx.generics_of(parent_item);
+                            for param in parent_generics.own_params.iter().rev() {
+                                if let ty::GenericParamDefKind::Lifetime = param.kind {
+                                    let def = ResolvedArg::EarlyBound(param.def_id.expect_local());
+                                    let ident = lifetime_ident(param.def_id.expect_local());
+                                    self.remap_opaque_captures(&opaque_capture_scopes, def, ident);
+                                }
+                            }
+                            opt_parent_item = parent_generics.parent.and_then(DefId::as_local);
+                        }
+                        break;
+                    }
+
+                    Scope::Opaque { captures, def_id, s } => {
+                        opaque_capture_scopes.push((def_id, captures));
+                        scope = s;
+                    }
+
+                    Scope::Body { .. } => {
+                        bug!("{:?}", scope)
+                    }
+
+                    Scope::ObjectLifetimeDefault { s, .. }
+                    | Scope::Supertrait { s, .. }
+                    | Scope::TraitRefBoundary { s, .. }
+                    | Scope::LateBoundary { s, .. } => {
+                        scope = s;
+                    }
+                }
+            }
+            captures.borrow_mut().reverse();
         }
 
-        let hir_id = self.tcx.local_def_id_to_hir_id(opaque.def_id);
-        let scope = Scope::Binder {
-            hir_id,
-            bound_vars,
-            s: self.scope,
-            scope_type: BinderScopeType::Normal,
-            where_bound_origin: None,
-        };
+        let scope = Scope::Opaque { captures: &captures, def_id: opaque.def_id, s: self.scope };
         self.with(scope, |this| {
             let scope = Scope::TraitRefBoundary { s: this.scope };
             this.with(scope, |this| intravisit::walk_opaque_ty(this, opaque))
-        })
+        });
+
+        let captures = captures.into_inner().into_iter().collect();
+        debug!(?captures);
+        self.map.opaque_captured_lifetimes.insert(opaque.def_id, captures);
     }
 
     #[instrument(level = "debug", skip(self))]
@@ -685,67 +803,6 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
                 };
                 self.with(scope, |this| this.visit_ty(mt.ty));
             }
-            hir::TyKind::OpaqueDef(opaque_ty, lifetimes) => {
-                self.visit_opaque_ty(opaque_ty);
-
-                // Resolve the lifetimes in the bounds to the lifetime defs in the generics.
-                // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
-                // `type MyAnonTy<'b> = impl MyTrait<'b>;`
-                //                 ^                  ^ this gets resolved in the scope of
-                //                                      the opaque_ty generics
-
-                // Resolve the lifetimes that are applied to the opaque type.
-                // These are resolved in the current scope.
-                // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
-                // `fn foo<'a>() -> MyAnonTy<'a> { ... }`
-                //          ^                 ^this gets resolved in the current scope
-                for lifetime in lifetimes {
-                    let hir::GenericArg::Lifetime(lifetime) = lifetime else { continue };
-                    self.visit_lifetime(lifetime);
-
-                    // Check for predicates like `impl for<'a> Trait<impl OtherTrait<'a>>`
-                    // and ban them. Type variables instantiated inside binders aren't
-                    // well-supported at the moment, so this doesn't work.
-                    // In the future, this should be fixed and this error should be removed.
-                    let def = self.map.defs.get(&lifetime.hir_id.local_id).copied();
-                    let Some(ResolvedArg::LateBound(_, _, lifetime_def_id)) = def else { continue };
-                    let lifetime_hir_id = self.tcx.local_def_id_to_hir_id(lifetime_def_id);
-
-                    let bad_place = match self.tcx.hir_node(self.tcx.parent_hir_id(lifetime_hir_id))
-                    {
-                        // Opaques do not declare their own lifetimes, so if a lifetime comes from an opaque
-                        // it must be a reified late-bound lifetime from a trait goal.
-                        hir::Node::OpaqueTy(_) => "higher-ranked lifetime from outer `impl Trait`",
-                        // Other items are fine.
-                        hir::Node::Item(_) | hir::Node::TraitItem(_) | hir::Node::ImplItem(_) => {
-                            continue;
-                        }
-                        hir::Node::Ty(hir::Ty { kind: hir::TyKind::BareFn(_), .. }) => {
-                            "higher-ranked lifetime from function pointer"
-                        }
-                        hir::Node::Ty(hir::Ty { kind: hir::TyKind::TraitObject(..), .. }) => {
-                            "higher-ranked lifetime from `dyn` type"
-                        }
-                        _ => "higher-ranked lifetime",
-                    };
-
-                    let (span, label) = if lifetime.ident.span == self.tcx.def_span(lifetime_def_id)
-                    {
-                        (opaque_ty.span, Some(opaque_ty.span))
-                    } else {
-                        (lifetime.ident.span, None)
-                    };
-
-                    // Ensure that the parent of the def is an item, not HRTB
-                    self.tcx.dcx().emit_err(errors::OpaqueCapturesHigherRankedLifetime {
-                        span,
-                        label,
-                        decl_span: self.tcx.def_span(lifetime_def_id),
-                        bad_place,
-                    });
-                    self.uninsert_lifetime_on_error(lifetime, def.unwrap());
-                }
-            }
             _ => intravisit::walk_ty(self, ty),
         }
     }
@@ -1129,6 +1186,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
         let mut scope = self.scope;
         let mut outermost_body = None;
         let mut crossed_late_boundary = None;
+        let mut opaque_capture_scopes = vec![];
         let result = loop {
             match *scope {
                 Scope::Body { id, s } => {
@@ -1204,6 +1262,12 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                     scope = s;
                 }
 
+                Scope::Opaque { captures, def_id, s } => {
+                    opaque_capture_scopes.push((def_id, captures));
+                    late_depth = 0;
+                    scope = s;
+                }
+
                 Scope::ObjectLifetimeDefault { s, .. }
                 | Scope::Supertrait { s, .. }
                 | Scope::TraitRefBoundary { s, .. } => {
@@ -1218,6 +1282,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
         };
 
         if let Some(mut def) = result {
+            def = self.remap_opaque_captures(&opaque_capture_scopes, def, lifetime_ref.ident);
+
             if let ResolvedArg::EarlyBound(..) = def {
                 // Do not free early-bound regions, only late-bound ones.
             } else if let ResolvedArg::LateBound(_, _, param_def_id) = def
@@ -1291,6 +1357,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                 Scope::Root { .. } => break,
                 Scope::Binder { s, .. }
                 | Scope::Body { s, .. }
+                | Scope::Opaque { s, .. }
                 | Scope::ObjectLifetimeDefault { s, .. }
                 | Scope::Supertrait { s, .. }
                 | Scope::TraitRefBoundary { s, .. }
@@ -1306,6 +1373,79 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
         );
     }
 
+    /// Check for predicates like `impl for<'a> Trait<impl OtherTrait<'a>>`
+    /// and ban them. Type variables instantiated inside binders aren't
+    /// well-supported at the moment, so this doesn't work.
+    /// In the future, this should be fixed and this error should be removed.
+    fn check_lifetime_is_capturable(
+        &self,
+        opaque_def_id: LocalDefId,
+        lifetime: ResolvedArg,
+        capture_span: Span,
+    ) -> Result<(), ErrorGuaranteed> {
+        let ResolvedArg::LateBound(_, _, lifetime_def_id) = lifetime else { return Ok(()) };
+        let lifetime_hir_id = self.tcx.local_def_id_to_hir_id(lifetime_def_id);
+        let bad_place = match self.tcx.hir_node(self.tcx.parent_hir_id(lifetime_hir_id)) {
+            // Opaques do not declare their own lifetimes, so if a lifetime comes from an opaque
+            // it must be a reified late-bound lifetime from a trait goal.
+            hir::Node::OpaqueTy(_) => "higher-ranked lifetime from outer `impl Trait`",
+            // Other items are fine.
+            hir::Node::Item(_) | hir::Node::TraitItem(_) | hir::Node::ImplItem(_) => return Ok(()),
+            hir::Node::Ty(hir::Ty { kind: hir::TyKind::BareFn(_), .. }) => {
+                "higher-ranked lifetime from function pointer"
+            }
+            hir::Node::Ty(hir::Ty { kind: hir::TyKind::TraitObject(..), .. }) => {
+                "higher-ranked lifetime from `dyn` type"
+            }
+            _ => "higher-ranked lifetime",
+        };
+
+        let decl_span = self.tcx.def_span(lifetime_def_id);
+        let (span, label) = if capture_span != decl_span {
+            (capture_span, None)
+        } else {
+            let opaque_span = self.tcx.def_span(opaque_def_id);
+            (opaque_span, Some(opaque_span))
+        };
+
+        // Ensure that the parent of the def is an item, not HRTB
+        let guar = self.tcx.dcx().emit_err(errors::OpaqueCapturesHigherRankedLifetime {
+            span,
+            label,
+            decl_span,
+            bad_place,
+        });
+        Err(guar)
+    }
+
+    #[instrument(level = "trace", skip(self, opaque_capture_scopes), ret)]
+    fn remap_opaque_captures(
+        &self,
+        opaque_capture_scopes: &Vec<(LocalDefId, &RefCell<FxIndexMap<ResolvedArg, LocalDefId>>)>,
+        mut lifetime: ResolvedArg,
+        ident: Ident,
+    ) -> ResolvedArg {
+        if let Some(&(opaque_def_id, _)) = opaque_capture_scopes.last() {
+            if let Err(guar) =
+                self.check_lifetime_is_capturable(opaque_def_id, lifetime, ident.span)
+            {
+                lifetime = ResolvedArg::Error(guar);
+            }
+        }
+
+        for &(opaque_def_id, captures) in opaque_capture_scopes.iter().rev() {
+            let mut captures = captures.borrow_mut();
+            let remapped = *captures.entry(lifetime).or_insert_with(|| {
+                let feed = self.tcx.create_def(opaque_def_id, ident.name, DefKind::LifetimeParam);
+                feed.def_span(ident.span);
+                feed.def_ident_span(Some(ident.span));
+                feed.def_id()
+            });
+            lifetime = ResolvedArg::EarlyBound(remapped);
+        }
+        lifetime
+    }
+
     fn resolve_type_ref(&mut self, param_def_id: LocalDefId, hir_id: HirId) {
         // Walk up the scope chain, tracking the number of fn scopes
         // that we pass through, until we find a lifetime with the
@@ -1345,6 +1485,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                 }
 
                 Scope::ObjectLifetimeDefault { s, .. }
+                | Scope::Opaque { s, .. }
                 | Scope::Supertrait { s, .. }
                 | Scope::TraitRefBoundary { s, .. } => {
                     scope = s;
@@ -1425,6 +1566,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                 Scope::Root { .. } => break,
                 Scope::Binder { s, .. }
                 | Scope::Body { s, .. }
+                | Scope::Opaque { s, .. }
                 | Scope::ObjectLifetimeDefault { s, .. }
                 | Scope::Supertrait { s, .. }
                 | Scope::TraitRefBoundary { s, .. }
@@ -1501,6 +1643,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
 
                         Scope::Binder { s, .. }
                         | Scope::ObjectLifetimeDefault { s, .. }
+                        | Scope::Opaque { s, .. }
                         | Scope::Supertrait { s, .. }
                         | Scope::TraitRefBoundary { s, .. }
                         | Scope::LateBoundary { s, .. } => {
@@ -1786,7 +1929,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
     fn resolve_object_lifetime_default(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
         let mut late_depth = 0;
         let mut scope = self.scope;
-        let lifetime = loop {
+        let mut opaque_capture_scopes = vec![];
+        let mut lifetime = loop {
             match *scope {
                 Scope::Binder { s, scope_type, .. } => {
                     match scope_type {
@@ -1800,7 +1944,15 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
 
                 Scope::Body { .. } | Scope::ObjectLifetimeDefault { lifetime: None, .. } => return,
 
-                Scope::ObjectLifetimeDefault { lifetime: Some(l), .. } => break l,
+                Scope::ObjectLifetimeDefault { lifetime: Some(l), .. } => {
+                    break l.shifted(late_depth);
+                }
+
+                Scope::Opaque { captures, def_id, s } => {
+                    opaque_capture_scopes.push((def_id, captures));
+                    late_depth = 0;
+                    scope = s;
+                }
 
                 Scope::Supertrait { s, .. }
                 | Scope::TraitRefBoundary { s, .. }
@@ -1809,7 +1961,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                 }
             }
         };
-        self.insert_lifetime(lifetime_ref, lifetime.shifted(late_depth));
+
+        lifetime = self.remap_opaque_captures(&opaque_capture_scopes, lifetime, lifetime_ref.ident);
+
+        self.insert_lifetime(lifetime_ref, lifetime);
     }
 
     #[instrument(level = "debug", skip(self))]
@@ -1818,18 +1973,6 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
         self.map.defs.insert(lifetime_ref.hir_id.local_id, def);
     }
 
-    /// Sometimes we resolve a lifetime, but later find that it is an
-    /// error (esp. around impl trait). In that case, we remove the
-    /// entry into `map.defs` so as not to confuse later code.
-    fn uninsert_lifetime_on_error(
-        &mut self,
-        lifetime_ref: &'tcx hir::Lifetime,
-        bad_def: ResolvedArg,
-    ) {
-        let old_value = self.map.defs.remove(&lifetime_ref.hir_id.local_id);
-        assert_eq!(old_value, Some(bad_def));
-    }
-
     // When we have a return type notation type in a where clause, like
     // `where <T as Trait>::method(..): Send`, we need to introduce new bound
     // vars to the existing where clause's binder, to represent the lifetimes
@@ -2013,18 +2156,22 @@ fn is_late_bound_map(
     tcx: TyCtxt<'_>,
     owner_id: hir::OwnerId,
 ) -> Option<&FxIndexSet<hir::ItemLocalId>> {
-    let decl = tcx.hir().fn_decl_by_hir_id(owner_id.into())?;
+    let sig = tcx.hir().fn_sig_by_hir_id(owner_id.into())?;
     let generics = tcx.hir().get_generics(owner_id.def_id)?;
 
     let mut late_bound = FxIndexSet::default();
 
     let mut constrained_by_input = ConstrainedCollector { regions: Default::default(), tcx };
-    for arg_ty in decl.inputs {
+    for arg_ty in sig.decl.inputs {
         constrained_by_input.visit_ty(arg_ty);
     }
 
-    let mut appears_in_output = AllCollector::default();
-    intravisit::walk_fn_ret_ty(&mut appears_in_output, &decl.output);
+    let mut appears_in_output =
+        AllCollector { tcx, has_fully_capturing_opaque: false, regions: Default::default() };
+    intravisit::walk_fn_ret_ty(&mut appears_in_output, &sig.decl.output);
+    if appears_in_output.has_fully_capturing_opaque {
+        appears_in_output.regions.extend(generics.params.iter().map(|param| param.def_id));
+    }
 
     debug!(?constrained_by_input.regions);
 
@@ -2032,7 +2179,8 @@ fn is_late_bound_map(
     //
     // Subtle point: because we disallow nested bindings, we can just
     // ignore binders here and scrape up all names we see.
-    let mut appears_in_where_clause = AllCollector::default();
+    let mut appears_in_where_clause =
+        AllCollector { tcx, has_fully_capturing_opaque: true, regions: Default::default() };
     appears_in_where_clause.visit_generics(generics);
     debug!(?appears_in_where_clause.regions);
 
@@ -2198,17 +2346,26 @@ fn is_late_bound_map(
         }
     }
 
-    #[derive(Default)]
-    struct AllCollector {
+    struct AllCollector<'tcx> {
+        tcx: TyCtxt<'tcx>,
+        has_fully_capturing_opaque: bool,
         regions: FxHashSet<LocalDefId>,
     }
 
-    impl<'v> Visitor<'v> for AllCollector {
+    impl<'v> Visitor<'v> for AllCollector<'v> {
         fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
             if let hir::LifetimeName::Param(def_id) = lifetime_ref.res {
                 self.regions.insert(def_id);
             }
         }
+
+        fn visit_opaque_ty(&mut self, opaque: &'v hir::OpaqueTy<'v>) {
+            if !self.has_fully_capturing_opaque {
+                self.has_fully_capturing_opaque =
+                    opaque_captures_all_in_scope_lifetimes(self.tcx, opaque);
+            }
+            intravisit::walk_opaque_ty(self, opaque);
+        }
     }
 }
 
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 77e81af3ca9..a92a5e4278c 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -1624,10 +1624,14 @@ pub(crate) struct InvalidReceiverTy<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_effects_without_next_solver)]
+#[diag(hir_analysis_invalid_generic_receiver_ty, code = E0801)]
 #[note]
-#[help]
-pub(crate) struct EffectsWithoutNextSolver;
+#[help(hir_analysis_invalid_generic_receiver_ty_help)]
+pub(crate) struct InvalidGenericReceiverTy<'tcx> {
+    #[primary_span]
+    pub span: Span,
+    pub receiver_ty: Ty<'tcx>,
+}
 
 #[derive(Diagnostic)]
 #[diag(hir_analysis_cmse_inputs_stack_spill, code = E0798)]
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
index a5709089db6..8cc475b536d 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
@@ -168,12 +168,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             match hir_bound {
                 hir::GenericBound::Trait(poly_trait_ref) => {
                     let hir::TraitBoundModifiers { constness, polarity } = poly_trait_ref.modifiers;
-                    let polarity = match polarity {
-                        rustc_ast::BoundPolarity::Positive => ty::PredicatePolarity::Positive,
-                        rustc_ast::BoundPolarity::Negative(_) => ty::PredicatePolarity::Negative,
-                        rustc_ast::BoundPolarity::Maybe(_) => continue,
-                    };
-
                     let _ = self.lower_poly_trait_ref(
                         &poly_trait_ref.trait_ref,
                         poly_trait_ref.span,
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
index f2ee4b0ccd4..5e27ace4cbe 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
@@ -51,7 +51,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 &trait_bound.trait_ref,
                 trait_bound.span,
                 hir::BoundConstness::Never,
-                ty::PredicatePolarity::Positive,
+                hir::BoundPolarity::Positive,
                 dummy_self,
                 &mut bounds,
                 PredicateFilter::SelfOnly,
@@ -140,9 +140,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                             tcx.associated_items(pred.def_id())
                                 .in_definition_order()
                                 .filter(|item| item.kind == ty::AssocKind::Type)
-                                .filter(|item| {
-                                    !item.is_impl_trait_in_trait() && !item.is_effects_desugaring
-                                })
+                                .filter(|item| !item.is_impl_trait_in_trait())
                                 .map(|item| item.def_id),
                         );
                     }
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index 0891642f2c8..848813ffcb8 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -20,6 +20,7 @@ pub mod errors;
 pub mod generics;
 mod lint;
 
+use std::assert_matches::assert_matches;
 use std::slice;
 
 use rustc_ast::TraitObjectSyntax;
@@ -39,7 +40,7 @@ use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
 use rustc_middle::ty::print::PrintPolyTraitRefExt as _;
 use rustc_middle::ty::{
     self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, ParamEnv, Ty, TyCtxt,
-    TypeVisitableExt,
+    TypeVisitableExt, TypingMode,
 };
 use rustc_middle::{bug, span_bug};
 use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
@@ -294,13 +295,23 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         lifetime: &hir::Lifetime,
         reason: RegionInferReason<'_>,
     ) -> ty::Region<'tcx> {
+        if let Some(resolved) = self.tcx().named_bound_var(lifetime.hir_id) {
+            self.lower_resolved_lifetime(resolved)
+        } else {
+            self.re_infer(lifetime.ident.span, reason)
+        }
+    }
+
+    /// Lower a lifetime from the HIR to our internal notion of a lifetime called a *region*.
+    #[instrument(level = "debug", skip(self), ret)]
+    pub fn lower_resolved_lifetime(&self, resolved: rbv::ResolvedArg) -> ty::Region<'tcx> {
         let tcx = self.tcx();
         let lifetime_name = |def_id| tcx.hir().name(tcx.local_def_id_to_hir_id(def_id));
 
-        match tcx.named_bound_var(lifetime.hir_id) {
-            Some(rbv::ResolvedArg::StaticLifetime) => tcx.lifetimes.re_static,
+        match resolved {
+            rbv::ResolvedArg::StaticLifetime => tcx.lifetimes.re_static,
 
-            Some(rbv::ResolvedArg::LateBound(debruijn, index, def_id)) => {
+            rbv::ResolvedArg::LateBound(debruijn, index, def_id) => {
                 let name = lifetime_name(def_id);
                 let br = ty::BoundRegion {
                     var: ty::BoundVar::from_u32(index),
@@ -309,7 +320,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 ty::Region::new_bound(tcx, debruijn, br)
             }
 
-            Some(rbv::ResolvedArg::EarlyBound(def_id)) => {
+            rbv::ResolvedArg::EarlyBound(def_id) => {
                 let name = tcx.hir().ty_param_name(def_id);
                 let item_def_id = tcx.hir().ty_param_owner(def_id);
                 let generics = tcx.generics_of(item_def_id);
@@ -317,7 +328,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 ty::Region::new_early_param(tcx, ty::EarlyParamRegion { index, name })
             }
 
-            Some(rbv::ResolvedArg::Free(scope, id)) => {
+            rbv::ResolvedArg::Free(scope, id) => {
                 let name = lifetime_name(id);
                 ty::Region::new_late_param(
                     tcx,
@@ -328,9 +339,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 // (*) -- not late-bound, won't change
             }
 
-            Some(rbv::ResolvedArg::Error(guar)) => ty::Region::new_error(tcx, guar),
-
-            None => self.re_infer(lifetime.ident.span, reason),
+            rbv::ResolvedArg::Error(guar) => ty::Region::new_error(tcx, guar),
         }
     }
 
@@ -659,7 +668,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         trait_ref: &hir::TraitRef<'tcx>,
         span: Span,
         constness: hir::BoundConstness,
-        polarity: ty::PredicatePolarity,
+        polarity: hir::BoundPolarity,
         self_ty: Ty<'tcx>,
         bounds: &mut Bounds<'tcx>,
         predicate_filter: PredicateFilter,
@@ -681,15 +690,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             Some(self_ty),
         );
 
-        if let hir::BoundConstness::Always(span) | hir::BoundConstness::Maybe(span) = constness
-            && !self.tcx().is_const_trait(trait_def_id)
-        {
-            self.dcx().emit_err(crate::errors::ConstBoundForNonConstTrait {
-                span,
-                modifier: constness.as_str(),
-            });
-        }
-
         let tcx = self.tcx();
         let bound_vars = tcx.late_bound_vars(trait_ref.hir_ref_id);
         debug!(?bound_vars);
@@ -699,6 +699,36 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             bound_vars,
         );
 
+        let polarity = match polarity {
+            rustc_ast::BoundPolarity::Positive => ty::PredicatePolarity::Positive,
+            rustc_ast::BoundPolarity::Negative(_) => ty::PredicatePolarity::Negative,
+            rustc_ast::BoundPolarity::Maybe(_) => {
+                // Validate associated type at least. We may want to reject these
+                // outright in the future...
+                for constraint in trait_segment.args().constraints {
+                    let _ = self.lower_assoc_item_constraint(
+                        trait_ref.hir_ref_id,
+                        poly_trait_ref,
+                        constraint,
+                        &mut Default::default(),
+                        &mut Default::default(),
+                        constraint.span,
+                        predicate_filter,
+                    );
+                }
+                return arg_count;
+            }
+        };
+
+        if let hir::BoundConstness::Always(span) | hir::BoundConstness::Maybe(span) = constness
+            && !self.tcx().is_const_trait(trait_def_id)
+        {
+            self.dcx().emit_err(crate::errors::ConstBoundForNonConstTrait {
+                span,
+                modifier: constness.as_str(),
+            });
+        }
+
         match predicate_filter {
             PredicateFilter::All
             | PredicateFilter::SelfOnly
@@ -713,7 +743,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                             bounds.push_const_bound(
                                 tcx,
                                 poly_trait_ref,
-                                ty::HostPolarity::Const,
+                                ty::BoundConstness::Const,
                                 span,
                             );
                         }
@@ -736,7 +766,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => match constness {
                 hir::BoundConstness::Maybe(span) => {
                     if polarity == ty::PredicatePolarity::Positive {
-                        bounds.push_const_bound(tcx, poly_trait_ref, ty::HostPolarity::Maybe, span);
+                        bounds.push_const_bound(
+                            tcx,
+                            poly_trait_ref,
+                            ty::BoundConstness::Maybe,
+                            span,
+                        );
                     }
                 }
                 hir::BoundConstness::Always(_) | hir::BoundConstness::Never => {}
@@ -749,11 +784,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             // since we should have emitted an error for them earlier, and they
             // would not be well-formed!
             if polarity != ty::PredicatePolarity::Positive {
-                assert!(
-                    self.dcx().has_errors().is_some(),
+                self.dcx().span_delayed_bug(
+                    constraint.span,
                     "negative trait bounds should not have assoc item constraints",
                 );
-                continue;
+                break;
             }
 
             // Specify type to assert that error was already reported in `Err` case.
@@ -1300,7 +1335,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             Some(infcx) => infcx,
             None => {
                 assert!(!self_ty.has_infer());
-                infcx_ = tcx.infer_ctxt().ignoring_regions().build();
+                infcx_ = tcx.infer_ctxt().ignoring_regions().build(TypingMode::non_body_analysis());
                 &infcx_
             }
         };
@@ -1492,7 +1527,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             infcx
         } else {
             assert!(!qself_ty.has_infer());
-            infcx_ = tcx.infer_ctxt().build();
+            infcx_ = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
             &infcx_
         };
 
@@ -1798,7 +1833,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         match path.res {
             Res::Def(DefKind::OpaqueTy, did) => {
                 // Check for desugared `impl Trait`.
-                assert!(tcx.is_type_alias_impl_trait(did));
+                assert_matches!(tcx.opaque_ty_origin(did), hir::OpaqueTyOrigin::TyAlias { .. });
                 let item_segment = path.segments.split_last().unwrap();
                 let _ = self
                     .prohibit_generic_args(item_segment.1.iter(), GenericsArgsErrExtend::OpaqueTy);
@@ -2094,13 +2129,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 let opt_self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself));
                 self.lower_path(opt_self_ty, path, hir_ty.hir_id, false)
             }
-            &hir::TyKind::OpaqueDef(opaque_ty, lifetimes) => {
-                let local_def_id = opaque_ty.def_id;
-
+            &hir::TyKind::OpaqueDef(opaque_ty) => {
                 // If this is an RPITIT and we are using the new RPITIT lowering scheme, we
                 // generate the def_id of an associated type for the trait and return as
                 // type a projection.
-                match opaque_ty.origin {
+                let in_trait = match opaque_ty.origin {
                     hir::OpaqueTyOrigin::FnReturn {
                         in_trait_or_impl: Some(hir::RpitContext::Trait),
                         ..
@@ -2108,11 +2141,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                     | hir::OpaqueTyOrigin::AsyncFn {
                         in_trait_or_impl: Some(hir::RpitContext::Trait),
                         ..
-                    } => self.lower_opaque_ty(
-                        tcx.associated_type_for_impl_trait_in_trait(local_def_id).to_def_id(),
-                        lifetimes,
-                        true,
-                    ),
+                    } => true,
                     hir::OpaqueTyOrigin::FnReturn {
                         in_trait_or_impl: None | Some(hir::RpitContext::TraitImpl),
                         ..
@@ -2121,10 +2150,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                         in_trait_or_impl: None | Some(hir::RpitContext::TraitImpl),
                         ..
                     }
-                    | hir::OpaqueTyOrigin::TyAlias { .. } => {
-                        self.lower_opaque_ty(local_def_id.to_def_id(), lifetimes, false)
-                    }
-                }
+                    | hir::OpaqueTyOrigin::TyAlias { .. } => false,
+                };
+
+                self.lower_opaque_ty(opaque_ty.def_id, in_trait)
             }
             // If we encounter a type relative path with RTN generics, then it must have
             // *not* gone through `lower_ty_maybe_return_type_notation`, and therefore
@@ -2264,40 +2293,34 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
     }
 
     /// Lower an opaque type (i.e., an existential impl-Trait type) from the HIR.
-    #[instrument(level = "debug", skip_all, ret)]
-    fn lower_opaque_ty(
-        &self,
-        def_id: DefId,
-        lifetimes: &[hir::GenericArg<'_>],
-        in_trait: bool,
-    ) -> Ty<'tcx> {
-        debug!(?def_id, ?lifetimes);
+    #[instrument(level = "debug", skip(self), ret)]
+    fn lower_opaque_ty(&self, def_id: LocalDefId, in_trait: bool) -> Ty<'tcx> {
         let tcx = self.tcx();
 
+        let lifetimes = tcx.opaque_captured_lifetimes(def_id);
+        debug!(?lifetimes);
+
+        // If this is an RPITIT and we are using the new RPITIT lowering scheme, we
+        // generate the def_id of an associated type for the trait and return as
+        // type a projection.
+        let def_id = if in_trait {
+            tcx.associated_type_for_impl_trait_in_trait(def_id).to_def_id()
+        } else {
+            def_id.to_def_id()
+        };
+
         let generics = tcx.generics_of(def_id);
         debug!(?generics);
 
+        // We use `generics.count() - lifetimes.len()` here instead of `generics.parent_count`
+        // since return-position impl trait in trait squashes all of the generics from its source fn
+        // into its own generics, so the opaque's "own" params isn't always just lifetimes.
+        let offset = generics.count() - lifetimes.len();
+
         let args = ty::GenericArgs::for_item(tcx, def_id, |param, _| {
-            // We use `generics.count() - lifetimes.len()` here instead of `generics.parent_count`
-            // since return-position impl trait in trait squashes all of the generics from its source fn
-            // into its own generics, so the opaque's "own" params isn't always just lifetimes.
-            if let Some(i) = (param.index as usize).checked_sub(generics.count() - lifetimes.len())
-            {
-                // Resolve our own lifetime parameters.
-                let GenericParamDefKind::Lifetime { .. } = param.kind else {
-                    span_bug!(
-                        tcx.def_span(param.def_id),
-                        "only expected lifetime for opaque's own generics, got {:?}",
-                        param
-                    );
-                };
-                let hir::GenericArg::Lifetime(lifetime) = &lifetimes[i] else {
-                    bug!(
-                        "expected lifetime argument for param {param:?}, found {:?}",
-                        &lifetimes[i]
-                    )
-                };
-                self.lower_lifetime(lifetime, RegionInferReason::Param(&param)).into()
+            if let Some(i) = (param.index as usize).checked_sub(offset) {
+                let (lifetime, _) = lifetimes[i];
+                self.lower_resolved_lifetime(lifetime).into()
             } else {
                 tcx.mk_param_from_def(param)
             }
diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
index 2fa4ca68073..5b0165bf993 100644
--- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
@@ -5,7 +5,7 @@ use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::{ObligationCause, WellFormedLoc};
 use rustc_middle::bug;
 use rustc_middle::query::Providers;
-use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::ty::{self, TyCtxt, TypingMode};
 use rustc_span::def_id::LocalDefId;
 use rustc_trait_selection::traits::{self, ObligationCtxt};
 use tracing::debug;
@@ -68,7 +68,7 @@ fn diagnostic_hir_wf_check<'tcx>(
 
     impl<'tcx> Visitor<'tcx> for HirWfCheck<'tcx> {
         fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
-            let infcx = self.tcx.infer_ctxt().build();
+            let infcx = self.tcx.infer_ctxt().build(TypingMode::non_body_analysis());
             let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
 
             let tcx_ty = self.icx.lower_ty(ty);
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 a394fc2fbb1..b0c9aed5d85 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
@@ -72,7 +72,9 @@ use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::traits::specialization_graph::Node;
 use rustc_middle::ty::trait_def::TraitSpecializationKind;
-use rustc_middle::ty::{self, GenericArg, GenericArgs, GenericArgsRef, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{
+    self, GenericArg, GenericArgs, GenericArgsRef, TyCtxt, TypeVisitableExt, TypingMode,
+};
 use rustc_span::{ErrorGuaranteed, Span};
 use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
@@ -195,7 +197,7 @@ fn get_impl_args(
     impl1_def_id: LocalDefId,
     impl2_node: Node,
 ) -> Result<(GenericArgsRef<'_>, GenericArgsRef<'_>), ErrorGuaranteed> {
-    let infcx = &tcx.infer_ctxt().build();
+    let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
     let ocx = ObligationCtxt::new_with_diagnostics(infcx);
     let param_env = tcx.param_env(impl1_def_id);
     let impl1_span = tcx.def_span(impl1_def_id);
@@ -409,7 +411,7 @@ fn check_predicates<'tcx>(
 
     // Include the well-formed predicates of the type parameters of the impl.
     for arg in tcx.impl_trait_ref(impl1_def_id).unwrap().instantiate_identity().args {
-        let infcx = &tcx.infer_ctxt().build();
+        let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
         let obligations =
             wf::obligations(infcx, tcx.param_env(impl1_def_id), impl1_def_id, 0, arg, span)
                 .unwrap();
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index 3ad35163191..339eddeeade 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -153,12 +153,6 @@ pub fn provide(providers: &mut Providers) {
 pub fn check_crate(tcx: TyCtxt<'_>) {
     let _prof_timer = tcx.sess.timer("type_check_crate");
 
-    // FIXME(effects): remove once effects is implemented in old trait solver
-    // or if the next solver is stabilized.
-    if tcx.features().effects() && !tcx.next_trait_solver_globally() {
-        tcx.dcx().emit_err(errors::EffectsWithoutNextSolver);
-    }
-
     tcx.sess.time("coherence_checking", || {
         tcx.hir().par_for_each_module(|module| {
             let _ = tcx.ensure().check_mod_type_wf(module);
diff --git a/compiler/rustc_hir_pretty/Cargo.toml b/compiler/rustc_hir_pretty/Cargo.toml
index aacf41b6eb7..9af1fb8279e 100644
--- a/compiler/rustc_hir_pretty/Cargo.toml
+++ b/compiler/rustc_hir_pretty/Cargo.toml
@@ -5,9 +5,9 @@ edition = "2021"
 
 [dependencies]
 # tidy-alphabetical-start
+rustc_abi = { path = "../rustc_abi" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_span = { path = "../rustc_span" }
-rustc_target = { path = "../rustc_target" }
 # tidy-alphabetical-end
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 61214b99215..0a3aa8fec90 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -9,6 +9,7 @@
 use std::cell::Cell;
 use std::vec;
 
+use rustc_abi::ExternAbi;
 use rustc_ast::util::parser::{self, AssocOp, Fixity};
 use rustc_ast_pretty::pp::Breaks::{Consistent, Inconsistent};
 use rustc_ast_pretty::pp::{self, Breaks};
@@ -20,7 +21,6 @@ use rustc_hir::{
 use rustc_span::FileName;
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::{Ident, Symbol, kw};
-use rustc_target::spec::abi::Abi;
 use {rustc_ast as ast, rustc_hir as hir};
 
 pub fn id_to_string(map: &dyn rustc_hir::intravisit::Map<'_>, hir_id: HirId) -> String {
@@ -659,8 +659,6 @@ impl<'a> State<'a> {
 
     fn print_opaque_ty(&mut self, o: &hir::OpaqueTy<'_>) {
         self.head("opaque");
-        self.print_generic_params(o.generics.params);
-        self.print_where_clause(o.generics);
         self.word("{");
         self.print_bounds("impl", o.bounds);
         self.word("}");
@@ -2242,7 +2240,7 @@ impl<'a> State<'a> {
 
     fn print_ty_fn(
         &mut self,
-        abi: Abi,
+        abi: ExternAbi,
         safety: hir::Safety,
         decl: &hir::FnDecl<'_>,
         name: Option<Symbol>,
@@ -2278,7 +2276,7 @@ impl<'a> State<'a> {
 
         self.print_safety(header.safety);
 
-        if header.abi != Abi::Rust {
+        if header.abi != ExternAbi::Rust {
             self.word_nbsp("extern");
             self.word_nbsp(header.abi.to_string());
         }
diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs
index 3372cae7a51..1774772b50b 100644
--- a/compiler/rustc_hir_typeck/src/_match.rs
+++ b/compiler/rustc_hir_typeck/src/_match.rs
@@ -601,7 +601,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             _ => return None,
         };
         let hir::OpaqueTyOrigin::FnReturn { parent: parent_def_id, .. } =
-            self.tcx.opaque_type_origin(def_id)
+            self.tcx.local_opaque_ty_origin(def_id)
         else {
             return None;
         };
diff --git a/compiler/rustc_hir_typeck/src/autoderef.rs b/compiler/rustc_hir_typeck/src/autoderef.rs
index e4ca1cee757..7af26623ce7 100644
--- a/compiler/rustc_hir_typeck/src/autoderef.rs
+++ b/compiler/rustc_hir_typeck/src/autoderef.rs
@@ -23,7 +23,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         span: Span,
         base_ty: Ty<'tcx>,
     ) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
-        self.try_overloaded_place_op(span, base_ty, &[], PlaceOp::Deref)
+        self.try_overloaded_place_op(span, base_ty, None, PlaceOp::Deref)
     }
 
     /// Returns the adjustment steps.
@@ -50,8 +50,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     self.try_overloaded_deref(autoderef.span(), source).and_then(
                         |InferOk { value: method, obligations: o }| {
                             obligations.extend(o);
-                            if let ty::Ref(region, _, mutbl) = *method.sig.output().kind() {
-                                Some(OverloadedDeref { region, mutbl, span: autoderef.span() })
+                            // FIXME: we should assert the sig is &T here... there's no reason for this to be fallible.
+                            if let ty::Ref(_, _, mutbl) = *method.sig.output().kind() {
+                                Some(OverloadedDeref { mutbl, span: autoderef.span() })
                             } else {
                                 None
                             }
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index ed56bb9c455..f9a21a9bef3 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -1,4 +1,4 @@
-use std::{iter, slice};
+use std::iter;
 
 use rustc_ast::util::parser::PREC_UNAMBIGUOUS;
 use rustc_errors::{Applicability, Diag, ErrorGuaranteed, StashKey};
@@ -300,14 +300,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 Ident::with_dummy_span(method_name),
                 trait_def_id,
                 adjusted_ty,
-                opt_input_type.as_ref().map(slice::from_ref),
+                opt_input_type,
             ) {
                 let method = self.register_infer_ok_obligations(ok);
                 let mut autoref = None;
                 if borrow {
                     // Check for &self vs &mut self in the method signature. Since this is either
                     // the Fn or FnMut trait, it should be one of those.
-                    let ty::Ref(region, _, mutbl) = method.sig.inputs()[0].kind() else {
+                    let ty::Ref(_, _, mutbl) = method.sig.inputs()[0].kind() else {
                         bug!("Expected `FnMut`/`Fn` to take receiver by-ref/by-mut")
                     };
 
@@ -317,7 +317,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     let mutbl = AutoBorrowMutability::new(*mutbl, AllowTwoPhase::No);
 
                     autoref = Some(Adjustment {
-                        kind: Adjust::Borrow(AutoBorrow::Ref(*region, mutbl)),
+                        kind: Adjust::Borrow(AutoBorrow::Ref(mutbl)),
                         target: method.sig.inputs()[0],
                     });
                 }
@@ -851,11 +851,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             return;
         }
 
+        // If we have `rustc_do_not_const_check`, do not check `~const` bounds.
+        if self.tcx.has_attr(self.body_id, sym::rustc_do_not_const_check) {
+            return;
+        }
+
         let host = match self.tcx.hir().body_const_context(self.body_id) {
             Some(hir::ConstContext::Const { .. } | hir::ConstContext::Static(_)) => {
-                ty::HostPolarity::Const
+                ty::BoundConstness::Const
             }
-            Some(hir::ConstContext::ConstFn) => ty::HostPolarity::Maybe,
+            Some(hir::ConstContext::ConstFn) => ty::BoundConstness::Maybe,
             None => return,
         };
 
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 6fa958d9496..87798ca3fd9 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -113,7 +113,7 @@ fn identity(_: Ty<'_>) -> Vec<Adjustment<'_>> {
     vec![]
 }
 
-fn simple<'tcx>(kind: Adjust<'tcx>) -> impl FnOnce(Ty<'tcx>) -> Vec<Adjustment<'tcx>> {
+fn simple<'tcx>(kind: Adjust) -> impl FnOnce(Ty<'tcx>) -> Vec<Adjustment<'tcx>> {
     move |target| vec![Adjustment { kind, target }]
 }
 
@@ -484,14 +484,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
 
         // Now apply the autoref. We have to extract the region out of
         // the final ref type we got.
-        let ty::Ref(r_borrow, _, _) = ty.kind() else {
+        let ty::Ref(..) = ty.kind() else {
             span_bug!(span, "expected a ref type, got {:?}", ty);
         };
         let mutbl = AutoBorrowMutability::new(mutbl_b, self.allow_two_phase);
-        adjustments.push(Adjustment {
-            kind: Adjust::Borrow(AutoBorrow::Ref(*r_borrow, mutbl)),
-            target: ty,
-        });
+        adjustments.push(Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(mutbl)), target: ty });
 
         debug!("coerce_borrowed_pointer: succeeded ty={:?} adjustments={:?}", ty, adjustments);
 
@@ -547,7 +544,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
                 let mutbl = AutoBorrowMutability::new(mutbl_b, AllowTwoPhase::No);
 
                 Some((Adjustment { kind: Adjust::Deref(None), target: ty_a }, Adjustment {
-                    kind: Adjust::Borrow(AutoBorrow::Ref(r_borrow, mutbl)),
+                    kind: Adjust::Borrow(AutoBorrow::Ref(mutbl)),
                     target: Ty::new_ref(self.tcx, r_borrow, ty_a, mutbl_b),
                 }))
             }
@@ -827,7 +824,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         };
 
         let (pin, a_region, a_ty, mut_a) = extract_pin_mut(a)?;
-        let (_, b_region, _b_ty, mut_b) = extract_pin_mut(b)?;
+        let (_, _, _b_ty, mut_b) = extract_pin_mut(b)?;
 
         coerce_mutbls(mut_a, mut_b)?;
 
@@ -841,7 +838,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         // To complete the reborrow, we need to make sure we can unify the inner types, and if so we
         // add the adjustments.
         self.unify_and(a, b, |_inner_ty| {
-            vec![Adjustment { kind: Adjust::ReborrowPin(b_region, mut_b), target: b }]
+            vec![Adjustment { kind: Adjust::ReborrowPin(mut_b), target: b }]
         })
     }
 
@@ -1321,7 +1318,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let noop = match self.typeck_results.borrow().expr_adjustments(expr) {
                 &[
                     Adjustment { kind: Adjust::Deref(_), .. },
-                    Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl_adj)), .. },
+                    Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(mutbl_adj)), .. },
                 ] => {
                     match *self.node_ty(expr.hir_id).kind() {
                         ty::Ref(_, _, mt_orig) => {
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index bb5f3511373..041ccfcddbb 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -781,7 +781,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
                     self.walk_autoref(expr, &place_with_id, autoref);
                 }
 
-                adjustment::Adjust::ReborrowPin(_, mutbl) => {
+                adjustment::Adjust::ReborrowPin(mutbl) => {
                     // Reborrowing a Pin is like a combinations of a deref and a borrow, so we do
                     // both.
                     let bk = match mutbl {
@@ -804,7 +804,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
         &self,
         expr: &hir::Expr<'_>,
         base_place: &PlaceWithHirId<'tcx>,
-        autoref: &adjustment::AutoBorrow<'tcx>,
+        autoref: &adjustment::AutoBorrow,
     ) {
         debug!(
             "walk_autoref(expr.hir_id={} base_place={:?} autoref={:?})",
@@ -812,7 +812,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
         );
 
         match *autoref {
-            adjustment::AutoBorrow::Ref(_, m) => {
+            adjustment::AutoBorrow::Ref(m) => {
                 self.delegate.borrow_mut().borrow(
                     base_place,
                     base_place.hir_id,
@@ -1283,7 +1283,12 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
             adjustment::Adjust::Deref(overloaded) => {
                 // Equivalent to *expr or something similar.
                 let base = if let Some(deref) = overloaded {
-                    let ref_ty = Ty::new_ref(self.cx.tcx(), deref.region, target, deref.mutbl);
+                    let ref_ty = Ty::new_ref(
+                        self.cx.tcx(),
+                        self.cx.tcx().lifetimes.re_erased,
+                        target,
+                        deref.mutbl,
+                    );
                     self.cat_rvalue(expr.hir_id, ref_ty)
                 } else {
                     previous()?
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 0fc566c58f7..a1a78371fbd 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -264,7 +264,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let autoborrow_mut = adj.iter().any(|adj| {
             matches!(adj, &Adjustment {
-                kind: Adjust::Borrow(AutoBorrow::Ref(_, AutoBorrowMutability::Mut { .. })),
+                kind: Adjust::Borrow(AutoBorrow::Ref(AutoBorrowMutability::Mut { .. })),
                 ..
             })
         });
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index f2b55d3aa4e..3754fd02428 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -200,10 +200,8 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
                 // for two-phase borrows.
                 let mutbl = AutoBorrowMutability::new(mutbl, AllowTwoPhase::Yes);
 
-                adjustments.push(Adjustment {
-                    kind: Adjust::Borrow(AutoBorrow::Ref(region, mutbl)),
-                    target,
-                });
+                adjustments
+                    .push(Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(mutbl)), target });
 
                 if unsize {
                     let unsized_ty = if let ty::Array(elem_ty, _) = base_ty.kind() {
@@ -250,7 +248,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
                     _ => bug!("Cannot adjust receiver type for reborrowing pin of {target:?}"),
                 };
 
-                adjustments.push(Adjustment { kind: Adjust::ReborrowPin(region, mutbl), target });
+                adjustments.push(Adjustment { kind: Adjust::ReborrowPin(mutbl), target });
             }
             None => {}
         }
@@ -533,9 +531,6 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
                 self.register_predicates(obligations);
             }
             Err(terr) => {
-                // FIXME(arbitrary_self_types): We probably should limit the
-                // situations where this can occur by adding additional restrictions
-                // to the feature, like the self type can't reference method args.
                 if self.tcx.features().arbitrary_self_types() {
                     self.err_ctxt()
                         .report_mismatched_types(
diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs
index e20a0cb67c3..e0b6ea0ac9d 100644
--- a/compiler/rustc_hir_typeck/src/method/mod.rs
+++ b/compiler/rustc_hir_typeck/src/method/mod.rs
@@ -324,35 +324,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         Ok(pick)
     }
 
-    pub(super) fn obligation_for_method(
-        &self,
-        cause: ObligationCause<'tcx>,
-        trait_def_id: DefId,
-        self_ty: Ty<'tcx>,
-        opt_input_types: Option<&[Ty<'tcx>]>,
-    ) -> (traits::PredicateObligation<'tcx>, ty::GenericArgsRef<'tcx>) {
-        // Construct a trait-reference `self_ty : Trait<input_tys>`
-        let args = GenericArgs::for_item(self.tcx, trait_def_id, |param, _| {
-            match param.kind {
-                GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => {}
-                GenericParamDefKind::Type { .. } => {
-                    if param.index == 0 {
-                        return self_ty.into();
-                    } else if let Some(input_types) = opt_input_types {
-                        return input_types[param.index as usize - 1].into();
-                    }
-                }
-            }
-            self.var_for_def(cause.span, param)
-        });
-
-        let trait_ref = ty::TraitRef::new_from_args(self.tcx, trait_def_id, args);
-
-        // Construct an obligation
-        let poly_trait_ref = ty::Binder::dummy(trait_ref);
-        (traits::Obligation::new(self.tcx, cause, self.param_env, poly_trait_ref), args)
-    }
-
     /// `lookup_method_in_trait` is used for overloaded operators.
     /// It does a very narrow slice of what the normal probe/confirm path does.
     /// In particular, it doesn't really do any probing: it simply constructs
@@ -365,24 +336,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         m_name: Ident,
         trait_def_id: DefId,
         self_ty: Ty<'tcx>,
-        opt_input_types: Option<&[Ty<'tcx>]>,
+        opt_rhs_ty: Option<Ty<'tcx>>,
     ) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
-        let (obligation, args) =
-            self.obligation_for_method(cause, trait_def_id, self_ty, opt_input_types);
-        self.construct_obligation_for_trait(m_name, trait_def_id, obligation, args)
-    }
+        // Construct a trait-reference `self_ty : Trait<input_tys>`
+        let args = GenericArgs::for_item(self.tcx, trait_def_id, |param, _| match param.kind {
+            GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => {
+                unreachable!("did not expect operator trait to have lifetime/const")
+            }
+            GenericParamDefKind::Type { .. } => {
+                if param.index == 0 {
+                    self_ty.into()
+                } else if let Some(rhs_ty) = opt_rhs_ty {
+                    assert_eq!(param.index, 1, "did not expect >1 param on operator trait");
+                    rhs_ty.into()
+                } else {
+                    // FIXME: We should stop passing `None` for the failure case
+                    // when probing for call exprs. I.e. `opt_rhs_ty` should always
+                    // be set when it needs to be.
+                    self.var_for_def(cause.span, param)
+                }
+            }
+        });
 
-    // FIXME(#18741): it seems likely that we can consolidate some of this
-    // code with the other method-lookup code. In particular, the second half
-    // of this method is basically the same as confirmation.
-    fn construct_obligation_for_trait(
-        &self,
-        m_name: Ident,
-        trait_def_id: DefId,
-        obligation: traits::PredicateObligation<'tcx>,
-        args: ty::GenericArgsRef<'tcx>,
-    ) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
-        debug!(?obligation);
+        let obligation = traits::Obligation::new(
+            self.tcx,
+            cause,
+            self.param_env,
+            ty::TraitRef::new_from_args(self.tcx, trait_def_id, args),
+        );
 
         // Now we want to know if this can be matched
         if !self.predicate_may_hold(&obligation) {
@@ -406,8 +387,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         debug!("lookup_in_trait_adjusted: method_item={:?}", method_item);
         let mut obligations = PredicateObligations::new();
 
-        // FIXME(effects): revisit when binops get `#[const_trait]`
-
         // Instantiate late-bound regions and instantiate the trait
         // parameters into the method type to get the actual method type.
         //
@@ -418,12 +397,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let fn_sig =
             self.instantiate_binder_with_fresh_vars(obligation.cause.span, infer::FnCall, fn_sig);
 
-        let InferOk { value, obligations: o } =
+        let InferOk { value: fn_sig, obligations: o } =
             self.at(&obligation.cause, self.param_env).normalize(fn_sig);
-        let fn_sig = {
-            obligations.extend(o);
-            value
-        };
+        obligations.extend(o);
 
         // Register obligations for the parameters. This will include the
         // `Self` parameter, which in turn has a bound of the main trait,
@@ -435,13 +411,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // any late-bound regions appearing in its bounds.
         let bounds = self.tcx.predicates_of(def_id).instantiate(self.tcx, args);
 
-        let InferOk { value, obligations: o } =
+        let InferOk { value: bounds, obligations: o } =
             self.at(&obligation.cause, self.param_env).normalize(bounds);
-        let bounds = {
-            obligations.extend(o);
-            value
-        };
-
+        obligations.extend(o);
         assert!(!bounds.has_escaping_bound_vars());
 
         let predicates_cause = obligation.cause.clone();
@@ -454,7 +426,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // Also add an obligation for the method type being well-formed.
         let method_ty = Ty::new_fn_ptr(tcx, ty::Binder::dummy(fn_sig));
         debug!(
-            "lookup_in_trait_adjusted: matched method method_ty={:?} obligation={:?}",
+            "lookup_method_in_trait: matched method method_ty={:?} obligation={:?}",
             method_ty, obligation
         );
         obligations.push(traits::Obligation::new(
@@ -467,7 +439,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         ));
 
         let callee = MethodCallee { def_id, args, sig: fn_sig };
-
         debug!("callee = {:?}", callee);
 
         Some(InferOk { obligations, value: callee })
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 569fdea11ce..eb5581f421b 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -1365,7 +1365,6 @@ impl<'tcx> Pick<'tcx> {
                     trait_item_def_id: _,
                     fn_has_self_parameter: _,
                     opt_rpitit_info: _,
-                    is_effects_desugaring: _,
                 },
             kind: _,
             import_ids: _,
diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs
index 1574e9e98d4..9c1459ee188 100644
--- a/compiler/rustc_hir_typeck/src/op.rs
+++ b/compiler/rustc_hir_typeck/src/op.rs
@@ -15,7 +15,7 @@ use rustc_span::Span;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{Ident, sym};
 use rustc_trait_selection::infer::InferCtxtExt;
-use rustc_trait_selection::traits::{FulfillmentError, ObligationCtxt};
+use rustc_trait_selection::traits::{FulfillmentError, Obligation, ObligationCtxt};
 use rustc_type_ir::TyKind::*;
 use tracing::debug;
 use {rustc_ast as ast, rustc_hir as hir};
@@ -256,23 +256,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             Ok(method) => {
                 let by_ref_binop = !op.node.is_by_value();
                 if is_assign == IsAssign::Yes || by_ref_binop {
-                    if let ty::Ref(region, _, mutbl) = method.sig.inputs()[0].kind() {
+                    if let ty::Ref(_, _, mutbl) = method.sig.inputs()[0].kind() {
                         let mutbl = AutoBorrowMutability::new(*mutbl, AllowTwoPhase::Yes);
                         let autoref = Adjustment {
-                            kind: Adjust::Borrow(AutoBorrow::Ref(*region, mutbl)),
+                            kind: Adjust::Borrow(AutoBorrow::Ref(mutbl)),
                             target: method.sig.inputs()[0],
                         };
                         self.apply_adjustments(lhs_expr, vec![autoref]);
                     }
                 }
                 if by_ref_binop {
-                    if let ty::Ref(region, _, mutbl) = method.sig.inputs()[1].kind() {
+                    if let ty::Ref(_, _, mutbl) = method.sig.inputs()[1].kind() {
                         // Allow two-phase borrows for binops in initial deployment
                         // since they desugar to methods
                         let mutbl = AutoBorrowMutability::new(*mutbl, AllowTwoPhase::Yes);
 
                         let autoref = Adjustment {
-                            kind: Adjust::Borrow(AutoBorrow::Ref(*region, mutbl)),
+                            kind: Adjust::Borrow(AutoBorrow::Ref(mutbl)),
                             target: method.sig.inputs()[1],
                         };
                         // HACK(eddyb) Bypass checks due to reborrows being in
@@ -895,7 +895,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let opname = Ident::with_dummy_span(opname);
         let (opt_rhs_expr, opt_rhs_ty) = opt_rhs.unzip();
-        let input_types = opt_rhs_ty.as_slice();
         let cause = self.cause(span, ObligationCauseCode::BinOp {
             lhs_hir_id: lhs_expr.hir_id,
             rhs_hir_id: opt_rhs_expr.map(|expr| expr.hir_id),
@@ -904,13 +903,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             output_ty: expected.only_has_type(self),
         });
 
-        let method = self.lookup_method_in_trait(
-            cause.clone(),
-            opname,
-            trait_did,
-            lhs_ty,
-            Some(input_types),
-        );
+        let method =
+            self.lookup_method_in_trait(cause.clone(), opname, trait_did, lhs_ty, opt_rhs_ty);
         match method {
             Some(ok) => {
                 let method = self.register_infer_ok_obligations(ok);
@@ -931,9 +925,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     self.check_expr_coercible_to_type(rhs_expr, rhs_ty, None);
                 }
 
-                let (obligation, _) =
-                    self.obligation_for_method(cause, trait_did, lhs_ty, Some(input_types));
-                // FIXME: This should potentially just add the obligation to the `FnCtxt`
+                // Construct an obligation `self_ty : Trait<input_tys>`
+                let args =
+                    ty::GenericArgs::for_item(self.tcx, trait_did, |param, _| match param.kind {
+                        ty::GenericParamDefKind::Lifetime
+                        | ty::GenericParamDefKind::Const { .. } => {
+                            unreachable!("did not expect operand trait to have lifetime/const args")
+                        }
+                        ty::GenericParamDefKind::Type { .. } => {
+                            if param.index == 0 {
+                                lhs_ty.into()
+                            } else {
+                                opt_rhs_ty.expect("expected RHS for binop").into()
+                            }
+                        }
+                    });
+                let obligation = Obligation::new(
+                    self.tcx,
+                    cause,
+                    self.param_env,
+                    ty::TraitRef::new_from_args(self.tcx, trait_did, args),
+                );
                 let ocx = ObligationCtxt::new_with_diagnostics(&self.infcx);
                 ocx.register_obligation(obligation);
                 Err(ocx.select_all_or_error())
diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs
index 8604f5f6920..d5c7fe5fff3 100644
--- a/compiler/rustc_hir_typeck/src/place_op.rs
+++ b/compiler/rustc_hir_typeck/src/place_op.rs
@@ -29,9 +29,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let ok = self.try_overloaded_deref(expr.span, oprnd_ty)?;
         let method = self.register_infer_ok_obligations(ok);
-        if let ty::Ref(region, _, hir::Mutability::Not) = method.sig.inputs()[0].kind() {
+        if let ty::Ref(_, _, hir::Mutability::Not) = method.sig.inputs()[0].kind() {
             self.apply_adjustments(oprnd_expr, vec![Adjustment {
-                kind: Adjust::Borrow(AutoBorrow::Ref(*region, AutoBorrowMutability::Not)),
+                kind: Adjust::Borrow(AutoBorrow::Ref(AutoBorrowMutability::Not)),
                 target: method.sig.inputs()[0],
             }]);
         } else {
@@ -149,7 +149,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // If some lookup succeeded, install method in table
             let input_ty = self.next_ty_var(base_expr.span);
             let method =
-                self.try_overloaded_place_op(expr.span, self_ty, &[input_ty], PlaceOp::Index);
+                self.try_overloaded_place_op(expr.span, self_ty, Some(input_ty), PlaceOp::Index);
 
             if let Some(result) = method {
                 debug!("try_index_step: success, using overloaded indexing");
@@ -158,7 +158,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let mut adjustments = self.adjust_steps(autoderef);
                 if let ty::Ref(region, _, hir::Mutability::Not) = method.sig.inputs()[0].kind() {
                     adjustments.push(Adjustment {
-                        kind: Adjust::Borrow(AutoBorrow::Ref(*region, AutoBorrowMutability::Not)),
+                        kind: Adjust::Borrow(AutoBorrow::Ref(AutoBorrowMutability::Not)),
                         target: Ty::new_imm_ref(self.tcx, *region, adjusted_ty),
                     });
                 } else {
@@ -189,7 +189,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         span: Span,
         base_ty: Ty<'tcx>,
-        arg_tys: &[Ty<'tcx>],
+        opt_rhs_ty: Option<Ty<'tcx>>,
         op: PlaceOp,
     ) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
         debug!("try_overloaded_place_op({:?},{:?},{:?})", span, base_ty, op);
@@ -207,7 +207,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             Ident::with_dummy_span(imm_op),
             imm_tr,
             base_ty,
-            Some(arg_tys),
+            opt_rhs_ty,
         )
     }
 
@@ -215,7 +215,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         span: Span,
         base_ty: Ty<'tcx>,
-        arg_tys: &[Ty<'tcx>],
+        opt_rhs_ty: Option<Ty<'tcx>>,
         op: PlaceOp,
     ) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
         debug!("try_mutable_overloaded_place_op({:?},{:?},{:?})", span, base_ty, op);
@@ -233,7 +233,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             Ident::with_dummy_span(mut_op),
             mut_tr,
             base_ty,
-            Some(arg_tys),
+            opt_rhs_ty,
         )
     }
 
@@ -284,14 +284,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         && let Some(ok) = self.try_mutable_overloaded_place_op(
                             expr.span,
                             source,
-                            &[],
+                            None,
                             PlaceOp::Deref,
                         )
                     {
                         let method = self.register_infer_ok_obligations(ok);
-                        if let ty::Ref(region, _, mutbl) = *method.sig.output().kind() {
-                            *deref = OverloadedDeref { region, mutbl, span: deref.span };
-                        }
+                        let ty::Ref(_, _, mutbl) = *method.sig.output().kind() else {
+                            span_bug!(
+                                self.tcx.def_span(method.def_id),
+                                "expected DerefMut to return a &mut"
+                            );
+                        };
+                        *deref = OverloadedDeref { mutbl, span: deref.span };
                         // If this is a union field, also throw an error for `DerefMut` of `ManuallyDrop` (see RFC 2514).
                         // This helps avoid accidental drops.
                         if inside_union
@@ -359,8 +363,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 Some(self.typeck_results.borrow().node_args(expr.hir_id).type_at(1))
             }
         };
-        let arg_tys = arg_ty.as_slice();
-        let method = self.try_mutable_overloaded_place_op(expr.span, base_ty, arg_tys, op);
+        let method = self.try_mutable_overloaded_place_op(expr.span, base_ty, arg_ty, op);
         let method = match method {
             Some(ok) => self.register_infer_ok_obligations(ok),
             // Couldn't find the mutable variant of the place op, keep the
@@ -391,7 +394,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         // not the case today.
                         allow_two_phase_borrow: AllowTwoPhase::No,
                     };
-                    adjustment.kind = Adjust::Borrow(AutoBorrow::Ref(*region, mutbl));
+                    adjustment.kind = Adjust::Borrow(AutoBorrow::Ref(mutbl));
                     adjustment.target = Ty::new_ref(self.tcx, *region, source, mutbl.into());
                 }
                 source = adjustment.target;
diff --git a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs
index 18e40cfa428..903be7e732a 100644
--- a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs
+++ b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs
@@ -8,7 +8,7 @@ use rustc_hir::{HirId, HirIdMap};
 use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
 use rustc_middle::span_bug;
 use rustc_middle::ty::visit::TypeVisitableExt;
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypingMode};
 use rustc_span::Span;
 use rustc_span::def_id::LocalDefIdMap;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
@@ -81,7 +81,8 @@ impl<'tcx> TypeckRootCtxt<'tcx> {
     pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
         let hir_owner = tcx.local_def_id_to_hir_id(def_id).owner;
 
-        let infcx = tcx.infer_ctxt().ignoring_regions().with_opaque_type_inference(def_id).build();
+        let infcx =
+            tcx.infer_ctxt().ignoring_regions().build(TypingMode::analysis_in_body(tcx, def_id));
         let typeck_results = RefCell::new(ty::TypeckResults::new(hir_owner));
 
         TypeckRootCtxt {
diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs
index 8c943a961e7..3eda3e9c67e 100644
--- a/compiler/rustc_infer/src/infer/at.rs
+++ b/compiler/rustc_infer/src/infer/at.rs
@@ -28,7 +28,7 @@
 use relate::lattice::{LatticeOp, LatticeOpKind};
 use rustc_middle::bug;
 use rustc_middle::ty::relate::solver_relating::RelateExt as NextSolverRelate;
-use rustc_middle::ty::{Const, ImplSubject};
+use rustc_middle::ty::{Const, ImplSubject, TypingMode};
 
 use super::*;
 use crate::infer::relate::type_relating::TypeRelating;
@@ -67,30 +67,48 @@ impl<'tcx> InferCtxt<'tcx> {
     /// variables in the same state. This can be used to "branch off" many tests from the same
     /// common state.
     pub fn fork(&self) -> Self {
-        self.fork_with_intercrate(self.intercrate)
+        Self {
+            tcx: self.tcx,
+            typing_mode: self.typing_mode,
+            considering_regions: self.considering_regions,
+            skip_leak_check: self.skip_leak_check,
+            inner: self.inner.clone(),
+            lexical_region_resolutions: self.lexical_region_resolutions.clone(),
+            selection_cache: self.selection_cache.clone(),
+            evaluation_cache: self.evaluation_cache.clone(),
+            reported_trait_errors: self.reported_trait_errors.clone(),
+            reported_signature_mismatch: self.reported_signature_mismatch.clone(),
+            tainted_by_errors: self.tainted_by_errors.clone(),
+            universe: self.universe.clone(),
+            next_trait_solver: self.next_trait_solver,
+            obligation_inspector: self.obligation_inspector.clone(),
+        }
     }
 
     /// Forks the inference context, creating a new inference context with the same inference
     /// variables in the same state, except possibly changing the intercrate mode. This can be
     /// used to "branch off" many tests from the same common state. Used in negative coherence.
-    pub fn fork_with_intercrate(&self, intercrate: bool) -> Self {
-        Self {
+    pub fn fork_with_typing_mode(&self, typing_mode: TypingMode<'tcx>) -> Self {
+        // Unlike `fork`, this invalidates all cache entries as they may depend on the
+        // typing mode.
+        let forked = Self {
             tcx: self.tcx,
-            defining_opaque_types: self.defining_opaque_types,
+            typing_mode,
             considering_regions: self.considering_regions,
             skip_leak_check: self.skip_leak_check,
             inner: self.inner.clone(),
             lexical_region_resolutions: self.lexical_region_resolutions.clone(),
-            selection_cache: self.selection_cache.clone(),
-            evaluation_cache: self.evaluation_cache.clone(),
+            selection_cache: Default::default(),
+            evaluation_cache: Default::default(),
             reported_trait_errors: self.reported_trait_errors.clone(),
             reported_signature_mismatch: self.reported_signature_mismatch.clone(),
             tainted_by_errors: self.tainted_by_errors.clone(),
             universe: self.universe.clone(),
-            intercrate,
             next_trait_solver: self.next_trait_solver,
             obligation_inspector: self.obligation_inspector.clone(),
-        }
+        };
+        forked.inner.borrow_mut().projection_cache().clear();
+        forked
     }
 }
 
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index 90d07964fda..c9d8ebecef0 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -46,7 +46,7 @@ impl<'tcx> InferCtxt<'tcx> {
         V: TypeFoldable<TyCtxt<'tcx>>,
     {
         let (param_env, value) = value.into_parts();
-        let param_env = self.tcx.canonical_param_env_cache.get_or_insert(
+        let canonical_param_env = self.tcx.canonical_param_env_cache.get_or_insert(
             self.tcx,
             param_env,
             query_state,
@@ -64,7 +64,7 @@ impl<'tcx> InferCtxt<'tcx> {
         );
 
         let canonical = Canonicalizer::canonicalize_with_base(
-            param_env,
+            canonical_param_env,
             value,
             Some(self),
             self.tcx,
@@ -72,7 +72,7 @@ impl<'tcx> InferCtxt<'tcx> {
             query_state,
         )
         .unchecked_map(|(param_env, value)| param_env.and(value));
-        CanonicalQueryInput { canonical, defining_opaque_types: self.defining_opaque_types() }
+        CanonicalQueryInput { canonical, typing_mode: self.typing_mode(param_env) }
     }
 
     /// Canonicalizes a query *response* `V`. When we canonicalize a
diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs
index 0c151a11ad4..ecda9c6eb00 100644
--- a/compiler/rustc_infer/src/infer/context.rs
+++ b/compiler/rustc_infer/src/infer/context.rs
@@ -1,7 +1,6 @@
 ///! Definition of `InferCtxtLike` from the librarified type layer.
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::DefId;
 use rustc_middle::traits::ObligationCause;
-use rustc_middle::traits::solve::SolverMode;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::relate::RelateResult;
 use rustc_middle::ty::relate::combine::PredicateEmittingRelation;
@@ -21,11 +20,11 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
         self.next_trait_solver
     }
 
-    fn solver_mode(&self) -> ty::solve::SolverMode {
-        match self.intercrate {
-            true => SolverMode::Coherence,
-            false => SolverMode::Normal,
-        }
+    fn typing_mode(
+        &self,
+        param_env_for_debug_assertion: ty::ParamEnv<'tcx>,
+    ) -> ty::TypingMode<'tcx> {
+        self.typing_mode(param_env_for_debug_assertion)
     }
 
     fn universe(&self) -> ty::UniverseIndex {
@@ -91,10 +90,6 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
         self.inner.borrow_mut().unwrap_region_constraints().opportunistic_resolve_var(self.tcx, vid)
     }
 
-    fn defining_opaque_types(&self) -> &'tcx ty::List<LocalDefId> {
-        self.defining_opaque_types()
-    }
-
     fn next_ty_infer(&self) -> Ty<'tcx> {
         self.next_ty_var(DUMMY_SP)
     }
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index be43cba97f0..fc54d69449f 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -38,11 +38,12 @@ use rustc_middle::ty::fold::{
 use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{
     self, ConstVid, FloatVid, GenericArg, GenericArgKind, GenericArgs, GenericArgsRef,
-    GenericParamDefKind, InferConst, IntVid, Ty, TyCtxt, TyVid,
+    GenericParamDefKind, InferConst, IntVid, Ty, TyCtxt, TyVid, TypingMode,
 };
 use rustc_middle::{bug, span_bug};
 use rustc_span::Span;
 use rustc_span::symbol::Symbol;
+use rustc_type_ir::solve::Reveal;
 use snapshot::undo_log::InferCtxtUndoLogs;
 use tracing::{debug, instrument};
 use type_variable::TypeVariableOrigin;
@@ -243,8 +244,9 @@ impl<'tcx> InferCtxtInner<'tcx> {
 pub struct InferCtxt<'tcx> {
     pub tcx: TyCtxt<'tcx>,
 
-    /// The `DefIds` of the opaque types that may have their hidden types constrained.
-    defining_opaque_types: &'tcx ty::List<LocalDefId>,
+    /// The mode of this inference context, see the struct documentation
+    /// for more details.
+    typing_mode: TypingMode<'tcx>,
 
     /// Whether this inference context should care about region obligations in
     /// the root universe. Most notably, this is used during hir typeck as region
@@ -296,26 +298,6 @@ pub struct InferCtxt<'tcx> {
     /// bound.
     universe: Cell<ty::UniverseIndex>,
 
-    /// During coherence we have to assume that other crates may add
-    /// additional impls which we currently don't know about.
-    ///
-    /// To deal with this evaluation, we should be conservative
-    /// and consider the possibility of impls from outside this crate.
-    /// This comes up primarily when resolving ambiguity. Imagine
-    /// there is some trait reference `$0: Bar` where `$0` is an
-    /// inference variable. If `intercrate` is true, then we can never
-    /// say for sure that this reference is not implemented, even if
-    /// there are *no impls at all for `Bar`*, because `$0` could be
-    /// bound to some type that in a downstream crate that implements
-    /// `Bar`.
-    ///
-    /// Outside of coherence, we set this to false because we are only
-    /// interested in types that the user could actually have written.
-    /// In other words, we consider `$0: Bar` to be unimplemented if
-    /// there is no type that the user could *actually name* that
-    /// would satisfy it. This avoids crippling inference, basically.
-    pub intercrate: bool,
-
     next_trait_solver: bool,
 
     pub obligation_inspector: Cell<Option<ObligationInspector<'tcx>>>,
@@ -529,11 +511,8 @@ pub struct RegionObligation<'tcx> {
 /// Used to configure inference contexts before their creation.
 pub struct InferCtxtBuilder<'tcx> {
     tcx: TyCtxt<'tcx>,
-    defining_opaque_types: &'tcx ty::List<LocalDefId>,
     considering_regions: bool,
     skip_leak_check: bool,
-    /// Whether we are in coherence mode.
-    intercrate: bool,
     /// Whether we should use the new trait solver in the local inference context,
     /// which affects things like which solver is used in `predicate_may_hold`.
     next_trait_solver: bool,
@@ -544,37 +523,19 @@ impl<'tcx> TyCtxt<'tcx> {
     fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> {
         InferCtxtBuilder {
             tcx: self,
-            defining_opaque_types: ty::List::empty(),
             considering_regions: true,
             skip_leak_check: false,
-            intercrate: false,
             next_trait_solver: self.next_trait_solver_globally(),
         }
     }
 }
 
 impl<'tcx> InferCtxtBuilder<'tcx> {
-    /// Whenever the `InferCtxt` should be able to handle defining uses of opaque types,
-    /// you need to call this function. Otherwise the opaque type will be treated opaquely.
-    ///
-    /// It is only meant to be called in two places, for typeck
-    /// (via `Inherited::build`) and for the inference context used
-    /// in mir borrowck.
-    pub fn with_opaque_type_inference(mut self, defining_anchor: LocalDefId) -> Self {
-        self.defining_opaque_types = self.tcx.opaque_types_defined_by(defining_anchor);
-        self
-    }
-
     pub fn with_next_trait_solver(mut self, next_trait_solver: bool) -> Self {
         self.next_trait_solver = next_trait_solver;
         self
     }
 
-    pub fn intercrate(mut self, intercrate: bool) -> Self {
-        self.intercrate = intercrate;
-        self
-    }
-
     pub fn ignoring_regions(mut self) -> Self {
         self.considering_regions = false;
         self
@@ -600,24 +561,17 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
     where
         T: TypeFoldable<TyCtxt<'tcx>>,
     {
-        self.defining_opaque_types = input.defining_opaque_types;
-        let infcx = self.build();
+        let infcx = self.build(input.typing_mode);
         let (value, args) = infcx.instantiate_canonical(span, &input.canonical);
         (infcx, value, args)
     }
 
-    pub fn build(&mut self) -> InferCtxt<'tcx> {
-        let InferCtxtBuilder {
-            tcx,
-            defining_opaque_types,
-            considering_regions,
-            skip_leak_check,
-            intercrate,
-            next_trait_solver,
-        } = *self;
+    pub fn build(&mut self, typing_mode: TypingMode<'tcx>) -> InferCtxt<'tcx> {
+        let InferCtxtBuilder { tcx, considering_regions, skip_leak_check, next_trait_solver } =
+            *self;
         InferCtxt {
             tcx,
-            defining_opaque_types,
+            typing_mode,
             considering_regions,
             skip_leak_check,
             inner: RefCell::new(InferCtxtInner::new()),
@@ -628,7 +582,6 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
             reported_signature_mismatch: Default::default(),
             tainted_by_errors: Cell::new(None),
             universe: Cell::new(ty::UniverseIndex::ROOT),
-            intercrate,
             next_trait_solver,
             obligation_inspector: Cell::new(None),
         }
@@ -659,14 +612,30 @@ impl<'tcx> InferCtxt<'tcx> {
         self.tcx.dcx().taintable_handle(&self.tainted_by_errors)
     }
 
-    pub fn defining_opaque_types(&self) -> &'tcx ty::List<LocalDefId> {
-        self.defining_opaque_types
-    }
-
     pub fn next_trait_solver(&self) -> bool {
         self.next_trait_solver
     }
 
+    #[inline(always)]
+    pub fn typing_mode(
+        &self,
+        param_env_for_debug_assertion: ty::ParamEnv<'tcx>,
+    ) -> TypingMode<'tcx> {
+        if cfg!(debug_assertions) {
+            match (param_env_for_debug_assertion.reveal(), self.typing_mode) {
+                (Reveal::All, TypingMode::PostAnalysis)
+                | (Reveal::UserFacing, TypingMode::Coherence | TypingMode::Analysis { .. }) => {}
+                (r, t) => unreachable!("TypingMode x Reveal mismatch: {r:?} {t:?}"),
+            }
+        }
+        self.typing_mode
+    }
+
+    #[inline(always)]
+    pub fn typing_mode_unchecked(&self) -> TypingMode<'tcx> {
+        self.typing_mode
+    }
+
     pub fn freshen<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> T {
         t.fold_with(&mut self.freshener())
     }
@@ -1029,8 +998,12 @@ impl<'tcx> InferCtxt<'tcx> {
 
     #[inline(always)]
     pub fn can_define_opaque_ty(&self, id: impl Into<DefId>) -> bool {
-        let Some(id) = id.into().as_local() else { return false };
-        self.defining_opaque_types.contains(&id)
+        match self.typing_mode_unchecked() {
+            TypingMode::Analysis { defining_opaque_types } => {
+                id.into().as_local().is_some_and(|def_id| defining_opaque_types.contains(&def_id))
+            }
+            TypingMode::Coherence | TypingMode::PostAnalysis => false,
+        }
     }
 
     pub fn ty_to_string(&self, t: Ty<'tcx>) -> String {
diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs
index 853ae6d2641..2bc006c37da 100644
--- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs
@@ -2,6 +2,7 @@ use hir::def_id::{DefId, LocalDefId};
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::sync::Lrc;
 use rustc_hir as hir;
+use rustc_middle::bug;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::traits::solve::Goal;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
@@ -100,7 +101,7 @@ impl<'tcx> InferCtxt<'tcx> {
         let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() {
             ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) if def_id.is_local() => {
                 let def_id = def_id.expect_local();
-                if self.intercrate {
+                if let ty::TypingMode::Coherence = self.typing_mode(param_env) {
                     // See comment on `insert_hidden_type` for why this is sufficient in coherence
                     return Some(self.register_hidden_type(
                         OpaqueTypeKey { def_id, args },
@@ -154,7 +155,10 @@ impl<'tcx> InferCtxt<'tcx> {
                     // however in `fn fut() -> impl Future<Output = i32> { async { 42 } }`, where
                     // it is of no concern, so we only check for TAITs.
                     if self.can_define_opaque_ty(b_def_id)
-                        && self.tcx.is_type_alias_impl_trait(b_def_id)
+                        && matches!(
+                            self.tcx.opaque_ty_origin(b_def_id),
+                            hir::OpaqueTyOrigin::TyAlias { .. }
+                        )
                     {
                         self.dcx().emit_err(OpaqueHiddenTypeDiag {
                             span,
@@ -364,7 +368,7 @@ impl<'tcx> InferCtxt<'tcx> {
                     span,
                     concrete_ty,
                     r,
-                    choice_regions.clone(),
+                    Lrc::clone(&choice_regions),
                 )
             },
         });
@@ -519,28 +523,32 @@ impl<'tcx> InferCtxt<'tcx> {
         // value being folded. In simple cases like `-> impl Foo`,
         // these are the same span, but not in cases like `-> (impl
         // Foo, impl Bar)`.
-        if self.intercrate {
-            // During intercrate we do not define opaque types but instead always
-            // force ambiguity unless the hidden type is known to not implement
-            // our trait.
-            goals.push(Goal::new(self.tcx, param_env, ty::PredicateKind::Ambiguous))
-        } else {
-            let prev = self
-                .inner
-                .borrow_mut()
-                .opaque_types()
-                .register(opaque_type_key, OpaqueHiddenType { ty: hidden_ty, span });
-            if let Some(prev) = prev {
-                goals.extend(
-                    self.at(&ObligationCause::dummy_with_span(span), param_env)
-                        .eq(DefineOpaqueTypes::Yes, prev, hidden_ty)?
-                        .obligations
-                        .into_iter()
-                        // FIXME: Shuttling between obligations and goals is awkward.
-                        .map(Goal::from),
-                );
+        match self.typing_mode(param_env) {
+            ty::TypingMode::Coherence => {
+                // During intercrate we do not define opaque types but instead always
+                // force ambiguity unless the hidden type is known to not implement
+                // our trait.
+                goals.push(Goal::new(self.tcx, param_env, ty::PredicateKind::Ambiguous));
             }
-        };
+            ty::TypingMode::Analysis { .. } => {
+                let prev = self
+                    .inner
+                    .borrow_mut()
+                    .opaque_types()
+                    .register(opaque_type_key, OpaqueHiddenType { ty: hidden_ty, span });
+                if let Some(prev) = prev {
+                    goals.extend(
+                        self.at(&ObligationCause::dummy_with_span(span), param_env)
+                            .eq(DefineOpaqueTypes::Yes, prev, hidden_ty)?
+                            .obligations
+                            .into_iter()
+                            // FIXME: Shuttling between obligations and goals is awkward.
+                            .map(Goal::from),
+                    );
+                }
+            }
+            ty::TypingMode::PostAnalysis => bug!("insert hidden type post-analysis"),
+        }
 
         Ok(())
     }
diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs
index 32817dbcb21..4c80bf4e07e 100644
--- a/compiler/rustc_infer/src/infer/relate/generalize.rs
+++ b/compiler/rustc_infer/src/infer/relate/generalize.rs
@@ -9,6 +9,7 @@ use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::visit::MaxUniverse;
 use rustc_middle::ty::{
     self, AliasRelationDirection, InferConst, Term, Ty, TyCtxt, TypeVisitable, TypeVisitableExt,
+    TypingMode,
 };
 use rustc_span::Span;
 use tracing::{debug, instrument, warn};
@@ -519,7 +520,10 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
                             //
                             // cc trait-system-refactor-initiative#108
                             if self.infcx.next_trait_solver()
-                                && !self.infcx.intercrate
+                                && !matches!(
+                                    self.infcx.typing_mode_unchecked(),
+                                    TypingMode::Coherence
+                                )
                                 && self.in_alias
                             {
                                 inner.type_variables().equate(vid, new_var_id);
@@ -650,7 +654,10 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
                             // See the comment for type inference variables
                             // for more details.
                             if self.infcx.next_trait_solver()
-                                && !self.infcx.intercrate
+                                && !matches!(
+                                    self.infcx.typing_mode_unchecked(),
+                                    TypingMode::Coherence
+                                )
                                 && self.in_alias
                             {
                                 variable_table.union(vid, new_var_id);
diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs
index 3a1833452d4..b6837ec764f 100644
--- a/compiler/rustc_interface/src/queries.rs
+++ b/compiler/rustc_interface/src/queries.rs
@@ -142,7 +142,7 @@ impl Linker {
 
         Ok(Linker {
             dep_graph: tcx.dep_graph.clone(),
-            output_filenames: tcx.output_filenames(()).clone(),
+            output_filenames: Arc::clone(tcx.output_filenames(())),
             crate_hash: if tcx.needs_crate_hash() {
                 Some(tcx.crate_hash(LOCAL_CRATE))
             } else {
diff --git a/compiler/rustc_lint/Cargo.toml b/compiler/rustc_lint/Cargo.toml
index 232d4c18fa4..dd7b40d0a32 100644
--- a/compiler/rustc_lint/Cargo.toml
+++ b/compiler/rustc_lint/Cargo.toml
@@ -5,6 +5,7 @@ edition = "2021"
 
 [dependencies]
 # tidy-alphabetical-start
+rustc_abi = { path = "../rustc_abi" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
 rustc_attr = { path = "../rustc_attr" }
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 3fa43296dfc..9187f6caad4 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -268,7 +268,7 @@ lint_extern_crate_not_idiomatic = `extern crate` is not idiomatic in the new edi
 
 lint_extern_without_abi = extern declarations without an explicit ABI are deprecated
     .label = ABI should be specified here
-    .help = the default ABI is {$default_abi}
+    .suggestion = explicitly specify the {$default_abi} ABI
 
 lint_for_loops_over_fallibles =
     for loop over {$article} `{$ref_prefix}{$ty}`. This is more readably written as an `if let` statement
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index dbb8c667532..02d22ee49bd 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -16,6 +16,7 @@
 use std::fmt::Write;
 
 use ast::token::TokenKind;
+use rustc_abi::BackendRepr;
 use rustc_ast::tokenstream::{TokenStream, TokenTree};
 use rustc_ast::visit::{FnCtxt, FnKind};
 use rustc_ast::{self as ast, *};
@@ -31,7 +32,7 @@ use rustc_middle::bug;
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, Upcast, VariantDef};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypingMode, Upcast, VariantDef};
 use rustc_session::lint::FutureIncompatibilityReason;
 // hardwired lints from rustc_lint_defs
 pub use rustc_session::lint::builtin::*;
@@ -40,7 +41,6 @@ use rustc_span::edition::Edition;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{Ident, Symbol, kw, sym};
 use rustc_span::{BytePos, InnerSpan, Span};
-use rustc_target::abi::Abi;
 use rustc_target::asm::InlineAsmArch;
 use rustc_trait_selection::infer::{InferCtxtExt, TyCtxtInferExt};
 use rustc_trait_selection::traits::misc::type_allowed_to_implement_copy;
@@ -604,7 +604,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
             && cx
                 .tcx
                 .infer_ctxt()
-                .build()
+                .build(cx.typing_mode())
                 .type_implements_trait(iter_trait, [ty], cx.param_env)
                 .must_apply_modulo_regions()
         {
@@ -648,7 +648,9 @@ fn type_implements_negative_copy_modulo_regions<'tcx>(
         predicate: pred.upcast(tcx),
     };
 
-    tcx.infer_ctxt().build().predicate_must_hold_modulo_regions(&obligation)
+    tcx.infer_ctxt()
+        .build(TypingMode::non_body_analysis())
+        .predicate_must_hold_modulo_regions(&obligation)
 }
 
 declare_lint! {
@@ -2466,7 +2468,9 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
 
             // Check if this ADT has a constrained layout (like `NonNull` and friends).
             if let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(ty)) {
-                if let Abi::Scalar(scalar) | Abi::ScalarPair(scalar, _) = &layout.abi {
+                if let BackendRepr::Scalar(scalar) | BackendRepr::ScalarPair(scalar, _) =
+                    &layout.backend_repr
+                {
                     let range = scalar.valid_range(cx);
                     let msg = if !range.contains(0) {
                         "must be non-null"
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 4af1fd1baf9..aa7ec2659d0 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -11,15 +11,15 @@ use rustc_data_structures::sync;
 use rustc_data_structures::unord::UnordMap;
 use rustc_errors::{Diag, LintDiagnostic, MultiSpan};
 use rustc_feature::Features;
-use rustc_hir as hir;
 use rustc_hir::def::Res;
 use rustc_hir::def_id::{CrateNum, DefId};
 use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
+use rustc_infer::traits::Reveal;
 use rustc_middle::bug;
 use rustc_middle::middle::privacy::EffectiveVisibilities;
 use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout};
 use rustc_middle::ty::print::{PrintError, PrintTraitRefExt as _, Printer, with_no_trimmed_paths};
-use rustc_middle::ty::{self, GenericArg, RegisteredTools, Ty, TyCtxt};
+use rustc_middle::ty::{self, GenericArg, RegisteredTools, Ty, TyCtxt, TypingMode};
 use rustc_session::lint::{
     BuiltinLintDiag, FutureIncompatibleInfo, Level, Lint, LintBuffer, LintExpectationId, LintId,
 };
@@ -27,8 +27,8 @@ use rustc_session::{LintStoreMarker, Session};
 use rustc_span::Span;
 use rustc_span::edit_distance::find_best_match_for_names;
 use rustc_span::symbol::{Ident, Symbol, sym};
-use rustc_target::abi;
 use tracing::debug;
+use {rustc_abi as abi, rustc_hir as hir};
 
 use self::TargetLint::*;
 use crate::levels::LintLevelsBuilder;
@@ -699,6 +699,15 @@ impl LintContext for EarlyContext<'_> {
 }
 
 impl<'tcx> LateContext<'tcx> {
+    /// The typing mode of the currently visited node. Use this when
+    /// building a new `InferCtxt`.
+    pub fn typing_mode(&self) -> TypingMode<'tcx> {
+        debug_assert_eq!(self.param_env.reveal(), Reveal::UserFacing);
+        // FIXME(#132279): In case we're in a body, we should use a typing
+        // mode which reveals the opaque types defined by that body.
+        TypingMode::non_body_analysis()
+    }
+
     /// Gets the type-checking results for the current body,
     /// or `None` if outside a body.
     pub fn maybe_typeck_results(&self) -> Option<&'tcx ty::TypeckResults<'tcx>> {
diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs
index fcb7a6108c0..cf68e41243f 100644
--- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs
+++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs
@@ -166,7 +166,7 @@ fn suggest_question_mark<'tcx>(
     }
 
     let ty = args.type_at(0);
-    let infcx = cx.tcx.infer_ctxt().build();
+    let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode());
     let ocx = ObligationCtxt::new(&infcx);
 
     let body_def_id = cx.tcx.hir().body_owner_def_id(body_id);
diff --git a/compiler/rustc_lint/src/foreign_modules.rs b/compiler/rustc_lint/src/foreign_modules.rs
index 816882962be..394ea798d3e 100644
--- a/compiler/rustc_lint/src/foreign_modules.rs
+++ b/compiler/rustc_lint/src/foreign_modules.rs
@@ -1,3 +1,4 @@
+use rustc_abi::FIRST_VARIANT;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_data_structures::unord::{UnordMap, UnordSet};
 use rustc_hir as hir;
@@ -6,7 +7,6 @@ use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, AdtDef, Instance, Ty, TyCtxt};
 use rustc_session::declare_lint;
 use rustc_span::{Span, Symbol, sym};
-use rustc_target::abi::FIRST_VARIANT;
 use tracing::{debug, instrument};
 
 use crate::lints::{BuiltinClashingExtern, BuiltinClashingExternSub};
@@ -217,7 +217,7 @@ fn structurally_same_type<'tcx>(
         // `extern` blocks cannot be generic, so we'll always get a layout here.
         let a_layout = tcx.layout_of(param_env.and(a)).unwrap();
         let b_layout = tcx.layout_of(param_env.and(b)).unwrap();
-        assert_eq!(a_layout.abi, b_layout.abi);
+        assert_eq!(a_layout.backend_repr, b_layout.backend_repr);
         assert_eq!(a_layout.size, b_layout.size);
         assert_eq!(a_layout.align, b_layout.align);
     }
diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs
index bdfcc2c0a10..afcfbebc14b 100644
--- a/compiler/rustc_lint/src/if_let_rescope.rs
+++ b/compiler/rustc_lint/src/if_let_rescope.rs
@@ -24,7 +24,6 @@ declare_lint! {
     /// ### Example
     ///
     /// ```rust,edition2021
-    /// #![feature(if_let_rescope)]
     /// #![warn(if_let_rescope)]
     /// #![allow(unused_variables)]
     ///
@@ -243,7 +242,7 @@ impl_lint_pass!(
 
 impl<'tcx> LateLintPass<'tcx> for IfLetRescope {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
-        if expr.span.edition().at_least_rust_2024() || !cx.tcx.features().if_let_rescope() {
+        if expr.span.edition().at_least_rust_2024() {
             return;
         }
         if let (Level::Allow, _) = cx.tcx.lint_level_at_node(IF_LET_RESCOPE, expr.hir_id) {
diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs
index cc40b67ab27..026826021c8 100644
--- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs
+++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs
@@ -15,7 +15,7 @@ use rustc_middle::ty::relate::{
     Relate, RelateResult, TypeRelation, structurally_relate_consts, structurally_relate_tys,
 };
 use rustc_middle::ty::{
-    self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
+    self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode,
 };
 use rustc_middle::{bug, span_bug};
 use rustc_session::lint::FutureIncompatibilityReason;
@@ -184,7 +184,7 @@ fn check_fn(tcx: TyCtxt<'_>, parent_def_id: LocalDefId) {
         }),
         outlives_env: LazyCell::new(|| {
             let param_env = tcx.param_env(parent_def_id);
-            let infcx = tcx.infer_ctxt().build();
+            let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env));
             let ocx = ObligationCtxt::new(&infcx);
             let assumed_wf_tys = ocx.assumed_wf_types(param_env, parent_def_id).unwrap_or_default();
             let implied_bounds =
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 000f4b697bd..38e52570e53 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -2738,11 +2738,9 @@ pub(crate) struct PatternsInFnsWithoutBodySub {
 
 #[derive(LintDiagnostic)]
 #[diag(lint_extern_without_abi)]
-#[help]
 pub(crate) struct MissingAbi {
-    #[label]
+    #[suggestion(code = "extern \"{default_abi}\"", applicability = "machine-applicable")]
     pub span: Span,
-
     pub default_abi: &'static str,
 }
 
diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs
index 51877e8a034..cf25ec99e67 100644
--- a/compiler/rustc_lint/src/non_fmt_panic.rs
+++ b/compiler/rustc_lint/src/non_fmt_panic.rs
@@ -157,7 +157,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
                 Some(ty_def) if cx.tcx.is_lang_item(ty_def.did(), LangItem::String),
             );
 
-            let infcx = cx.tcx.infer_ctxt().build();
+            let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode());
             let suggest_display = is_str
                 || cx.tcx.get_diagnostic_item(sym::Display).is_some_and(|t| {
                     infcx.type_implements_trait(t, [ty], cx.param_env).may_apply()
diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
index ffbcf7f808e..5de0d4bc870 100644
--- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
+++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
@@ -69,7 +69,7 @@ declare_lint_pass!(OpaqueHiddenInferredBound => [OPAQUE_HIDDEN_INFERRED_BOUND]);
 
 impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
     fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx hir::Ty<'tcx>) {
-        let hir::TyKind::OpaqueDef(opaque, _) = &ty.kind else {
+        let hir::TyKind::OpaqueDef(opaque) = &ty.kind else {
             return;
         };
 
@@ -85,7 +85,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
         }
 
         let def_id = opaque.def_id.to_def_id();
-        let infcx = &cx.tcx.infer_ctxt().build();
+        let infcx = &cx.tcx.infer_ctxt().build(cx.typing_mode());
         // For every projection predicate in the opaque type's explicit bounds,
         // check that the type that we're assigning actually satisfies the bounds
         // of the associated type.
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index 0751d35cb9c..88878a018e7 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -1,6 +1,7 @@
 use std::iter;
 use std::ops::ControlFlow;
 
+use rustc_abi::{BackendRepr, TagEncoding, Variants, WrappingRange};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::DiagMessage;
 use rustc_hir::{Expr, ExprKind};
@@ -13,7 +14,6 @@ use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::symbol::sym;
 use rustc_span::{Span, Symbol, source_map};
-use rustc_target::abi::{Abi, TagEncoding, Variants, WrappingRange};
 use rustc_target::spec::abi::Abi as SpecAbi;
 use tracing::debug;
 use {rustc_ast as ast, rustc_hir as hir};
@@ -776,8 +776,8 @@ pub(crate) fn repr_nullable_ptr<'tcx>(
             bug!("should be able to compute the layout of non-polymorphic type");
         }
 
-        let field_ty_abi = &field_ty_layout.ok()?.abi;
-        if let Abi::Scalar(field_ty_scalar) = field_ty_abi {
+        let field_ty_abi = &field_ty_layout.ok()?.backend_repr;
+        if let BackendRepr::Scalar(field_ty_scalar) = field_ty_abi {
             match field_ty_scalar.valid_range(&tcx) {
                 WrappingRange { start: 0, end }
                     if end == field_ty_scalar.size(&tcx).unsigned_int_max() - 1 =>
diff --git a/compiler/rustc_lint/src/types/literal.rs b/compiler/rustc_lint/src/types/literal.rs
index d1e850990dc..dca42fea57d 100644
--- a/compiler/rustc_lint/src/types/literal.rs
+++ b/compiler/rustc_lint/src/types/literal.rs
@@ -1,8 +1,8 @@
 use hir::{ExprKind, Node, is_range_literal};
+use rustc_abi::{Integer, Size};
 use rustc_middle::ty::Ty;
 use rustc_middle::ty::layout::IntegerExt;
 use rustc_middle::{bug, ty};
-use rustc_target::abi::{Integer, Size};
 use {rustc_ast as ast, rustc_attr as attr, rustc_hir as hir};
 
 use crate::LateContext;
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index bbb290c9459..b50a95e7d2b 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -1610,7 +1610,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAllocation {
         }
 
         for adj in cx.typeck_results().expr_adjustments(e) {
-            if let adjustment::Adjust::Borrow(adjustment::AutoBorrow::Ref(_, m)) = adj.kind {
+            if let adjustment::Adjust::Borrow(adjustment::AutoBorrow::Ref(m)) = adj.kind {
                 match m {
                     adjustment::AutoBorrowMutability::Not => {
                         cx.emit_span_lint(UNUSED_ALLOCATION, e.span, UnusedAllocationDiag);
diff --git a/compiler/rustc_lint_defs/Cargo.toml b/compiler/rustc_lint_defs/Cargo.toml
index eb2a184ef84..450885e7164 100644
--- a/compiler/rustc_lint_defs/Cargo.toml
+++ b/compiler/rustc_lint_defs/Cargo.toml
@@ -5,6 +5,7 @@ edition = "2021"
 
 [dependencies]
 # tidy-alphabetical-start
+rustc_abi = { path = "../rustc_abi" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_error_messages = { path = "../rustc_error_messages" }
@@ -12,6 +13,5 @@ rustc_hir = { path = "../rustc_hir" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_span = { path = "../rustc_span" }
-rustc_target = { path = "../rustc_target" }
 serde = { version = "1.0.125", features = ["derive"] }
 # tidy-alphabetical-end
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index 601784f9732..0caf6ef3a6d 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -2,6 +2,7 @@
 #![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
+use rustc_abi::ExternAbi;
 use rustc_ast::node_id::NodeId;
 use rustc_ast::{AttrId, Attribute};
 use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
@@ -15,7 +16,6 @@ use rustc_macros::{Decodable, Encodable, HashStable_Generic};
 pub use rustc_span::edition::Edition;
 use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent};
 use rustc_span::{Span, Symbol, sym};
-use rustc_target::spec::abi::Abi;
 use serde::{Deserialize, Serialize};
 
 pub use self::Level::*;
@@ -602,7 +602,7 @@ pub enum BuiltinLintDiag {
         path: String,
         since_kind: DeprecatedSinceKind,
     },
-    MissingAbi(Span, Abi),
+    MissingAbi(Span, ExternAbi),
     UnusedDocComment(Span),
     UnusedBuiltinAttribute {
         attr_name: Symbol,
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 4b303511dbc..3e906f89c15 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -1251,12 +1251,12 @@ getFirstDefinitionForLinker(const GlobalValueSummaryList &GVSummaryList) {
 // here is basically the same as before threads are spawned in the `run`
 // function of `lib/LTO/ThinLTOCodeGenerator.cpp`.
 extern "C" LLVMRustThinLTOData *
-LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, int num_modules,
-                          const char **preserved_symbols, int num_symbols) {
+LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, size_t num_modules,
+                          const char **preserved_symbols, size_t num_symbols) {
   auto Ret = std::make_unique<LLVMRustThinLTOData>();
 
   // Load each module's summary and merge it into one combined index
-  for (int i = 0; i < num_modules; i++) {
+  for (size_t i = 0; i < num_modules; i++) {
     auto module = &modules[i];
     auto buffer = StringRef(module->data, module->len);
     auto mem_buffer = MemoryBufferRef(buffer, module->identifier);
@@ -1275,7 +1275,7 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, int num_modules,
 
   // Convert the preserved symbols set from string to GUID, this is then needed
   // for internalization.
-  for (int i = 0; i < num_symbols; i++) {
+  for (size_t i = 0; i < num_symbols; i++) {
     auto GUID = GlobalValue::getGUID(preserved_symbols[i]);
     Ret->GUIDPreservedSymbols.insert(GUID);
   }
@@ -1559,8 +1559,10 @@ extern "C" LLVMModuleRef LLVMRustParseBitcodeForLTO(LLVMContextRef Context,
 extern "C" const char *LLVMRustGetSliceFromObjectDataByName(const char *data,
                                                             size_t len,
                                                             const char *name,
+                                                            size_t name_len,
                                                             size_t *out_len) {
   *out_len = 0;
+  auto Name = StringRef(name, name_len);
   auto Data = StringRef(data, len);
   auto Buffer = MemoryBufferRef(Data, ""); // The id is unused.
   file_magic Type = identify_magic(Buffer.getBuffer());
@@ -1571,8 +1573,8 @@ extern "C" const char *LLVMRustGetSliceFromObjectDataByName(const char *data,
     return nullptr;
   }
   for (const object::SectionRef &Sec : (*ObjFileOrError)->sections()) {
-    Expected<StringRef> Name = Sec.getName();
-    if (Name && *Name == name) {
+    Expected<StringRef> SecName = Sec.getName();
+    if (SecName && *SecName == Name) {
       Expected<StringRef> SectionOrError = Sec.getContents();
       if (!SectionOrError) {
         LLVMRustSetLastError(toString(SectionOrError.takeError()).c_str());
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index 9f941637d8c..645b4082be5 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -853,25 +853,63 @@ extern "C" uint32_t LLVMRustVersionMinor() { return LLVM_VERSION_MINOR; }
 
 extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; }
 
-extern "C" void LLVMRustAddModuleFlagU32(LLVMModuleRef M,
-                                         Module::ModFlagBehavior MergeBehavior,
-                                         const char *Name, uint32_t Value) {
-  unwrap(M)->addModuleFlag(MergeBehavior, Name, Value);
+// FFI equivalent of LLVM's `llvm::Module::ModFlagBehavior`.
+// Must match the layout of
+// `rustc_codegen_llvm::llvm::ffi::ModuleFlagMergeBehavior`.
+//
+// There is a stable LLVM-C version of this enum (`LLVMModuleFlagBehavior`),
+// but as of LLVM 19 it does not support all of the enum values in the unstable
+// C++ API.
+enum class LLVMRustModuleFlagMergeBehavior {
+  Error = 1,
+  Warning = 2,
+  Require = 3,
+  Override = 4,
+  Append = 5,
+  AppendUnique = 6,
+  Max = 7,
+  Min = 8,
+};
+
+static Module::ModFlagBehavior
+fromRust(LLVMRustModuleFlagMergeBehavior Behavior) {
+  switch (Behavior) {
+  case LLVMRustModuleFlagMergeBehavior::Error:
+    return Module::ModFlagBehavior::Error;
+  case LLVMRustModuleFlagMergeBehavior::Warning:
+    return Module::ModFlagBehavior::Warning;
+  case LLVMRustModuleFlagMergeBehavior::Require:
+    return Module::ModFlagBehavior::Require;
+  case LLVMRustModuleFlagMergeBehavior::Override:
+    return Module::ModFlagBehavior::Override;
+  case LLVMRustModuleFlagMergeBehavior::Append:
+    return Module::ModFlagBehavior::Append;
+  case LLVMRustModuleFlagMergeBehavior::AppendUnique:
+    return Module::ModFlagBehavior::AppendUnique;
+  case LLVMRustModuleFlagMergeBehavior::Max:
+    return Module::ModFlagBehavior::Max;
+  case LLVMRustModuleFlagMergeBehavior::Min:
+    return Module::ModFlagBehavior::Min;
+  }
+  report_fatal_error("bad LLVMRustModuleFlagMergeBehavior");
+}
+
+extern "C" void
+LLVMRustAddModuleFlagU32(LLVMModuleRef M,
+                         LLVMRustModuleFlagMergeBehavior MergeBehavior,
+                         const char *Name, size_t NameLen, uint32_t Value) {
+  unwrap(M)->addModuleFlag(fromRust(MergeBehavior), StringRef(Name, NameLen),
+                           Value);
 }
 
 extern "C" void LLVMRustAddModuleFlagString(
-    LLVMModuleRef M, Module::ModFlagBehavior MergeBehavior, const char *Name,
-    const char *Value, size_t ValueLen) {
+    LLVMModuleRef M, LLVMRustModuleFlagMergeBehavior MergeBehavior,
+    const char *Name, size_t NameLen, const char *Value, size_t ValueLen) {
   unwrap(M)->addModuleFlag(
-      MergeBehavior, Name,
+      fromRust(MergeBehavior), StringRef(Name, NameLen),
       MDString::get(unwrap(M)->getContext(), StringRef(Value, ValueLen)));
 }
 
-extern "C" bool LLVMRustHasModuleFlag(LLVMModuleRef M, const char *Name,
-                                      size_t Len) {
-  return unwrap(M)->getModuleFlag(StringRef(Name, Len)) != nullptr;
-}
-
 extern "C" void LLVMRustGlobalAddMetadata(LLVMValueRef Global, unsigned Kind,
                                           LLVMMetadataRef MD) {
   unwrap<GlobalObject>(Global)->addMetadata(Kind, *unwrap<MDNode>(MD));
@@ -1231,7 +1269,7 @@ extern "C" uint64_t LLVMRustDIBuilderCreateOpPlusUconst() {
   return dwarf::DW_OP_plus_uconst;
 }
 
-extern "C" int64_t LLVMRustDIBuilderCreateOpLLVMFragment() {
+extern "C" uint64_t LLVMRustDIBuilderCreateOpLLVMFragment() {
   return dwarf::DW_OP_LLVM_fragment;
 }
 
@@ -1499,38 +1537,6 @@ LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef, RustStringRef MessageOut,
   return true;
 }
 
-extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name,
-                                                           LLVMValueRef *Inputs,
-                                                           unsigned NumInputs) {
-  return new OperandBundleDef(Name,
-                              ArrayRef<Value *>(unwrap(Inputs), NumInputs));
-}
-
-extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) {
-  delete Bundle;
-}
-
-// OpBundlesIndirect is an array of pointers (*not* a pointer to an array).
-extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty,
-                                          LLVMValueRef Fn, LLVMValueRef *Args,
-                                          unsigned NumArgs,
-                                          OperandBundleDef **OpBundlesIndirect,
-                                          unsigned NumOpBundles) {
-  Value *Callee = unwrap(Fn);
-  FunctionType *FTy = unwrap<FunctionType>(Ty);
-
-  // FIXME: Is there a way around this?
-  SmallVector<OperandBundleDef> OpBundles;
-  OpBundles.reserve(NumOpBundles);
-  for (unsigned i = 0; i < NumOpBundles; ++i) {
-    OpBundles.push_back(*OpBundlesIndirect[i]);
-  }
-
-  return wrap(unwrap(B)->CreateCall(FTy, Callee,
-                                    ArrayRef<Value *>(unwrap(Args), NumArgs),
-                                    ArrayRef<OperandBundleDef>(OpBundles)));
-}
-
 extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst,
                                             unsigned DstAlign, LLVMValueRef Src,
                                             unsigned SrcAlign,
@@ -1558,37 +1564,18 @@ extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B, LLVMValueRef Dst,
                                       MaybeAlign(DstAlign), IsVolatile));
 }
 
-// OpBundlesIndirect is an array of pointers (*not* a pointer to an array).
-extern "C" LLVMValueRef
-LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
-                    LLVMValueRef *Args, unsigned NumArgs,
-                    LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
-                    OperandBundleDef **OpBundlesIndirect, unsigned NumOpBundles,
-                    const char *Name) {
-  Value *Callee = unwrap(Fn);
-  FunctionType *FTy = unwrap<FunctionType>(Ty);
-
-  // FIXME: Is there a way around this?
-  SmallVector<OperandBundleDef> OpBundles;
-  OpBundles.reserve(NumOpBundles);
-  for (unsigned i = 0; i < NumOpBundles; ++i) {
-    OpBundles.push_back(*OpBundlesIndirect[i]);
-  }
-
-  return wrap(unwrap(B)->CreateInvoke(FTy, Callee, unwrap(Then), unwrap(Catch),
-                                      ArrayRef<Value *>(unwrap(Args), NumArgs),
-                                      ArrayRef<OperandBundleDef>(OpBundles),
-                                      Name));
-}
+// Polyfill for `LLVMBuildCallBr`, which was added in LLVM 19.
+// <https://github.com/llvm/llvm-project/commit/584253c4e2f788f870488fc32193b52d67ddaccc>
+// FIXME: Remove when Rust's minimum supported LLVM version reaches 19.
+#if LLVM_VERSION_LT(19, 0)
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OperandBundleDef, LLVMOperandBundleRef)
 
-// OpBundlesIndirect is an array of pointers (*not* a pointer to an array).
 extern "C" LLVMValueRef
-LLVMRustBuildCallBr(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
-                    LLVMBasicBlockRef DefaultDest,
-                    LLVMBasicBlockRef *IndirectDests, unsigned NumIndirectDests,
-                    LLVMValueRef *Args, unsigned NumArgs,
-                    OperandBundleDef **OpBundlesIndirect, unsigned NumOpBundles,
-                    const char *Name) {
+LLVMBuildCallBr(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
+                LLVMBasicBlockRef DefaultDest, LLVMBasicBlockRef *IndirectDests,
+                unsigned NumIndirectDests, LLVMValueRef *Args, unsigned NumArgs,
+                LLVMOperandBundleRef *Bundles, unsigned NumBundles,
+                const char *Name) {
   Value *Callee = unwrap(Fn);
   FunctionType *FTy = unwrap<FunctionType>(Ty);
 
@@ -1601,9 +1588,9 @@ LLVMRustBuildCallBr(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
 
   // FIXME: Is there a way around this?
   SmallVector<OperandBundleDef> OpBundles;
-  OpBundles.reserve(NumOpBundles);
-  for (unsigned i = 0; i < NumOpBundles; ++i) {
-    OpBundles.push_back(*OpBundlesIndirect[i]);
+  OpBundles.reserve(NumBundles);
+  for (unsigned i = 0; i < NumBundles; ++i) {
+    OpBundles.push_back(*unwrap(Bundles[i]));
   }
 
   return wrap(
@@ -1612,6 +1599,7 @@ LLVMRustBuildCallBr(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
                               ArrayRef<Value *>(unwrap(Args), NumArgs),
                               ArrayRef<OperandBundleDef>(OpBundles), Name));
 }
+#endif
 
 extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B,
                                                LLVMBasicBlockRef BB) {
diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml
index 79d3482472a..cece700b4dd 100644
--- a/compiler/rustc_metadata/Cargo.toml
+++ b/compiler/rustc_metadata/Cargo.toml
@@ -8,6 +8,7 @@ edition = "2021"
 bitflags = "2.4.1"
 libloading = "0.8.0"
 odht = { version = "0.3.1", features = ["nightly"] }
+rustc_abi = { path = "../rustc_abi" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_attr = { path = "../rustc_attr" }
 rustc_data_structures = { path = "../rustc_data_structures" }
@@ -26,7 +27,6 @@ rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
 rustc_type_ir = { path = "../rustc_type_ir" }
-snap = "1"
 tempfile = "3.2"
 tracing = "0.1"
 # tidy-alphabetical-end
diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs
index a4a69ae9514..f924ed48b6f 100644
--- a/compiler/rustc_metadata/src/locator.rs
+++ b/compiler/rustc_metadata/src/locator.rs
@@ -213,7 +213,7 @@
 //! metadata::locator or metadata::creader for all the juicy details!
 
 use std::borrow::Cow;
-use std::io::{Read, Result as IoResult, Write};
+use std::io::{Result as IoResult, Write};
 use std::ops::Deref;
 use std::path::{Path, PathBuf};
 use std::{cmp, fmt};
@@ -232,7 +232,6 @@ use rustc_session::utils::CanonicalizedPath;
 use rustc_span::Span;
 use rustc_span::symbol::Symbol;
 use rustc_target::spec::{Target, TargetTriple};
-use snap::read::FrameDecoder;
 use tracing::{debug, info};
 
 use crate::creader::{Library, MetadataLoader};
@@ -792,7 +791,6 @@ fn get_metadata_section<'p>(
         CrateFlavor::Dylib => {
             let buf =
                 loader.get_dylib_metadata(target, filename).map_err(MetadataError::LoadFailure)?;
-            // The header is uncompressed
             let header_len = METADATA_HEADER.len();
             // header + u64 length of data
             let data_start = header_len + 8;
@@ -806,7 +804,7 @@ fn get_metadata_section<'p>(
                 )));
             }
 
-            // Length of the compressed stream - this allows linkers to pad the section if they want
+            // Length of the metadata - this allows linkers to pad the section if they want
             let Ok(len_bytes) =
                 <[u8; 8]>::try_from(&buf[header_len..cmp::min(data_start, buf.len())])
             else {
@@ -814,29 +812,10 @@ fn get_metadata_section<'p>(
                     "invalid metadata length found".to_string(),
                 ));
             };
-            let compressed_len = u64::from_le_bytes(len_bytes) as usize;
+            let metadata_len = u64::from_le_bytes(len_bytes) as usize;
 
             // Header is okay -> inflate the actual metadata
-            let compressed_bytes = buf.slice(|buf| &buf[data_start..(data_start + compressed_len)]);
-            if &compressed_bytes[..cmp::min(METADATA_HEADER.len(), compressed_bytes.len())]
-                == METADATA_HEADER
-            {
-                // The metadata was not actually compressed.
-                compressed_bytes
-            } else {
-                debug!("inflating {} bytes of compressed metadata", compressed_bytes.len());
-                // Assume the decompressed data will be at least the size of the compressed data, so we
-                // don't have to grow the buffer as much.
-                let mut inflated = Vec::with_capacity(compressed_bytes.len());
-                FrameDecoder::new(&*compressed_bytes).read_to_end(&mut inflated).map_err(|_| {
-                    MetadataError::LoadFailure(format!(
-                        "failed to decompress metadata: {}",
-                        filename.display()
-                    ))
-                })?;
-
-                slice_owned(inflated, Deref::deref)
-            }
+            buf.slice(|buf| &buf[data_start..(data_start + metadata_len)])
         }
         CrateFlavor::Rmeta => {
             // mmap the file, because only a small fraction of it is read.
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 4b406496337..ebfd3c09fc1 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -1317,9 +1317,7 @@ impl<'a> CrateMetadataRef<'a> {
     }
 
     fn get_associated_item(self, id: DefIndex, sess: &'a Session) -> ty::AssocItem {
-        let name = if self.root.tables.opt_rpitit_info.get(self, id).is_some()
-            || self.root.tables.is_effects_desugaring.get(self, id)
-        {
+        let name = if self.root.tables.opt_rpitit_info.get(self, id).is_some() {
             kw::Empty
         } else {
             self.item_name(id)
@@ -1342,7 +1340,6 @@ impl<'a> CrateMetadataRef<'a> {
             container,
             fn_has_self_parameter: has_self,
             opt_rpitit_info,
-            is_effects_desugaring: self.root.tables.is_effects_desugaring.get(self, id),
         }
     }
 
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 926eb4f6210..f06f2fdc5e5 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -316,10 +316,7 @@ provide! { tcx, def_id, other, cdata,
             })
             .unwrap_or_default()
     }
-    is_type_alias_impl_trait => {
-        debug_assert_eq!(tcx.def_kind(def_id), DefKind::OpaqueTy);
-        cdata.root.tables.is_type_alias_impl_trait.get(cdata, def_id.index)
-    }
+    opaque_ty_origin => { table }
     assumed_wf_types_for_rpitit => { table }
     collect_return_position_impl_trait_in_trait_tys => {
         Ok(cdata
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 47f7a8b7c20..7277039bb7d 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -278,7 +278,7 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for SpanData {
             let source_map = s.tcx.sess.source_map();
             let source_file_index = source_map.lookup_source_file_idx(self.lo);
             s.source_file_cache =
-                (source_map.files()[source_file_index].clone(), source_file_index);
+                (Lrc::clone(&source_map.files()[source_file_index]), source_file_index);
         }
         let (ref source_file, source_file_index) = s.source_file_cache;
         debug_assert!(source_file.contains(self.lo));
@@ -1188,7 +1188,7 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) ->
         | DefKind::SyntheticCoroutineBody => true,
 
         DefKind::OpaqueTy => {
-            let origin = tcx.opaque_type_origin(def_id);
+            let origin = tcx.local_opaque_ty_origin(def_id);
             if let hir::OpaqueTyOrigin::FnReturn { parent, .. }
             | hir::OpaqueTyOrigin::AsyncFn { parent, .. } = origin
                 && let hir::Node::TraitItem(trait_item) = tcx.hir_node_by_def_id(parent)
@@ -1530,9 +1530,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             if let DefKind::OpaqueTy = def_kind {
                 self.encode_explicit_item_bounds(def_id);
                 self.encode_explicit_item_super_predicates(def_id);
-                self.tables
-                    .is_type_alias_impl_trait
-                    .set(def_id.index, self.tcx.is_type_alias_impl_trait(def_id));
+                record!(self.tables.opaque_ty_origin[def_id] <- self.tcx.opaque_ty_origin(def_id));
                 self.encode_precise_capturing_args(def_id);
             }
             if tcx.impl_method_has_trait_impl_trait_tys(def_id)
@@ -1677,9 +1675,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                 self.encode_precise_capturing_args(def_id);
             }
         }
-        if item.is_effects_desugaring {
-            self.tables.is_effects_desugaring.set(def_id.index, true);
-        }
     }
 
     fn encode_precise_capturing_args(&mut self, def_id: DefId) {
@@ -2275,7 +2270,7 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
     encoder.emit_raw_bytes(&0u64.to_le_bytes());
 
     let source_map_files = tcx.sess.source_map().files();
-    let source_file_cache = (source_map_files[0].clone(), 0);
+    let source_file_cache = (Lrc::clone(&source_map_files[0]), 0);
     let required_source_files = Some(FxIndexSet::default());
     drop(source_map_files);
 
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index a00ca27aacc..ab878760c00 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -6,6 +6,7 @@ use decoder::{DecodeContext, Metadata};
 use def_path_hash_map::DefPathHashMapRef;
 use encoder::EncodeContext;
 pub use encoder::{EncodedMetadata, encode_metadata, rendered_const};
+use rustc_abi::{FieldIdx, VariantIdx};
 use rustc_ast::expand::StrippedCfgItem;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::svh::Svh;
@@ -37,7 +38,6 @@ use rustc_span::edition::Edition;
 use rustc_span::hygiene::{ExpnIndex, MacroKind, SyntaxContextData};
 use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::{self, ExpnData, ExpnHash, ExpnId, Span};
-use rustc_target::abi::{FieldIdx, VariantIdx};
 use rustc_target::spec::{PanicStrategy, TargetTriple};
 use table::TableBuilder;
 use {rustc_ast as ast, rustc_attr as attr, rustc_hir as hir};
@@ -378,7 +378,6 @@ define_tables! {
 - defaulted:
     intrinsic: Table<DefIndex, Option<LazyValue<ty::IntrinsicDef>>>,
     is_macro_rules: Table<DefIndex, bool>,
-    is_type_alias_impl_trait: Table<DefIndex, bool>,
     type_alias_is_lazy: Table<DefIndex, bool>,
     attr_flags: Table<DefIndex, AttrFlags>,
     // The u64 is the crate-local part of the DefPathHash. All hashes in this crate have the same
@@ -396,7 +395,6 @@ define_tables! {
     inherent_impls: Table<DefIndex, LazyArray<DefIndex>>,
     associated_types_for_impl_traits_in_associated_fn: Table<DefIndex, LazyArray<DefId>>,
     opt_rpitit_info: Table<DefIndex, Option<LazyValue<ty::ImplTraitInTraitData>>>,
-    is_effects_desugaring: Table<DefIndex, bool>,
     unused_generic_params: Table<DefIndex, UnusedGenericParams>,
     // Reexported names are not associated with individual `DefId`s,
     // e.g. a glob import can introduce a lot of names, all with the same `DefId`.
@@ -469,6 +467,7 @@ define_tables! {
     doc_link_resolutions: Table<DefIndex, LazyValue<DocLinkResMap>>,
     doc_link_traits_in_scope: Table<DefIndex, LazyArray<DefId>>,
     assumed_wf_types_for_rpitit: Table<DefIndex, LazyArray<(Ty<'static>, Span)>>,
+    opaque_ty_origin: Table<DefIndex, LazyValue<hir::OpaqueTyOrigin<DefId>>>,
 }
 
 #[derive(TyEncodable, TyDecodable)]
diff --git a/compiler/rustc_middle/src/middle/debugger_visualizer.rs b/compiler/rustc_middle/src/middle/debugger_visualizer.rs
index 615a7402139..c241c06fce4 100644
--- a/compiler/rustc_middle/src/middle/debugger_visualizer.rs
+++ b/compiler/rustc_middle/src/middle/debugger_visualizer.rs
@@ -32,7 +32,7 @@ impl DebuggerVisualizerFile {
 
     pub fn path_erased(&self) -> Self {
         DebuggerVisualizerFile {
-            src: self.src.clone(),
+            src: Lrc::clone(&self.src),
             visualizer_type: self.visualizer_type,
             path: None,
         }
diff --git a/compiler/rustc_middle/src/middle/resolve_bound_vars.rs b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs
index 13e35cd0909..111ac990bc7 100644
--- a/compiler/rustc_middle/src/middle/resolve_bound_vars.rs
+++ b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs
@@ -3,7 +3,7 @@
 use rustc_data_structures::sorted_map::SortedMap;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::ItemLocalId;
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdMap};
 use rustc_macros::{Decodable, Encodable, HashStable, TyDecodable, TyEncodable};
 
 use crate::ty;
@@ -54,4 +54,6 @@ pub struct ResolveBoundVars {
     pub defs: SortedMap<ItemLocalId, ResolvedArg>,
 
     pub late_bound_vars: SortedMap<ItemLocalId, Vec<ty::BoundVariableKind>>,
+
+    pub opaque_captured_lifetimes: LocalDefIdMap<Vec<(ResolvedArg, LocalDefId)>>,
 }
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index cd148aef29b..978abab8b08 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -39,7 +39,7 @@ use crate::ty::fold::{FallibleTypeFolder, TypeFoldable};
 use crate::ty::print::{FmtPrinter, Printer, pretty_print_const, with_no_trimmed_paths};
 use crate::ty::visit::TypeVisitableExt;
 use crate::ty::{
-    self, AdtDef, GenericArg, GenericArgsRef, Instance, InstanceKind, List, Ty, TyCtxt,
+    self, AdtDef, GenericArg, GenericArgsRef, Instance, InstanceKind, List, Ty, TyCtxt, TypingMode,
     UserTypeAnnotationIndex,
 };
 
@@ -452,6 +452,15 @@ impl<'tcx> Body<'tcx> {
         self.basic_blocks.as_mut()
     }
 
+    pub fn typing_mode(&self, _tcx: TyCtxt<'tcx>) -> TypingMode<'tcx> {
+        match self.phase {
+            // FIXME(#132279): the MIR is quite clearly inside of a body, so we
+            // should instead reveal opaques defined by that body here.
+            MirPhase::Built | MirPhase::Analysis(_) => TypingMode::non_body_analysis(),
+            MirPhase::Runtime(_) => TypingMode::PostAnalysis,
+        }
+    }
+
     #[inline]
     pub fn local_kind(&self, local: Local) -> LocalKind {
         let index = local.as_usize();
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index c610fac80f6..85beb6ef1e7 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -19,9 +19,8 @@ use smallvec::SmallVec;
 
 use super::{BasicBlock, Const, Local, UserTypeProjection};
 use crate::mir::coverage::CoverageKind;
-use crate::traits::Reveal;
 use crate::ty::adjustment::PointerCoercion;
-use crate::ty::{self, GenericArgsRef, List, Region, Ty, UserTypeAnnotationIndex};
+use crate::ty::{self, GenericArgsRef, List, Region, Ty, TyCtxt, UserTypeAnnotationIndex};
 
 /// Represents the "flavors" of MIR.
 ///
@@ -102,10 +101,10 @@ impl MirPhase {
         }
     }
 
-    pub fn reveal(&self) -> Reveal {
-        match *self {
-            MirPhase::Built | MirPhase::Analysis(_) => Reveal::UserFacing,
-            MirPhase::Runtime(_) => Reveal::All,
+    pub fn param_env<'tcx>(&self, tcx: TyCtxt<'tcx>, body_def_id: DefId) -> ty::ParamEnv<'tcx> {
+        match self {
+            MirPhase::Built | MirPhase::Analysis(_) => tcx.param_env(body_def_id),
+            MirPhase::Runtime(_) => tcx.param_env_reveal_all_normalized(body_def_id),
         }
     }
 }
diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs
index 5f8427bd707..8cfc7f1e33e 100644
--- a/compiler/rustc_middle/src/query/erase.rs
+++ b/compiler/rustc_middle/src/query/erase.rs
@@ -280,6 +280,7 @@ trivial! {
     rustc_hir::IsAsync,
     rustc_hir::ItemLocalId,
     rustc_hir::LangItem,
+    rustc_hir::OpaqueTyOrigin<rustc_hir::def_id::DefId>,
     rustc_hir::OwnerId,
     rustc_hir::Upvar,
     rustc_index::bit_set::FiniteBitSet<u32>,
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index d7a60a843b7..088b5d4ec96 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -260,11 +260,10 @@ rustc_queries! {
         separate_provide_extern
     }
 
-    query is_type_alias_impl_trait(key: DefId) -> bool
+    query opaque_ty_origin(key: DefId) -> hir::OpaqueTyOrigin<DefId>
     {
-        desc { "determine whether the opaque is a type-alias impl trait" }
+        desc { "determine where the opaque originates from" }
         separate_provide_extern
-        feedable
     }
 
     query unsizing_params_for_adt(key: DefId) -> &'tcx rustc_index::bit_set::BitSet<u32>
@@ -1781,6 +1780,23 @@ rustc_queries! {
         -> &'tcx SortedMap<ItemLocalId, Vec<ty::BoundVariableKind>> {
         desc { |tcx| "looking up late bound vars inside `{}`", tcx.def_path_str(owner_id) }
     }
+    /// For an opaque type, return the list of (captured lifetime, inner generic param).
+    /// ```ignore (illustrative)
+    /// fn foo<'a: 'a, 'b, T>(&'b u8) -> impl Into<Self> + 'b { ... }
+    /// ```
+    ///
+    /// We would return `[('a, '_a), ('b, '_b)]`, with `'a` early-bound and `'b` late-bound.
+    ///
+    /// After hir_ty_lowering, we get:
+    /// ```ignore (pseudo-code)
+    /// opaque foo::<'a>::opaque<'_a, '_b>: Into<Foo<'_a>> + '_b;
+    ///                          ^^^^^^^^ inner generic params
+    /// fn foo<'a>: for<'b> fn(&'b u8) -> foo::<'a>::opaque::<'a, 'b>
+    ///                                                       ^^^^^^ captured lifetimes
+    /// ```
+    query opaque_captured_lifetimes(def_id: LocalDefId) -> &'tcx [(ResolvedArg, LocalDefId)] {
+        desc { |tcx| "listing captured lifetimes for opaque `{}`", tcx.def_path_str(def_id) }
+    }
 
     /// Computes the visibility of the provided `def_id`.
     ///
diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs
index 35a16684615..8b77a4a81ca 100644
--- a/compiler/rustc_middle/src/query/on_disk_cache.rs
+++ b/compiler/rustc_middle/src/query/on_disk_cache.rs
@@ -472,32 +472,27 @@ impl<'a, 'tcx> CacheDecoder<'a, 'tcx> {
         let CacheDecoder { tcx, file_index_to_file, file_index_to_stable_id, source_map, .. } =
             *self;
 
-        file_index_to_file
-            .borrow_mut()
-            .entry(index)
-            .or_insert_with(|| {
-                let source_file_id = &file_index_to_stable_id[&index];
-                let source_file_cnum =
-                    tcx.stable_crate_id_to_crate_num(source_file_id.stable_crate_id);
-
-                // If this `SourceFile` is from a foreign crate, then make sure
-                // that we've imported all of the source files from that crate.
-                // This has usually already been done during macro invocation.
-                // However, when encoding query results like `TypeckResults`,
-                // we might encode an `AdtDef` for a foreign type (because it
-                // was referenced in the body of the function). There is no guarantee
-                // that we will load the source files from that crate during macro
-                // expansion, so we use `import_source_files` to ensure that the foreign
-                // source files are actually imported before we call `source_file_by_stable_id`.
-                if source_file_cnum != LOCAL_CRATE {
-                    self.tcx.import_source_files(source_file_cnum);
-                }
+        Lrc::clone(file_index_to_file.borrow_mut().entry(index).or_insert_with(|| {
+            let source_file_id = &file_index_to_stable_id[&index];
+            let source_file_cnum = tcx.stable_crate_id_to_crate_num(source_file_id.stable_crate_id);
+
+            // If this `SourceFile` is from a foreign crate, then make sure
+            // that we've imported all of the source files from that crate.
+            // This has usually already been done during macro invocation.
+            // However, when encoding query results like `TypeckResults`,
+            // we might encode an `AdtDef` for a foreign type (because it
+            // was referenced in the body of the function). There is no guarantee
+            // that we will load the source files from that crate during macro
+            // expansion, so we use `import_source_files` to ensure that the foreign
+            // source files are actually imported before we call `source_file_by_stable_id`.
+            if source_file_cnum != LOCAL_CRATE {
+                self.tcx.import_source_files(source_file_cnum);
+            }
 
-                source_map
-                    .source_file_by_stable_id(source_file_id.stable_source_file_id)
-                    .expect("failed to lookup `SourceFile` in new context")
-            })
-            .clone()
+            source_map
+                .source_file_by_stable_id(source_file_id.stable_source_file_id)
+                .expect("failed to lookup `SourceFile` in new context")
+        }))
     }
 }
 
diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs
index 564d274bc8b..57da5b39ba7 100644
--- a/compiler/rustc_middle/src/query/plumbing.rs
+++ b/compiler/rustc_middle/src/query/plumbing.rs
@@ -323,7 +323,7 @@ macro_rules! define_callbacks {
                 // Increase this limit if necessary, but do try to keep the size low if possible
                 #[cfg(target_pointer_width = "64")]
                 const _: () = {
-                    if mem::size_of::<Key<'static>>() > 72 {
+                    if mem::size_of::<Key<'static>>() > 80 {
                         panic!("{}", concat!(
                             "the query `",
                             stringify!($name),
diff --git a/compiler/rustc_middle/src/ty/adjustment.rs b/compiler/rustc_middle/src/ty/adjustment.rs
index 71833eea5c0..c56038d358c 100644
--- a/compiler/rustc_middle/src/ty/adjustment.rs
+++ b/compiler/rustc_middle/src/ty/adjustment.rs
@@ -82,7 +82,7 @@ pub enum PointerCoercion {
 ///    `Box<[i32]>` is an `Adjust::Unsize` with the target `Box<[i32]>`.
 #[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
 pub struct Adjustment<'tcx> {
-    pub kind: Adjust<'tcx>,
+    pub kind: Adjust,
     pub target: Ty<'tcx>,
 }
 
@@ -93,20 +93,20 @@ impl<'tcx> Adjustment<'tcx> {
 }
 
 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
-pub enum Adjust<'tcx> {
+pub enum Adjust {
     /// Go from ! to any type.
     NeverToAny,
 
     /// Dereference once, producing a place.
-    Deref(Option<OverloadedDeref<'tcx>>),
+    Deref(Option<OverloadedDeref>),
 
     /// Take the address and produce either a `&` or `*` pointer.
-    Borrow(AutoBorrow<'tcx>),
+    Borrow(AutoBorrow),
 
     Pointer(PointerCoercion),
 
     /// Take a pinned reference and reborrow as a `Pin<&mut T>` or `Pin<&T>`.
-    ReborrowPin(ty::Region<'tcx>, hir::Mutability),
+    ReborrowPin(hir::Mutability),
 }
 
 /// An overloaded autoderef step, representing a `Deref(Mut)::deref(_mut)`
@@ -115,17 +115,16 @@ pub enum Adjust<'tcx> {
 /// being those shared by both the receiver and the returned reference.
 #[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)]
 #[derive(TypeFoldable, TypeVisitable)]
-pub struct OverloadedDeref<'tcx> {
-    pub region: ty::Region<'tcx>,
+pub struct OverloadedDeref {
     pub mutbl: hir::Mutability,
     /// The `Span` associated with the field access or method call
     /// that triggered this overloaded deref.
     pub span: Span,
 }
 
-impl<'tcx> OverloadedDeref<'tcx> {
+impl OverloadedDeref {
     /// Get the zst function item type for this method call.
-    pub fn method_call(&self, tcx: TyCtxt<'tcx>, source: Ty<'tcx>) -> Ty<'tcx> {
+    pub fn method_call<'tcx>(&self, tcx: TyCtxt<'tcx>, source: Ty<'tcx>) -> Ty<'tcx> {
         let trait_def_id = match self.mutbl {
             hir::Mutability::Not => tcx.require_lang_item(LangItem::Deref, None),
             hir::Mutability::Mut => tcx.require_lang_item(LangItem::DerefMut, None),
@@ -187,9 +186,9 @@ impl From<AutoBorrowMutability> for hir::Mutability {
 
 #[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)]
 #[derive(TypeFoldable, TypeVisitable)]
-pub enum AutoBorrow<'tcx> {
+pub enum AutoBorrow {
     /// Converts from T to &T.
-    Ref(ty::Region<'tcx>, AutoBorrowMutability),
+    Ref(AutoBorrowMutability),
 
     /// Converts from T to *T.
     RawPtr(hir::Mutability),
diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs
index db56e0016a2..3137fe9bd1d 100644
--- a/compiler/rustc_middle/src/ty/assoc.rs
+++ b/compiler/rustc_middle/src/ty/assoc.rs
@@ -34,8 +34,6 @@ pub struct AssocItem {
     /// return-position `impl Trait` in trait desugaring. The `ImplTraitInTraitData`
     /// provides additional information about its source.
     pub opt_rpitit_info: Option<ty::ImplTraitInTraitData>,
-
-    pub is_effects_desugaring: bool,
 }
 
 impl AssocItem {
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 5ae9c589ec4..9abad6d1a68 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -54,9 +54,8 @@ use rustc_type_ir::TyKind::*;
 use rustc_type_ir::fold::TypeFoldable;
 use rustc_type_ir::lang_items::TraitSolverLangItem;
 pub use rustc_type_ir::lift::Lift;
-use rustc_type_ir::solve::SolverMode;
 use rustc_type_ir::{CollectAndApply, Interner, TypeFlags, WithCachedTypeInfo, search_graph};
-use tracing::{debug, trace};
+use tracing::{debug, instrument};
 
 use crate::arena::Arena;
 use crate::dep_graph::{DepGraph, DepKindStruct};
@@ -77,8 +76,8 @@ use crate::traits::solve::{
 };
 use crate::ty::predicate::ExistentialPredicateStableCmpExt as _;
 use crate::ty::{
-    self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Clauses, Const, GenericArg, GenericArgs,
-    GenericArgsRef, GenericParamDefKind, HostPolarity, ImplPolarity, List, ListWithCachedTypeInfo,
+    self, AdtDef, AdtDefData, AdtKind, Binder, BoundConstness, Clause, Clauses, Const, GenericArg,
+    GenericArgs, GenericArgsRef, GenericParamDefKind, ImplPolarity, List, ListWithCachedTypeInfo,
     ParamConst, ParamTy, Pattern, PatternKind, PolyExistentialPredicate, PolyFnSig, Predicate,
     PredicateKind, PredicatePolarity, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty,
     TyKind, TyVid, Visibility,
@@ -170,15 +169,8 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
         tracked.get(self)
     }
 
-    fn with_global_cache<R>(
-        self,
-        mode: SolverMode,
-        f: impl FnOnce(&mut search_graph::GlobalCache<Self>) -> R,
-    ) -> R {
-        match mode {
-            SolverMode::Normal => f(&mut *self.new_solver_evaluation_cache.lock()),
-            SolverMode::Coherence => f(&mut *self.new_solver_coherence_evaluation_cache.lock()),
-        }
+    fn with_global_cache<R>(self, f: impl FnOnce(&mut search_graph::GlobalCache<Self>) -> R) -> R {
+        f(&mut *self.new_solver_evaluation_cache.lock())
     }
 
     fn evaluation_is_concurrent(&self) -> bool {
@@ -629,6 +621,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
     ) -> ty::Binder<'tcx, T> {
         self.anonymize_bound_vars(binder)
     }
+
+    fn opaque_types_defined_by(self, defining_anchor: LocalDefId) -> Self::DefiningOpaqueTypes {
+        self.opaque_types_defined_by(defining_anchor)
+    }
 }
 
 macro_rules! bidirectional_lang_item_map {
@@ -1334,7 +1330,6 @@ pub struct GlobalCtxt<'tcx> {
 
     /// Caches the results of goal evaluation in the new solver.
     pub new_solver_evaluation_cache: Lock<search_graph::GlobalCache<TyCtxt<'tcx>>>,
-    pub new_solver_coherence_evaluation_cache: Lock<search_graph::GlobalCache<TyCtxt<'tcx>>>,
 
     pub canonical_param_env_cache: CanonicalParamEnvCache<'tcx>,
 
@@ -1561,7 +1556,6 @@ impl<'tcx> TyCtxt<'tcx> {
             selection_cache: Default::default(),
             evaluation_cache: Default::default(),
             new_solver_evaluation_cache: Default::default(),
-            new_solver_coherence_evaluation_cache: Default::default(),
             canonical_param_env_cache: Default::default(),
             data_layout,
             alloc_map: Lock::new(interpret::AllocMap::new()),
@@ -2109,11 +2103,9 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     /// Returns the origin of the opaque type `def_id`.
-    #[track_caller]
-    pub fn opaque_type_origin(self, def_id: LocalDefId) -> hir::OpaqueTyOrigin {
-        let origin = self.hir().expect_opaque_ty(def_id).origin;
-        trace!("opaque_type_origin({def_id:?}) => {origin:?}");
-        origin
+    #[instrument(skip(self), level = "trace", ret)]
+    pub fn local_opaque_ty_origin(self, def_id: LocalDefId) -> hir::OpaqueTyOrigin<LocalDefId> {
+        self.hir().expect_opaque_ty(def_id).origin
     }
 }
 
@@ -2211,7 +2203,7 @@ macro_rules! nop_slice_lift {
 nop_slice_lift! {ty::ValTree<'a> => ty::ValTree<'tcx>}
 
 TrivialLiftImpls! {
-    ImplPolarity, PredicatePolarity, Promoted, HostPolarity,
+    ImplPolarity, PredicatePolarity, Promoted, BoundConstness,
 }
 
 macro_rules! sty_debug_print {
@@ -3066,7 +3058,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
         loop {
             let parent = self.local_parent(opaque_lifetime_param_def_id);
-            let hir::OpaqueTy { lifetime_mapping, .. } = self.hir().expect_opaque_ty(parent);
+            let lifetime_mapping = self.opaque_captured_lifetimes(parent);
 
             let Some((lifetime, _)) = lifetime_mapping
                 .iter()
@@ -3075,8 +3067,8 @@ impl<'tcx> TyCtxt<'tcx> {
                 bug!("duplicated lifetime param should be present");
             };
 
-            match self.named_bound_var(lifetime.hir_id) {
-                Some(resolve_bound_vars::ResolvedArg::EarlyBound(ebv)) => {
+            match *lifetime {
+                resolve_bound_vars::ResolvedArg::EarlyBound(ebv) => {
                     let new_parent = self.local_parent(ebv);
 
                     // If we map to another opaque, then it should be a parent
@@ -3095,7 +3087,7 @@ impl<'tcx> TyCtxt<'tcx> {
                         name: self.item_name(ebv.to_def_id()),
                     });
                 }
-                Some(resolve_bound_vars::ResolvedArg::LateBound(_, _, lbv)) => {
+                resolve_bound_vars::ResolvedArg::LateBound(_, _, lbv) => {
                     let new_parent = self.local_parent(lbv);
                     return ty::Region::new_late_param(
                         self,
@@ -3106,13 +3098,13 @@ impl<'tcx> TyCtxt<'tcx> {
                         ),
                     );
                 }
-                Some(resolve_bound_vars::ResolvedArg::Error(guar)) => {
+                resolve_bound_vars::ResolvedArg::Error(guar) => {
                     return ty::Region::new_error(self, guar);
                 }
                 _ => {
                     return ty::Region::new_error_with_message(
                         self,
-                        lifetime.ident.span,
+                        self.def_span(opaque_lifetime_param_def_id),
                         "cannot resolve lifetime",
                     );
                 }
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index 704a197aa49..04d03187541 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -267,7 +267,7 @@ impl FlagComputation {
             }
             ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
                 trait_ref,
-                host: _,
+                constness: _,
             })) => {
                 self.add_args(trait_ref.args);
             }
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 990fc37a1f3..0560ffe058a 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -4,8 +4,9 @@ use std::{cmp, fmt};
 
 use rustc_abi::Primitive::{self, Float, Int, Pointer};
 use rustc_abi::{
-    Abi, AddressSpace, Align, FieldsShape, HasDataLayout, Integer, LayoutCalculator, LayoutData,
-    PointeeInfo, PointerKind, ReprOptions, Scalar, Size, TagEncoding, TargetDataLayout, Variants,
+    AddressSpace, Align, BackendRepr, FieldsShape, HasDataLayout, Integer, LayoutCalculator,
+    LayoutData, PointeeInfo, PointerKind, ReprOptions, Scalar, Size, TagEncoding, TargetDataLayout,
+    Variants,
 };
 use rustc_error_messages::DiagMessage;
 use rustc_errors::{
@@ -346,7 +347,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
         // First try computing a static layout.
         let err = match tcx.layout_of(param_env.and(ty)) {
             Ok(layout) => {
-                if layout.abi.is_sized() {
+                if layout.is_sized() {
                     return Ok(SizeSkeleton::Known(layout.size, Some(layout.align.abi)));
                 } else {
                     // Just to be safe, don't claim a known layout for unsized types.
@@ -757,7 +758,7 @@ where
                         Some(fields) => FieldsShape::Union(fields),
                         None => FieldsShape::Arbitrary { offsets: IndexVec::new(), memory_index: IndexVec::new() },
                     },
-                    abi: Abi::Uninhabited,
+                    backend_repr: BackendRepr::Uninhabited,
                     largest_niche: None,
                     align: tcx.data_layout.i8_align,
                     size: Size::ZERO,
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index b92fc864b49..dac81a6dfbb 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -100,7 +100,7 @@ pub use self::rvalue_scopes::RvalueScopes;
 pub use self::sty::{
     AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig,
     CoroutineArgsExt, EarlyBinder, FnSig, InlineConstArgs, InlineConstArgsParts, ParamConst,
-    ParamTy, PolyFnSig, TyKind, TypeAndMut, UpvarArgs,
+    ParamTy, PolyFnSig, TyKind, TypeAndMut, TypingMode, UpvarArgs,
 };
 pub use self::trait_def::TraitDef;
 pub use self::typeck_results::{
@@ -1625,16 +1625,6 @@ impl<'tcx> TyCtxt<'tcx> {
         }
     }
 
-    /// Whether the `def_id` is an associated type that was desugared from a
-    /// `#[const_trait]` or `impl_const`.
-    pub fn is_effects_desugared_assoc_ty(self, def_id: DefId) -> bool {
-        if let DefKind::AssocTy = self.def_kind(def_id) {
-            self.associated_item(def_id).is_effects_desugaring
-        } else {
-            false
-        }
-    }
-
     pub fn find_field_index(self, ident: Ident, variant: &VariantDef) -> Option<FieldIdx> {
         variant.fields.iter_enumerated().find_map(|(i, field)| {
             self.hygienic_eq(ident, field.ident(self), variant.def_id).then_some(i)
diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs
index 43bdce5b576..7c280bc8b49 100644
--- a/compiler/rustc_middle/src/ty/parameterized.rs
+++ b/compiler/rustc_middle/src/ty/parameterized.rs
@@ -94,6 +94,7 @@ trivially_parameterized_over_tcx! {
     rustc_hir::def_id::DefId,
     rustc_hir::def_id::DefIndex,
     rustc_hir::definitions::DefKey,
+    rustc_hir::OpaqueTyOrigin<rustc_hir::def_id::DefId>,
     rustc_index::bit_set::BitSet<u32>,
     rustc_index::bit_set::FiniteBitSet<u32>,
     rustc_session::cstore::ForeignModule,
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 0248aad53e2..2480cee3dc4 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1959,7 +1959,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
             ty::BoundConstness::Const => {
                 p!("const ");
             }
-            ty::BoundConstness::ConstIfConst => {
+            ty::BoundConstness::Maybe => {
                 p!("~const ");
             }
         }
@@ -3076,9 +3076,9 @@ define_print! {
     }
 
     ty::HostEffectPredicate<'tcx> {
-        let constness = match self.host {
-            ty::HostPolarity::Const => { "const" }
-            ty::HostPolarity::Maybe => { "~const" }
+        let constness = match self.constness {
+            ty::BoundConstness::Const => { "const" }
+            ty::BoundConstness::Maybe => { "~const" }
         };
         p!(print(self.trait_ref.self_ty()), ": {constness} ");
         p!(print(self.trait_ref.print_trait_sugared()))
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index d8362ccc0a9..f54afdbc929 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -40,6 +40,7 @@ pub type AliasTy<'tcx> = ir::AliasTy<TyCtxt<'tcx>>;
 pub type FnSig<'tcx> = ir::FnSig<TyCtxt<'tcx>>;
 pub type Binder<'tcx, T> = ir::Binder<TyCtxt<'tcx>, T>;
 pub type EarlyBinder<'tcx, T> = ir::EarlyBinder<TyCtxt<'tcx>, T>;
+pub type TypingMode<'tcx> = ir::TypingMode<TyCtxt<'tcx>>;
 
 pub trait Article {
     fn article(&self) -> &'static str;
@@ -1353,6 +1354,7 @@ impl<'tcx> Ty<'tcx> {
         }
     }
 
+    #[tracing::instrument(level = "trace", skip(tcx))]
     pub fn fn_sig(self, tcx: TyCtxt<'tcx>) -> PolyFnSig<'tcx> {
         match self.kind() {
             FnDef(def_id, args) => tcx.fn_sig(*def_id).instantiate(tcx, args),
diff --git a/compiler/rustc_mir_build/Cargo.toml b/compiler/rustc_mir_build/Cargo.toml
index 529e9cc2711..11904722743 100644
--- a/compiler/rustc_mir_build/Cargo.toml
+++ b/compiler/rustc_mir_build/Cargo.toml
@@ -7,6 +7,8 @@ edition = "2021"
 # tidy-alphabetical-start
 either = "1.5.0"
 itertools = "0.12"
+
+rustc_abi = { path = "../rustc_abi" }
 rustc_apfloat = "0.2.0"
 rustc_arena = { path = "../rustc_arena" }
 rustc_ast = { path = "../rustc_ast" }
@@ -22,7 +24,6 @@ rustc_middle = { path = "../rustc_middle" }
 rustc_pattern_analysis = { path = "../rustc_pattern_analysis" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
-rustc_target = { path = "../rustc_target" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
 tracing = "0.1"
 # tidy-alphabetical-end
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 9e3af891052..07964e304b9 100644
--- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
+++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
@@ -1,3 +1,4 @@
+use rustc_abi::{FieldIdx, VariantIdx};
 use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::mir::*;
@@ -6,7 +7,6 @@ use rustc_middle::ty;
 use rustc_middle::ty::cast::mir_cast_kind;
 use rustc_span::Span;
 use rustc_span::source_map::Spanned;
-use rustc_target::abi::{FieldIdx, VariantIdx};
 
 use super::{PResult, ParseCtxt, parse_by_kind};
 use crate::build::custom::ParseError;
diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
index ae164cf7605..3f2e3b956fc 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
@@ -1,5 +1,6 @@
 //! See docs in build/expr/mod.rs
 
+use rustc_abi::Size;
 use rustc_ast as ast;
 use rustc_hir::LangItem;
 use rustc_middle::mir::interpret::{
@@ -11,7 +12,6 @@ use rustc_middle::ty::{
     self, CanonicalUserType, CanonicalUserTypeAnnotation, Ty, TyCtxt, UserTypeAnnotationIndex,
 };
 use rustc_middle::{bug, mir, span_bug};
-use rustc_target::abi::Size;
 use tracing::{instrument, trace};
 
 use crate::build::{Builder, parse_float_into_constval};
diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs
index c7298e3ddfa..9f6e0735b48 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_place.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs
@@ -3,6 +3,7 @@
 use std::assert_matches::assert_matches;
 use std::iter;
 
+use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx};
 use rustc_hir::def_id::LocalDefId;
 use rustc_middle::hir::place::{Projection as HirProjection, ProjectionKind as HirProjectionKind};
 use rustc_middle::middle::region;
@@ -12,7 +13,6 @@ use rustc_middle::thir::*;
 use rustc_middle::ty::{self, AdtDef, CanonicalUserTypeAnnotation, Ty, Variance};
 use rustc_middle::{bug, span_bug};
 use rustc_span::Span;
-use rustc_target::abi::{FIRST_VARIANT, FieldIdx, VariantIdx};
 use tracing::{debug, instrument, trace};
 
 use crate::build::ForGuard::{OutsideGuard, RefWithinGuard};
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 fd949a53384..1985dd3fca0 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -1,5 +1,6 @@
 //! See docs in `build/expr/mod.rs`.
 
+use rustc_abi::{BackendRepr, FieldIdx, Primitive};
 use rustc_hir::lang_items::LangItem;
 use rustc_index::{Idx, IndexVec};
 use rustc_middle::bug;
@@ -13,7 +14,6 @@ use rustc_middle::ty::util::IntTypeExt;
 use rustc_middle::ty::{self, Ty, UpvarArgs};
 use rustc_span::source_map::Spanned;
 use rustc_span::{DUMMY_SP, Span};
-use rustc_target::abi::{Abi, FieldIdx, Primitive};
 use tracing::debug;
 
 use crate::build::expr::as_place::PlaceBase;
@@ -207,7 +207,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     );
                     let (op, ty) = (Operand::Move(discr), discr_ty);
 
-                    if let Abi::Scalar(scalar) = layout.unwrap().abi
+                    if let BackendRepr::Scalar(scalar) = layout.unwrap().backend_repr
                         && !scalar.is_always_valid(&this.tcx)
                         && let Primitive::Int(int_width, _signed) = scalar.primitive()
                     {
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index 51ead570205..a62d4e9d873 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -5,6 +5,7 @@
 //! This also includes code for pattern bindings in `let` statements and
 //! function parameters.
 
+use rustc_abi::VariantIdx;
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir::{BindingMode, ByRef};
@@ -15,7 +16,6 @@ use rustc_middle::thir::{self, *};
 use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty};
 use rustc_span::symbol::Symbol;
 use rustc_span::{BytePos, Pos, Span};
-use rustc_target::abi::VariantIdx;
 use tracing::{debug, instrument};
 
 use crate::build::ForGuard::{self, OutsideGuard, RefWithinGuard};
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index 8c20d2e0d3a..1f853f6e1c3 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -1,4 +1,5 @@
 use itertools::Itertools;
+use rustc_abi::{ExternAbi, FieldIdx};
 use rustc_apfloat::Float;
 use rustc_apfloat::ieee::{Double, Half, Quad, Single};
 use rustc_ast::attr;
@@ -16,12 +17,10 @@ use rustc_middle::middle::region;
 use rustc_middle::mir::*;
 use rustc_middle::query::TyCtxtAt;
 use rustc_middle::thir::{self, ExprId, LintLevel, LocalVarId, Param, ParamId, PatKind, Thir};
-use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt, TypeVisitableExt, TypingMode};
 use rustc_middle::{bug, span_bug};
 use rustc_span::symbol::sym;
 use rustc_span::{Span, Symbol};
-use rustc_target::abi::FieldIdx;
-use rustc_target::spec::abi::Abi;
 
 use super::lints;
 use crate::build::expr::as_place::PlaceBuilder;
@@ -467,7 +466,7 @@ fn construct_fn<'tcx>(
     if let DefKind::Closure = tcx.def_kind(fn_def) {
         // HACK(eddyb) Avoid having RustCall on closures,
         // as it adds unnecessary (and wrong) auto-tupling.
-        abi = Abi::Rust;
+        abi = ExternAbi::Rust;
     }
 
     let arguments = &thir.params;
@@ -500,7 +499,9 @@ fn construct_fn<'tcx>(
         );
     }
 
-    let infcx = tcx.infer_ctxt().build();
+    // FIXME(#132279): This should be able to reveal opaque
+    // types defined during HIR typeck.
+    let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
     let mut builder = Builder::new(
         thir,
         infcx,
@@ -538,7 +539,7 @@ fn construct_fn<'tcx>(
 
     let mut body = builder.finish();
 
-    body.spread_arg = if abi == Abi::RustCall {
+    body.spread_arg = if abi == ExternAbi::RustCall {
         // RustCall pseudo-ABI untuples the last argument.
         Some(Local::new(arguments.len()))
     } else {
@@ -578,7 +579,9 @@ fn construct_const<'a, 'tcx>(
         _ => span_bug!(tcx.def_span(def), "can't build MIR for {:?}", def),
     };
 
-    let infcx = tcx.infer_ctxt().build();
+    // FIXME(#132279): We likely want to be able to use the hidden types of
+    // opaques used by this function here.
+    let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
     let mut builder =
         Builder::new(thir, infcx, def, hir_id, span, 0, const_ty, const_ty_span, None);
 
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index e2823456477..0481f715019 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -1,4 +1,5 @@
 use itertools::Itertools;
+use rustc_abi::{FIRST_VARIANT, FieldIdx};
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
@@ -18,7 +19,6 @@ use rustc_middle::ty::{
 };
 use rustc_middle::{bug, span_bug};
 use rustc_span::{Span, sym};
-use rustc_target::abi::{FIRST_VARIANT, FieldIdx};
 use tracing::{debug, info, instrument, trace};
 
 use crate::errors;
@@ -140,7 +140,7 @@ impl<'tcx> Cx<'tcx> {
 
                 expr = Expr {
                     temp_lifetime,
-                    ty: Ty::new_ref(self.tcx, deref.region, expr.ty, deref.mutbl),
+                    ty: Ty::new_ref(self.tcx, self.tcx.lifetimes.re_erased, expr.ty, deref.mutbl),
                     span,
                     kind: ExprKind::Borrow {
                         borrow_kind: deref.mutbl.to_borrow_kind(),
@@ -152,14 +152,14 @@ impl<'tcx> Cx<'tcx> {
 
                 self.overloaded_place(hir_expr, adjustment.target, Some(call), expr, deref.span)
             }
-            Adjust::Borrow(AutoBorrow::Ref(_, m)) => ExprKind::Borrow {
+            Adjust::Borrow(AutoBorrow::Ref(m)) => ExprKind::Borrow {
                 borrow_kind: m.to_borrow_kind(),
                 arg: self.thir.exprs.push(expr),
             },
             Adjust::Borrow(AutoBorrow::RawPtr(mutability)) => {
                 ExprKind::RawBorrow { mutability, arg: self.thir.exprs.push(expr) }
             }
-            Adjust::ReborrowPin(region, mutbl) => {
+            Adjust::ReborrowPin(mutbl) => {
                 debug!("apply ReborrowPin adjustment");
                 // Rewrite `$expr` as `Pin { __pointer: &(mut)? *($expr).__pointer }`
 
@@ -197,7 +197,8 @@ impl<'tcx> Cx<'tcx> {
                     hir::Mutability::Mut => BorrowKind::Mut { kind: mir::MutBorrowKind::Default },
                     hir::Mutability::Not => BorrowKind::Shared,
                 };
-                let new_pin_target = Ty::new_ref(self.tcx, region, ptr_target_ty, mutbl);
+                let new_pin_target =
+                    Ty::new_ref(self.tcx, self.tcx.lifetimes.re_erased, ptr_target_ty, mutbl);
                 let expr = self.thir.exprs.push(Expr {
                     temp_lifetime,
                     ty: new_pin_target,
@@ -784,7 +785,7 @@ impl<'tcx> Cx<'tcx> {
                 if_then_scope: region::Scope {
                     id: then.hir_id.local_id,
                     data: {
-                        if expr.span.at_least_rust_2024() && tcx.features().if_let_rescope() {
+                        if expr.span.at_least_rust_2024() {
                             region::ScopeData::IfThenRescope
                         } else {
                             region::ScopeData::IfThen
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 8498df59ce6..f222a869c03 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -79,6 +79,8 @@ enum LetSource {
     IfLetGuard,
     LetElse,
     WhileLet,
+    Else,
+    ElseIfLet,
 }
 
 struct MatchVisitor<'p, 'tcx> {
@@ -129,15 +131,20 @@ impl<'p, 'tcx> Visitor<'p, 'tcx> for MatchVisitor<'p, 'tcx> {
                 // Give a specific `let_source` for the condition.
                 let let_source = match ex.span.desugaring_kind() {
                     Some(DesugaringKind::WhileLoop) => LetSource::WhileLet,
-                    _ => LetSource::IfLet,
+                    _ => match self.let_source {
+                        LetSource::Else => LetSource::ElseIfLet,
+                        _ => LetSource::IfLet,
+                    },
                 };
                 self.with_let_source(let_source, |this| this.visit_expr(&self.thir[cond]));
                 self.with_let_source(LetSource::None, |this| {
                     this.visit_expr(&this.thir[then]);
-                    if let Some(else_) = else_opt {
-                        this.visit_expr(&this.thir[else_]);
-                    }
                 });
+                if let Some(else_) = else_opt {
+                    self.with_let_source(LetSource::Else, |this| {
+                        this.visit_expr(&this.thir[else_])
+                    });
+                }
                 return;
             }
             ExprKind::Match { scrutinee, scrutinee_hir_id: _, box ref arms, match_source } => {
@@ -573,9 +580,13 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
             // and we shouldn't lint.
             // For let guards inside a match, prefixes might use bindings of the match pattern,
             // so can't always be moved out.
+            // For `else if let`, an extra indentation level would be required to move the bindings.
             // FIXME: Add checking whether the bindings are actually used in the prefix,
             // and lint if they are not.
-            if !matches!(self.let_source, LetSource::WhileLet | LetSource::IfLetGuard) {
+            if !matches!(
+                self.let_source,
+                LetSource::WhileLet | LetSource::IfLetGuard | LetSource::ElseIfLet
+            ) {
                 // Emit the lint
                 let prefix = &chain_refutabilities[..until];
                 let span_start = prefix[0].unwrap().0;
@@ -906,8 +917,8 @@ fn report_irrefutable_let_patterns(
     }
 
     match source {
-        LetSource::None | LetSource::PlainLet => bug!(),
-        LetSource::IfLet => emit_diag!(IrrefutableLetPatternsIfLet),
+        LetSource::None | LetSource::PlainLet | LetSource::Else => bug!(),
+        LetSource::IfLet | LetSource::ElseIfLet => emit_diag!(IrrefutableLetPatternsIfLet),
         LetSource::IfLetGuard => emit_diag!(IrrefutableLetPatternsIfLetGuard),
         LetSource::LetElse => emit_diag!(IrrefutableLetPatternsLetElse),
         LetSource::WhileLet => emit_diag!(IrrefutableLetPatternsWhileLet),
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index 0dfa9168f7c..983853d2de1 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -1,4 +1,5 @@
 use either::Either;
+use rustc_abi::{FieldIdx, VariantIdx};
 use rustc_apfloat::Float;
 use rustc_hir as hir;
 use rustc_index::Idx;
@@ -7,9 +8,8 @@ use rustc_infer::traits::Obligation;
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::thir::{FieldPat, Pat, PatKind};
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, ValTree};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypingMode, ValTree};
 use rustc_span::Span;
-use rustc_target::abi::{FieldIdx, VariantIdx};
 use rustc_trait_selection::traits::ObligationCause;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
 use tracing::{debug, instrument, trace};
@@ -36,7 +36,9 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         id: hir::HirId,
         span: Span,
     ) -> Box<Pat<'tcx>> {
-        let infcx = self.tcx.infer_ctxt().build();
+        // FIXME(#132279): We likely want to be able to reveal the hidden types
+        // of opaques defined in this function here.
+        let infcx = self.tcx.infer_ctxt().build(TypingMode::non_body_analysis());
         let mut convert = ConstToPat::new(self, id, span, infcx);
         convert.to_pat(c, ty)
     }
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 56e5156a91f..ec852add94d 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -5,6 +5,7 @@ mod const_to_pat;
 
 use std::cmp::Ordering;
 
+use rustc_abi::{FieldIdx, Integer};
 use rustc_errors::codes::*;
 use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::pat_util::EnumerateAndAdjustIterator;
@@ -20,7 +21,6 @@ use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, TypeVisita
 use rustc_middle::{bug, span_bug};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::{ErrorGuaranteed, Span};
-use rustc_target::abi::{FieldIdx, Integer};
 use tracing::{debug, instrument};
 
 pub(crate) use self::check_match::check_match;
diff --git a/compiler/rustc_mir_dataflow/Cargo.toml b/compiler/rustc_mir_dataflow/Cargo.toml
index 7199db677c4..62a69b3464f 100644
--- a/compiler/rustc_mir_dataflow/Cargo.toml
+++ b/compiler/rustc_mir_dataflow/Cargo.toml
@@ -7,6 +7,7 @@ edition = "2021"
 # tidy-alphabetical-start
 polonius-engine = "0.13.0"
 regex = "1"
+rustc_abi = { path = "../rustc_abi" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
diff --git a/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs b/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs
index bb53eaf6cbd..e5cddd0e5e4 100644
--- a/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs
+++ b/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs
@@ -1,5 +1,5 @@
+use rustc_abi::VariantIdx;
 use rustc_middle::mir::{self, Body, Location, Terminator, TerminatorKind};
-use rustc_target::abi::VariantIdx;
 use tracing::debug;
 
 use super::move_paths::{InitKind, LookupResult, MoveData, MovePathIndex};
diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
index 7f2a07e2f5e..9a1f000d39d 100644
--- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
@@ -1,5 +1,6 @@
 use std::{fmt, iter};
 
+use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx};
 use rustc_hir::lang_items::LangItem;
 use rustc_index::Idx;
 use rustc_middle::mir::patch::MirPatch;
@@ -10,7 +11,6 @@ use rustc_middle::ty::util::IntTypeExt;
 use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt};
 use rustc_span::DUMMY_SP;
 use rustc_span::source_map::Spanned;
-use rustc_target::abi::{FIRST_VARIANT, FieldIdx, VariantIdx};
 use tracing::{debug, instrument};
 
 /// The value of an inserted drop flag.
diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
index 96a70f4fa5b..bac75b972f9 100644
--- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
@@ -32,8 +32,11 @@ pub(crate) struct Formatter<'mir, 'tcx, A>
 where
     A: Analysis<'tcx>,
 {
-    body: &'mir Body<'tcx>,
-    results: RefCell<Option<Results<'tcx, A>>>,
+    // The `RefCell` is used because `<Formatter as Labeller>::node_label`
+    // takes `&self`, but it needs to modify the cursor. This is also the
+    // reason for the `Formatter`/`BlockFormatter` split; `BlockFormatter` has
+    // the operations that involve the mutation, i.e. within the `borrow_mut`.
+    cursor: RefCell<ResultsCursor<'mir, 'tcx, A>>,
     style: OutputStyle,
     reachable: BitSet<BasicBlock>,
 }
@@ -48,11 +51,15 @@ where
         style: OutputStyle,
     ) -> Self {
         let reachable = mir::traversal::reachable_as_bitset(body);
-        Formatter { body, results: Some(results).into(), style, reachable }
+        Formatter { cursor: results.into_results_cursor(body).into(), style, reachable }
+    }
+
+    fn body(&self) -> &'mir Body<'tcx> {
+        self.cursor.borrow().body()
     }
 
     pub(crate) fn into_results(self) -> Results<'tcx, A> {
-        self.results.into_inner().unwrap()
+        self.cursor.into_inner().into_results()
     }
 }
 
@@ -81,7 +88,7 @@ where
     type Edge = CfgEdge;
 
     fn graph_id(&self) -> dot::Id<'_> {
-        let name = graphviz_safe_def_name(self.body.source.def_id());
+        let name = graphviz_safe_def_name(self.body().source.def_id());
         dot::Id::new(format!("graph_for_def_id_{name}")).unwrap()
     }
 
@@ -90,20 +97,11 @@ where
     }
 
     fn node_label(&self, block: &Self::Node) -> dot::LabelText<'_> {
-        let mut label = Vec::new();
-        self.results.replace_with(|results| {
-            // `Formatter::result` is a `RefCell<Option<_>>` so we can replace
-            // the value with `None`, move it into the results cursor, move it
-            // back out, and return it to the refcell wrapped in `Some`.
-            let mut fmt = BlockFormatter {
-                results: results.take().unwrap().into_results_cursor(self.body),
-                style: self.style,
-                bg: Background::Light,
-            };
+        let mut cursor = self.cursor.borrow_mut();
+        let mut fmt =
+            BlockFormatter { cursor: &mut cursor, style: self.style, bg: Background::Light };
+        let label = fmt.write_node_label(*block).unwrap();
 
-            fmt.write_node_label(&mut label, *block).unwrap();
-            Some(fmt.results.into_results())
-        });
         dot::LabelText::html(String::from_utf8(label).unwrap())
     }
 
@@ -112,12 +110,12 @@ where
     }
 
     fn edge_label(&self, e: &Self::Edge) -> dot::LabelText<'_> {
-        let label = &self.body[e.source].terminator().kind.fmt_successor_labels()[e.index];
+        let label = &self.body()[e.source].terminator().kind.fmt_successor_labels()[e.index];
         dot::LabelText::label(label.clone())
     }
 }
 
-impl<'mir, 'tcx, A> dot::GraphWalk<'mir> for Formatter<'mir, 'tcx, A>
+impl<'tcx, A> dot::GraphWalk<'_> for Formatter<'_, 'tcx, A>
 where
     A: Analysis<'tcx>,
 {
@@ -125,7 +123,7 @@ where
     type Edge = CfgEdge;
 
     fn nodes(&self) -> dot::Nodes<'_, Self::Node> {
-        self.body
+        self.body()
             .basic_blocks
             .indices()
             .filter(|&idx| self.reachable.contains(idx))
@@ -134,10 +132,10 @@ where
     }
 
     fn edges(&self) -> dot::Edges<'_, Self::Edge> {
-        self.body
-            .basic_blocks
+        let body = self.body();
+        body.basic_blocks
             .indices()
-            .flat_map(|bb| dataflow_successors(self.body, bb))
+            .flat_map(|bb| dataflow_successors(body, bb))
             .collect::<Vec<_>>()
             .into()
     }
@@ -147,20 +145,20 @@ where
     }
 
     fn target(&self, edge: &Self::Edge) -> Self::Node {
-        self.body[edge.source].terminator().successors().nth(edge.index).unwrap()
+        self.body()[edge.source].terminator().successors().nth(edge.index).unwrap()
     }
 }
 
-struct BlockFormatter<'mir, 'tcx, A>
+struct BlockFormatter<'a, 'mir, 'tcx, A>
 where
     A: Analysis<'tcx>,
 {
-    results: ResultsCursor<'mir, 'tcx, A>,
+    cursor: &'a mut ResultsCursor<'mir, 'tcx, A>,
     bg: Background,
     style: OutputStyle,
 }
 
-impl<'mir, 'tcx, A> BlockFormatter<'mir, 'tcx, A>
+impl<'tcx, A> BlockFormatter<'_, '_, 'tcx, A>
 where
     A: Analysis<'tcx>,
     A::Domain: DebugWithContext<A>,
@@ -173,7 +171,9 @@ where
         bg
     }
 
-    fn write_node_label(&mut self, w: &mut impl io::Write, block: BasicBlock) -> io::Result<()> {
+    fn write_node_label(&mut self, block: BasicBlock) -> io::Result<Vec<u8>> {
+        use std::io::Write;
+
         //   Sample output:
         //   +-+-----------------------------------------------+
         // A |                      bb4                        |
@@ -200,6 +200,9 @@ where
         // attributes. Make sure to test the output before trying to remove the redundancy.
         // Notably, `align` was found to have no effect when applied only to <table>.
 
+        let mut v = vec![];
+        let w = &mut v;
+
         let table_fmt = concat!(
             " border=\"1\"",
             " cellborder=\"1\"",
@@ -219,8 +222,8 @@ where
 
         // C: State at start of block
         self.bg = Background::Light;
-        self.results.seek_to_block_start(block);
-        let block_start_state = self.results.get().clone();
+        self.cursor.seek_to_block_start(block);
+        let block_start_state = self.cursor.get().clone();
         self.write_row_with_full_state(w, "", "(on start)")?;
 
         // D + E: Statement and terminator transfer functions
@@ -228,12 +231,12 @@ where
 
         // F: State at end of block
 
-        let terminator = self.results.body()[block].terminator();
+        let terminator = self.cursor.body()[block].terminator();
 
         // Write the full dataflow state immediately after the terminator if it differs from the
         // state at block entry.
-        self.results.seek_to_block_end(block);
-        if self.results.get() != &block_start_state || A::Direction::IS_BACKWARD {
+        self.cursor.seek_to_block_end(block);
+        if self.cursor.get() != &block_start_state || A::Direction::IS_BACKWARD {
             let after_terminator_name = match terminator.kind {
                 mir::TerminatorKind::Call { target: Some(_), .. } => "(on unwind)",
                 _ => "(on end)",
@@ -250,8 +253,8 @@ where
         match terminator.kind {
             mir::TerminatorKind::Call { destination, .. } => {
                 self.write_row(w, "", "(on successful return)", |this, w, fmt| {
-                    let state_on_unwind = this.results.get().clone();
-                    this.results.apply_custom_effect(|analysis, state| {
+                    let state_on_unwind = this.cursor.get().clone();
+                    this.cursor.apply_custom_effect(|analysis, state| {
                         analysis.apply_call_return_effect(
                             state,
                             block,
@@ -265,9 +268,9 @@ where
                         colspan = this.style.num_state_columns(),
                         fmt = fmt,
                         diff = diff_pretty(
-                            this.results.get(),
+                            this.cursor.get(),
                             &state_on_unwind,
-                            this.results.analysis()
+                            this.cursor.analysis()
                         ),
                     )
                 })?;
@@ -275,8 +278,8 @@ where
 
             mir::TerminatorKind::Yield { resume, resume_arg, .. } => {
                 self.write_row(w, "", "(on yield resume)", |this, w, fmt| {
-                    let state_on_coroutine_drop = this.results.get().clone();
-                    this.results.apply_custom_effect(|analysis, state| {
+                    let state_on_coroutine_drop = this.cursor.get().clone();
+                    this.cursor.apply_custom_effect(|analysis, state| {
                         analysis.apply_call_return_effect(
                             state,
                             resume,
@@ -290,9 +293,9 @@ where
                         colspan = this.style.num_state_columns(),
                         fmt = fmt,
                         diff = diff_pretty(
-                            this.results.get(),
+                            this.cursor.get(),
                             &state_on_coroutine_drop,
-                            this.results.analysis()
+                            this.cursor.analysis()
                         ),
                     )
                 })?;
@@ -302,8 +305,8 @@ where
                 if !targets.is_empty() =>
             {
                 self.write_row(w, "", "(on successful return)", |this, w, fmt| {
-                    let state_on_unwind = this.results.get().clone();
-                    this.results.apply_custom_effect(|analysis, state| {
+                    let state_on_unwind = this.cursor.get().clone();
+                    this.cursor.apply_custom_effect(|analysis, state| {
                         analysis.apply_call_return_effect(
                             state,
                             block,
@@ -317,9 +320,9 @@ where
                         colspan = this.style.num_state_columns(),
                         fmt = fmt,
                         diff = diff_pretty(
-                            this.results.get(),
+                            this.cursor.get(),
                             &state_on_unwind,
-                            this.results.analysis()
+                            this.cursor.analysis()
                         ),
                     )
                 })?;
@@ -328,7 +331,9 @@ where
             _ => {}
         };
 
-        write!(w, "</table>")
+        write!(w, "</table>")?;
+
+        Ok(v)
     }
 
     fn write_block_header_simple(
@@ -407,9 +412,9 @@ where
         block: BasicBlock,
     ) -> io::Result<()> {
         let diffs = StateDiffCollector::run(
-            self.results.body(),
+            self.cursor.body(),
             block,
-            self.results.mut_results(),
+            self.cursor.mut_results(),
             self.style,
         );
 
@@ -420,7 +425,7 @@ where
             if A::Direction::IS_FORWARD { it.next().unwrap() } else { it.next_back().unwrap() }
         };
 
-        for (i, statement) in self.results.body()[block].statements.iter().enumerate() {
+        for (i, statement) in self.cursor.body()[block].statements.iter().enumerate() {
             let statement_str = format!("{statement:?}");
             let index_str = format!("{i}");
 
@@ -442,7 +447,7 @@ where
         assert!(diffs_after.is_empty());
         assert!(diffs_before.as_ref().map_or(true, ExactSizeIterator::is_empty));
 
-        let terminator = self.results.body()[block].terminator();
+        let terminator = self.cursor.body()[block].terminator();
         let mut terminator_str = String::new();
         terminator.kind.fmt_head(&mut terminator_str).unwrap();
 
@@ -492,8 +497,8 @@ where
         mir: &str,
     ) -> io::Result<()> {
         self.write_row(w, i, mir, |this, w, fmt| {
-            let state = this.results.get();
-            let analysis = this.results.analysis();
+            let state = this.cursor.get();
+            let analysis = this.cursor.analysis();
 
             // FIXME: The full state vector can be quite long. It would be nice to split on commas
             // and use some text wrapping algorithm.
diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs
index 959f1ea5340..8f81da8bb04 100644
--- a/compiler/rustc_mir_dataflow/src/framework/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs
@@ -7,18 +7,17 @@
 //!
 //! The `impls` module contains several examples of dataflow analyses.
 //!
-//! Create an `Engine` for your analysis using the `into_engine` method on the `Analysis` trait,
-//! then call `iterate_to_fixpoint`. From there, you can use a `ResultsCursor` to inspect the
-//! fixpoint solution to your dataflow problem, or implement the `ResultsVisitor` interface and use
-//! `visit_results`. The following example uses the `ResultsCursor` approach.
+//! Then call `iterate_to_fixpoint` on your type that impls `Analysis` to get a `Results`. From
+//! there, you can use a `ResultsCursor` to inspect the fixpoint solution to your dataflow problem,
+//! or implement the `ResultsVisitor` interface and use `visit_results`. The following example uses
+//! the `ResultsCursor` approach.
 //!
 //! ```ignore (cross-crate-imports)
-//! use rustc_const_eval::dataflow::Analysis; // Makes `into_engine` available.
+//! use rustc_const_eval::dataflow::Analysis; // Makes `iterate_to_fixpoint` available.
 //!
 //! fn do_my_analysis(tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>) {
 //!     let analysis = MyAnalysis::new()
-//!         .into_engine(tcx, body)
-//!         .iterate_to_fixpoint()
+//!         .iterate_to_fixpoint(tcx, body, None)
 //!         .into_results_cursor(body);
 //!
 //!     // Print the dataflow state *after* each statement in the start block.
@@ -34,23 +33,29 @@
 
 use std::cmp::Ordering;
 
-use rustc_index::Idx;
+use rustc_data_structures::work_queue::WorkQueue;
 use rustc_index::bit_set::{BitSet, ChunkedBitSet, HybridBitSet};
-use rustc_middle::mir::{self, BasicBlock, CallReturnPlaces, Location, TerminatorEdges};
+use rustc_index::{Idx, IndexVec};
+use rustc_middle::bug;
+use rustc_middle::mir::{self, BasicBlock, CallReturnPlaces, Location, TerminatorEdges, traversal};
 use rustc_middle::ty::TyCtxt;
+use tracing::error;
+
+use self::results::write_graphviz_results;
+use super::fmt::DebugWithContext;
 
 mod cursor;
 mod direction;
-mod engine;
 pub mod fmt;
 pub mod graphviz;
 pub mod lattice;
+mod results;
 mod visitor;
 
 pub use self::cursor::ResultsCursor;
 pub use self::direction::{Backward, Direction, Forward};
-pub use self::engine::{Engine, Results};
 pub use self::lattice::{JoinSemiLattice, MaybeReachable};
+pub use self::results::Results;
 pub use self::visitor::{ResultsVisitable, ResultsVisitor, visit_results};
 
 /// Analysis domains are all bitsets of various kinds. This trait holds
@@ -223,26 +228,92 @@ pub trait Analysis<'tcx> {
 
     /* Extension methods */
 
-    /// Creates an `Engine` to find the fixpoint for this dataflow problem.
+    /// Finds the fixpoint for this dataflow problem.
     ///
     /// You shouldn't need to override this. Its purpose is to enable method chaining like so:
     ///
     /// ```ignore (cross-crate-imports)
     /// let results = MyAnalysis::new(tcx, body)
-    ///     .into_engine(tcx, body, def_id)
-    ///     .iterate_to_fixpoint()
+    ///     .iterate_to_fixpoint(tcx, body, None)
     ///     .into_results_cursor(body);
     /// ```
-    #[inline]
-    fn into_engine<'mir>(
-        self,
+    /// You can optionally add a `pass_name` to the graphviz output for this particular run of a
+    /// dataflow analysis. Some analyses are run multiple times in the compilation pipeline.
+    /// Without a `pass_name` to differentiates them, only the results for the latest run will be
+    /// saved.
+    fn iterate_to_fixpoint<'mir>(
+        mut self,
         tcx: TyCtxt<'tcx>,
         body: &'mir mir::Body<'tcx>,
-    ) -> Engine<'mir, 'tcx, Self>
+        pass_name: Option<&'static str>,
+    ) -> Results<'tcx, Self>
     where
         Self: Sized,
+        Self::Domain: DebugWithContext<Self>,
     {
-        Engine::new(tcx, body, self)
+        let mut entry_sets =
+            IndexVec::from_fn_n(|_| self.bottom_value(body), body.basic_blocks.len());
+        self.initialize_start_block(body, &mut entry_sets[mir::START_BLOCK]);
+
+        if Self::Direction::IS_BACKWARD && entry_sets[mir::START_BLOCK] != self.bottom_value(body) {
+            bug!("`initialize_start_block` is not yet supported for backward dataflow analyses");
+        }
+
+        let mut dirty_queue: WorkQueue<BasicBlock> = WorkQueue::with_none(body.basic_blocks.len());
+
+        if Self::Direction::IS_FORWARD {
+            for (bb, _) in traversal::reverse_postorder(body) {
+                dirty_queue.insert(bb);
+            }
+        } else {
+            // Reverse post-order on the reverse CFG may generate a better iteration order for
+            // backward dataflow analyses, but probably not enough to matter.
+            for (bb, _) in traversal::postorder(body) {
+                dirty_queue.insert(bb);
+            }
+        }
+
+        // `state` is not actually used between iterations;
+        // this is just an optimization to avoid reallocating
+        // every iteration.
+        let mut state = self.bottom_value(body);
+        while let Some(bb) = dirty_queue.pop() {
+            let bb_data = &body[bb];
+
+            // Set the state to the entry state of the block.
+            // This is equivalent to `state = entry_sets[bb].clone()`,
+            // but it saves an allocation, thus improving compile times.
+            state.clone_from(&entry_sets[bb]);
+
+            // Apply the block transfer function, using the cached one if it exists.
+            let edges = Self::Direction::apply_effects_in_block(&mut self, &mut state, bb, bb_data);
+
+            Self::Direction::join_state_into_successors_of(
+                &mut self,
+                body,
+                &mut state,
+                bb,
+                edges,
+                |target: BasicBlock, state: &Self::Domain| {
+                    let set_changed = entry_sets[target].join(state);
+                    if set_changed {
+                        dirty_queue.insert(target);
+                    }
+                },
+            );
+        }
+
+        let results = Results { analysis: self, entry_sets };
+
+        if tcx.sess.opts.unstable_opts.dump_mir_dataflow {
+            let (res, results) = write_graphviz_results(tcx, body, results, pass_name);
+            if let Err(e) = res {
+                error!("Failed to write graphviz dataflow results: {}", e);
+            }
+            results
+        } else {
+            results
+        }
     }
 }
 
diff --git a/compiler/rustc_mir_dataflow/src/framework/engine.rs b/compiler/rustc_mir_dataflow/src/framework/results.rs
index cbd1083d037..366fcbf33ba 100644
--- a/compiler/rustc_mir_dataflow/src/framework/engine.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/results.rs
@@ -1,23 +1,19 @@
-//! A solver for dataflow problems.
+//! Dataflow analysis results.
 
 use std::ffi::OsString;
 use std::path::PathBuf;
 
-use rustc_data_structures::work_queue::WorkQueue;
 use rustc_hir::def_id::DefId;
 use rustc_index::IndexVec;
-use rustc_middle::bug;
 use rustc_middle::mir::{self, BasicBlock, create_dump_file, dump_enabled, traversal};
 use rustc_middle::ty::TyCtxt;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_span::symbol::{Symbol, sym};
-use tracing::{debug, error};
+use tracing::debug;
 use {rustc_ast as ast, rustc_graphviz as dot};
 
 use super::fmt::DebugWithContext;
-use super::{
-    Analysis, Direction, JoinSemiLattice, ResultsCursor, ResultsVisitor, graphviz, visit_results,
-};
+use super::{Analysis, ResultsCursor, ResultsVisitor, graphviz, visit_results};
 use crate::errors::{
     DuplicateValuesFor, PathMustEndInFilename, RequiresAnArgument, UnknownFormatter,
 };
@@ -65,124 +61,17 @@ where
         body: &'mir mir::Body<'tcx>,
         vis: &mut impl ResultsVisitor<'mir, 'tcx, Self, Domain = A::Domain>,
     ) {
-        let blocks = mir::traversal::reachable(body);
+        let blocks = traversal::reachable(body);
         visit_results(body, blocks.map(|(bb, _)| bb), self, vis)
     }
 }
 
-/// A solver for dataflow problems.
-pub struct Engine<'mir, 'tcx, A>
-where
-    A: Analysis<'tcx>,
-{
-    tcx: TyCtxt<'tcx>,
-    body: &'mir mir::Body<'tcx>,
-    entry_sets: IndexVec<BasicBlock, A::Domain>,
-    pass_name: Option<&'static str>,
-    analysis: A,
-}
-
-impl<'mir, 'tcx, A, D> Engine<'mir, 'tcx, A>
-where
-    A: Analysis<'tcx, Domain = D>,
-    D: Clone + JoinSemiLattice,
-{
-    /// Creates a new `Engine` to solve a dataflow problem with an arbitrary transfer
-    /// function.
-    pub(crate) fn new(tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>, analysis: A) -> Self {
-        let mut entry_sets =
-            IndexVec::from_fn_n(|_| analysis.bottom_value(body), body.basic_blocks.len());
-        analysis.initialize_start_block(body, &mut entry_sets[mir::START_BLOCK]);
-
-        if A::Direction::IS_BACKWARD && entry_sets[mir::START_BLOCK] != analysis.bottom_value(body)
-        {
-            bug!("`initialize_start_block` is not yet supported for backward dataflow analyses");
-        }
-
-        Engine { analysis, tcx, body, pass_name: None, entry_sets }
-    }
-
-    /// Adds an identifier to the graphviz output for this particular run of a dataflow analysis.
-    ///
-    /// Some analyses are run multiple times in the compilation pipeline. Give them a `pass_name`
-    /// to differentiate them. Otherwise, only the results for the latest run will be saved.
-    pub fn pass_name(mut self, name: &'static str) -> Self {
-        self.pass_name = Some(name);
-        self
-    }
-
-    /// Computes the fixpoint for this dataflow problem and returns it.
-    pub fn iterate_to_fixpoint(self) -> Results<'tcx, A>
-    where
-        A::Domain: DebugWithContext<A>,
-    {
-        let Engine { mut analysis, body, mut entry_sets, tcx, pass_name } = self;
-
-        let mut dirty_queue: WorkQueue<BasicBlock> = WorkQueue::with_none(body.basic_blocks.len());
-
-        if A::Direction::IS_FORWARD {
-            for (bb, _) in traversal::reverse_postorder(body) {
-                dirty_queue.insert(bb);
-            }
-        } else {
-            // Reverse post-order on the reverse CFG may generate a better iteration order for
-            // backward dataflow analyses, but probably not enough to matter.
-            for (bb, _) in traversal::postorder(body) {
-                dirty_queue.insert(bb);
-            }
-        }
-
-        // `state` is not actually used between iterations;
-        // this is just an optimization to avoid reallocating
-        // every iteration.
-        let mut state = analysis.bottom_value(body);
-        while let Some(bb) = dirty_queue.pop() {
-            let bb_data = &body[bb];
-
-            // Set the state to the entry state of the block.
-            // This is equivalent to `state = entry_sets[bb].clone()`,
-            // but it saves an allocation, thus improving compile times.
-            state.clone_from(&entry_sets[bb]);
-
-            // Apply the block transfer function, using the cached one if it exists.
-            let edges =
-                A::Direction::apply_effects_in_block(&mut analysis, &mut state, bb, bb_data);
-
-            A::Direction::join_state_into_successors_of(
-                &mut analysis,
-                body,
-                &mut state,
-                bb,
-                edges,
-                |target: BasicBlock, state: &A::Domain| {
-                    let set_changed = entry_sets[target].join(state);
-                    if set_changed {
-                        dirty_queue.insert(target);
-                    }
-                },
-            );
-        }
-
-        let results = Results { analysis, entry_sets };
-
-        if tcx.sess.opts.unstable_opts.dump_mir_dataflow {
-            let (res, results) = write_graphviz_results(tcx, body, results, pass_name);
-            if let Err(e) = res {
-                error!("Failed to write graphviz dataflow results: {}", e);
-            }
-            results
-        } else {
-            results
-        }
-    }
-}
-
 // Graphviz
 
 /// Writes a DOT file containing the results of a dataflow analysis if the user requested it via
 /// `rustc_mir` attributes and `-Z dump-mir-dataflow`. The `Result` in and the `Results` out are
 /// the same.
-fn write_graphviz_results<'tcx, A>(
+pub(super) fn write_graphviz_results<'tcx, A>(
     tcx: TyCtxt<'tcx>,
     body: &mir::Body<'tcx>,
     results: Results<'tcx, A>,
diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs
index b284f0308f9..b404e3bfb72 100644
--- a/compiler/rustc_mir_dataflow/src/lib.rs
+++ b/compiler/rustc_mir_dataflow/src/lib.rs
@@ -18,9 +18,9 @@ pub use self::drop_flag_effects::{
     move_path_children_matching, on_all_children_bits, on_lookup_result_bits,
 };
 pub use self::framework::{
-    Analysis, Backward, Direction, Engine, Forward, GenKill, JoinSemiLattice, MaybeReachable,
-    Results, ResultsCursor, ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects, fmt, graphviz,
-    lattice, visit_results,
+    Analysis, Backward, Direction, Forward, GenKill, JoinSemiLattice, MaybeReachable, Results,
+    ResultsCursor, ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects, fmt, graphviz, lattice,
+    visit_results,
 };
 use self::move_paths::MoveData;
 
diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs
index 5727517bd61..99d0ccde105 100644
--- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs
+++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs
@@ -43,31 +43,28 @@ pub fn sanity_check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
     let move_data = MoveData::gather_moves(body, tcx, |_| true);
 
     if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_maybe_init).is_some() {
-        let flow_inits = MaybeInitializedPlaces::new(tcx, body, &move_data)
-            .into_engine(tcx, body)
-            .iterate_to_fixpoint();
+        let flow_inits =
+            MaybeInitializedPlaces::new(tcx, body, &move_data).iterate_to_fixpoint(tcx, body, None);
 
         sanity_check_via_rustc_peek(tcx, flow_inits.into_results_cursor(body));
     }
 
     if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_maybe_uninit).is_some() {
         let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &move_data)
-            .into_engine(tcx, body)
-            .iterate_to_fixpoint();
+            .iterate_to_fixpoint(tcx, body, None);
 
         sanity_check_via_rustc_peek(tcx, flow_uninits.into_results_cursor(body));
     }
 
     if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_definite_init).is_some() {
-        let flow_def_inits = DefinitelyInitializedPlaces::new(body, &move_data)
-            .into_engine(tcx, body)
-            .iterate_to_fixpoint();
+        let flow_def_inits =
+            DefinitelyInitializedPlaces::new(body, &move_data).iterate_to_fixpoint(tcx, body, None);
 
         sanity_check_via_rustc_peek(tcx, flow_def_inits.into_results_cursor(body));
     }
 
     if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_liveness).is_some() {
-        let flow_liveness = MaybeLiveLocals.into_engine(tcx, body).iterate_to_fixpoint();
+        let flow_liveness = MaybeLiveLocals.iterate_to_fixpoint(tcx, body, None);
 
         sanity_check_via_rustc_peek(tcx, flow_liveness.into_results_cursor(body));
     }
diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs
index d0f62bd82d1..af2d514fc76 100644
--- a/compiler/rustc_mir_dataflow/src/value_analysis.rs
+++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs
@@ -1,400 +1,20 @@
-//! This module provides a framework on top of the normal MIR dataflow framework to simplify the
-//! implementation of analyses that track information about the values stored in certain places.
-//! We are using the term "place" here to refer to a `mir::Place` (a place expression) instead of
-//! an `interpret::Place` (a memory location).
-//!
-//! The default methods of [`ValueAnalysis`] (prefixed with `super_` instead of `handle_`)
-//! provide some behavior that should be valid for all abstract domains that are based only on the
-//! value stored in a certain place. On top of these default rules, an implementation should
-//! override some of the `handle_` methods. For an example, see `ConstAnalysis`.
-//!
-//! An implementation must also provide a [`Map`]. Before the analysis begins, all places that
-//! should be tracked during the analysis must be registered. During the analysis, no new places
-//! can be registered. The [`State`] can be queried to retrieve the abstract value stored for a
-//! certain place by passing the map.
-//!
-//! This framework is currently experimental. Originally, it supported shared references and enum
-//! variants. However, it was discovered that both of these were unsound, and especially references
-//! had subtle but serious issues. In the future, they could be added back in, but we should clarify
-//! the rules for optimizations that rely on the aliasing model first.
-//!
-//!
-//! # Notes
-//!
-//! - The bottom state denotes uninitialized memory. Because we are only doing a sound approximation
-//! of the actual execution, we can also use this state for places where access would be UB.
-//!
-//! - The assignment logic in `State::insert_place_idx` assumes that the places are non-overlapping,
-//! or identical. Note that this refers to place expressions, not memory locations.
-//!
-//! - Currently, places that have their reference taken cannot be tracked. Although this would be
-//! possible, it has to rely on some aliasing model, which we are not ready to commit to yet.
-//! Because of that, we can assume that the only way to change the value behind a tracked place is
-//! by direct assignment.
-
-use std::assert_matches::assert_matches;
 use std::fmt::{Debug, Formatter};
 use std::ops::Range;
 
+use rustc_abi::{FieldIdx, VariantIdx};
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::{FxHashMap, FxIndexSet, StdEntry};
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_index::IndexVec;
 use rustc_index::bit_set::BitSet;
-use rustc_middle::bug;
 use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_target::abi::{FieldIdx, VariantIdx};
 use tracing::debug;
 
-use crate::fmt::DebugWithContext;
+use crate::JoinSemiLattice;
 use crate::lattice::{HasBottom, HasTop};
-use crate::{Analysis, JoinSemiLattice, SwitchIntEdgeEffects};
-
-pub trait ValueAnalysis<'tcx> {
-    /// For each place of interest, the analysis tracks a value of the given type.
-    type Value: Clone + JoinSemiLattice + HasBottom + HasTop + Debug;
-
-    const NAME: &'static str;
-
-    fn map(&self) -> &Map<'tcx>;
-
-    fn handle_statement(&self, statement: &Statement<'tcx>, state: &mut State<Self::Value>) {
-        self.super_statement(statement, state)
-    }
-
-    fn super_statement(&self, statement: &Statement<'tcx>, state: &mut State<Self::Value>) {
-        match &statement.kind {
-            StatementKind::Assign(box (place, rvalue)) => {
-                self.handle_assign(*place, rvalue, state);
-            }
-            StatementKind::SetDiscriminant { box place, variant_index } => {
-                self.handle_set_discriminant(*place, *variant_index, state);
-            }
-            StatementKind::Intrinsic(box intrinsic) => {
-                self.handle_intrinsic(intrinsic, state);
-            }
-            StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => {
-                // StorageLive leaves the local in an uninitialized state.
-                // StorageDead makes it UB to access the local afterwards.
-                state.flood_with(Place::from(*local).as_ref(), self.map(), Self::Value::BOTTOM);
-            }
-            StatementKind::Deinit(box place) => {
-                // Deinit makes the place uninitialized.
-                state.flood_with(place.as_ref(), self.map(), Self::Value::BOTTOM);
-            }
-            StatementKind::Retag(..) => {
-                // We don't track references.
-            }
-            StatementKind::ConstEvalCounter
-            | StatementKind::Nop
-            | StatementKind::FakeRead(..)
-            | StatementKind::PlaceMention(..)
-            | StatementKind::Coverage(..)
-            | StatementKind::AscribeUserType(..) => (),
-        }
-    }
-
-    fn handle_set_discriminant(
-        &self,
-        place: Place<'tcx>,
-        variant_index: VariantIdx,
-        state: &mut State<Self::Value>,
-    ) {
-        self.super_set_discriminant(place, variant_index, state)
-    }
-
-    fn super_set_discriminant(
-        &self,
-        place: Place<'tcx>,
-        _variant_index: VariantIdx,
-        state: &mut State<Self::Value>,
-    ) {
-        state.flood_discr(place.as_ref(), self.map());
-    }
-
-    fn handle_intrinsic(
-        &self,
-        intrinsic: &NonDivergingIntrinsic<'tcx>,
-        state: &mut State<Self::Value>,
-    ) {
-        self.super_intrinsic(intrinsic, state);
-    }
-
-    fn super_intrinsic(
-        &self,
-        intrinsic: &NonDivergingIntrinsic<'tcx>,
-        _state: &mut State<Self::Value>,
-    ) {
-        match intrinsic {
-            NonDivergingIntrinsic::Assume(..) => {
-                // Could use this, but ignoring it is sound.
-            }
-            NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping {
-                dst: _,
-                src: _,
-                count: _,
-            }) => {
-                // This statement represents `*dst = *src`, `count` times.
-            }
-        }
-    }
-
-    fn handle_assign(
-        &self,
-        target: Place<'tcx>,
-        rvalue: &Rvalue<'tcx>,
-        state: &mut State<Self::Value>,
-    ) {
-        self.super_assign(target, rvalue, state)
-    }
-
-    fn super_assign(
-        &self,
-        target: Place<'tcx>,
-        rvalue: &Rvalue<'tcx>,
-        state: &mut State<Self::Value>,
-    ) {
-        let result = self.handle_rvalue(rvalue, state);
-        state.assign(target.as_ref(), result, self.map());
-    }
-
-    fn handle_rvalue(
-        &self,
-        rvalue: &Rvalue<'tcx>,
-        state: &mut State<Self::Value>,
-    ) -> ValueOrPlace<Self::Value> {
-        self.super_rvalue(rvalue, state)
-    }
-
-    fn super_rvalue(
-        &self,
-        rvalue: &Rvalue<'tcx>,
-        state: &mut State<Self::Value>,
-    ) -> ValueOrPlace<Self::Value> {
-        match rvalue {
-            Rvalue::Use(operand) => self.handle_operand(operand, state),
-            Rvalue::CopyForDeref(place) => self.handle_operand(&Operand::Copy(*place), state),
-            Rvalue::Ref(..) | Rvalue::RawPtr(..) => {
-                // We don't track such places.
-                ValueOrPlace::TOP
-            }
-            Rvalue::Repeat(..)
-            | Rvalue::ThreadLocalRef(..)
-            | Rvalue::Len(..)
-            | Rvalue::Cast(..)
-            | Rvalue::BinaryOp(..)
-            | Rvalue::NullaryOp(..)
-            | Rvalue::UnaryOp(..)
-            | Rvalue::Discriminant(..)
-            | Rvalue::Aggregate(..)
-            | Rvalue::ShallowInitBox(..) => {
-                // No modification is possible through these r-values.
-                ValueOrPlace::TOP
-            }
-        }
-    }
-
-    fn handle_operand(
-        &self,
-        operand: &Operand<'tcx>,
-        state: &mut State<Self::Value>,
-    ) -> ValueOrPlace<Self::Value> {
-        self.super_operand(operand, state)
-    }
-
-    fn super_operand(
-        &self,
-        operand: &Operand<'tcx>,
-        state: &mut State<Self::Value>,
-    ) -> ValueOrPlace<Self::Value> {
-        match operand {
-            Operand::Constant(box constant) => {
-                ValueOrPlace::Value(self.handle_constant(constant, state))
-            }
-            Operand::Copy(place) | Operand::Move(place) => {
-                // On move, we would ideally flood the place with bottom. But with the current
-                // framework this is not possible (similar to `InterpCx::eval_operand`).
-                self.map()
-                    .find(place.as_ref())
-                    .map(ValueOrPlace::Place)
-                    .unwrap_or(ValueOrPlace::TOP)
-            }
-        }
-    }
-
-    fn handle_constant(
-        &self,
-        constant: &ConstOperand<'tcx>,
-        state: &mut State<Self::Value>,
-    ) -> Self::Value {
-        self.super_constant(constant, state)
-    }
-
-    fn super_constant(
-        &self,
-        _constant: &ConstOperand<'tcx>,
-        _state: &mut State<Self::Value>,
-    ) -> Self::Value {
-        Self::Value::TOP
-    }
-
-    /// The effect of a successful function call return should not be
-    /// applied here, see [`Analysis::apply_terminator_effect`].
-    fn handle_terminator<'mir>(
-        &self,
-        terminator: &'mir Terminator<'tcx>,
-        state: &mut State<Self::Value>,
-    ) -> TerminatorEdges<'mir, 'tcx> {
-        self.super_terminator(terminator, state)
-    }
-
-    fn super_terminator<'mir>(
-        &self,
-        terminator: &'mir Terminator<'tcx>,
-        state: &mut State<Self::Value>,
-    ) -> TerminatorEdges<'mir, 'tcx> {
-        match &terminator.kind {
-            TerminatorKind::Call { .. } | TerminatorKind::InlineAsm { .. } => {
-                // Effect is applied by `handle_call_return`.
-            }
-            TerminatorKind::Drop { place, .. } => {
-                state.flood_with(place.as_ref(), self.map(), Self::Value::BOTTOM);
-            }
-            TerminatorKind::Yield { .. } => {
-                // They would have an effect, but are not allowed in this phase.
-                bug!("encountered disallowed terminator");
-            }
-            TerminatorKind::SwitchInt { discr, targets } => {
-                return self.handle_switch_int(discr, targets, state);
-            }
-            TerminatorKind::TailCall { .. } => {
-                // FIXME(explicit_tail_calls): determine if we need to do something here (probably not)
-            }
-            TerminatorKind::Goto { .. }
-            | TerminatorKind::UnwindResume
-            | TerminatorKind::UnwindTerminate(_)
-            | TerminatorKind::Return
-            | TerminatorKind::Unreachable
-            | TerminatorKind::Assert { .. }
-            | TerminatorKind::CoroutineDrop
-            | TerminatorKind::FalseEdge { .. }
-            | TerminatorKind::FalseUnwind { .. } => {
-                // These terminators have no effect on the analysis.
-            }
-        }
-        terminator.edges()
-    }
-
-    fn handle_call_return(
-        &self,
-        return_places: CallReturnPlaces<'_, 'tcx>,
-        state: &mut State<Self::Value>,
-    ) {
-        self.super_call_return(return_places, state)
-    }
-
-    fn super_call_return(
-        &self,
-        return_places: CallReturnPlaces<'_, 'tcx>,
-        state: &mut State<Self::Value>,
-    ) {
-        return_places.for_each(|place| {
-            state.flood(place.as_ref(), self.map());
-        })
-    }
-
-    fn handle_switch_int<'mir>(
-        &self,
-        discr: &'mir Operand<'tcx>,
-        targets: &'mir SwitchTargets,
-        state: &mut State<Self::Value>,
-    ) -> TerminatorEdges<'mir, 'tcx> {
-        self.super_switch_int(discr, targets, state)
-    }
-
-    fn super_switch_int<'mir>(
-        &self,
-        discr: &'mir Operand<'tcx>,
-        targets: &'mir SwitchTargets,
-        _state: &mut State<Self::Value>,
-    ) -> TerminatorEdges<'mir, 'tcx> {
-        TerminatorEdges::SwitchInt { discr, targets }
-    }
-
-    fn wrap(self) -> ValueAnalysisWrapper<Self>
-    where
-        Self: Sized,
-    {
-        ValueAnalysisWrapper(self)
-    }
-}
-
-pub struct ValueAnalysisWrapper<T>(pub T);
-
-impl<'tcx, T: ValueAnalysis<'tcx>> Analysis<'tcx> for ValueAnalysisWrapper<T> {
-    type Domain = State<T::Value>;
-
-    const NAME: &'static str = T::NAME;
-
-    fn bottom_value(&self, _body: &Body<'tcx>) -> Self::Domain {
-        State::Unreachable
-    }
-
-    fn initialize_start_block(&self, body: &Body<'tcx>, state: &mut Self::Domain) {
-        // The initial state maps all tracked places of argument projections to ⊤ and the rest to ⊥.
-        assert_matches!(state, State::Unreachable);
-        *state = State::new_reachable();
-        for arg in body.args_iter() {
-            state.flood(PlaceRef { local: arg, projection: &[] }, self.0.map());
-        }
-    }
-
-    fn apply_statement_effect(
-        &mut self,
-        state: &mut Self::Domain,
-        statement: &Statement<'tcx>,
-        _location: Location,
-    ) {
-        if state.is_reachable() {
-            self.0.handle_statement(statement, state);
-        }
-    }
-
-    fn apply_terminator_effect<'mir>(
-        &mut self,
-        state: &mut Self::Domain,
-        terminator: &'mir Terminator<'tcx>,
-        _location: Location,
-    ) -> TerminatorEdges<'mir, 'tcx> {
-        if state.is_reachable() {
-            self.0.handle_terminator(terminator, state)
-        } else {
-            TerminatorEdges::None
-        }
-    }
-
-    fn apply_call_return_effect(
-        &mut self,
-        state: &mut Self::Domain,
-        _block: BasicBlock,
-        return_places: CallReturnPlaces<'_, 'tcx>,
-    ) {
-        if state.is_reachable() {
-            self.0.handle_call_return(return_places, state)
-        }
-    }
-
-    fn apply_switch_int_edge_effects(
-        &mut self,
-        _block: BasicBlock,
-        _discr: &Operand<'tcx>,
-        _apply_edge_effects: &mut impl SwitchIntEdgeEffects<Self::Domain>,
-    ) {
-    }
-}
 
 rustc_index::newtype_index!(
     /// This index uniquely identifies a place.
@@ -464,7 +84,7 @@ impl<V: JoinSemiLattice + Clone + HasBottom> JoinSemiLattice for StateData<V> {
     }
 }
 
-/// The dataflow state for an instance of [`ValueAnalysis`].
+/// Dataflow state.
 ///
 /// Every instance specifies a lattice that represents the possible values of a single tracked
 /// place. If we call this lattice `V` and set of tracked places `P`, then a [`State`] is an
@@ -514,7 +134,7 @@ impl<V: Clone + HasBottom> State<V> {
         }
     }
 
-    fn is_reachable(&self) -> bool {
+    pub fn is_reachable(&self) -> bool {
         matches!(self, State::Reachable(_))
     }
 
@@ -858,7 +478,7 @@ impl<'tcx> Map<'tcx> {
             // Allocate a value slot if it doesn't have one, and the user requested one.
             assert!(place_info.value_index.is_none());
             if let Ok(layout) = tcx.layout_of(param_env.and(place_info.ty))
-                && layout.abi.is_scalar()
+                && layout.backend_repr.is_scalar()
             {
                 place_info.value_index = Some(self.value_count.into());
                 self.value_count += 1;
@@ -1317,34 +937,6 @@ pub fn excluded_locals(body: &Body<'_>) -> BitSet<Local> {
     collector.result
 }
 
-/// This is used to visualize the dataflow analysis.
-impl<'tcx, T> DebugWithContext<ValueAnalysisWrapper<T>> for State<T::Value>
-where
-    T: ValueAnalysis<'tcx>,
-    T::Value: Debug,
-{
-    fn fmt_with(&self, ctxt: &ValueAnalysisWrapper<T>, f: &mut Formatter<'_>) -> std::fmt::Result {
-        match self {
-            State::Reachable(values) => debug_with_context(values, None, ctxt.0.map(), f),
-            State::Unreachable => write!(f, "unreachable"),
-        }
-    }
-
-    fn fmt_diff_with(
-        &self,
-        old: &Self,
-        ctxt: &ValueAnalysisWrapper<T>,
-        f: &mut Formatter<'_>,
-    ) -> std::fmt::Result {
-        match (self, old) {
-            (State::Reachable(this), State::Reachable(old)) => {
-                debug_with_context(this, Some(old), ctxt.0.map(), f)
-            }
-            _ => Ok(()), // Consider printing something here.
-        }
-    }
-}
-
 fn debug_with_context_rec<V: Debug + Eq + HasBottom>(
     place: PlaceIndex,
     place_str: &str,
@@ -1391,7 +983,7 @@ fn debug_with_context_rec<V: Debug + Eq + HasBottom>(
     Ok(())
 }
 
-fn debug_with_context<V: Debug + Eq + HasBottom>(
+pub fn debug_with_context<V: Debug + Eq + HasBottom>(
     new: &StateData<V>,
     old: Option<&StateData<V>>,
     map: &Map<'_>,
diff --git a/compiler/rustc_mir_transform/Cargo.toml b/compiler/rustc_mir_transform/Cargo.toml
index 07ca51a67ae..4b648d21084 100644
--- a/compiler/rustc_mir_transform/Cargo.toml
+++ b/compiler/rustc_mir_transform/Cargo.toml
@@ -7,6 +7,7 @@ edition = "2021"
 # tidy-alphabetical-start
 either = "1"
 itertools = "0.12"
+rustc_abi = { path = "../rustc_abi" }
 rustc_arena = { path = "../rustc_arena" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_attr = { path = "../rustc_attr" }
diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs
index cd291058977..6d5665b4331 100644
--- a/compiler/rustc_mir_transform/src/coroutine.rs
+++ b/compiler/rustc_mir_transform/src/coroutine.rs
@@ -64,7 +64,7 @@ use rustc_index::{Idx, IndexVec};
 use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
 use rustc_middle::mir::*;
 use rustc_middle::ty::{
-    self, CoroutineArgs, CoroutineArgsExt, GenericArgsRef, InstanceKind, Ty, TyCtxt,
+    self, CoroutineArgs, CoroutineArgsExt, GenericArgsRef, InstanceKind, Ty, TyCtxt, TypingMode,
 };
 use rustc_middle::{bug, span_bug};
 use rustc_mir_dataflow::Analysis;
@@ -666,14 +666,13 @@ fn locals_live_across_suspend_points<'tcx>(
     // Calculate when MIR locals have live storage. This gives us an upper bound of their
     // lifetimes.
     let mut storage_live = MaybeStorageLive::new(std::borrow::Cow::Borrowed(always_live_locals))
-        .into_engine(tcx, body)
-        .iterate_to_fixpoint()
+        .iterate_to_fixpoint(tcx, body, None)
         .into_results_cursor(body);
 
     // Calculate the MIR locals which have been previously
     // borrowed (even if they are still active).
     let borrowed_locals_results =
-        MaybeBorrowedLocals.into_engine(tcx, body).pass_name("coroutine").iterate_to_fixpoint();
+        MaybeBorrowedLocals.iterate_to_fixpoint(tcx, body, Some("coroutine"));
 
     let mut borrowed_locals_cursor = borrowed_locals_results.clone().into_results_cursor(body);
 
@@ -681,16 +680,12 @@ fn locals_live_across_suspend_points<'tcx>(
     // for.
     let mut requires_storage_cursor =
         MaybeRequiresStorage::new(borrowed_locals_results.into_results_cursor(body))
-            .into_engine(tcx, body)
-            .iterate_to_fixpoint()
+            .iterate_to_fixpoint(tcx, body, None)
             .into_results_cursor(body);
 
     // Calculate the liveness of MIR locals ignoring borrows.
-    let mut liveness = MaybeLiveLocals
-        .into_engine(tcx, body)
-        .pass_name("coroutine")
-        .iterate_to_fixpoint()
-        .into_results_cursor(body);
+    let mut liveness =
+        MaybeLiveLocals.iterate_to_fixpoint(tcx, body, Some("coroutine")).into_results_cursor(body);
 
     let mut storage_liveness_map = IndexVec::from_elem(None, &body.basic_blocks);
     let mut live_locals_at_suspension_points = Vec::new();
@@ -1501,7 +1496,11 @@ fn check_field_tys_sized<'tcx>(
         return;
     }
 
-    let infcx = tcx.infer_ctxt().ignoring_regions().build();
+    // FIXME(#132279): @lcnr believes that we may want to support coroutines
+    // whose `Sized`-ness relies on the hidden types of opaques defined by the
+    // parent function. In this case we'd have to be able to reveal only these
+    // opaques here.
+    let infcx = tcx.infer_ctxt().ignoring_regions().build(TypingMode::non_body_analysis());
     let param_env = tcx.param_env(def_id);
 
     let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
index 002216f50f2..dd85d06540d 100644
--- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
+++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
@@ -2,6 +2,10 @@
 //!
 //! Currently, this pass only propagates scalar values.
 
+use std::assert_matches::assert_matches;
+use std::fmt::Formatter;
+
+use rustc_abi::{BackendRepr, FIRST_VARIANT, FieldIdx, Size, VariantIdx};
 use rustc_const_eval::const_eval::{DummyMachine, throw_machine_stop_str};
 use rustc_const_eval::interpret::{
     ImmTy, Immediate, InterpCx, OpTy, PlaceTy, Projectable, interp_ok,
@@ -14,13 +18,13 @@ use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
 use rustc_middle::mir::*;
 use rustc_middle::ty::layout::{HasParamEnv, LayoutOf};
 use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_mir_dataflow::lattice::FlatSet;
+use rustc_mir_dataflow::fmt::DebugWithContext;
+use rustc_mir_dataflow::lattice::{FlatSet, HasBottom};
 use rustc_mir_dataflow::value_analysis::{
-    Map, PlaceIndex, State, TrackElem, ValueAnalysis, ValueAnalysisWrapper, ValueOrPlace,
+    Map, PlaceIndex, State, TrackElem, ValueOrPlace, debug_with_context,
 };
 use rustc_mir_dataflow::{Analysis, Results, ResultsVisitor};
 use rustc_span::DUMMY_SP;
-use rustc_target::abi::{Abi, FIRST_VARIANT, FieldIdx, Size, VariantIdx};
 use tracing::{debug, debug_span, instrument};
 
 // These constants are somewhat random guesses and have not been optimized.
@@ -58,8 +62,8 @@ impl<'tcx> crate::MirPass<'tcx> for DataflowConstProp {
 
         // Perform the actual dataflow analysis.
         let analysis = ConstAnalysis::new(tcx, body, map);
-        let mut results = debug_span!("analyze")
-            .in_scope(|| analysis.wrap().into_engine(tcx, body).iterate_to_fixpoint());
+        let mut results =
+            debug_span!("analyze").in_scope(|| analysis.iterate_to_fixpoint(tcx, body, None));
 
         // Collect results and patch the body afterwards.
         let mut visitor = Collector::new(tcx, &body.local_decls);
@@ -69,6 +73,10 @@ impl<'tcx> crate::MirPass<'tcx> for DataflowConstProp {
     }
 }
 
+// Note: Currently, places that have their reference taken cannot be tracked. Although this would
+// be possible, it has to rely on some aliasing model, which we are not ready to commit to yet.
+// Because of that, we can assume that the only way to change the value behind a tracked place is
+// by direct assignment.
 struct ConstAnalysis<'a, 'tcx> {
     map: Map<'tcx>,
     tcx: TyCtxt<'tcx>,
@@ -77,20 +85,198 @@ struct ConstAnalysis<'a, 'tcx> {
     param_env: ty::ParamEnv<'tcx>,
 }
 
-impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
-    type Value = FlatSet<Scalar>;
+impl<'tcx> Analysis<'tcx> for ConstAnalysis<'_, 'tcx> {
+    type Domain = State<FlatSet<Scalar>>;
 
     const NAME: &'static str = "ConstAnalysis";
 
-    fn map(&self) -> &Map<'tcx> {
-        &self.map
+    // The bottom state denotes uninitialized memory. Because we are only doing a sound
+    // approximation of the actual execution, we can also use this state for places where access
+    // would be UB.
+    fn bottom_value(&self, _body: &Body<'tcx>) -> Self::Domain {
+        State::Unreachable
+    }
+
+    fn initialize_start_block(&self, body: &Body<'tcx>, state: &mut Self::Domain) {
+        // The initial state maps all tracked places of argument projections to ⊤ and the rest to ⊥.
+        assert_matches!(state, State::Unreachable);
+        *state = State::new_reachable();
+        for arg in body.args_iter() {
+            state.flood(PlaceRef { local: arg, projection: &[] }, &self.map);
+        }
+    }
+
+    fn apply_statement_effect(
+        &mut self,
+        state: &mut Self::Domain,
+        statement: &Statement<'tcx>,
+        _location: Location,
+    ) {
+        if state.is_reachable() {
+            self.handle_statement(statement, state);
+        }
+    }
+
+    fn apply_terminator_effect<'mir>(
+        &mut self,
+        state: &mut Self::Domain,
+        terminator: &'mir Terminator<'tcx>,
+        _location: Location,
+    ) -> TerminatorEdges<'mir, 'tcx> {
+        if state.is_reachable() {
+            self.handle_terminator(terminator, state)
+        } else {
+            TerminatorEdges::None
+        }
+    }
+
+    fn apply_call_return_effect(
+        &mut self,
+        state: &mut Self::Domain,
+        _block: BasicBlock,
+        return_places: CallReturnPlaces<'_, 'tcx>,
+    ) {
+        if state.is_reachable() {
+            self.handle_call_return(return_places, state)
+        }
+    }
+}
+
+impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
+    fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, map: Map<'tcx>) -> Self {
+        let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
+        Self {
+            map,
+            tcx,
+            local_decls: &body.local_decls,
+            ecx: InterpCx::new(tcx, DUMMY_SP, param_env, DummyMachine),
+            param_env,
+        }
+    }
+
+    fn handle_statement(&self, statement: &Statement<'tcx>, state: &mut State<FlatSet<Scalar>>) {
+        match &statement.kind {
+            StatementKind::Assign(box (place, rvalue)) => {
+                self.handle_assign(*place, rvalue, state);
+            }
+            StatementKind::SetDiscriminant { box place, variant_index } => {
+                self.handle_set_discriminant(*place, *variant_index, state);
+            }
+            StatementKind::Intrinsic(box intrinsic) => {
+                self.handle_intrinsic(intrinsic);
+            }
+            StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => {
+                // StorageLive leaves the local in an uninitialized state.
+                // StorageDead makes it UB to access the local afterwards.
+                state.flood_with(
+                    Place::from(*local).as_ref(),
+                    &self.map,
+                    FlatSet::<Scalar>::BOTTOM,
+                );
+            }
+            StatementKind::Deinit(box place) => {
+                // Deinit makes the place uninitialized.
+                state.flood_with(place.as_ref(), &self.map, FlatSet::<Scalar>::BOTTOM);
+            }
+            StatementKind::Retag(..) => {
+                // We don't track references.
+            }
+            StatementKind::ConstEvalCounter
+            | StatementKind::Nop
+            | StatementKind::FakeRead(..)
+            | StatementKind::PlaceMention(..)
+            | StatementKind::Coverage(..)
+            | StatementKind::AscribeUserType(..) => (),
+        }
+    }
+
+    fn handle_intrinsic(&self, intrinsic: &NonDivergingIntrinsic<'tcx>) {
+        match intrinsic {
+            NonDivergingIntrinsic::Assume(..) => {
+                // Could use this, but ignoring it is sound.
+            }
+            NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping {
+                dst: _,
+                src: _,
+                count: _,
+            }) => {
+                // This statement represents `*dst = *src`, `count` times.
+            }
+        }
+    }
+
+    fn handle_operand(
+        &self,
+        operand: &Operand<'tcx>,
+        state: &mut State<FlatSet<Scalar>>,
+    ) -> ValueOrPlace<FlatSet<Scalar>> {
+        match operand {
+            Operand::Constant(box constant) => {
+                ValueOrPlace::Value(self.handle_constant(constant, state))
+            }
+            Operand::Copy(place) | Operand::Move(place) => {
+                // On move, we would ideally flood the place with bottom. But with the current
+                // framework this is not possible (similar to `InterpCx::eval_operand`).
+                self.map.find(place.as_ref()).map(ValueOrPlace::Place).unwrap_or(ValueOrPlace::TOP)
+            }
+        }
+    }
+
+    /// The effect of a successful function call return should not be
+    /// applied here, see [`Analysis::apply_terminator_effect`].
+    fn handle_terminator<'mir>(
+        &self,
+        terminator: &'mir Terminator<'tcx>,
+        state: &mut State<FlatSet<Scalar>>,
+    ) -> TerminatorEdges<'mir, 'tcx> {
+        match &terminator.kind {
+            TerminatorKind::Call { .. } | TerminatorKind::InlineAsm { .. } => {
+                // Effect is applied by `handle_call_return`.
+            }
+            TerminatorKind::Drop { place, .. } => {
+                state.flood_with(place.as_ref(), &self.map, FlatSet::<Scalar>::BOTTOM);
+            }
+            TerminatorKind::Yield { .. } => {
+                // They would have an effect, but are not allowed in this phase.
+                bug!("encountered disallowed terminator");
+            }
+            TerminatorKind::SwitchInt { discr, targets } => {
+                return self.handle_switch_int(discr, targets, state);
+            }
+            TerminatorKind::TailCall { .. } => {
+                // FIXME(explicit_tail_calls): determine if we need to do something here (probably
+                // not)
+            }
+            TerminatorKind::Goto { .. }
+            | TerminatorKind::UnwindResume
+            | TerminatorKind::UnwindTerminate(_)
+            | TerminatorKind::Return
+            | TerminatorKind::Unreachable
+            | TerminatorKind::Assert { .. }
+            | TerminatorKind::CoroutineDrop
+            | TerminatorKind::FalseEdge { .. }
+            | TerminatorKind::FalseUnwind { .. } => {
+                // These terminators have no effect on the analysis.
+            }
+        }
+        terminator.edges()
+    }
+
+    fn handle_call_return(
+        &self,
+        return_places: CallReturnPlaces<'_, 'tcx>,
+        state: &mut State<FlatSet<Scalar>>,
+    ) {
+        return_places.for_each(|place| {
+            state.flood(place.as_ref(), &self.map);
+        })
     }
 
     fn handle_set_discriminant(
         &self,
         place: Place<'tcx>,
         variant_index: VariantIdx,
-        state: &mut State<Self::Value>,
+        state: &mut State<FlatSet<Scalar>>,
     ) {
         state.flood_discr(place.as_ref(), &self.map);
         if self.map.find_discr(place.as_ref()).is_some() {
@@ -109,17 +295,17 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
         &self,
         target: Place<'tcx>,
         rvalue: &Rvalue<'tcx>,
-        state: &mut State<Self::Value>,
+        state: &mut State<FlatSet<Scalar>>,
     ) {
         match rvalue {
             Rvalue::Use(operand) => {
-                state.flood(target.as_ref(), self.map());
+                state.flood(target.as_ref(), &self.map);
                 if let Some(target) = self.map.find(target.as_ref()) {
                     self.assign_operand(state, target, operand);
                 }
             }
             Rvalue::CopyForDeref(rhs) => {
-                state.flood(target.as_ref(), self.map());
+                state.flood(target.as_ref(), &self.map);
                 if let Some(target) = self.map.find(target.as_ref()) {
                     self.assign_operand(state, target, &Operand::Copy(*rhs));
                 }
@@ -127,9 +313,9 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
             Rvalue::Aggregate(kind, operands) => {
                 // If we assign `target = Enum::Variant#0(operand)`,
                 // we must make sure that all `target as Variant#i` are `Top`.
-                state.flood(target.as_ref(), self.map());
+                state.flood(target.as_ref(), &self.map);
 
-                let Some(target_idx) = self.map().find(target.as_ref()) else { return };
+                let Some(target_idx) = self.map.find(target.as_ref()) else { return };
 
                 let (variant_target, variant_index) = match **kind {
                     AggregateKind::Tuple | AggregateKind::Closure(..) => (Some(target_idx), None),
@@ -148,14 +334,14 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
                 if let Some(variant_target_idx) = variant_target {
                     for (field_index, operand) in operands.iter_enumerated() {
                         if let Some(field) =
-                            self.map().apply(variant_target_idx, TrackElem::Field(field_index))
+                            self.map.apply(variant_target_idx, TrackElem::Field(field_index))
                         {
                             self.assign_operand(state, field, operand);
                         }
                     }
                 }
                 if let Some(variant_index) = variant_index
-                    && let Some(discr_idx) = self.map().apply(target_idx, TrackElem::Discriminant)
+                    && let Some(discr_idx) = self.map.apply(target_idx, TrackElem::Discriminant)
                 {
                     // We are assigning the discriminant as part of an aggregate.
                     // This discriminant can only alias a variant field's value if the operand
@@ -170,23 +356,23 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
             }
             Rvalue::BinaryOp(op, box (left, right)) if op.is_overflowing() => {
                 // Flood everything now, so we can use `insert_value_idx` directly later.
-                state.flood(target.as_ref(), self.map());
+                state.flood(target.as_ref(), &self.map);
 
-                let Some(target) = self.map().find(target.as_ref()) else { return };
+                let Some(target) = self.map.find(target.as_ref()) else { return };
 
-                let value_target = self.map().apply(target, TrackElem::Field(0_u32.into()));
-                let overflow_target = self.map().apply(target, TrackElem::Field(1_u32.into()));
+                let value_target = self.map.apply(target, TrackElem::Field(0_u32.into()));
+                let overflow_target = self.map.apply(target, TrackElem::Field(1_u32.into()));
 
                 if value_target.is_some() || overflow_target.is_some() {
                     let (val, overflow) = self.binary_op(state, *op, left, right);
 
                     if let Some(value_target) = value_target {
                         // We have flooded `target` earlier.
-                        state.insert_value_idx(value_target, val, self.map());
+                        state.insert_value_idx(value_target, val, &self.map);
                     }
                     if let Some(overflow_target) = overflow_target {
                         // We have flooded `target` earlier.
-                        state.insert_value_idx(overflow_target, overflow, self.map());
+                        state.insert_value_idx(overflow_target, overflow, &self.map);
                     }
                 }
             }
@@ -196,27 +382,30 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
                 _,
             ) => {
                 let pointer = self.handle_operand(operand, state);
-                state.assign(target.as_ref(), pointer, self.map());
+                state.assign(target.as_ref(), pointer, &self.map);
 
-                if let Some(target_len) = self.map().find_len(target.as_ref())
+                if let Some(target_len) = self.map.find_len(target.as_ref())
                     && let operand_ty = operand.ty(self.local_decls, self.tcx)
                     && let Some(operand_ty) = operand_ty.builtin_deref(true)
                     && let ty::Array(_, len) = operand_ty.kind()
                     && let Some(len) = Const::Ty(self.tcx.types.usize, *len)
                         .try_eval_scalar_int(self.tcx, self.param_env)
                 {
-                    state.insert_value_idx(target_len, FlatSet::Elem(len.into()), self.map());
+                    state.insert_value_idx(target_len, FlatSet::Elem(len.into()), &self.map);
                 }
             }
-            _ => self.super_assign(target, rvalue, state),
+            _ => {
+                let result = self.handle_rvalue(rvalue, state);
+                state.assign(target.as_ref(), result, &self.map);
+            }
         }
     }
 
     fn handle_rvalue(
         &self,
         rvalue: &Rvalue<'tcx>,
-        state: &mut State<Self::Value>,
-    ) -> ValueOrPlace<Self::Value> {
+        state: &mut State<FlatSet<Scalar>>,
+    ) -> ValueOrPlace<FlatSet<Scalar>> {
         let val = match rvalue {
             Rvalue::Len(place) => {
                 let place_ty = place.ty(self.local_decls, self.tcx);
@@ -225,7 +414,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
                         .try_eval_scalar(self.tcx, self.param_env)
                         .map_or(FlatSet::Top, FlatSet::Elem)
                 } else if let [ProjectionElem::Deref] = place.projection[..] {
-                    state.get_len(place.local.into(), self.map())
+                    state.get_len(place.local.into(), &self.map)
                 } else {
                     FlatSet::Top
                 }
@@ -296,8 +485,24 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
                 };
                 FlatSet::Elem(Scalar::from_target_usize(val, &self.tcx))
             }
-            Rvalue::Discriminant(place) => state.get_discr(place.as_ref(), self.map()),
-            _ => return self.super_rvalue(rvalue, state),
+            Rvalue::Discriminant(place) => state.get_discr(place.as_ref(), &self.map),
+            Rvalue::Use(operand) => return self.handle_operand(operand, state),
+            Rvalue::CopyForDeref(place) => {
+                return self.handle_operand(&Operand::Copy(*place), state);
+            }
+            Rvalue::Ref(..) | Rvalue::RawPtr(..) => {
+                // We don't track such places.
+                return ValueOrPlace::TOP;
+            }
+            Rvalue::Repeat(..)
+            | Rvalue::ThreadLocalRef(..)
+            | Rvalue::Cast(..)
+            | Rvalue::BinaryOp(..)
+            | Rvalue::Aggregate(..)
+            | Rvalue::ShallowInitBox(..) => {
+                // No modification is possible through these r-values.
+                return ValueOrPlace::TOP;
+            }
         };
         ValueOrPlace::Value(val)
     }
@@ -305,8 +510,8 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
     fn handle_constant(
         &self,
         constant: &ConstOperand<'tcx>,
-        _state: &mut State<Self::Value>,
-    ) -> Self::Value {
+        _state: &mut State<FlatSet<Scalar>>,
+    ) -> FlatSet<Scalar> {
         constant
             .const_
             .try_eval_scalar(self.tcx, self.param_env)
@@ -317,11 +522,11 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
         &self,
         discr: &'mir Operand<'tcx>,
         targets: &'mir SwitchTargets,
-        state: &mut State<Self::Value>,
+        state: &mut State<FlatSet<Scalar>>,
     ) -> TerminatorEdges<'mir, 'tcx> {
         let value = match self.handle_operand(discr, state) {
             ValueOrPlace::Value(value) => value,
-            ValueOrPlace::Place(place) => state.get_idx(place, self.map()),
+            ValueOrPlace::Place(place) => state.get_idx(place, &self.map),
         };
         match value {
             // We are branching on uninitialized data, this is UB, treat it as unreachable.
@@ -334,19 +539,6 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
             FlatSet::Top => TerminatorEdges::SwitchInt { discr, targets },
         }
     }
-}
-
-impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
-    fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, map: Map<'tcx>) -> Self {
-        let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
-        Self {
-            map,
-            tcx,
-            local_decls: &body.local_decls,
-            ecx: InterpCx::new(tcx, DUMMY_SP, param_env, DummyMachine),
-            param_env,
-        }
-    }
 
     /// The caller must have flooded `place`.
     fn assign_operand(
@@ -457,7 +649,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
                     // a pair and sometimes not. But as a hack we always return a pair
                     // and just make the 2nd component `Bottom` when it does not exist.
                     Some(val) => {
-                        if matches!(val.layout.abi, Abi::ScalarPair(..)) {
+                        if matches!(val.layout.backend_repr, BackendRepr::ScalarPair(..)) {
                             let (val, overflow) = val.to_scalar_pair();
                             (FlatSet::Elem(val), FlatSet::Elem(overflow))
                         } else {
@@ -470,7 +662,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
             // Exactly one side is known, attempt some algebraic simplifications.
             (FlatSet::Elem(const_arg), _) | (_, FlatSet::Elem(const_arg)) => {
                 let layout = const_arg.layout;
-                if !matches!(layout.abi, rustc_target::abi::Abi::Scalar(..)) {
+                if !matches!(layout.backend_repr, rustc_target::abi::BackendRepr::Scalar(..)) {
                     return (FlatSet::Top, FlatSet::Top);
                 }
 
@@ -537,16 +729,40 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
     }
 }
 
-pub(crate) struct Patch<'tcx> {
+/// This is used to visualize the dataflow analysis.
+impl<'tcx> DebugWithContext<ConstAnalysis<'_, 'tcx>> for State<FlatSet<Scalar>> {
+    fn fmt_with(&self, ctxt: &ConstAnalysis<'_, 'tcx>, f: &mut Formatter<'_>) -> std::fmt::Result {
+        match self {
+            State::Reachable(values) => debug_with_context(values, None, &ctxt.map, f),
+            State::Unreachable => write!(f, "unreachable"),
+        }
+    }
+
+    fn fmt_diff_with(
+        &self,
+        old: &Self,
+        ctxt: &ConstAnalysis<'_, 'tcx>,
+        f: &mut Formatter<'_>,
+    ) -> std::fmt::Result {
+        match (self, old) {
+            (State::Reachable(this), State::Reachable(old)) => {
+                debug_with_context(this, Some(old), &ctxt.map, f)
+            }
+            _ => Ok(()), // Consider printing something here.
+        }
+    }
+}
+
+struct Patch<'tcx> {
     tcx: TyCtxt<'tcx>,
 
     /// For a given MIR location, this stores the values of the operands used by that location. In
     /// particular, this is before the effect, such that the operands of `_1 = _1 + _2` are
     /// properly captured. (This may become UB soon, but it is currently emitted even by safe code.)
-    pub(crate) before_effect: FxHashMap<(Location, Place<'tcx>), Const<'tcx>>,
+    before_effect: FxHashMap<(Location, Place<'tcx>), Const<'tcx>>,
 
     /// Stores the assigned values for assignments where the Rvalue is constant.
-    pub(crate) assignments: FxHashMap<Location, Const<'tcx>>,
+    assignments: FxHashMap<Location, Const<'tcx>>,
 }
 
 impl<'tcx> Patch<'tcx> {
@@ -589,13 +805,13 @@ impl<'a, 'tcx> Collector<'a, 'tcx> {
         }
 
         let place = map.find(place.as_ref())?;
-        if layout.abi.is_scalar()
+        if layout.backend_repr.is_scalar()
             && let Some(value) = propagatable_scalar(place, state, map)
         {
             return Some(Const::Val(ConstValue::Scalar(value), ty));
         }
 
-        if matches!(layout.abi, Abi::Scalar(..) | Abi::ScalarPair(..)) {
+        if matches!(layout.backend_repr, BackendRepr::Scalar(..) | BackendRepr::ScalarPair(..)) {
             let alloc_id = ecx
                 .intern_with_temp_alloc(layout, |ecx, dest| {
                     try_write_constant(ecx, dest, place, ty, state, map)
@@ -641,7 +857,7 @@ fn try_write_constant<'tcx>(
     }
 
     // Fast path for scalars.
-    if layout.abi.is_scalar()
+    if layout.backend_repr.is_scalar()
         && let Some(value) = propagatable_scalar(place, state, map)
     {
         return ecx.write_immediate(Immediate::Scalar(value), dest);
@@ -725,8 +941,7 @@ fn try_write_constant<'tcx>(
     interp_ok(())
 }
 
-impl<'mir, 'tcx>
-    ResultsVisitor<'mir, 'tcx, Results<'tcx, ValueAnalysisWrapper<ConstAnalysis<'_, 'tcx>>>>
+impl<'mir, 'tcx> ResultsVisitor<'mir, 'tcx, Results<'tcx, ConstAnalysis<'_, 'tcx>>>
     for Collector<'_, 'tcx>
 {
     type Domain = State<FlatSet<Scalar>>;
@@ -734,7 +949,7 @@ impl<'mir, 'tcx>
     #[instrument(level = "trace", skip(self, results, statement))]
     fn visit_statement_before_primary_effect(
         &mut self,
-        results: &mut Results<'tcx, ValueAnalysisWrapper<ConstAnalysis<'_, 'tcx>>>,
+        results: &mut Results<'tcx, ConstAnalysis<'_, 'tcx>>,
         state: &Self::Domain,
         statement: &'mir Statement<'tcx>,
         location: Location,
@@ -744,8 +959,8 @@ impl<'mir, 'tcx>
                 OperandCollector {
                     state,
                     visitor: self,
-                    ecx: &mut results.analysis.0.ecx,
-                    map: &results.analysis.0.map,
+                    ecx: &mut results.analysis.ecx,
+                    map: &results.analysis.map,
                 }
                 .visit_rvalue(rvalue, location);
             }
@@ -756,7 +971,7 @@ impl<'mir, 'tcx>
     #[instrument(level = "trace", skip(self, results, statement))]
     fn visit_statement_after_primary_effect(
         &mut self,
-        results: &mut Results<'tcx, ValueAnalysisWrapper<ConstAnalysis<'_, 'tcx>>>,
+        results: &mut Results<'tcx, ConstAnalysis<'_, 'tcx>>,
         state: &Self::Domain,
         statement: &'mir Statement<'tcx>,
         location: Location,
@@ -767,10 +982,10 @@ impl<'mir, 'tcx>
             }
             StatementKind::Assign(box (place, _)) => {
                 if let Some(value) = self.try_make_constant(
-                    &mut results.analysis.0.ecx,
+                    &mut results.analysis.ecx,
                     place,
                     state,
-                    &results.analysis.0.map,
+                    &results.analysis.map,
                 ) {
                     self.patch.assignments.insert(location, value);
                 }
@@ -781,7 +996,7 @@ impl<'mir, 'tcx>
 
     fn visit_terminator_before_primary_effect(
         &mut self,
-        results: &mut Results<'tcx, ValueAnalysisWrapper<ConstAnalysis<'_, 'tcx>>>,
+        results: &mut Results<'tcx, ConstAnalysis<'_, 'tcx>>,
         state: &Self::Domain,
         terminator: &'mir Terminator<'tcx>,
         location: Location,
@@ -789,8 +1004,8 @@ impl<'mir, 'tcx>
         OperandCollector {
             state,
             visitor: self,
-            ecx: &mut results.analysis.0.ecx,
-            map: &results.analysis.0.map,
+            ecx: &mut results.analysis.ecx,
+            map: &results.analysis.map,
         }
         .visit_terminator(terminator, location);
     }
diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs
index edffe6ce78f..2898f82e25c 100644
--- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs
+++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs
@@ -37,8 +37,7 @@ fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
     always_live.union(&borrowed_locals);
 
     let mut live = MaybeTransitiveLiveLocals::new(&always_live)
-        .into_engine(tcx, body)
-        .iterate_to_fixpoint()
+        .iterate_to_fixpoint(tcx, body, None)
         .into_results_cursor(body);
 
     // For blocks with a call terminator, if an argument copy can be turned into a move,
diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs
index ad83c0295ba..beeab0d4a66 100644
--- a/compiler/rustc_mir_transform/src/dest_prop.rs
+++ b/compiler/rustc_mir_transform/src/dest_prop.rs
@@ -169,10 +169,7 @@ impl<'tcx> crate::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 live = MaybeLiveLocals.iterate_to_fixpoint(tcx, body, Some("MaybeLiveLocals-DestProp"));
         let points = DenseLocationMap::new(body);
         let mut live = save_as_intervals(&points, body, live);
 
diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs
index 30e1ac05e03..58e1db19438 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs
@@ -64,18 +64,14 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateDrops {
 
             let mut inits = MaybeInitializedPlaces::new(tcx, body, &env.move_data)
                 .skipping_unreachable_unwind()
-                .into_engine(tcx, body)
-                .pass_name("elaborate_drops")
-                .iterate_to_fixpoint()
+                .iterate_to_fixpoint(tcx, body, Some("elaborate_drops"))
                 .into_results_cursor(body);
             let dead_unwinds = compute_dead_unwinds(body, &mut inits);
 
             let uninits = MaybeUninitializedPlaces::new(tcx, body, &env.move_data)
                 .mark_inactive_variants_as_uninit()
                 .skipping_unreachable_unwind(dead_unwinds)
-                .into_engine(tcx, body)
-                .pass_name("elaborate_drops")
-                .iterate_to_fixpoint()
+                .iterate_to_fixpoint(tcx, body, Some("elaborate_drops"))
                 .into_results_cursor(body);
 
             let drop_flags = IndexVec::from_elem(None, &env.move_data.move_paths);
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index 79c62372df0..274eea9563f 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -85,6 +85,7 @@
 use std::borrow::Cow;
 
 use either::Either;
+use rustc_abi::{self as abi, BackendRepr, FIRST_VARIANT, FieldIdx, Primitive, Size, VariantIdx};
 use rustc_const_eval::const_eval::DummyMachine;
 use rustc_const_eval::interpret::{
     ImmTy, Immediate, InterpCx, MemPlaceMeta, MemoryKind, OpTy, Projectable, Scalar,
@@ -103,7 +104,6 @@ use rustc_middle::ty::layout::{HasParamEnv, LayoutOf};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::DUMMY_SP;
 use rustc_span::def_id::DefId;
-use rustc_target::abi::{self, Abi, FIRST_VARIANT, FieldIdx, Primitive, Size, VariantIdx};
 use smallvec::SmallVec;
 use tracing::{debug, instrument, trace};
 
@@ -427,7 +427,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
                     };
                     let ptr_imm = Immediate::new_pointer_with_meta(data, meta, &self.ecx);
                     ImmTy::from_immediate(ptr_imm, ty).into()
-                } else if matches!(ty.abi, Abi::Scalar(..) | Abi::ScalarPair(..)) {
+                } else if matches!(
+                    ty.backend_repr,
+                    BackendRepr::Scalar(..) | BackendRepr::ScalarPair(..)
+                ) {
                     let dest = self.ecx.allocate(ty, MemoryKind::Stack).discard_err()?;
                     let variant_dest = if let Some(variant) = variant {
                         self.ecx.project_downcast(&dest, variant).discard_err()?
@@ -573,12 +576,12 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
                     // limited transmutes: it only works between types with the same layout, and
                     // cannot transmute pointers to integers.
                     if value.as_mplace_or_imm().is_right() {
-                        let can_transmute = match (value.layout.abi, to.abi) {
-                            (Abi::Scalar(s1), Abi::Scalar(s2)) => {
+                        let can_transmute = match (value.layout.backend_repr, to.backend_repr) {
+                            (BackendRepr::Scalar(s1), BackendRepr::Scalar(s2)) => {
                                 s1.size(&self.ecx) == s2.size(&self.ecx)
                                     && !matches!(s1.primitive(), Primitive::Pointer(..))
                             }
-                            (Abi::ScalarPair(a1, b1), Abi::ScalarPair(a2, b2)) => {
+                            (BackendRepr::ScalarPair(a1, b1), BackendRepr::ScalarPair(a2, b2)) => {
                                 a1.size(&self.ecx) == a2.size(&self.ecx) &&
                                 b1.size(&self.ecx) == b2.size(&self.ecx) &&
                                 // The alignment of the second component determines its offset, so that also needs to match.
@@ -1079,7 +1082,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
             }
         }
 
-        if let AggregateTy::Def(_, _) = ty
+        // unsound: https://github.com/rust-lang/rust/issues/132353
+        if tcx.sess.opts.unstable_opts.unsound_mir_opts
+            && let AggregateTy::Def(_, _) = ty
             && let Some(value) =
                 self.simplify_aggregate_to_copy(rvalue, location, &fields, variant_index)
         {
@@ -1241,7 +1246,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
 
         let as_bits = |value| {
             let constant = self.evaluated[value].as_ref()?;
-            if layout.abi.is_scalar() {
+            if layout.backend_repr.is_scalar() {
                 let scalar = self.ecx.read_scalar(constant).discard_err()?;
                 scalar.to_bits(constant.layout.size).discard_err()
             } else {
@@ -1497,12 +1502,12 @@ fn op_to_prop_const<'tcx>(
 
     // Do not synthetize too large constants. Codegen will just memcpy them, which we'd like to
     // avoid.
-    if !matches!(op.layout.abi, Abi::Scalar(..) | Abi::ScalarPair(..)) {
+    if !matches!(op.layout.backend_repr, BackendRepr::Scalar(..) | BackendRepr::ScalarPair(..)) {
         return None;
     }
 
     // If this constant has scalar ABI, return it as a `ConstValue::Scalar`.
-    if let Abi::Scalar(abi::Scalar::Initialized { .. }) = op.layout.abi
+    if let BackendRepr::Scalar(abi::Scalar::Initialized { .. }) = op.layout.backend_repr
         && let Some(scalar) = ecx.read_scalar(op).discard_err()
     {
         if !scalar.try_to_scalar_int().is_ok() {
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 42d6bdf6cee..404470db5c5 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -244,8 +244,13 @@ impl<'tcx> Inliner<'tcx> {
         // Normally, this shouldn't be required, but trait normalization failure can create a
         // validation ICE.
         let output_type = callee_body.return_ty();
-        if !util::relate_types(self.tcx, self.param_env, ty::Covariant, output_type, destination_ty)
-        {
+        if !util::sub_types(
+            self.tcx,
+            caller_body.typing_mode(self.tcx),
+            self.param_env,
+            output_type,
+            destination_ty,
+        ) {
             trace!(?output_type, ?destination_ty);
             return Err("failed to normalize return type");
         }
@@ -275,8 +280,13 @@ impl<'tcx> Inliner<'tcx> {
                 self_arg_ty.into_iter().chain(arg_tuple_tys).zip(callee_body.args_iter())
             {
                 let input_type = callee_body.local_decls[input].ty;
-                if !util::relate_types(self.tcx, self.param_env, ty::Covariant, input_type, arg_ty)
-                {
+                if !util::sub_types(
+                    self.tcx,
+                    caller_body.typing_mode(self.tcx),
+                    self.param_env,
+                    input_type,
+                    arg_ty,
+                ) {
                     trace!(?arg_ty, ?input_type);
                     return Err("failed to normalize tuple argument type");
                 }
@@ -285,8 +295,13 @@ impl<'tcx> Inliner<'tcx> {
             for (arg, input) in args.iter().zip(callee_body.args_iter()) {
                 let input_type = callee_body.local_decls[input].ty;
                 let arg_ty = arg.node.ty(&caller_body.local_decls, self.tcx);
-                if !util::relate_types(self.tcx, self.param_env, ty::Covariant, input_type, arg_ty)
-                {
+                if !util::sub_types(
+                    self.tcx,
+                    caller_body.typing_mode(self.tcx),
+                    self.param_env,
+                    input_type,
+                    arg_ty,
+                ) {
                     trace!(?arg_ty, ?input_type);
                     return Err("failed to normalize argument type");
                 }
diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs
index 08923748eb2..0604665642a 100644
--- a/compiler/rustc_mir_transform/src/known_panics_lint.rs
+++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs
@@ -4,6 +4,7 @@
 
 use std::fmt::Debug;
 
+use rustc_abi::{BackendRepr, FieldIdx, HasDataLayout, Size, TargetDataLayout, VariantIdx};
 use rustc_const_eval::const_eval::DummyMachine;
 use rustc_const_eval::interpret::{
     ImmTy, InterpCx, InterpResult, Projectable, Scalar, format_interp_error, interp_ok,
@@ -19,7 +20,6 @@ use rustc_middle::mir::*;
 use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
 use rustc_middle::ty::{self, ConstInt, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitableExt};
 use rustc_span::Span;
-use rustc_target::abi::{Abi, FieldIdx, HasDataLayout, Size, TargetDataLayout, VariantIdx};
 use tracing::{debug, instrument, trace};
 
 use crate::errors::{AssertLint, AssertLintKind};
@@ -557,7 +557,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                 let right = self.use_ecx(|this| this.ecx.read_immediate(&right))?;
 
                 let val = self.use_ecx(|this| this.ecx.binary_op(bin_op, &left, &right))?;
-                if matches!(val.layout.abi, Abi::ScalarPair(..)) {
+                if matches!(val.layout.backend_repr, BackendRepr::ScalarPair(..)) {
                     // FIXME `Value` should properly support pairs in `Immediate`... but currently
                     // it does not.
                     let (val, overflow) = val.to_pair(&self.ecx);
@@ -651,9 +651,9 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                     let to = self.ecx.layout_of(to).ok()?;
                     // `offset` for immediates only supports scalar/scalar-pair ABIs,
                     // so bail out if the target is not one.
-                    match (value.layout.abi, to.abi) {
-                        (Abi::Scalar(..), Abi::Scalar(..)) => {}
-                        (Abi::ScalarPair(..), Abi::ScalarPair(..)) => {}
+                    match (value.layout.backend_repr, to.backend_repr) {
+                        (BackendRepr::Scalar(..), BackendRepr::Scalar(..)) => {}
+                        (BackendRepr::ScalarPair(..), BackendRepr::ScalarPair(..)) => {}
                         _ => return None,
                     }
 
diff --git a/compiler/rustc_mir_transform/src/lint.rs b/compiler/rustc_mir_transform/src/lint.rs
index 23733994a8b..d8ff1cfc90b 100644
--- a/compiler/rustc_mir_transform/src/lint.rs
+++ b/compiler/rustc_mir_transform/src/lint.rs
@@ -17,13 +17,11 @@ pub(super) fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String
     let always_live_locals = &always_storage_live_locals(body);
 
     let maybe_storage_live = MaybeStorageLive::new(Cow::Borrowed(always_live_locals))
-        .into_engine(tcx, body)
-        .iterate_to_fixpoint()
+        .iterate_to_fixpoint(tcx, body, None)
         .into_results_cursor(body);
 
     let maybe_storage_dead = MaybeStorageDead::new(Cow::Borrowed(always_live_locals))
-        .into_engine(tcx, body)
-        .iterate_to_fixpoint()
+        .iterate_to_fixpoint(tcx, body, None)
         .into_results_cursor(body);
 
     let mut lint = Lint {
diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs
index 53e53d9d5ba..b11b503e8d4 100644
--- a/compiler/rustc_mir_transform/src/ref_prop.rs
+++ b/compiler/rustc_mir_transform/src/ref_prop.rs
@@ -126,8 +126,7 @@ fn compute_replacement<'tcx>(
     // Compute `MaybeStorageDead` dataflow to check that we only replace when the pointee is
     // definitely live.
     let mut maybe_dead = MaybeStorageDead::new(Cow::Owned(always_live_locals))
-        .into_engine(tcx, body)
-        .iterate_to_fixpoint()
+        .iterate_to_fixpoint(tcx, body, None)
         .into_results_cursor(body);
 
     // Map for each local to the pointee.
diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
index 09969a4c7cc..55dd96100b0 100644
--- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
+++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
@@ -22,9 +22,7 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveUninitDrops {
         let move_data = MoveData::gather_moves(body, tcx, |ty| ty.needs_drop(tcx, param_env));
 
         let mut maybe_inits = MaybeInitializedPlaces::new(tcx, body, &move_data)
-            .into_engine(tcx, body)
-            .pass_name("remove_uninit_drops")
-            .iterate_to_fixpoint()
+            .iterate_to_fixpoint(tcx, body, Some("remove_uninit_drops"))
             .into_results_cursor(body);
 
         let mut to_remove = vec![];
diff --git a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
index 5612e779d6b..3011af4d9d7 100644
--- a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
+++ b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
@@ -1,5 +1,6 @@
 //! A pass that eliminates branches on uninhabited or unreachable enum variants.
 
+use rustc_abi::Variants;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_middle::bug;
 use rustc_middle::mir::patch::MirPatch;
@@ -9,7 +10,6 @@ use rustc_middle::mir::{
 };
 use rustc_middle::ty::layout::TyAndLayout;
 use rustc_middle::ty::{Ty, TyCtxt};
-use rustc_target::abi::{Abi, Variants};
 use tracing::trace;
 
 pub(super) struct UnreachableEnumBranching;
@@ -65,7 +65,7 @@ fn variant_discriminants<'tcx>(
         Variants::Multiple { variants, .. } => variants
             .iter_enumerated()
             .filter_map(|(idx, layout)| {
-                (layout.abi != Abi::Uninhabited)
+                (!layout.is_uninhabited())
                     .then(|| ty.discriminant_for_variant(tcx, idx).unwrap().val)
             })
             .collect(),
diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs
index 25e68f44456..8109a9b8ba0 100644
--- a/compiler/rustc_mir_transform/src/validate.rs
+++ b/compiler/rustc_mir_transform/src/validate.rs
@@ -5,7 +5,7 @@ use rustc_hir::LangItem;
 use rustc_index::IndexVec;
 use rustc_index::bit_set::BitSet;
 use rustc_infer::infer::TyCtxtInferExt;
-use rustc_infer::traits::{Obligation, ObligationCause, Reveal};
+use rustc_infer::traits::{Obligation, ObligationCause};
 use rustc_middle::mir::coverage::CoverageKind;
 use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
@@ -20,7 +20,7 @@ use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::traits::ObligationCtxt;
 use rustc_type_ir::Upcast;
 
-use crate::util::{is_within_packed, relate_types};
+use crate::util::{self, is_within_packed};
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 enum EdgeKind {
@@ -50,11 +50,7 @@ impl<'tcx> crate::MirPass<'tcx> for Validator {
         }
         let def_id = body.source.def_id();
         let mir_phase = self.mir_phase;
-        let param_env = match mir_phase.reveal() {
-            Reveal::UserFacing => tcx.param_env(def_id),
-            Reveal::All => tcx.param_env_reveal_all_normalized(def_id),
-        };
-
+        let param_env = mir_phase.param_env(tcx, def_id);
         let can_unwind = if mir_phase <= MirPhase::Runtime(RuntimePhase::Initial) {
             // In this case `AbortUnwindingCalls` haven't yet been executed.
             true
@@ -587,7 +583,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             Variance::Covariant
         };
 
-        crate::util::relate_types(self.tcx, self.param_env, variance, src, dest)
+        crate::util::relate_types(
+            self.tcx,
+            self.body.typing_mode(self.tcx),
+            self.param_env,
+            variance,
+            src,
+            dest,
+        )
     }
 
     /// Check that the given predicate definitely holds in the param-env of this MIR body.
@@ -606,7 +609,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             return true;
         }
 
-        let infcx = self.tcx.infer_ctxt().build();
+        let infcx = self.tcx.infer_ctxt().build(self.body.typing_mode(self.tcx));
         let ocx = ObligationCtxt::new(&infcx);
         ocx.register_obligation(Obligation::new(
             self.tcx,
@@ -798,10 +801,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                 }
             }
             ProjectionElem::Subtype(ty) => {
-                if !relate_types(
+                if !util::sub_types(
                     self.tcx,
+                    self.body.typing_mode(self.tcx),
                     self.param_env,
-                    Variance::Covariant,
                     ty,
                     place_ref.ty(&self.body.local_decls, self.tcx).ty,
                 ) {
diff --git a/compiler/rustc_next_trait_solver/src/delegate.rs b/compiler/rustc_next_trait_solver/src/delegate.rs
index 4da1e7fa711..f7fbfed5b8e 100644
--- a/compiler/rustc_next_trait_solver/src/delegate.rs
+++ b/compiler/rustc_next_trait_solver/src/delegate.rs
@@ -1,7 +1,7 @@
 use std::ops::Deref;
 
 use rustc_type_ir::fold::TypeFoldable;
-use rustc_type_ir::solve::{Certainty, Goal, NoSolution, SolverMode};
+use rustc_type_ir::solve::{Certainty, Goal, NoSolution};
 use rustc_type_ir::{self as ty, InferCtxtLike, Interner};
 
 pub trait SolverDelegate: Deref<Target = <Self as SolverDelegate>::Infcx> + Sized {
@@ -15,7 +15,6 @@ pub trait SolverDelegate: Deref<Target = <Self as SolverDelegate>::Infcx> + Size
 
     fn build_with_canonical<V>(
         cx: Self::Interner,
-        solver_mode: SolverMode,
         canonical: &ty::CanonicalQueryInput<Self::Interner, V>,
     ) -> (Self, V, ty::CanonicalVarValues<Self::Interner>)
     where
@@ -93,7 +92,6 @@ pub trait SolverDelegate: Deref<Target = <Self as SolverDelegate>::Infcx> + Size
 
     fn fetch_eligible_assoc_item(
         &self,
-        param_env: <Self::Interner as Interner>::ParamEnv,
         goal_trait_ref: ty::TraitRef<Self::Interner>,
         trait_assoc_def_id: <Self::Interner as Interner>::DefId,
         impl_def_id: <Self::Interner as Interner>::DefId,
diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
index f6a5f20a639..ebf7372926f 100644
--- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
@@ -8,14 +8,14 @@ use rustc_type_ir::inherent::*;
 use rustc_type_ir::lang_items::TraitSolverLangItem;
 use rustc_type_ir::solve::inspect;
 use rustc_type_ir::visit::TypeVisitableExt as _;
-use rustc_type_ir::{self as ty, Interner, Upcast as _, elaborate};
+use rustc_type_ir::{self as ty, Interner, TypingMode, Upcast as _, elaborate};
 use tracing::{debug, instrument};
 
 use crate::delegate::SolverDelegate;
 use crate::solve::inspect::ProbeKind;
 use crate::solve::{
     BuiltinImplSource, CandidateSource, CanonicalResponse, Certainty, EvalCtxt, Goal, GoalSource,
-    MaybeCause, NoSolution, QueryResult, SolverMode,
+    MaybeCause, NoSolution, QueryResult,
 };
 
 /// A candidate is a possible way to prove a goal.
@@ -328,11 +328,12 @@ where
 
         let mut candidates = vec![];
 
-        if self.solver_mode() == SolverMode::Coherence {
+        if let TypingMode::Coherence = self.typing_mode(goal.param_env) {
             if let Ok(candidate) = self.consider_coherence_unknowable_candidate(goal) {
                 return vec![candidate];
             }
         }
+
         self.assemble_impl_candidates(goal, &mut candidates);
 
         self.assemble_builtin_impl_candidates(goal, &mut candidates);
@@ -343,8 +344,11 @@ where
 
         self.assemble_param_env_candidates(goal, &mut candidates);
 
-        if self.solver_mode() == SolverMode::Normal {
-            self.discard_impls_shadowed_by_env(goal, &mut candidates);
+        match self.typing_mode(goal.param_env) {
+            TypingMode::Coherence => {}
+            TypingMode::Analysis { .. } | TypingMode::PostAnalysis => {
+                self.discard_impls_shadowed_by_env(goal, &mut candidates);
+            }
         }
 
         candidates
diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs
index 8d57ad8f255..5bfc156ed94 100644
--- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs
@@ -44,7 +44,7 @@ where
     ) -> Result<Candidate<I>, NoSolution> {
         if let Some(host_clause) = assumption.as_host_effect_clause() {
             if host_clause.def_id() == goal.predicate.def_id()
-                && host_clause.host().satisfies(goal.predicate.host)
+                && host_clause.constness().satisfies(goal.predicate.constness)
             {
                 if !DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify(
                     goal.predicate.trait_ref.args,
@@ -91,7 +91,7 @@ where
             cx,
             cx.implied_const_bounds(alias_ty.def_id)
                 .iter_instantiated(cx, alias_ty.args)
-                .map(|trait_ref| trait_ref.to_host_effect_clause(cx, goal.predicate.host)),
+                .map(|trait_ref| trait_ref.to_host_effect_clause(cx, goal.predicate.constness)),
         ) {
             candidates.extend(Self::probe_and_match_goal_against_assumption(
                 ecx,
@@ -107,7 +107,7 @@ where
                             .map(|trait_ref| {
                                 goal.with(
                                     cx,
-                                    trait_ref.to_host_effect_clause(cx, goal.predicate.host),
+                                    trait_ref.to_host_effect_clause(cx, goal.predicate.constness),
                                 )
                             }),
                     );
@@ -163,7 +163,10 @@ where
                 .const_conditions(impl_def_id)
                 .iter_instantiated(cx, impl_args)
                 .map(|bound_trait_ref| {
-                    goal.with(cx, bound_trait_ref.to_host_effect_clause(cx, goal.predicate.host))
+                    goal.with(
+                        cx,
+                        bound_trait_ref.to_host_effect_clause(cx, goal.predicate.constness),
+                    )
                 });
             ecx.add_goals(GoalSource::ImplWhereBound, const_conditions);
 
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
index e2fd0dd2a25..2f50070d438 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
@@ -55,6 +55,7 @@ where
         &self,
         goal: Goal<I, T>,
     ) -> (Vec<I::GenericArg>, CanonicalInput<I, T>) {
+        let param_env_for_debug_assertion = goal.param_env;
         let opaque_types = self.delegate.clone_opaque_types_for_query_response();
         let (goal, opaque_types) =
             (goal, opaque_types).fold_with(&mut EagerResolver::new(self.delegate));
@@ -73,7 +74,7 @@ where
         );
         let query_input = ty::CanonicalQueryInput {
             canonical,
-            defining_opaque_types: self.delegate.defining_opaque_types(),
+            typing_mode: self.typing_mode(param_env_for_debug_assertion),
         };
         (orig_values, query_input)
     }
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
index 7608253882a..8685896715e 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
@@ -10,7 +10,7 @@ use rustc_type_ir::inherent::*;
 use rustc_type_ir::relate::Relate;
 use rustc_type_ir::relate::solver_relating::RelateExt;
 use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
-use rustc_type_ir::{self as ty, CanonicalVarValues, InferCtxtLike, Interner};
+use rustc_type_ir::{self as ty, CanonicalVarValues, InferCtxtLike, Interner, TypingMode};
 use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
 use tracing::{instrument, trace};
 
@@ -21,7 +21,6 @@ use crate::solve::search_graph::SearchGraph;
 use crate::solve::{
     CanonicalInput, Certainty, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluationKind, GoalSource,
     HasChanged, NestedNormalizationGoals, NoSolution, PredefinedOpaquesData, QueryResult,
-    SolverMode,
 };
 
 pub(super) mod canonical;
@@ -215,8 +214,8 @@ where
     D: SolverDelegate<Interner = I>,
     I: Interner,
 {
-    pub(super) fn solver_mode(&self) -> SolverMode {
-        self.search_graph.solver_mode()
+    pub(super) fn typing_mode(&self, param_env_for_debug_assertion: I::ParamEnv) -> TypingMode<I> {
+        self.delegate.typing_mode(param_env_for_debug_assertion)
     }
 
     pub(super) fn set_is_normalizes_to_goal(&mut self) {
@@ -232,7 +231,7 @@ where
         generate_proof_tree: GenerateProofTree,
         f: impl FnOnce(&mut EvalCtxt<'_, D>) -> R,
     ) -> (R, Option<inspect::GoalEvaluation<I>>) {
-        let mut search_graph = SearchGraph::new(delegate.solver_mode(), root_depth);
+        let mut search_graph = SearchGraph::new(root_depth);
 
         let mut ecx = EvalCtxt {
             delegate,
@@ -279,7 +278,7 @@ where
         f: impl FnOnce(&mut EvalCtxt<'_, D>, Goal<I, I::Predicate>) -> R,
     ) -> R {
         let (ref delegate, input, var_values) =
-            SolverDelegate::build_with_canonical(cx, search_graph.solver_mode(), &canonical_input);
+            SolverDelegate::build_with_canonical(cx, &canonical_input);
 
         let mut ecx = EvalCtxt {
             delegate,
@@ -942,21 +941,11 @@ where
 
     pub(super) fn fetch_eligible_assoc_item(
         &self,
-        param_env: I::ParamEnv,
         goal_trait_ref: ty::TraitRef<I>,
         trait_assoc_def_id: I::DefId,
         impl_def_id: I::DefId,
     ) -> Result<Option<I::DefId>, NoSolution> {
-        self.delegate.fetch_eligible_assoc_item(
-            param_env,
-            goal_trait_ref,
-            trait_assoc_def_id,
-            impl_def_id,
-        )
-    }
-
-    pub(super) fn can_define_opaque_ty(&self, def_id: I::LocalDefId) -> bool {
-        self.delegate.defining_opaque_types().contains(&def_id)
+        self.delegate.fetch_eligible_assoc_item(goal_trait_ref, trait_assoc_def_id, impl_def_id)
     }
 
     pub(super) fn insert_hidden_type(
diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
index 7287cdf74bf..129744b4db7 100644
--- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
@@ -6,7 +6,7 @@ mod weak_types;
 use rustc_type_ir::fast_reject::DeepRejectCtxt;
 use rustc_type_ir::inherent::*;
 use rustc_type_ir::lang_items::TraitSolverLangItem;
-use rustc_type_ir::{self as ty, Interner, NormalizesTo, Upcast as _};
+use rustc_type_ir::{self as ty, Interner, NormalizesTo, TypingMode, Upcast as _};
 use tracing::instrument;
 
 use crate::delegate::SolverDelegate;
@@ -15,7 +15,7 @@ use crate::solve::assembly::{self, Candidate};
 use crate::solve::inspect::ProbeKind;
 use crate::solve::{
     BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, MaybeCause,
-    NoSolution, QueryResult, Reveal,
+    NoSolution, QueryResult,
 };
 
 impl<D, I> EvalCtxt<'_, D>
@@ -71,21 +71,21 @@ where
                 Ok(())
             }
             ty::AliasTermKind::OpaqueTy => {
-                match param_env.reveal() {
-                    // In user-facing mode, paques are only rigid if we may not define it.
-                    Reveal::UserFacing => {
+                match self.typing_mode(param_env) {
+                    // Opaques are never rigid outside of analysis mode.
+                    TypingMode::Coherence | TypingMode::PostAnalysis => Err(NoSolution),
+                    // During analysis, opaques are only rigid if we may not define it.
+                    TypingMode::Analysis { defining_opaque_types } => {
                         if rigid_alias
                             .def_id
                             .as_local()
-                            .is_some_and(|def_id| self.can_define_opaque_ty(def_id))
+                            .is_some_and(|def_id| defining_opaque_types.contains(&def_id))
                         {
                             Err(NoSolution)
                         } else {
                             Ok(())
                         }
                     }
-                    // Opaques are never rigid in reveal-all mode.
-                    Reveal::All => Err(NoSolution),
                 }
             }
             // FIXME(generic_const_exprs): we would need to support generic consts here
@@ -252,7 +252,6 @@ where
             // return ambiguity this would otherwise be incomplete, resulting in
             // unsoundness during coherence (#105782).
             let Some(target_item_def_id) = ecx.fetch_eligible_assoc_item(
-                goal.param_env,
                 goal_trait_ref,
                 goal.predicate.def_id(),
                 impl_def_id,
diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs
index f8d51f304f3..d1d701695ab 100644
--- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs
@@ -4,12 +4,10 @@
 
 use rustc_index::bit_set::GrowableBitSet;
 use rustc_type_ir::inherent::*;
-use rustc_type_ir::{self as ty, Interner};
+use rustc_type_ir::{self as ty, Interner, TypingMode};
 
 use crate::delegate::SolverDelegate;
-use crate::solve::{
-    Certainty, EvalCtxt, Goal, NoSolution, QueryResult, Reveal, SolverMode, inspect,
-};
+use crate::solve::{Certainty, EvalCtxt, Goal, NoSolution, QueryResult, inspect};
 
 impl<D, I> EvalCtxt<'_, D>
 where
@@ -24,17 +22,27 @@ where
         let opaque_ty = goal.predicate.alias;
         let expected = goal.predicate.term.as_type().expect("no such thing as an opaque const");
 
-        match (goal.param_env.reveal(), self.solver_mode()) {
-            (Reveal::UserFacing, SolverMode::Normal) => {
-                let Some(opaque_ty_def_id) = opaque_ty.def_id.as_local() else {
+        match self.typing_mode(goal.param_env) {
+            TypingMode::Coherence => {
+                // An impossible opaque type bound is the only way this goal will fail
+                // e.g. assigning `impl Copy := NotCopy`
+                self.add_item_bounds_for_hidden_type(
+                    opaque_ty.def_id,
+                    opaque_ty.args,
+                    goal.param_env,
+                    expected,
+                );
+                self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
+            }
+            TypingMode::Analysis { defining_opaque_types } => {
+                let Some(def_id) = opaque_ty.def_id.as_local() else {
                     return Err(NoSolution);
                 };
-                // FIXME: at some point we should call queries without defining
-                // new opaque types but having the existing opaque type definitions.
-                // This will require moving this below "Prefer opaques registered already".
-                if !self.can_define_opaque_ty(opaque_ty_def_id) {
+
+                if !defining_opaque_types.contains(&def_id) {
                     return Err(NoSolution);
                 }
+
                 // FIXME: This may have issues when the args contain aliases...
                 match uses_unique_placeholders_ignoring_regions(self.cx(), opaque_ty.args) {
                     Err(NotUniqueParam::NotParam(param)) if param.is_non_region_infer() => {
@@ -48,8 +56,7 @@ where
                     Ok(()) => {}
                 }
                 // Prefer opaques registered already.
-                let opaque_type_key =
-                    ty::OpaqueTypeKey { def_id: opaque_ty_def_id, args: opaque_ty.args };
+                let opaque_type_key = ty::OpaqueTypeKey { def_id, args: opaque_ty.args };
                 // FIXME: This also unifies the previous hidden type with the expected.
                 //
                 // If that fails, we insert `expected` as a new hidden type instead of
@@ -69,7 +76,7 @@ where
                             }
                             ecx.eq(goal.param_env, candidate_ty, expected)?;
                             ecx.add_item_bounds_for_hidden_type(
-                                candidate_key.def_id.into(),
+                                def_id.into(),
                                 candidate_key.args,
                                 goal.param_env,
                                 candidate_ty,
@@ -82,25 +89,14 @@ where
                 // FIXME: should we use `inject_hidden_type_unchecked` here?
                 self.insert_hidden_type(opaque_type_key, goal.param_env, expected)?;
                 self.add_item_bounds_for_hidden_type(
-                    opaque_ty.def_id,
+                    def_id.into(),
                     opaque_ty.args,
                     goal.param_env,
                     expected,
                 );
                 self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
             }
-            (Reveal::UserFacing, SolverMode::Coherence) => {
-                // An impossible opaque type bound is the only way this goal will fail
-                // e.g. assigning `impl Copy := NotCopy`
-                self.add_item_bounds_for_hidden_type(
-                    opaque_ty.def_id,
-                    opaque_ty.args,
-                    goal.param_env,
-                    expected,
-                );
-                self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
-            }
-            (Reveal::All, _) => {
+            TypingMode::PostAnalysis => {
                 // FIXME: Add an assertion that opaque type storage is empty.
                 let actual = cx.type_of(opaque_ty.def_id).instantiate(cx, opaque_ty.args);
                 self.eq(goal.param_env, expected, actual)?;
diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
index 08cc89d950e..e23e475a2a6 100644
--- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
@@ -6,7 +6,7 @@ use rustc_type_ir::fast_reject::DeepRejectCtxt;
 use rustc_type_ir::inherent::*;
 use rustc_type_ir::lang_items::TraitSolverLangItem;
 use rustc_type_ir::visit::TypeVisitableExt as _;
-use rustc_type_ir::{self as ty, Interner, TraitPredicate, Upcast as _, elaborate};
+use rustc_type_ir::{self as ty, Interner, TraitPredicate, TypingMode, Upcast as _, elaborate};
 use tracing::{instrument, trace};
 
 use crate::delegate::SolverDelegate;
@@ -15,7 +15,7 @@ use crate::solve::assembly::{self, Candidate};
 use crate::solve::inspect::ProbeKind;
 use crate::solve::{
     BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, MaybeCause,
-    NoSolution, QueryResult, Reveal, SolverMode,
+    NoSolution, QueryResult,
 };
 
 impl<D, I> assembly::GoalKind<D> for TraitPredicate<I>
@@ -67,9 +67,9 @@ where
         let maximal_certainty = match (impl_polarity, goal.predicate.polarity) {
             // In intercrate mode, this is ambiguous. But outside of intercrate,
             // it's not a real impl.
-            (ty::ImplPolarity::Reservation, _) => match ecx.solver_mode() {
-                SolverMode::Coherence => Certainty::AMBIGUOUS,
-                SolverMode::Normal => return Err(NoSolution),
+            (ty::ImplPolarity::Reservation, _) => match ecx.typing_mode(goal.param_env) {
+                TypingMode::Coherence => Certainty::AMBIGUOUS,
+                TypingMode::Analysis { .. } | TypingMode::PostAnalysis => return Err(NoSolution),
             },
 
             // Impl matches polarity
@@ -167,30 +167,26 @@ where
             return result;
         }
 
-        // Don't call `type_of` on a local TAIT that's in the defining scope,
-        // since that may require calling `typeck` on the same item we're
+        // We only look into opaque types during analysis for opaque types
+        // outside of their defining scope. Doing so for opaques in the
+        // defining scope may require calling `typeck` on the same item we're
         // currently type checking, which will result in a fatal cycle that
         // ideally we want to avoid, since we can make progress on this goal
         // via an alias bound or a locally-inferred hidden type instead.
-        //
-        // Also, don't call `type_of` on a TAIT in `Reveal::All` mode, since
-        // we already normalize the self type in
-        // `assemble_candidates_after_normalizing_self_ty`, and we'd
-        // just be registering an identical candidate here.
-        //
-        // We always return `Err(NoSolution)` here in `SolverMode::Coherence`
-        // since we'll always register an ambiguous candidate in
-        // `assemble_candidates_after_normalizing_self_ty` due to normalizing
-        // the TAIT.
         if let ty::Alias(ty::Opaque, opaque_ty) = goal.predicate.self_ty().kind() {
-            if matches!(goal.param_env.reveal(), Reveal::All)
-                || matches!(ecx.solver_mode(), SolverMode::Coherence)
-                || opaque_ty
-                    .def_id
-                    .as_local()
-                    .is_some_and(|def_id| ecx.can_define_opaque_ty(def_id))
-            {
-                return Err(NoSolution);
+            match ecx.typing_mode(goal.param_env) {
+                TypingMode::Coherence | TypingMode::PostAnalysis => {
+                    unreachable!("rigid opaque outside of analysis: {goal:?}");
+                }
+                TypingMode::Analysis { defining_opaque_types } => {
+                    if opaque_ty
+                        .def_id
+                        .as_local()
+                        .is_some_and(|def_id| defining_opaque_types.contains(&def_id))
+                    {
+                        return Err(NoSolution);
+                    }
+                }
             }
         }
 
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index a9384501547..a1fe5508970 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -14,6 +14,7 @@ use rustc_ast::{
 };
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::sync::Lrc;
 use rustc_errors::{
     Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, FatalError, PErr, PResult, Subdiagnostic,
     Suggestions, pluralize,
@@ -2437,7 +2438,7 @@ impl<'a> Parser<'a> {
         let mut labels = vec![];
         while let TokenKind::Interpolated(nt) = &tok.kind {
             let tokens = nt.tokens();
-            labels.push(nt.clone());
+            labels.push(Lrc::clone(nt));
             if let Some(tokens) = tokens
                 && let tokens = tokens.to_attr_token_stream()
                 && let tokens = tokens.0.deref()
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 36733726564..6b4e2d0f4e2 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -1194,6 +1194,7 @@ impl<'a> Parser<'a> {
         attrs: &mut AttrVec,
         mut safety: Safety,
     ) -> PResult<'a, ItemInfo> {
+        let extern_span = self.prev_token.uninterpolated_span();
         let abi = self.parse_abi(); // ABI?
         // FIXME: This recovery should be tested better.
         if safety == Safety::Default
@@ -1205,6 +1206,7 @@ impl<'a> Parser<'a> {
             let _ = self.eat_keyword(kw::Unsafe);
         }
         let module = ast::ForeignMod {
+            extern_span,
             safety,
             abi,
             items: self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No))?,
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 77ad4fdeeb1..50a8b6542df 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -424,7 +424,7 @@ impl TokenDescription {
     }
 }
 
-pub(super) fn token_descr(token: &Token) -> String {
+pub fn token_descr(token: &Token) -> String {
     let name = pprust::token_to_string(token).to_string();
 
     let kind = match (TokenDescription::from_token(token), &token.kind) {
diff --git a/compiler/rustc_passes/Cargo.toml b/compiler/rustc_passes/Cargo.toml
index b45a8dae277..ed5991459ac 100644
--- a/compiler/rustc_passes/Cargo.toml
+++ b/compiler/rustc_passes/Cargo.toml
@@ -5,6 +5,7 @@ edition = "2021"
 
 [dependencies]
 # tidy-alphabetical-start
+rustc_abi = { path = "../rustc_abi" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
 rustc_attr = { path = "../rustc_attr" }
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 8c4592cbb36..0a2926c0404 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -25,7 +25,7 @@ use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault;
 use rustc_middle::query::Providers;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
-use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::ty::{self, TyCtxt, TypingMode};
 use rustc_middle::{bug, span_bug};
 use rustc_session::lint::builtin::{
     CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, INVALID_MACRO_EXPORT_ARGUMENTS,
@@ -2267,7 +2267,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         let def_id = hir_id.expect_owner().def_id;
         let param_env = ty::ParamEnv::empty();
 
-        let infcx = tcx.infer_ctxt().build();
+        let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
         let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
 
         let span = tcx.def_span(def_id);
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index af17fbf7e4d..b1db66fa52d 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -7,6 +7,7 @@ use std::mem;
 
 use hir::ItemKind;
 use hir::def_id::{LocalDefIdMap, LocalDefIdSet};
+use rustc_abi::FieldIdx;
 use rustc_data_structures::unord::UnordSet;
 use rustc_errors::MultiSpan;
 use rustc_hir as hir;
@@ -22,7 +23,6 @@ use rustc_middle::{bug, span_bug};
 use rustc_session::lint;
 use rustc_session::lint::builtin::DEAD_CODE;
 use rustc_span::symbol::{Symbol, sym};
-use rustc_target::abi::FieldIdx;
 
 use crate::errors::{
     ChangeFields, IgnoredDerivedImpls, MultipleDeadCodes, ParentInfo, UselessAssignment,
diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs
index 93729a7f6df..986dce5b56d 100644
--- a/compiler/rustc_passes/src/layout_test.rs
+++ b/compiler/rustc_passes/src/layout_test.rs
@@ -1,13 +1,14 @@
+use rustc_abi::{HasDataLayout, TargetDataLayout};
 use rustc_ast::Attribute;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
+use rustc_middle::infer::canonical::ir::TypingMode;
 use rustc_middle::span_bug;
 use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers};
 use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt};
 use rustc_span::Span;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::sym;
-use rustc_target::abi::{HasDataLayout, TargetDataLayout};
 use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::infer::TyCtxtInferExt;
 use rustc_trait_selection::traits;
@@ -54,7 +55,7 @@ pub fn ensure_wf<'tcx>(
         param_env,
         pred,
     );
-    let infcx = tcx.infer_ctxt().build();
+    let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env));
     let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx);
     ocx.register_obligation(obligation);
     let errors = ocx.select_all_or_error();
@@ -81,8 +82,12 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
             let meta_items = attr.meta_item_list().unwrap_or_default();
             for meta_item in meta_items {
                 match meta_item.name_or_empty() {
+                    // FIXME: this never was about ABI and now this dump arg is confusing
                     sym::abi => {
-                        tcx.dcx().emit_err(LayoutAbi { span, abi: format!("{:?}", ty_layout.abi) });
+                        tcx.dcx().emit_err(LayoutAbi {
+                            span,
+                            abi: format!("{:?}", ty_layout.backend_repr),
+                        });
                     }
 
                     sym::align => {
diff --git a/compiler/rustc_pattern_analysis/Cargo.toml b/compiler/rustc_pattern_analysis/Cargo.toml
index 34fb1bdf6fa..f98e4243375 100644
--- a/compiler/rustc_pattern_analysis/Cargo.toml
+++ b/compiler/rustc_pattern_analysis/Cargo.toml
@@ -6,6 +6,8 @@ edition = "2021"
 [dependencies]
 # tidy-alphabetical-start
 rustc-hash = "2.0.0"
+
+rustc_abi = { path = "../rustc_abi", optional = true }
 rustc_apfloat = "0.2.0"
 rustc_arena = { path = "../rustc_arena", optional = true }
 rustc_data_structures = { path = "../rustc_data_structures", optional = true }
@@ -29,6 +31,7 @@ tracing-tree = "0.3.0"
 [features]
 default = ["rustc"]
 rustc = [
+    "dep:rustc_abi",
     "dep:rustc_arena",
     "dep:rustc_data_structures",
     "dep:rustc_errors",
diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs
index 0e132b27fb4..9ea5023064c 100644
--- a/compiler/rustc_pattern_analysis/src/rustc.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc.rs
@@ -1,6 +1,7 @@
 use std::fmt;
 use std::iter::once;
 
+use rustc_abi::{FIRST_VARIANT, FieldIdx, Integer, VariantIdx};
 use rustc_arena::DroplessArena;
 use rustc_hir::HirId;
 use rustc_hir::def_id::DefId;
@@ -15,7 +16,6 @@ use rustc_middle::ty::{
 use rustc_middle::{bug, span_bug};
 use rustc_session::lint;
 use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
-use rustc_target::abi::{FIRST_VARIANT, FieldIdx, Integer, VariantIdx};
 
 use crate::constructor::Constructor::*;
 use crate::constructor::{
diff --git a/compiler/rustc_pattern_analysis/src/rustc/print.rs b/compiler/rustc_pattern_analysis/src/rustc/print.rs
index 17e389df17e..7649f72f868 100644
--- a/compiler/rustc_pattern_analysis/src/rustc/print.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc/print.rs
@@ -11,10 +11,10 @@
 
 use std::fmt;
 
+use rustc_abi::{FieldIdx, VariantIdx};
 use rustc_middle::bug;
 use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
 use rustc_span::sym;
-use rustc_target::abi::{FieldIdx, VariantIdx};
 
 #[derive(Clone, Debug)]
 pub(crate) struct FieldPat {
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 05954143aee..1a5c29afdc9 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -139,7 +139,7 @@ where
             }
             ty::ClauseKind::HostEffect(pred) => {
                 try_visit!(self.visit_trait(pred.trait_ref));
-                pred.host.visit_with(self)
+                pred.constness.visit_with(self)
             }
             ty::ClauseKind::Projection(ty::ProjectionPredicate {
                 projection_term: projection_ty,
diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs
index cd7725d2d70..5e30f17d626 100644
--- a/compiler/rustc_query_system/src/dep_graph/graph.rs
+++ b/compiler/rustc_query_system/src/dep_graph/graph.rs
@@ -134,7 +134,7 @@ impl<D: Deps> DepGraph<D> {
             encoder,
             record_graph,
             record_stats,
-            prev_graph.clone(),
+            Arc::clone(&prev_graph),
         );
 
         let colors = DepNodeColorMap::new(prev_graph_node_count);
diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs
index ca3efc11201..5af41b9e687 100644
--- a/compiler/rustc_query_system/src/query/job.rs
+++ b/compiler/rustc_query_system/src/query/job.rs
@@ -237,7 +237,7 @@ impl QueryLatch {
             // the `wait` call below, by 1) the `set` method or 2) by deadlock detection.
             // Both of these will remove it from the `waiters` list before resuming
             // this thread.
-            info.waiters.push(waiter.clone());
+            info.waiters.push(Arc::clone(waiter));
 
             // If this detects a deadlock and the deadlock handler wants to resume this thread
             // we have to be in the `wait` call. This is ensured by the deadlock handler
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index adb0ba7c820..f4a85c358e3 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -841,10 +841,9 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
                 self.r.record_partial_res(ty.id, PartialRes::new(res));
                 visit::walk_ty(self, ty)
             }
-            TyKind::ImplTrait(node_id, _) => {
+            TyKind::ImplTrait(..) => {
                 let candidates = self.lifetime_elision_candidates.take();
                 visit::walk_ty(self, ty);
-                self.record_lifetime_params_for_impl_trait(*node_id);
                 self.lifetime_elision_candidates = candidates;
             }
             TyKind::TraitObject(bounds, ..) => {
@@ -977,14 +976,6 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
                             sig.decl.inputs.iter().map(|Param { ty, .. }| (None, &**ty)),
                             &sig.decl.output,
                         );
-
-                        if let Some((coro_node_id, _)) = sig
-                            .header
-                            .coroutine_kind
-                            .map(|coroutine_kind| coroutine_kind.return_id())
-                        {
-                            this.record_lifetime_params_for_impl_trait(coro_node_id);
-                        }
                     },
                 );
                 return;
@@ -1026,10 +1017,6 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
                                         .map(|Param { pat, ty, .. }| (Some(&**pat), &**ty)),
                                     &declaration.output,
                                 );
-
-                                if let Some((async_node_id, _)) = coro_node_id {
-                                    this.record_lifetime_params_for_impl_trait(async_node_id);
-                                }
                             },
                         );
 
@@ -1220,7 +1207,6 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
                 }
             },
             AssocItemConstraintKind::Bound { ref bounds } => {
-                self.record_lifetime_params_for_impl_trait(constraint.id);
                 walk_list!(self, visit_param_bound, bounds, BoundKind::Bound);
             }
         }
@@ -4795,30 +4781,6 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
         )
     }
 
-    /// Construct the list of in-scope lifetime parameters for impl trait lowering.
-    /// We include all lifetime parameters, either named or "Fresh".
-    /// The order of those parameters does not matter, as long as it is
-    /// deterministic.
-    fn record_lifetime_params_for_impl_trait(&mut self, impl_trait_node_id: NodeId) {
-        let mut extra_lifetime_params = vec![];
-
-        for rib in self.lifetime_ribs.iter().rev() {
-            extra_lifetime_params
-                .extend(rib.bindings.iter().map(|(&ident, &(node_id, res))| (ident, node_id, res)));
-            match rib.kind {
-                LifetimeRibKind::Item => break,
-                LifetimeRibKind::AnonymousCreateParameter { binder, .. } => {
-                    if let Some(earlier_fresh) = self.r.extra_lifetime_params_map.get(&binder) {
-                        extra_lifetime_params.extend(earlier_fresh);
-                    }
-                }
-                _ => {}
-            }
-        }
-
-        self.r.extra_lifetime_params_map.insert(impl_trait_node_id, extra_lifetime_params);
-    }
-
     fn resolve_and_cache_rustdoc_path(&mut self, path_str: &str, ns: Namespace) -> Option<Res> {
         // FIXME: This caching may be incorrect in case of multiple `macro_rules`
         // items with the same name in the same module.
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 35d491cfc18..9abb3180388 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -1694,9 +1694,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
 
     fn dummy_ext(&self, macro_kind: MacroKind) -> Lrc<SyntaxExtension> {
         match macro_kind {
-            MacroKind::Bang => self.dummy_ext_bang.clone(),
-            MacroKind::Derive => self.dummy_ext_derive.clone(),
-            MacroKind::Attr => self.non_macro_attr.ext.clone(),
+            MacroKind::Bang => Lrc::clone(&self.dummy_ext_bang),
+            MacroKind::Derive => Lrc::clone(&self.dummy_ext_derive),
+            MacroKind::Attr => Lrc::clone(&self.non_macro_attr.ext),
         }
     }
 
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 1dc27776cb0..0b4d0e04c29 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -826,7 +826,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                 }
                 _ => None,
             },
-            None => self.get_macro(res).map(|macro_data| macro_data.ext.clone()),
+            None => self.get_macro(res).map(|macro_data| Lrc::clone(&macro_data.ext)),
         };
         Ok((ext, res))
     }
diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml
index 75cc8f18a54..e9983699609 100644
--- a/compiler/rustc_session/Cargo.toml
+++ b/compiler/rustc_session/Cargo.toml
@@ -7,6 +7,7 @@ edition = "2021"
 # tidy-alphabetical-start
 bitflags = "2.4.1"
 getopts = "0.2"
+rustc_abi = { path = "../rustc_abi" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
diff --git a/compiler/rustc_session/src/code_stats.rs b/compiler/rustc_session/src/code_stats.rs
index 7a32c0c2655..f3c21992784 100644
--- a/compiler/rustc_session/src/code_stats.rs
+++ b/compiler/rustc_session/src/code_stats.rs
@@ -1,10 +1,10 @@
 use std::cmp;
 
+use rustc_abi::{Align, Size};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::Lock;
 use rustc_span::Symbol;
 use rustc_span::def_id::DefId;
-use rustc_target::abi::{Align, Size};
 
 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
 pub struct VariantInfo {
diff --git a/compiler/rustc_session/src/config/cfg.rs b/compiler/rustc_session/src/config/cfg.rs
index ccc01728958..31ef2bda4f1 100644
--- a/compiler/rustc_session/src/config/cfg.rs
+++ b/compiler/rustc_session/src/config/cfg.rs
@@ -23,12 +23,12 @@
 use std::hash::Hash;
 use std::iter;
 
+use rustc_abi::Align;
 use rustc_ast::ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
 use rustc_lint_defs::BuiltinLintDiag;
 use rustc_lint_defs::builtin::EXPLICIT_BUILTIN_CFGS_IN_FLAGS;
 use rustc_span::symbol::{Symbol, sym};
-use rustc_target::abi::Align;
 use rustc_target::spec::{PanicStrategy, RelocModel, SanitizerSet, TARGETS, Target, TargetTriple};
 
 use crate::Session;
diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs
index 4aae2649843..b3e3381d986 100644
--- a/compiler/rustc_session/src/filesearch.rs
+++ b/compiler/rustc_session/src/filesearch.rs
@@ -84,7 +84,7 @@ fn current_dll_path() -> Result<PathBuf, String> {
         loop {
             if libc::loadquery(
                 libc::L_GETINFO,
-                buffer.as_mut_ptr() as *mut i8,
+                buffer.as_mut_ptr() as *mut u8,
                 (std::mem::size_of::<libc::ld_info>() * buffer.len()) as u32,
             ) >= 0
             {
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index 3d44810e7dd..f20ae85b8e8 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -241,7 +241,7 @@ impl ParseSess {
         let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
         let emitter = Box::new(
             HumanEmitter::new(stderr_destination(ColorConfig::Auto), fallback_bundle)
-                .sm(Some(sm.clone())),
+                .sm(Some(Lrc::clone(&sm))),
         );
         let dcx = DiagCtxt::new(emitter);
         ParseSess::with_dcx(dcx, sm)
@@ -278,7 +278,7 @@ impl ParseSess {
         let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
         let emitter = Box::new(HumanEmitter::new(
             stderr_destination(ColorConfig::Auto),
-            fallback_bundle.clone(),
+            Lrc::clone(&fallback_bundle),
         ));
         let fatal_dcx = DiagCtxt::new(emitter);
         let dcx = DiagCtxt::new(Box::new(SilentEmitter {
@@ -297,7 +297,7 @@ impl ParseSess {
     }
 
     pub fn clone_source_map(&self) -> Lrc<SourceMap> {
-        self.source_map.clone()
+        Lrc::clone(&self.source_map)
     }
 
     pub fn buffer_lint(
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 1963cf4eb7c..45434534c75 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -1036,7 +1036,8 @@ pub fn build_session(
         sopts.unstable_opts.translate_directionality_markers,
     );
     let source_map = rustc_span::source_map::get_source_map().unwrap();
-    let emitter = default_emitter(&sopts, registry, source_map.clone(), bundle, fallback_bundle);
+    let emitter =
+        default_emitter(&sopts, registry, Lrc::clone(&source_map), bundle, fallback_bundle);
 
     let mut dcx =
         DiagCtxt::new(emitter).with_flags(sopts.unstable_opts.dcx_flags(can_emit_warnings));
@@ -1079,7 +1080,7 @@ pub fn build_session(
     let target_tlib_path = if host_triple == target_triple {
         // Use the same `SearchPath` if host and target triple are identical to avoid unnecessary
         // rescanning of the target lib path and an unnecessary allocation.
-        host_tlib_path.clone()
+        Lrc::clone(&host_tlib_path)
     } else {
         Lrc::new(SearchPath::from_sysroot_and_triple(&sysroot, target_triple))
     };
diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs
index 55b47817f9a..a326e8583ea 100644
--- a/compiler/rustc_smir/src/rustc_internal/mod.rs
+++ b/compiler/rustc_smir/src/rustc_internal/mod.rs
@@ -170,7 +170,7 @@ impl<'tcx> Tables<'tcx> {
         stable_mir::mir::mono::StaticDef(self.create_def_id(did))
     }
 
-    pub(crate) fn layout_id(&mut self, layout: rustc_target::abi::Layout<'tcx>) -> Layout {
+    pub(crate) fn layout_id(&mut self, layout: rustc_abi::Layout<'tcx>) -> Layout {
         self.layouts.create_or_fetch(layout)
     }
 }
diff --git a/compiler/rustc_smir/src/rustc_smir/alloc.rs b/compiler/rustc_smir/src/rustc_smir/alloc.rs
index 0d8740ae31f..5c09879f60e 100644
--- a/compiler/rustc_smir/src/rustc_smir/alloc.rs
+++ b/compiler/rustc_smir/src/rustc_smir/alloc.rs
@@ -1,3 +1,4 @@
+use rustc_abi::{Align, Size};
 use rustc_middle::mir::ConstValue;
 use rustc_middle::mir::interpret::{AllocRange, Pointer, alloc_range};
 use stable_mir::Error;
@@ -7,7 +8,7 @@ use stable_mir::ty::{Allocation, ProvenanceMap};
 use crate::rustc_smir::{Stable, Tables};
 
 /// Creates new empty `Allocation` from given `Align`.
-fn new_empty_allocation(align: rustc_target::abi::Align) -> Allocation {
+fn new_empty_allocation(align: Align) -> Allocation {
     Allocation {
         bytes: Vec::new(),
         provenance: ProvenanceMap { ptrs: Vec::new() },
@@ -45,7 +46,7 @@ pub(crate) fn try_new_allocation<'tcx>(
                 .align;
             let mut allocation = rustc_middle::mir::interpret::Allocation::uninit(size, align.abi);
             allocation
-                .write_scalar(&tables.tcx, alloc_range(rustc_target::abi::Size::ZERO, size), scalar)
+                .write_scalar(&tables.tcx, alloc_range(Size::ZERO, size), scalar)
                 .map_err(|e| e.stable(tables))?;
             allocation.stable(tables)
         }
@@ -59,7 +60,7 @@ pub(crate) fn try_new_allocation<'tcx>(
         }
         ConstValue::Slice { data, meta } => {
             let alloc_id = tables.tcx.reserve_and_set_memory_alloc(data);
-            let ptr = Pointer::new(alloc_id.into(), rustc_target::abi::Size::ZERO);
+            let ptr = Pointer::new(alloc_id.into(), Size::ZERO);
             let scalar_ptr = rustc_middle::mir::interpret::Scalar::from_pointer(ptr, &tables.tcx);
             let scalar_meta =
                 rustc_middle::mir::interpret::Scalar::from_target_usize(meta, &tables.tcx);
@@ -72,7 +73,7 @@ pub(crate) fn try_new_allocation<'tcx>(
             allocation
                 .write_scalar(
                     &tables.tcx,
-                    alloc_range(rustc_target::abi::Size::ZERO, tables.tcx.data_layout.pointer_size),
+                    alloc_range(Size::ZERO, tables.tcx.data_layout.pointer_size),
                     scalar_ptr,
                 )
                 .map_err(|e| e.stable(tables))?;
@@ -112,10 +113,7 @@ pub(super) fn allocation_filter<'tcx>(
         .map(Some)
         .collect();
     for (i, b) in bytes.iter_mut().enumerate() {
-        if !alloc
-            .init_mask()
-            .get(rustc_target::abi::Size::from_bytes(i + alloc_range.start.bytes_usize()))
-        {
+        if !alloc.init_mask().get(Size::from_bytes(i + alloc_range.start.bytes_usize())) {
             *b = None;
         }
     }
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs
index dbfcde56f6e..af24fd23f50 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs
@@ -1,9 +1,9 @@
-//! Conversion of internal Rust compiler `rustc_target::abi` and `rustc_abi` items to stable ones.
+//! Conversion of internal Rust compiler `rustc_target` and `rustc_abi` items to stable ones.
 
 #![allow(rustc::usage_of_qualified_ty)]
 
 use rustc_middle::ty;
-use rustc_target::abi::call::Conv;
+use rustc_target::callconv::{self, Conv};
 use stable_mir::abi::{
     AddressSpace, ArgAbi, CallConvention, FieldsShape, FloatLength, FnAbi, IntegerLength, Layout,
     LayoutShape, PassMode, Primitive, Scalar, TagEncoding, TyAndLayout, ValueAbi, VariantsShape,
@@ -15,7 +15,7 @@ use stable_mir::ty::{Align, IndexedVal, VariantIdx};
 
 use crate::rustc_smir::{Stable, Tables};
 
-impl<'tcx> Stable<'tcx> for rustc_target::abi::VariantIdx {
+impl<'tcx> Stable<'tcx> for rustc_abi::VariantIdx {
     type T = VariantIdx;
     fn stable(&self, _: &mut Tables<'_>) -> Self::T {
         VariantIdx::to_val(self.as_usize())
@@ -33,7 +33,7 @@ impl<'tcx> Stable<'tcx> for rustc_abi::Endian {
     }
 }
 
-impl<'tcx> Stable<'tcx> for rustc_target::abi::TyAndLayout<'tcx, ty::Ty<'tcx>> {
+impl<'tcx> Stable<'tcx> for rustc_abi::TyAndLayout<'tcx, ty::Ty<'tcx>> {
     type T = TyAndLayout;
 
     fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
@@ -41,7 +41,7 @@ impl<'tcx> Stable<'tcx> for rustc_target::abi::TyAndLayout<'tcx, ty::Ty<'tcx>> {
     }
 }
 
-impl<'tcx> Stable<'tcx> for rustc_target::abi::Layout<'tcx> {
+impl<'tcx> Stable<'tcx> for rustc_abi::Layout<'tcx> {
     type T = Layout;
 
     fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
@@ -49,23 +49,21 @@ impl<'tcx> Stable<'tcx> for rustc_target::abi::Layout<'tcx> {
     }
 }
 
-impl<'tcx> Stable<'tcx>
-    for rustc_abi::LayoutData<rustc_target::abi::FieldIdx, rustc_target::abi::VariantIdx>
-{
+impl<'tcx> Stable<'tcx> for rustc_abi::LayoutData<rustc_abi::FieldIdx, rustc_abi::VariantIdx> {
     type T = LayoutShape;
 
     fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
         LayoutShape {
             fields: self.fields.stable(tables),
             variants: self.variants.stable(tables),
-            abi: self.abi.stable(tables),
+            abi: self.backend_repr.stable(tables),
             abi_align: self.align.abi.stable(tables),
             size: self.size.stable(tables),
         }
     }
 }
 
-impl<'tcx> Stable<'tcx> for rustc_target::abi::call::FnAbi<'tcx, ty::Ty<'tcx>> {
+impl<'tcx> Stable<'tcx> for callconv::FnAbi<'tcx, ty::Ty<'tcx>> {
     type T = FnAbi;
 
     fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
@@ -81,7 +79,7 @@ impl<'tcx> Stable<'tcx> for rustc_target::abi::call::FnAbi<'tcx, ty::Ty<'tcx>> {
     }
 }
 
-impl<'tcx> Stable<'tcx> for rustc_target::abi::call::ArgAbi<'tcx, ty::Ty<'tcx>> {
+impl<'tcx> Stable<'tcx> for callconv::ArgAbi<'tcx, ty::Ty<'tcx>> {
     type T = ArgAbi;
 
     fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
@@ -93,7 +91,7 @@ impl<'tcx> Stable<'tcx> for rustc_target::abi::call::ArgAbi<'tcx, ty::Ty<'tcx>>
     }
 }
 
-impl<'tcx> Stable<'tcx> for rustc_target::abi::call::Conv {
+impl<'tcx> Stable<'tcx> for callconv::Conv {
     type T = CallConvention;
 
     fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
@@ -122,31 +120,29 @@ impl<'tcx> Stable<'tcx> for rustc_target::abi::call::Conv {
     }
 }
 
-impl<'tcx> Stable<'tcx> for rustc_target::abi::call::PassMode {
+impl<'tcx> Stable<'tcx> for callconv::PassMode {
     type T = PassMode;
 
     fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
         match self {
-            rustc_target::abi::call::PassMode::Ignore => PassMode::Ignore,
-            rustc_target::abi::call::PassMode::Direct(attr) => PassMode::Direct(opaque(attr)),
-            rustc_target::abi::call::PassMode::Pair(first, second) => {
+            callconv::PassMode::Ignore => PassMode::Ignore,
+            callconv::PassMode::Direct(attr) => PassMode::Direct(opaque(attr)),
+            callconv::PassMode::Pair(first, second) => {
                 PassMode::Pair(opaque(first), opaque(second))
             }
-            rustc_target::abi::call::PassMode::Cast { pad_i32, cast } => {
+            callconv::PassMode::Cast { pad_i32, cast } => {
                 PassMode::Cast { pad_i32: *pad_i32, cast: opaque(cast) }
             }
-            rustc_target::abi::call::PassMode::Indirect { attrs, meta_attrs, on_stack } => {
-                PassMode::Indirect {
-                    attrs: opaque(attrs),
-                    meta_attrs: opaque(meta_attrs),
-                    on_stack: *on_stack,
-                }
-            }
+            callconv::PassMode::Indirect { attrs, meta_attrs, on_stack } => PassMode::Indirect {
+                attrs: opaque(attrs),
+                meta_attrs: opaque(meta_attrs),
+                on_stack: *on_stack,
+            },
         }
     }
 }
 
-impl<'tcx> Stable<'tcx> for rustc_abi::FieldsShape<rustc_target::abi::FieldIdx> {
+impl<'tcx> Stable<'tcx> for rustc_abi::FieldsShape<rustc_abi::FieldIdx> {
     type T = FieldsShape;
 
     fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
@@ -163,9 +159,7 @@ impl<'tcx> Stable<'tcx> for rustc_abi::FieldsShape<rustc_target::abi::FieldIdx>
     }
 }
 
-impl<'tcx> Stable<'tcx>
-    for rustc_abi::Variants<rustc_target::abi::FieldIdx, rustc_target::abi::VariantIdx>
-{
+impl<'tcx> Stable<'tcx> for rustc_abi::Variants<rustc_abi::FieldIdx, rustc_abi::VariantIdx> {
     type T = VariantsShape;
 
     fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
@@ -185,7 +179,7 @@ impl<'tcx> Stable<'tcx>
     }
 }
 
-impl<'tcx> Stable<'tcx> for rustc_abi::TagEncoding<rustc_target::abi::VariantIdx> {
+impl<'tcx> Stable<'tcx> for rustc_abi::TagEncoding<rustc_abi::VariantIdx> {
     type T = TagEncoding;
 
     fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
@@ -202,20 +196,20 @@ impl<'tcx> Stable<'tcx> for rustc_abi::TagEncoding<rustc_target::abi::VariantIdx
     }
 }
 
-impl<'tcx> Stable<'tcx> for rustc_abi::Abi {
+impl<'tcx> Stable<'tcx> for rustc_abi::BackendRepr {
     type T = ValueAbi;
 
     fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
         match *self {
-            rustc_abi::Abi::Uninhabited => ValueAbi::Uninhabited,
-            rustc_abi::Abi::Scalar(scalar) => ValueAbi::Scalar(scalar.stable(tables)),
-            rustc_abi::Abi::ScalarPair(first, second) => {
+            rustc_abi::BackendRepr::Uninhabited => ValueAbi::Uninhabited,
+            rustc_abi::BackendRepr::Scalar(scalar) => ValueAbi::Scalar(scalar.stable(tables)),
+            rustc_abi::BackendRepr::ScalarPair(first, second) => {
                 ValueAbi::ScalarPair(first.stable(tables), second.stable(tables))
             }
-            rustc_abi::Abi::Vector { element, count } => {
+            rustc_abi::BackendRepr::Vector { element, count } => {
                 ValueAbi::Vector { element: element.stable(tables), count }
             }
-            rustc_abi::Abi::Aggregate { sized } => ValueAbi::Aggregate { sized },
+            rustc_abi::BackendRepr::Memory { sized } => ValueAbi::Aggregate { sized },
         }
     }
 }
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
index dbae4b7e719..820d8a6be25 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
@@ -691,11 +691,7 @@ impl<'tcx> Stable<'tcx> for mir::interpret::Allocation {
     type T = stable_mir::ty::Allocation;
 
     fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
-        alloc::allocation_filter(
-            self,
-            alloc_range(rustc_target::abi::Size::ZERO, self.size()),
-            tables,
-        )
+        alloc::allocation_filter(self, alloc_range(rustc_abi::Size::ZERO, self.size()), tables)
     }
 }
 
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index 9b27b94fb5a..9032156b257 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -36,7 +36,7 @@ pub struct Tables<'tcx> {
     pub(crate) instances: IndexMap<ty::Instance<'tcx>, InstanceDef>,
     pub(crate) ty_consts: IndexMap<ty::Const<'tcx>, TyConstId>,
     pub(crate) mir_consts: IndexMap<mir::Const<'tcx>, MirConstId>,
-    pub(crate) layouts: IndexMap<rustc_target::abi::Layout<'tcx>, Layout>,
+    pub(crate) layouts: IndexMap<rustc_abi::Layout<'tcx>, Layout>,
 }
 
 impl<'tcx> Tables<'tcx> {
diff --git a/compiler/rustc_span/src/caching_source_map_view.rs b/compiler/rustc_span/src/caching_source_map_view.rs
index 26aa782e5d7..9f977b98b82 100644
--- a/compiler/rustc_span/src/caching_source_map_view.rs
+++ b/compiler/rustc_span/src/caching_source_map_view.rs
@@ -63,7 +63,7 @@ pub struct CachingSourceMapView<'sm> {
 impl<'sm> CachingSourceMapView<'sm> {
     pub fn new(source_map: &'sm SourceMap) -> CachingSourceMapView<'sm> {
         let files = source_map.files();
-        let first_file = files[0].clone();
+        let first_file = Lrc::clone(&files[0]);
         let entry = CacheEntry {
             time_stamp: 0,
             line_number: 0,
@@ -92,7 +92,7 @@ impl<'sm> CachingSourceMapView<'sm> {
             cache_entry.touch(self.time_stamp);
 
             let col = RelativeBytePos(pos.to_u32() - cache_entry.line.start.to_u32());
-            return Some((cache_entry.file.clone(), cache_entry.line_number, col));
+            return Some((Lrc::clone(&cache_entry.file), cache_entry.line_number, col));
         }
 
         // No cache hit ...
@@ -109,7 +109,7 @@ impl<'sm> CachingSourceMapView<'sm> {
         cache_entry.update(new_file_and_idx, pos, self.time_stamp);
 
         let col = RelativeBytePos(pos.to_u32() - cache_entry.line.start.to_u32());
-        Some((cache_entry.file.clone(), cache_entry.line_number, col))
+        Some((Lrc::clone(&cache_entry.file), cache_entry.line_number, col))
     }
 
     pub fn span_data_to_lines_and_cols(
@@ -133,7 +133,7 @@ impl<'sm> CachingSourceMapView<'sm> {
                 }
 
                 (
-                    lo.file.clone(),
+                    Lrc::clone(&lo.file),
                     lo.line_number,
                     span_data.lo - lo.line.start,
                     hi.line_number,
@@ -181,7 +181,7 @@ impl<'sm> CachingSourceMapView<'sm> {
                 lo.update(new_file_and_idx, span_data.lo, self.time_stamp);
 
                 if !lo.line.contains(&span_data.hi) {
-                    let new_file_and_idx = Some((lo.file.clone(), lo.file_index));
+                    let new_file_and_idx = Some((Lrc::clone(&lo.file), lo.file_index));
                     let next_oldest = self.oldest_cache_entry_index_avoid(oldest);
                     let hi = &mut self.line_cache[next_oldest];
                     hi.update(new_file_and_idx, span_data.hi, self.time_stamp);
@@ -227,7 +227,7 @@ impl<'sm> CachingSourceMapView<'sm> {
         assert_eq!(lo.file_index, hi.file_index);
 
         Some((
-            lo.file.clone(),
+            Lrc::clone(&lo.file),
             lo.line_number,
             span_data.lo - lo.line.start,
             hi.line_number,
@@ -277,7 +277,7 @@ impl<'sm> CachingSourceMapView<'sm> {
             let file = &self.source_map.files()[file_idx];
 
             if file_contains(file, pos) {
-                return Some((file.clone(), file_idx));
+                return Some((Lrc::clone(file), file_idx));
             }
         }
 
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index 8a023305937..f36bb38623e 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -286,8 +286,8 @@ impl SourceMap {
         });
 
         let file = Lrc::new(file);
-        files.source_files.push(file.clone());
-        files.stable_id_to_source_file.insert(file_id, file.clone());
+        files.source_files.push(Lrc::clone(&file));
+        files.stable_id_to_source_file.insert(file_id, Lrc::clone(&file));
 
         Ok(file)
     }
@@ -386,7 +386,7 @@ impl SourceMap {
     /// Return the SourceFile that contains the given `BytePos`
     pub fn lookup_source_file(&self, pos: BytePos) -> Lrc<SourceFile> {
         let idx = self.lookup_source_file_idx(pos);
-        (*self.files.borrow().source_files)[idx].clone()
+        Lrc::clone(&(*self.files.borrow().source_files)[idx])
     }
 
     /// Looks up source information about a `BytePos`.
@@ -468,7 +468,7 @@ impl SourceMap {
         if lo != hi {
             return true;
         }
-        let f = (*self.files.borrow().source_files)[lo].clone();
+        let f = Lrc::clone(&(*self.files.borrow().source_files)[lo]);
         let lo = f.relative_position(sp.lo());
         let hi = f.relative_position(sp.hi());
         f.lookup_line(lo) != f.lookup_line(hi)
@@ -994,7 +994,7 @@ impl SourceMap {
         let filename = self.path_mapping().map_filename_prefix(filename).0;
         for sf in self.files.borrow().source_files.iter() {
             if filename == sf.name {
-                return Some(sf.clone());
+                return Some(Lrc::clone(&sf));
             }
         }
         None
@@ -1003,7 +1003,7 @@ impl SourceMap {
     /// For a global `BytePos`, computes the local offset within the containing `SourceFile`.
     pub fn lookup_byte_offset(&self, bpos: BytePos) -> SourceFileAndBytePos {
         let idx = self.lookup_source_file_idx(bpos);
-        let sf = (*self.files.borrow().source_files)[idx].clone();
+        let sf = Lrc::clone(&(*self.files.borrow().source_files)[idx]);
         let offset = bpos - sf.start_pos;
         SourceFileAndBytePos { sf, pos: offset }
     }
diff --git a/compiler/rustc_symbol_mangling/Cargo.toml b/compiler/rustc_symbol_mangling/Cargo.toml
index 65aa9e40c8b..644e710d1db 100644
--- a/compiler/rustc_symbol_mangling/Cargo.toml
+++ b/compiler/rustc_symbol_mangling/Cargo.toml
@@ -7,6 +7,8 @@ edition = "2021"
 # tidy-alphabetical-start
 punycode = "0.4.0"
 rustc-demangle = "0.1.21"
+
+rustc_abi = { path = "../rustc_abi" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_hir = { path = "../rustc_hir" }
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index d092fa8f082..868345c7594 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -2,6 +2,7 @@ use std::fmt::Write;
 use std::iter;
 use std::ops::Range;
 
+use rustc_abi::Integer;
 use rustc_data_structures::base_n::ToBaseN;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::intern::Interned;
@@ -17,7 +18,6 @@ use rustc_middle::ty::{
     TyCtxt, TypeVisitable, TypeVisitableExt, UintTy,
 };
 use rustc_span::symbol::kw;
-use rustc_target::abi::Integer;
 use rustc_target::spec::abi::Abi;
 
 pub(super) fn mangle<'tcx>(
diff --git a/compiler/rustc_target/src/callconv/loongarch.rs b/compiler/rustc_target/src/callconv/loongarch.rs
index ffec76370d0..d1234c3cc91 100644
--- a/compiler/rustc_target/src/callconv/loongarch.rs
+++ b/compiler/rustc_target/src/callconv/loongarch.rs
@@ -1,5 +1,7 @@
 use crate::abi::call::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform};
-use crate::abi::{self, Abi, FieldsShape, HasDataLayout, Size, TyAbiInterface, TyAndLayout};
+use crate::abi::{
+    self, BackendRepr, FieldsShape, HasDataLayout, Size, TyAbiInterface, TyAndLayout,
+};
 use crate::spec::HasTargetSpec;
 use crate::spec::abi::Abi as SpecAbi;
 
@@ -21,8 +23,8 @@ enum FloatConv {
 struct CannotUseFpConv;
 
 fn is_loongarch_aggregate<Ty>(arg: &ArgAbi<'_, Ty>) -> bool {
-    match arg.layout.abi {
-        Abi::Vector { .. } => true,
+    match arg.layout.backend_repr {
+        BackendRepr::Vector { .. } => true,
         _ => arg.layout.is_aggregate(),
     }
 }
@@ -38,8 +40,8 @@ fn should_use_fp_conv_helper<'a, Ty, C>(
 where
     Ty: TyAbiInterface<'a, C> + Copy,
 {
-    match arg_layout.abi {
-        Abi::Scalar(scalar) => match scalar.primitive() {
+    match arg_layout.backend_repr {
+        BackendRepr::Scalar(scalar) => match scalar.primitive() {
             abi::Int(..) | abi::Pointer(_) => {
                 if arg_layout.size.bits() > xlen {
                     return Err(CannotUseFpConv);
@@ -77,8 +79,8 @@ where
                 }
             }
         },
-        Abi::Vector { .. } | Abi::Uninhabited => return Err(CannotUseFpConv),
-        Abi::ScalarPair(..) | Abi::Aggregate { .. } => match arg_layout.fields {
+        BackendRepr::Vector { .. } | BackendRepr::Uninhabited => return Err(CannotUseFpConv),
+        BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => match arg_layout.fields {
             FieldsShape::Primitive => {
                 unreachable!("aggregates can't have `FieldsShape::Primitive`")
             }
@@ -311,7 +313,7 @@ fn classify_arg<'a, Ty, C>(
 }
 
 fn extend_integer_width<Ty>(arg: &mut ArgAbi<'_, Ty>, xlen: u64) {
-    if let Abi::Scalar(scalar) = arg.layout.abi {
+    if let BackendRepr::Scalar(scalar) = arg.layout.backend_repr {
         if let abi::Int(i, _) = scalar.primitive() {
             // 32-bit integers are always sign-extended
             if i.size().bits() == 32 && xlen > 32 {
diff --git a/compiler/rustc_target/src/callconv/mips64.rs b/compiler/rustc_target/src/callconv/mips64.rs
index 2c3258c8d42..5bdf4c2ad77 100644
--- a/compiler/rustc_target/src/callconv/mips64.rs
+++ b/compiler/rustc_target/src/callconv/mips64.rs
@@ -5,7 +5,7 @@ use crate::abi::{self, HasDataLayout, Size, TyAbiInterface};
 
 fn extend_integer_width_mips<Ty>(arg: &mut ArgAbi<'_, Ty>, bits: u64) {
     // Always sign extend u32 values on 64-bit mips
-    if let abi::Abi::Scalar(scalar) = arg.layout.abi {
+    if let abi::BackendRepr::Scalar(scalar) = arg.layout.backend_repr {
         if let abi::Int(i, signed) = scalar.primitive() {
             if !signed && i.size().bits() == 32 {
                 if let PassMode::Direct(ref mut attrs) = arg.mode {
@@ -24,8 +24,8 @@ where
     Ty: TyAbiInterface<'a, C> + Copy,
     C: HasDataLayout,
 {
-    match ret.layout.field(cx, i).abi {
-        abi::Abi::Scalar(scalar) => match scalar.primitive() {
+    match ret.layout.field(cx, i).backend_repr {
+        abi::BackendRepr::Scalar(scalar) => match scalar.primitive() {
             abi::Float(abi::F32) => Some(Reg::f32()),
             abi::Float(abi::F64) => Some(Reg::f64()),
             _ => None,
@@ -109,7 +109,7 @@ where
                 let offset = arg.layout.fields.offset(i);
 
                 // We only care about aligned doubles
-                if let abi::Abi::Scalar(scalar) = field.abi {
+                if let abi::BackendRepr::Scalar(scalar) = field.backend_repr {
                     if scalar.primitive() == abi::Float(abi::F64) {
                         if offset.is_aligned(dl.f64_align.abi) {
                             // Insert enough integers to cover [last_offset, offset)
diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs
index 25b001b57e8..8c3df9c426b 100644
--- a/compiler/rustc_target/src/callconv/mod.rs
+++ b/compiler/rustc_target/src/callconv/mod.rs
@@ -6,7 +6,8 @@ use rustc_macros::HashStable_Generic;
 use rustc_span::Symbol;
 
 use crate::abi::{
-    self, Abi, AddressSpace, Align, HasDataLayout, Pointer, Size, TyAbiInterface, TyAndLayout,
+    self, AddressSpace, Align, BackendRepr, HasDataLayout, Pointer, Size, TyAbiInterface,
+    TyAndLayout,
 };
 use crate::spec::abi::Abi as SpecAbi;
 use crate::spec::{self, HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, WasmCAbi};
@@ -350,15 +351,17 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
         layout: TyAndLayout<'a, Ty>,
         scalar_attrs: impl Fn(&TyAndLayout<'a, Ty>, abi::Scalar, Size) -> ArgAttributes,
     ) -> Self {
-        let mode = match layout.abi {
-            Abi::Uninhabited => PassMode::Ignore,
-            Abi::Scalar(scalar) => PassMode::Direct(scalar_attrs(&layout, scalar, Size::ZERO)),
-            Abi::ScalarPair(a, b) => PassMode::Pair(
+        let mode = match layout.backend_repr {
+            BackendRepr::Uninhabited => PassMode::Ignore,
+            BackendRepr::Scalar(scalar) => {
+                PassMode::Direct(scalar_attrs(&layout, scalar, Size::ZERO))
+            }
+            BackendRepr::ScalarPair(a, b) => PassMode::Pair(
                 scalar_attrs(&layout, a, Size::ZERO),
                 scalar_attrs(&layout, b, a.size(cx).align_to(b.align(cx).abi)),
             ),
-            Abi::Vector { .. } => PassMode::Direct(ArgAttributes::new()),
-            Abi::Aggregate { .. } => Self::indirect_pass_mode(&layout),
+            BackendRepr::Vector { .. } => PassMode::Direct(ArgAttributes::new()),
+            BackendRepr::Memory { .. } => Self::indirect_pass_mode(&layout),
         };
         ArgAbi { layout, mode }
     }
@@ -460,7 +463,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
 
     pub fn extend_integer_width_to(&mut self, bits: u64) {
         // Only integers have signedness
-        if let Abi::Scalar(scalar) = self.layout.abi {
+        if let BackendRepr::Scalar(scalar) = self.layout.backend_repr {
             if let abi::Int(i, signed) = scalar.primitive() {
                 if i.size().bits() < bits {
                     if let PassMode::Direct(ref mut attrs) = self.mode {
@@ -512,7 +515,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
             // That elevates any type difference to an ABI difference since we just use the
             // full Rust type as the LLVM argument/return type.
             if matches!(self.mode, PassMode::Direct(..))
-                && matches!(self.layout.abi, Abi::Aggregate { .. })
+                && matches!(self.layout.backend_repr, BackendRepr::Memory { .. })
             {
                 // For aggregates in `Direct` mode to be compatible, the types need to be equal.
                 self.layout.ty == other.layout.ty
@@ -791,8 +794,8 @@ impl<'a, Ty> FnAbi<'a, Ty> {
                 continue;
             }
 
-            match arg.layout.abi {
-                Abi::Aggregate { .. } => {}
+            match arg.layout.backend_repr {
+                BackendRepr::Memory { .. } => {}
 
                 // This is a fun case! The gist of what this is doing is
                 // that we want callers and callees to always agree on the
@@ -813,7 +816,9 @@ impl<'a, Ty> FnAbi<'a, Ty> {
                 // Note that the intrinsic ABI is exempt here as
                 // that's how we connect up to LLVM and it's unstable
                 // anyway, we control all calls to it in libstd.
-                Abi::Vector { .. } if abi != SpecAbi::RustIntrinsic && spec.simd_types_indirect => {
+                BackendRepr::Vector { .. }
+                    if abi != SpecAbi::RustIntrinsic && spec.simd_types_indirect =>
+                {
                     arg.make_indirect();
                     continue;
                 }
diff --git a/compiler/rustc_target/src/callconv/riscv.rs b/compiler/rustc_target/src/callconv/riscv.rs
index f96169e6a61..c0298edb5ab 100644
--- a/compiler/rustc_target/src/callconv/riscv.rs
+++ b/compiler/rustc_target/src/callconv/riscv.rs
@@ -4,8 +4,10 @@
 // Reference: Clang RISC-V ELF psABI lowering code
 // https://github.com/llvm/llvm-project/blob/8e780252a7284be45cf1ba224cabd884847e8e92/clang/lib/CodeGen/TargetInfo.cpp#L9311-L9773
 
+use rustc_abi::{BackendRepr, FieldsShape, HasDataLayout, Size, TyAbiInterface, TyAndLayout};
+
+use crate::abi;
 use crate::abi::call::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform};
-use crate::abi::{self, Abi, FieldsShape, HasDataLayout, Size, TyAbiInterface, TyAndLayout};
 use crate::spec::HasTargetSpec;
 use crate::spec::abi::Abi as SpecAbi;
 
@@ -27,8 +29,8 @@ enum FloatConv {
 struct CannotUseFpConv;
 
 fn is_riscv_aggregate<Ty>(arg: &ArgAbi<'_, Ty>) -> bool {
-    match arg.layout.abi {
-        Abi::Vector { .. } => true,
+    match arg.layout.backend_repr {
+        BackendRepr::Vector { .. } => true,
         _ => arg.layout.is_aggregate(),
     }
 }
@@ -44,8 +46,8 @@ fn should_use_fp_conv_helper<'a, Ty, C>(
 where
     Ty: TyAbiInterface<'a, C> + Copy,
 {
-    match arg_layout.abi {
-        Abi::Scalar(scalar) => match scalar.primitive() {
+    match arg_layout.backend_repr {
+        BackendRepr::Scalar(scalar) => match scalar.primitive() {
             abi::Int(..) | abi::Pointer(_) => {
                 if arg_layout.size.bits() > xlen {
                     return Err(CannotUseFpConv);
@@ -83,8 +85,8 @@ where
                 }
             }
         },
-        Abi::Vector { .. } | Abi::Uninhabited => return Err(CannotUseFpConv),
-        Abi::ScalarPair(..) | Abi::Aggregate { .. } => match arg_layout.fields {
+        BackendRepr::Vector { .. } | BackendRepr::Uninhabited => return Err(CannotUseFpConv),
+        BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => match arg_layout.fields {
             FieldsShape::Primitive => {
                 unreachable!("aggregates can't have `FieldsShape::Primitive`")
             }
@@ -317,7 +319,7 @@ fn classify_arg<'a, Ty, C>(
 }
 
 fn extend_integer_width<Ty>(arg: &mut ArgAbi<'_, Ty>, xlen: u64) {
-    if let Abi::Scalar(scalar) = arg.layout.abi {
+    if let BackendRepr::Scalar(scalar) = arg.layout.backend_repr {
         if let abi::Int(i, _) = scalar.primitive() {
             // 32-bit integers are always sign-extended
             if i.size().bits() == 32 && xlen > 32 {
diff --git a/compiler/rustc_target/src/callconv/sparc64.rs b/compiler/rustc_target/src/callconv/sparc64.rs
index 835353f76fc..313d8730399 100644
--- a/compiler/rustc_target/src/callconv/sparc64.rs
+++ b/compiler/rustc_target/src/callconv/sparc64.rs
@@ -109,11 +109,11 @@ where
         return data;
     }
 
-    match layout.abi {
-        abi::Abi::Scalar(scalar) => {
+    match layout.backend_repr {
+        abi::BackendRepr::Scalar(scalar) => {
             data = arg_scalar(cx, &scalar, offset, data);
         }
-        abi::Abi::Aggregate { .. } => {
+        abi::BackendRepr::Memory { .. } => {
             for i in 0..layout.fields.count() {
                 if offset < layout.fields.offset(i) {
                     offset = layout.fields.offset(i);
@@ -122,7 +122,7 @@ where
             }
         }
         _ => {
-            if let abi::Abi::ScalarPair(scalar1, scalar2) = &layout.abi {
+            if let abi::BackendRepr::ScalarPair(scalar1, scalar2) = &layout.backend_repr {
                 data = arg_scalar_pair(cx, scalar1, scalar2, offset, data);
             }
         }
diff --git a/compiler/rustc_target/src/callconv/x86.rs b/compiler/rustc_target/src/callconv/x86.rs
index e907beecb38..a5af975d4d2 100644
--- a/compiler/rustc_target/src/callconv/x86.rs
+++ b/compiler/rustc_target/src/callconv/x86.rs
@@ -1,6 +1,6 @@
 use crate::abi::call::{ArgAttribute, FnAbi, PassMode, Reg, RegKind};
 use crate::abi::{
-    Abi, AddressSpace, Align, Float, HasDataLayout, Pointer, TyAbiInterface, TyAndLayout,
+    AddressSpace, Align, BackendRepr, Float, HasDataLayout, Pointer, TyAbiInterface, TyAndLayout,
 };
 use crate::spec::HasTargetSpec;
 use crate::spec::abi::Abi as SpecAbi;
@@ -105,10 +105,12 @@ where
             where
                 Ty: TyAbiInterface<'a, C> + Copy,
             {
-                match layout.abi {
-                    Abi::Uninhabited | Abi::Scalar(_) | Abi::ScalarPair(..) => false,
-                    Abi::Vector { .. } => true,
-                    Abi::Aggregate { .. } => {
+                match layout.backend_repr {
+                    BackendRepr::Uninhabited
+                    | BackendRepr::Scalar(_)
+                    | BackendRepr::ScalarPair(..) => false,
+                    BackendRepr::Vector { .. } => true,
+                    BackendRepr::Memory { .. } => {
                         for i in 0..layout.fields.count() {
                             if contains_vector(cx, layout.field(cx, i)) {
                                 return true;
@@ -223,9 +225,9 @@ where
         // Intrinsics themselves are not actual "real" functions, so theres no need to change their ABIs.
         && abi != SpecAbi::RustIntrinsic
     {
-        let has_float = match fn_abi.ret.layout.abi {
-            Abi::Scalar(s) => matches!(s.primitive(), Float(_)),
-            Abi::ScalarPair(s1, s2) => {
+        let has_float = match fn_abi.ret.layout.backend_repr {
+            BackendRepr::Scalar(s) => matches!(s.primitive(), Float(_)),
+            BackendRepr::ScalarPair(s1, s2) => {
                 matches!(s1.primitive(), Float(_)) || matches!(s2.primitive(), Float(_))
             }
             _ => false, // anyway not passed via registers on x86
diff --git a/compiler/rustc_target/src/callconv/x86_64.rs b/compiler/rustc_target/src/callconv/x86_64.rs
index 9910e623ac9..bd101b23ea1 100644
--- a/compiler/rustc_target/src/callconv/x86_64.rs
+++ b/compiler/rustc_target/src/callconv/x86_64.rs
@@ -1,8 +1,10 @@
 // The classification code for the x86_64 ABI is taken from the clay language
 // https://github.com/jckarter/clay/blob/db0bd2702ab0b6e48965cd85f8859bbd5f60e48e/compiler/externals.cpp
 
+use rustc_abi::{BackendRepr, HasDataLayout, Size, TyAbiInterface, TyAndLayout};
+
+use crate::abi;
 use crate::abi::call::{ArgAbi, CastTarget, FnAbi, Reg, RegKind};
-use crate::abi::{self, Abi, HasDataLayout, Size, TyAbiInterface, TyAndLayout};
 
 /// Classification of "eightbyte" components.
 // N.B., the order of the variants is from general to specific,
@@ -46,17 +48,17 @@ where
             return Ok(());
         }
 
-        let mut c = match layout.abi {
-            Abi::Uninhabited => return Ok(()),
+        let mut c = match layout.backend_repr {
+            BackendRepr::Uninhabited => return Ok(()),
 
-            Abi::Scalar(scalar) => match scalar.primitive() {
+            BackendRepr::Scalar(scalar) => match scalar.primitive() {
                 abi::Int(..) | abi::Pointer(_) => Class::Int,
                 abi::Float(_) => Class::Sse,
             },
 
-            Abi::Vector { .. } => Class::Sse,
+            BackendRepr::Vector { .. } => Class::Sse,
 
-            Abi::ScalarPair(..) | Abi::Aggregate { .. } => {
+            BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => {
                 for i in 0..layout.fields.count() {
                     let field_off = off + layout.fields.offset(i);
                     classify(cx, layout.field(cx, i), cls, field_off)?;
diff --git a/compiler/rustc_target/src/callconv/x86_win64.rs b/compiler/rustc_target/src/callconv/x86_win64.rs
index e5a20b248e4..83d94cb11ba 100644
--- a/compiler/rustc_target/src/callconv/x86_win64.rs
+++ b/compiler/rustc_target/src/callconv/x86_win64.rs
@@ -1,25 +1,28 @@
+use rustc_abi::{BackendRepr, Float, Primitive};
+
 use crate::abi::call::{ArgAbi, FnAbi, Reg};
-use crate::abi::{Abi, Float, Primitive};
 use crate::spec::HasTargetSpec;
 
 // Win64 ABI: https://docs.microsoft.com/en-us/cpp/build/parameter-passing
 
 pub(crate) fn compute_abi_info<Ty>(cx: &impl HasTargetSpec, fn_abi: &mut FnAbi<'_, Ty>) {
     let fixup = |a: &mut ArgAbi<'_, Ty>| {
-        match a.layout.abi {
-            Abi::Uninhabited | Abi::Aggregate { sized: false } => {}
-            Abi::ScalarPair(..) | Abi::Aggregate { sized: true } => match a.layout.size.bits() {
-                8 => a.cast_to(Reg::i8()),
-                16 => a.cast_to(Reg::i16()),
-                32 => a.cast_to(Reg::i32()),
-                64 => a.cast_to(Reg::i64()),
-                _ => a.make_indirect(),
-            },
-            Abi::Vector { .. } => {
+        match a.layout.backend_repr {
+            BackendRepr::Uninhabited | BackendRepr::Memory { sized: false } => {}
+            BackendRepr::ScalarPair(..) | BackendRepr::Memory { sized: true } => {
+                match a.layout.size.bits() {
+                    8 => a.cast_to(Reg::i8()),
+                    16 => a.cast_to(Reg::i16()),
+                    32 => a.cast_to(Reg::i32()),
+                    64 => a.cast_to(Reg::i64()),
+                    _ => a.make_indirect(),
+                }
+            }
+            BackendRepr::Vector { .. } => {
                 // FIXME(eddyb) there should be a size cap here
                 // (probably what clang calls "illegal vectors").
             }
-            Abi::Scalar(scalar) => {
+            BackendRepr::Scalar(scalar) => {
                 // Match what LLVM does for `f128` so that `compiler-builtins` builtins match up
                 // with what LLVM expects.
                 if a.layout.size.bytes() > 8
diff --git a/compiler/rustc_target/src/callconv/xtensa.rs b/compiler/rustc_target/src/callconv/xtensa.rs
index e1728b08a39..9d313d16500 100644
--- a/compiler/rustc_target/src/callconv/xtensa.rs
+++ b/compiler/rustc_target/src/callconv/xtensa.rs
@@ -6,7 +6,7 @@
 //! Section 2.3 from the Xtensa programmers guide.
 
 use crate::abi::call::{ArgAbi, FnAbi, Reg, Uniform};
-use crate::abi::{Abi, HasDataLayout, Size, TyAbiInterface};
+use crate::abi::{BackendRepr, HasDataLayout, Size, TyAbiInterface};
 use crate::spec::HasTargetSpec;
 
 const NUM_ARG_GPRS: u64 = 6;
@@ -114,8 +114,8 @@ where
 }
 
 fn is_xtensa_aggregate<'a, Ty>(arg: &ArgAbi<'a, Ty>) -> bool {
-    match arg.layout.abi {
-        Abi::Vector { .. } => true,
+    match arg.layout.backend_repr {
+        BackendRepr::Vector { .. } => true,
         _ => arg.layout.is_aggregate(),
     }
 }
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index f4cbe47e0f3..3e7b42d3d1c 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -55,9 +55,15 @@ use crate::json::{Json, ToJson};
 use crate::spec::abi::Abi;
 use crate::spec::crt_objects::CrtObjects;
 
-pub mod abi;
 pub mod crt_objects;
 
+pub mod abi {
+    pub use rustc_abi::{
+        AbiDisabled, AbiUnsupported, ExternAbi as Abi, all_names, enabled_names, is_enabled,
+        is_stable, lookup,
+    };
+}
+
 mod base;
 pub use base::apple::{
     deployment_target_for_target as current_apple_deployment_target,
diff --git a/compiler/rustc_target/src/spec/targets/mipsel_sony_psx.rs b/compiler/rustc_target/src/spec/targets/mipsel_sony_psx.rs
index c60bf650311..1b8f9b71e93 100644
--- a/compiler/rustc_target/src/spec/targets/mipsel_sony_psx.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsel_sony_psx.rs
@@ -14,8 +14,11 @@ pub(crate) fn target() -> Target {
         arch: "mips".into(),
 
         options: TargetOptions {
-            os: "none".into(),
-            env: "psx".into(),
+            // The Playstation 1 is mostly bare-metal, but the BIOS does provide some a slight bit
+            // of functionality post load, so we still declare it as `cfg!(target_os = "psx")`.
+            //
+            // See <https://github.com/rust-lang/rust/pull/131168> for details.
+            os: "psx".into(),
             vendor: "sony".into(),
             linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
             cpu: "mips1".into(),
diff --git a/compiler/rustc_target/src/spec/targets/sparc64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/sparc64_unknown_linux_gnu.rs
index 7d089aeb787..ac2141f9b08 100644
--- a/compiler/rustc_target/src/spec/targets/sparc64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/sparc64_unknown_linux_gnu.rs
@@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
             std: Some(true),
         },
         pointer_width: 64,
-        data_layout: "E-m:e-i64:64-n32:64-S128".into(),
+        data_layout: "E-m:e-i64:64-i128:128-n32:64-S128".into(),
         arch: "sparc64".into(),
         options: base,
     }
diff --git a/compiler/rustc_target/src/spec/targets/sparc64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/sparc64_unknown_netbsd.rs
index 21f09d6428e..d16b3776cfb 100644
--- a/compiler/rustc_target/src/spec/targets/sparc64_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/sparc64_unknown_netbsd.rs
@@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
             std: Some(true),
         },
         pointer_width: 64,
-        data_layout: "E-m:e-i64:64-n32:64-S128".into(),
+        data_layout: "E-m:e-i64:64-i128:128-n32:64-S128".into(),
         arch: "sparc64".into(),
         options: TargetOptions { endian: Endian::Big, mcount: "__mcount".into(), ..base },
     }
diff --git a/compiler/rustc_target/src/spec/targets/sparc64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/sparc64_unknown_openbsd.rs
index 12626dce477..91e64061020 100644
--- a/compiler/rustc_target/src/spec/targets/sparc64_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/sparc64_unknown_openbsd.rs
@@ -17,7 +17,7 @@ pub(crate) fn target() -> Target {
             std: Some(true),
         },
         pointer_width: 64,
-        data_layout: "E-m:e-i64:64-n32:64-S128".into(),
+        data_layout: "E-m:e-i64:64-i128:128-n32:64-S128".into(),
         arch: "sparc64".into(),
         options: base,
     }
diff --git a/compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs
index 08f0bb302dd..2777395757f 100644
--- a/compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs
@@ -11,7 +11,7 @@ pub(crate) fn target() -> Target {
             std: Some(true),
         },
         pointer_width: 32,
-        data_layout: "E-m:e-p:32:32-i64:64-f128:64-n32-S64".into(),
+        data_layout: "E-m:e-p:32:32-i64:64-i128:128-f128:64-n32-S64".into(),
         arch: "sparc".into(),
         options: TargetOptions {
             cpu: "v9".into(),
diff --git a/compiler/rustc_target/src/spec/targets/sparc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/sparc_unknown_none_elf.rs
index 0157d03f854..987f69429c0 100644
--- a/compiler/rustc_target/src/spec/targets/sparc_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/sparc_unknown_none_elf.rs
@@ -17,7 +17,7 @@ pub(crate) fn target() -> Target {
         ..Default::default()
     };
     Target {
-        data_layout: "E-m:e-p:32:32-i64:64-f128:64-n32-S64".into(),
+        data_layout: "E-m:e-p:32:32-i64:64-i128:128-f128:64-n32-S64".into(),
         llvm_target: "sparc-unknown-none-elf".into(),
         metadata: crate::spec::TargetMetadata {
             description: Some("Bare 32-bit SPARC V7+".into()),
diff --git a/compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs b/compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs
index 138ce902d5e..fdc9628f78e 100644
--- a/compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs
+++ b/compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs
@@ -19,7 +19,7 @@ pub(crate) fn target() -> Target {
             std: Some(true),
         },
         pointer_width: 64,
-        data_layout: "E-m:e-i64:64-n32:64-S128".into(),
+        data_layout: "E-m:e-i64:64-i128:128-n32:64-S128".into(),
         // Use "sparc64" instead of "sparcv9" here, since the former is already
         // used widely in the source base. If we ever needed ABI
         // differentiation from the sparc64, we could, but that would probably
diff --git a/compiler/rustc_target/src/spec/tests/tests_impl.rs b/compiler/rustc_target/src/spec/tests/tests_impl.rs
index cc5931be860..bd47d12ef9f 100644
--- a/compiler/rustc_target/src/spec/tests/tests_impl.rs
+++ b/compiler/rustc_target/src/spec/tests/tests_impl.rs
@@ -165,7 +165,8 @@ impl Target {
                 assert_matches!(&*self.llvm_abiname, "ilp32" | "ilp32f" | "ilp32d" | "ilp32e")
             }
             "riscv64" => {
-                assert_matches!(&*self.llvm_abiname, "lp64" | "lp64f" | "lp64d" | "lp64q")
+                // Note that the `lp64e` is still unstable as it's not (yet) part of the ELF psABI.
+                assert_matches!(&*self.llvm_abiname, "lp64" | "lp64f" | "lp64d" | "lp64q" | "lp64e")
             }
             _ => {}
         }
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
index a6474f10d5b..af3b5e0d5d4 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
@@ -551,10 +551,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         ] => "",
                         [
                             ..,
-                            Adjustment {
-                                kind: Adjust::Borrow(AutoBorrow::Ref(_, mut_)),
-                                target: _,
-                            },
+                            Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(mut_)), target: _ },
                         ] => hir::Mutability::from(*mut_).ref_prefix_str(),
                         _ => "",
                     };
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs
index 8541621b23b..2b19db2c14e 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs
@@ -284,7 +284,7 @@ pub fn suggest_new_region_bound(
         }
         match fn_return.kind {
             // FIXME(precise_captures): Suggest adding to `use<...>` list instead.
-            TyKind::OpaqueDef(opaque, _) => {
+            TyKind::OpaqueDef(opaque) => {
                 // Get the identity type for this RPIT
                 let did = opaque.def_id.to_def_id();
                 let ty = Ty::new_opaque(tcx, did, ty::GenericArgs::identity_for_item(tcx, did));
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs
index 0cf7c43beb5..b97f3dc303b 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs
@@ -384,7 +384,10 @@ impl<T> Trait<T> for X {
                                     | DefKind::AssocFn
                                     | DefKind::AssocConst
                             )
-                            && tcx.is_type_alias_impl_trait(opaque_ty.def_id)
+                            && matches!(
+                                tcx.opaque_ty_origin(opaque_ty.def_id),
+                                hir::OpaqueTyOrigin::TyAlias { .. }
+                            )
                             && !tcx
                                 .opaque_types_defined_by(body_owner_def_id.expect_local())
                                 .contains(&opaque_ty.def_id.expect_local())
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
index 833358b2e14..438639e72f9 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
@@ -862,22 +862,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     self.add_lt_suggs.push(lt.suggestion(self.new_lt));
                 }
             }
-
-            fn visit_ty(&mut self, ty: &'hir hir::Ty<'hir>) {
-                let hir::TyKind::OpaqueDef(opaque_ty, _) = ty.kind else {
-                    return hir::intravisit::walk_ty(self, ty);
-                };
-                if let Some(&(_, b)) =
-                    opaque_ty.lifetime_mapping.iter().find(|&(a, _)| a.res == self.needle)
-                {
-                    let prev_needle =
-                        std::mem::replace(&mut self.needle, hir::LifetimeName::Param(b));
-                    for bound in opaque_ty.bounds {
-                        self.visit_param_bound(bound);
-                    }
-                    self.needle = prev_needle;
-                }
-            }
         }
 
         let (lifetime_def_id, lifetime_scope) =
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
index 6014ed555b6..7aa558cfd3f 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -545,10 +545,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                                 polarity: ty::PredicatePolarity::Positive,
                             }),
                             None,
-                            Some(match predicate.host {
-                                ty::HostPolarity::Maybe => ty::BoundConstness::ConstIfConst,
-                                ty::HostPolarity::Const => ty::BoundConstness::Const,
-                            }),
+                            Some(predicate.constness),
                             None,
                             String::new(),
                         );
@@ -2238,18 +2235,16 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     (None, _) => Some(cannot_do_this),
                     // suggested using default post message
                     (
-                        Some(ty::BoundConstness::Const | ty::BoundConstness::ConstIfConst),
+                        Some(ty::BoundConstness::Const | ty::BoundConstness::Maybe),
                         Some(AppendConstMessage::Default),
                     ) => Some(format!("{cannot_do_this} in const contexts")),
                     // overridden post message
                     (
-                        Some(ty::BoundConstness::Const | ty::BoundConstness::ConstIfConst),
+                        Some(ty::BoundConstness::Const | ty::BoundConstness::Maybe),
                         Some(AppendConstMessage::Custom(custom_msg, _)),
                     ) => Some(format!("{cannot_do_this}{custom_msg}")),
                     // fallback to generic message
-                    (Some(ty::BoundConstness::Const | ty::BoundConstness::ConstIfConst), None) => {
-                        None
-                    }
+                    (Some(ty::BoundConstness::Const | ty::BoundConstness::Maybe), None) => None,
                 }
             })
             .unwrap_or_else(|| {
@@ -2653,7 +2648,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         obligation: &PredicateObligation<'tcx>,
         def_id: DefId,
     ) -> ErrorGuaranteed {
-        let name = match self.tcx.opaque_type_origin(def_id.expect_local()) {
+        let name = match self.tcx.local_opaque_ty_origin(def_id.expect_local()) {
             hir::OpaqueTyOrigin::FnReturn { .. } | hir::OpaqueTyOrigin::AsyncFn { .. } => {
                 "opaque type".to_string()
             }
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index a7d1f1bd8d0..553bb61ed04 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -361,7 +361,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 })
                 | hir::Node::TraitItem(hir::TraitItem { generics, .. })
                 | hir::Node::ImplItem(hir::ImplItem { generics, .. })
-                | hir::Node::OpaqueTy(hir::OpaqueTy { generics, .. })
                     if param_ty =>
                 {
                     // We skip the 0'th arg (self) because we do not want
@@ -424,10 +423,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         | hir::ItemKind::Const(_, generics, _)
                         | hir::ItemKind::TraitAlias(generics, _),
                     ..
-                })
-                | hir::Node::OpaqueTy(hir::OpaqueTy { generics, .. })
-                    if !param_ty =>
-                {
+                }) if !param_ty => {
                     // Missing generic type parameter bound.
                     if suggest_arbitrary_trait_bound(
                         self.tcx,
@@ -5105,24 +5101,13 @@ pub(super) fn get_explanation_based_on_obligation<'tcx>(
             _ => None,
         };
 
-        let pred = obligation.predicate;
-        let (_, base) = obligation.cause.code().peel_derives_with_predicate();
-        let post = if let ty::PredicateKind::Clause(clause) = pred.kind().skip_binder()
-            && let ty::ClauseKind::Trait(pred) = clause
-            && let Some(base) = base
-            && base.skip_binder() != pred
-        {
-            format!(", which is required by `{base}`")
-        } else {
-            String::new()
-        };
         let desc = match ty_desc {
             Some(desc) => format!(" {desc}"),
             None => String::new(),
         };
         if let ty::PredicatePolarity::Positive = trait_predicate.polarity() {
             format!(
-                "{pre_message}the trait `{}` is not implemented for{desc} `{}`{post}",
+                "{pre_message}the trait `{}` is not implemented for{desc} `{}`",
                 trait_predicate.print_modifiers_and_trait_path(),
                 tcx.short_ty_string(trait_predicate.self_ty().skip_binder(), &mut None),
             )
@@ -5130,7 +5115,7 @@ pub(super) fn get_explanation_based_on_obligation<'tcx>(
             // "the trait bound `T: !Send` is not satisfied" reads better than "`!Send` is
             // not implemented for `T`".
             // FIXME: add note explaining explicit negative trait bounds.
-            format!("{pre_message}the trait bound `{trait_predicate}` is not satisfied{post}")
+            format!("{pre_message}the trait bound `{trait_predicate}` is not satisfied")
         }
     }
 }
@@ -5237,12 +5222,6 @@ fn point_at_assoc_type_restriction<G: EmissionGuarantee>(
     let ty::ClauseKind::Projection(proj) = clause else {
         return;
     };
-    // avoid ICEing since effects desugared associated types don't have names.
-    // this path should only be hit for `~const` on invalid places, so they
-    // will have an informative error already.
-    if tcx.is_effects_desugared_assoc_ty(proj.projection_term.def_id) {
-        return;
-    }
     let name = tcx.item_name(proj.projection_term.def_id);
     let mut predicates = generics.predicates.iter().peekable();
     let mut prev: Option<&hir::WhereBoundPredicate<'_>> = None;
diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs
index 5793ac2fc31..c53689b211d 100644
--- a/compiler/rustc_trait_selection/src/solve/delegate.rs
+++ b/compiler/rustc_trait_selection/src/solve/delegate.rs
@@ -7,13 +7,13 @@ use rustc_infer::infer::canonical::{
     Canonical, CanonicalExt as _, CanonicalQueryInput, CanonicalVarInfo, CanonicalVarValues,
 };
 use rustc_infer::infer::{InferCtxt, RegionVariableOrigin, TyCtxtInferExt};
+use rustc_infer::traits::ObligationCause;
 use rustc_infer::traits::solve::Goal;
-use rustc_infer::traits::{ObligationCause, Reveal};
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt as _};
 use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
-use rustc_type_ir::solve::{Certainty, NoSolution, SolverMode};
-use tracing::trace;
+use rustc_type_ir::TypingMode;
+use rustc_type_ir::solve::{Certainty, NoSolution};
 
 use crate::traits::specialization_graph;
 
@@ -47,7 +47,6 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
 
     fn build_with_canonical<V>(
         interner: TyCtxt<'tcx>,
-        solver_mode: SolverMode,
         canonical: &CanonicalQueryInput<'tcx, V>,
     ) -> (Self, V, CanonicalVarValues<'tcx>)
     where
@@ -56,10 +55,6 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
         let (infcx, value, vars) = interner
             .infer_ctxt()
             .with_next_trait_solver(true)
-            .intercrate(match solver_mode {
-                SolverMode::Normal => false,
-                SolverMode::Coherence => true,
-            })
             .build_with_canonical(DUMMY_SP, canonical);
         (SolverDelegate(infcx), value, vars)
     }
@@ -195,7 +190,6 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
 
     fn fetch_eligible_assoc_item(
         &self,
-        param_env: ty::ParamEnv<'tcx>,
         goal_trait_ref: ty::TraitRef<'tcx>,
         trait_assoc_def_id: DefId,
         impl_def_id: DefId,
@@ -211,12 +205,12 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
             // and the obligation is monomorphic, otherwise passes such as
             // transmute checking and polymorphic MIR optimizations could
             // get a result which isn't correct for all monomorphizations.
-            if param_env.reveal() == Reveal::All {
-                let poly_trait_ref = self.resolve_vars_if_possible(goal_trait_ref);
-                !poly_trait_ref.still_further_specializable()
-            } else {
-                trace!(?node_item.item.def_id, "not eligible due to default");
-                false
+            match self.typing_mode_unchecked() {
+                TypingMode::Coherence | TypingMode::Analysis { .. } => false,
+                TypingMode::PostAnalysis => {
+                    let poly_trait_ref = self.resolve_vars_if_possible(goal_trait_ref);
+                    !poly_trait_ref.still_further_specializable()
+                }
             }
         };
 
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index 934fe9ec47c..52ba5621d31 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -10,6 +10,7 @@ use rustc_infer::infer::DefineOpaqueTypes;
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::ty::{Region, RegionVid};
 use tracing::debug;
+use ty::TypingMode;
 
 use super::*;
 use crate::errors::UnableToConstructConstantValue;
@@ -79,7 +80,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
 
         let trait_ref = ty::TraitRef::new(tcx, trait_did, [ty]);
 
-        let infcx = tcx.infer_ctxt().build();
+        let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
         let mut selcx = SelectionContext::new(&infcx);
         for polarity in [ty::PredicatePolarity::Positive, ty::PredicatePolarity::Negative] {
             let result = selcx.select(&Obligation::new(
@@ -99,7 +100,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
             }
         }
 
-        let infcx = tcx.infer_ctxt().build();
+        let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
         let mut fresh_preds = FxIndexSet::default();
 
         // Due to the way projections are handled by SelectionContext, we need to run
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index f8fb297e36c..3cd11d7c8e8 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -18,7 +18,7 @@ use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal};
 use rustc_middle::traits::specialization_graph::OverlapMode;
 use rustc_middle::ty::fast_reject::DeepRejectCtxt;
 use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypingMode};
 pub use rustc_next_trait_solver::coherence::*;
 use rustc_next_trait_solver::solve::SolverDelegateEvalExt;
 use rustc_span::symbol::sym;
@@ -195,9 +195,8 @@ fn overlap<'tcx>(
     let infcx = tcx
         .infer_ctxt()
         .skip_leak_check(skip_leak_check.is_yes())
-        .intercrate(true)
         .with_next_trait_solver(tcx.next_trait_solver_in_coherence())
-        .build();
+        .build(TypingMode::Coherence);
     let selcx = &mut SelectionContext::new(&infcx);
     if track_ambiguity_causes.is_yes() {
         selcx.enable_tracking_intercrate_ambiguity_causes();
@@ -419,7 +418,7 @@ fn impl_intersection_has_negative_obligation(
 
     // N.B. We need to unify impl headers *with* intercrate mode, even if proving negative predicates
     // do not need intercrate mode enabled.
-    let ref infcx = tcx.infer_ctxt().intercrate(true).with_next_trait_solver(true).build();
+    let ref infcx = tcx.infer_ctxt().with_next_trait_solver(true).build(TypingMode::Coherence);
     let root_universe = infcx.universe();
     assert_eq!(root_universe, ty::UniverseIndex::ROOT);
 
@@ -570,7 +569,9 @@ fn try_prove_negated_where_clause<'tcx>(
     // the *existence* of a negative goal, not the non-existence of a positive goal.
     // Without this, we over-eagerly register coherence ambiguity candidates when
     // impl candidates do exist.
-    let ref infcx = root_infcx.fork_with_intercrate(false);
+    // FIXME(#132279): `TypingMode::non_body_analysis` is a bit questionable here as it
+    // would cause us to reveal opaque types to leak their auto traits.
+    let ref infcx = root_infcx.fork_with_typing_mode(TypingMode::non_body_analysis());
     let ocx = ObligationCtxt::new(infcx);
     ocx.register_obligation(Obligation::new(
         infcx.tcx,
@@ -714,7 +715,10 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> {
 
             // It is only relevant that a goal is unknowable if it would have otherwise
             // failed.
-            let non_intercrate_infcx = infcx.fork_with_intercrate(false);
+            // FIXME(#132279): Forking with `TypingMode::non_body_analysis` is a bit questionable
+            // as it would allow us to reveal opaque types, potentially causing unexpected
+            // cycles.
+            let non_intercrate_infcx = infcx.fork_with_typing_mode(TypingMode::non_body_analysis());
             if non_intercrate_infcx.predicate_may_hold(&Obligation::new(
                 infcx.tcx,
                 ObligationCause::dummy(),
diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
index a068f25fe35..0eaacbcfbea 100644
--- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
+++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
@@ -14,11 +14,11 @@ use rustc_middle::query::Providers;
 use rustc_middle::ty::{
     self, EarlyBinder, ExistentialPredicateStableCmpExt as _, GenericArgs, Ty, TyCtxt,
     TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable,
-    TypeVisitableExt, TypeVisitor, Upcast,
+    TypeVisitableExt, TypeVisitor, TypingMode, Upcast,
 };
 use rustc_span::Span;
 use rustc_span::symbol::Symbol;
-use rustc_target::abi::Abi;
+use rustc_target::abi::BackendRepr;
 use smallvec::SmallVec;
 use tracing::{debug, instrument};
 
@@ -523,8 +523,8 @@ fn check_receiver_correct<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, method:
 
     // e.g., `Rc<()>`
     let unit_receiver_ty = receiver_for_self_ty(tcx, receiver_ty, tcx.types.unit, method_def_id);
-    match tcx.layout_of(param_env.and(unit_receiver_ty)).map(|l| l.abi) {
-        Ok(Abi::Scalar(..)) => (),
+    match tcx.layout_of(param_env.and(unit_receiver_ty)).map(|l| l.backend_repr) {
+        Ok(BackendRepr::Scalar(..)) => (),
         abi => {
             tcx.dcx().span_delayed_bug(
                 tcx.def_span(method_def_id),
@@ -538,8 +538,8 @@ fn check_receiver_correct<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, method:
     // e.g., `Rc<dyn Trait>`
     let trait_object_receiver =
         receiver_for_self_ty(tcx, receiver_ty, trait_object_ty, method_def_id);
-    match tcx.layout_of(param_env.and(trait_object_receiver)).map(|l| l.abi) {
-        Ok(Abi::ScalarPair(..)) => (),
+    match tcx.layout_of(param_env.and(trait_object_receiver)).map(|l| l.backend_repr) {
+        Ok(BackendRepr::ScalarPair(..)) => (),
         abi => {
             tcx.dcx().span_delayed_bug(
                 tcx.def_span(method_def_id),
@@ -718,7 +718,7 @@ fn receiver_is_dispatchable<'tcx>(
         Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate)
     };
 
-    let infcx = tcx.infer_ctxt().build();
+    let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
     // the receiver is dispatchable iff the obligation holds
     infcx.predicate_must_hold_modulo_regions(&obligation)
 }
diff --git a/compiler/rustc_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs
new file mode 100644
index 00000000000..cb36f1a62db
--- /dev/null
+++ b/compiler/rustc_trait_selection/src/traits/effects.rs
@@ -0,0 +1,154 @@
+use rustc_hir as hir;
+use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt};
+use rustc_infer::traits::{ImplSource, Obligation, PredicateObligation};
+use rustc_middle::span_bug;
+use rustc_middle::ty::fast_reject::DeepRejectCtxt;
+use rustc_middle::ty::{self, TypingMode};
+use rustc_type_ir::solve::NoSolution;
+use thin_vec::ThinVec;
+
+use super::SelectionContext;
+
+pub type HostEffectObligation<'tcx> = Obligation<'tcx, ty::HostEffectPredicate<'tcx>>;
+
+pub enum EvaluationFailure {
+    Ambiguous,
+    NoSolution,
+}
+
+pub fn evaluate_host_effect_obligation<'tcx>(
+    selcx: &mut SelectionContext<'_, 'tcx>,
+    obligation: &HostEffectObligation<'tcx>,
+) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
+    if matches!(selcx.infcx.typing_mode(obligation.param_env), TypingMode::Coherence) {
+        span_bug!(
+            obligation.cause.span,
+            "should not select host obligation in old solver in intercrate mode"
+        );
+    }
+
+    match evaluate_host_effect_from_bounds(selcx, obligation) {
+        Ok(result) => return Ok(result),
+        Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous),
+        Err(EvaluationFailure::NoSolution) => {}
+    }
+
+    match evaluate_host_effect_from_selection_candiate(selcx, obligation) {
+        Ok(result) => return Ok(result),
+        Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous),
+        Err(EvaluationFailure::NoSolution) => {}
+    }
+
+    Err(EvaluationFailure::NoSolution)
+}
+
+fn match_candidate<'tcx>(
+    infcx: &InferCtxt<'tcx>,
+    obligation: &HostEffectObligation<'tcx>,
+    candidate: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
+) -> Result<ThinVec<PredicateObligation<'tcx>>, NoSolution> {
+    if !candidate.skip_binder().constness.satisfies(obligation.predicate.constness) {
+        return Err(NoSolution);
+    }
+
+    let candidate = infcx.instantiate_binder_with_fresh_vars(
+        obligation.cause.span,
+        BoundRegionConversionTime::HigherRankedType,
+        candidate,
+    );
+
+    let mut nested = infcx
+        .at(&obligation.cause, obligation.param_env)
+        .eq(DefineOpaqueTypes::Yes, obligation.predicate.trait_ref, candidate.trait_ref)?
+        .into_obligations();
+
+    for nested in &mut nested {
+        nested.set_depth_from_parent(obligation.recursion_depth);
+    }
+
+    Ok(nested)
+}
+
+fn evaluate_host_effect_from_bounds<'tcx>(
+    selcx: &mut SelectionContext<'_, 'tcx>,
+    obligation: &HostEffectObligation<'tcx>,
+) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
+    let infcx = selcx.infcx;
+    let drcx = DeepRejectCtxt::relate_rigid_rigid(selcx.tcx());
+    let mut candidate = None;
+
+    for predicate in obligation.param_env.caller_bounds() {
+        let bound_predicate = predicate.kind();
+        if let ty::ClauseKind::HostEffect(data) = predicate.kind().skip_binder() {
+            let data = bound_predicate.rebind(data);
+            if data.skip_binder().trait_ref.def_id != obligation.predicate.trait_ref.def_id {
+                continue;
+            }
+
+            if !drcx.args_may_unify(
+                obligation.predicate.trait_ref.args,
+                data.skip_binder().trait_ref.args,
+            ) {
+                continue;
+            }
+
+            let is_match = infcx.probe(|_| match_candidate(infcx, obligation, data).is_ok());
+
+            if is_match {
+                if candidate.is_some() {
+                    return Err(EvaluationFailure::Ambiguous);
+                } else {
+                    candidate = Some(data);
+                }
+            }
+        }
+    }
+
+    if let Some(data) = candidate {
+        Ok(match_candidate(infcx, obligation, data)
+            .expect("candidate matched before, so it should match again"))
+    } else {
+        Err(EvaluationFailure::NoSolution)
+    }
+}
+
+fn evaluate_host_effect_from_selection_candiate<'tcx>(
+    selcx: &mut SelectionContext<'_, 'tcx>,
+    obligation: &HostEffectObligation<'tcx>,
+) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
+    let tcx = selcx.tcx();
+    selcx.infcx.commit_if_ok(|_| {
+        match selcx.select(&obligation.with(tcx, obligation.predicate.trait_ref)) {
+            Ok(None) => Err(EvaluationFailure::Ambiguous),
+            Err(_) => Err(EvaluationFailure::NoSolution),
+            Ok(Some(source)) => match source {
+                ImplSource::UserDefined(impl_) => {
+                    if tcx.constness(impl_.impl_def_id) != hir::Constness::Const {
+                        return Err(EvaluationFailure::NoSolution);
+                    }
+
+                    let mut nested = impl_.nested;
+                    nested.extend(
+                        tcx.const_conditions(impl_.impl_def_id)
+                            .instantiate(tcx, impl_.args)
+                            .into_iter()
+                            .map(|(trait_ref, _)| {
+                                obligation.with(
+                                    tcx,
+                                    trait_ref
+                                        .to_host_effect_clause(tcx, obligation.predicate.constness),
+                                )
+                            }),
+                    );
+
+                    for nested in &mut nested {
+                        nested.set_depth_from_parent(obligation.recursion_depth);
+                    }
+
+                    Ok(nested)
+                }
+                _ => Err(EvaluationFailure::NoSolution),
+            },
+        }
+    })
+}
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 1754418156d..29e60e3c428 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -13,10 +13,11 @@ use rustc_middle::bug;
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::ty::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
-use rustc_middle::ty::{self, Binder, Const, GenericArgsRef, TypeVisitableExt};
+use rustc_middle::ty::{self, Binder, Const, GenericArgsRef, TypeVisitableExt, TypingMode};
 use thin_vec::ThinVec;
 use tracing::{debug, debug_span, instrument};
 
+use super::effects::{self, HostEffectObligation};
 use super::project::{self, ProjectAndUnifyResult};
 use super::select::SelectionContext;
 use super::{
@@ -402,8 +403,13 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                     )
                 }
 
-                ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..)) => {
-                    ProcessResult::Changed(Default::default())
+                ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(data)) => {
+                    let host_obligation = obligation.with(infcx.tcx, data);
+
+                    self.process_host_obligation(
+                        host_obligation,
+                        &mut pending_obligation.stalled_on,
+                    )
                 }
 
                 ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(data)) => {
@@ -754,7 +760,9 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
         stalled_on: &mut Vec<TyOrConstInferVar>,
     ) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
         let infcx = self.selcx.infcx;
-        if obligation.predicate.is_global() && !self.selcx.is_intercrate() {
+        if obligation.predicate.is_global()
+            && !matches!(infcx.typing_mode(obligation.param_env), TypingMode::Coherence)
+        {
             // no type variables present, can use evaluation for better caching.
             // FIXME: consider caching errors too.
             if infcx.predicate_must_hold_considering_regions(obligation) {
@@ -807,11 +815,13 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
         stalled_on: &mut Vec<TyOrConstInferVar>,
     ) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
         let tcx = self.selcx.tcx();
-
-        if obligation.predicate.is_global() && !self.selcx.is_intercrate() {
+        let infcx = self.selcx.infcx;
+        if obligation.predicate.is_global()
+            && !matches!(infcx.typing_mode(obligation.param_env), TypingMode::Coherence)
+        {
             // no type variables present, can use evaluation for better caching.
             // FIXME: consider caching errors too.
-            if self.selcx.infcx.predicate_must_hold_considering_regions(obligation) {
+            if infcx.predicate_must_hold_considering_regions(obligation) {
                 if let Some(key) = ProjectionCacheKey::from_poly_projection_obligation(
                     &mut self.selcx,
                     &project_obligation,
@@ -819,8 +829,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
                     // If `predicate_must_hold_considering_regions` succeeds, then we've
                     // evaluated all sub-obligations. We can therefore mark the 'root'
                     // obligation as complete, and skip evaluating sub-obligations.
-                    self.selcx
-                        .infcx
+                    infcx
                         .inner
                         .borrow_mut()
                         .projection_cache()
@@ -854,6 +863,27 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
             }
         }
     }
+
+    fn process_host_obligation(
+        &mut self,
+        host_obligation: HostEffectObligation<'tcx>,
+        stalled_on: &mut Vec<TyOrConstInferVar>,
+    ) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
+        match effects::evaluate_host_effect_obligation(&mut self.selcx, &host_obligation) {
+            Ok(nested) => ProcessResult::Changed(mk_pending(nested)),
+            Err(effects::EvaluationFailure::Ambiguous) => {
+                stalled_on.clear();
+                stalled_on.extend(args_infer_vars(
+                    &self.selcx,
+                    ty::Binder::dummy(host_obligation.predicate.trait_ref.args),
+                ));
+                ProcessResult::Unchanged
+            }
+            Err(effects::EvaluationFailure::NoSolution) => {
+                ProcessResult::Error(FulfillmentErrorCode::Select(SelectionError::Unimplemented))
+            }
+        }
+    }
 }
 
 /// Returns the set of inference variables contained in `args`.
diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs
index 3e65194577e..3b17fa6b032 100644
--- a/compiler/rustc_trait_selection/src/traits/misc.rs
+++ b/compiler/rustc_trait_selection/src/traits/misc.rs
@@ -8,7 +8,7 @@ use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir as hir;
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
-use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeVisitableExt, TypingMode};
 
 use super::outlives_bounds::InferCtxtExt;
 use crate::regions::InferCtxtRegionExt;
@@ -143,7 +143,7 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
     let mut infringing_inner_tys = vec![];
     for inner_ty in inner_tys {
         // We use an ocx per inner ty for better diagnostics
-        let infcx = tcx.infer_ctxt().build();
+        let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
         let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx);
 
         ocx.register_bound(
@@ -200,7 +200,7 @@ pub fn all_fields_implement_trait<'tcx>(
     for variant in adt.variants() {
         for field in &variant.fields {
             // Do this per-field to get better error messages.
-            let infcx = tcx.infer_ctxt().build();
+            let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
             let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx);
 
             let unnormalized_ty = field.ty(tcx, args);
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index cdf24887e76..436c0fabd29 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -6,6 +6,7 @@ pub mod auto_trait;
 pub(crate) mod coherence;
 pub mod const_evaluatable;
 mod dyn_compatibility;
+pub mod effects;
 mod engine;
 mod fulfill;
 pub mod misc;
@@ -33,7 +34,8 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
 use rustc_middle::ty::{
-    self, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFolder, TypeSuperVisitable, Upcast,
+    self, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFolder, TypeSuperVisitable, TypingMode,
+    Upcast,
 };
 use rustc_span::Span;
 use rustc_span::def_id::DefId;
@@ -273,7 +275,7 @@ fn do_normalize_predicates<'tcx>(
     // by wfcheck anyway, so I'm not sure we have to check
     // them here too, and we will remove this function when
     // we move over to lazy normalization *anyway*.
-    let infcx = tcx.infer_ctxt().ignoring_regions().build();
+    let infcx = tcx.infer_ctxt().ignoring_regions().build(TypingMode::non_body_analysis());
     let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
     let predicates = ocx.normalize(&cause, elaborated_env, predicates);
 
@@ -409,7 +411,7 @@ pub fn normalize_param_env_or_error<'tcx>(
     debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates);
 
     let elaborated_env = ty::ParamEnv::new(tcx.mk_clauses(&predicates), unnormalized_env.reveal());
-    if !normalize::needs_normalization(&elaborated_env, unnormalized_env.reveal()) {
+    if !elaborated_env.has_aliases() {
         return elaborated_env;
     }
 
@@ -474,11 +476,11 @@ pub fn normalize_param_env_or_error<'tcx>(
 
 /// Normalizes the predicates and checks whether they hold in an empty environment. If this
 /// returns true, then either normalize encountered an error or one of the predicates did not
-/// hold. Used when creating vtables to check for unsatisfiable methods.
+/// hold. Used when creating vtables to check for unsatisfiable methods. This should not be
+/// used during analysis.
 pub fn impossible_predicates<'tcx>(tcx: TyCtxt<'tcx>, predicates: Vec<ty::Clause<'tcx>>) -> bool {
     debug!("impossible_predicates(predicates={:?})", predicates);
-
-    let infcx = tcx.infer_ctxt().build();
+    let infcx = tcx.infer_ctxt().build(TypingMode::PostAnalysis);
     let param_env = ty::ParamEnv::reveal_all();
     let ocx = ObligationCtxt::new(&infcx);
     let predicates = ocx.normalize(&ObligationCause::dummy(), param_env, predicates);
@@ -567,8 +569,11 @@ fn is_impossible_associated_item(
     // since that method *may* have some substitutions where the predicates hold.
     //
     // This replicates the logic we use in coherence.
-    let infcx =
-        tcx.infer_ctxt().ignoring_regions().with_next_trait_solver(true).intercrate(true).build();
+    let infcx = tcx
+        .infer_ctxt()
+        .ignoring_regions()
+        .with_next_trait_solver(true)
+        .build(TypingMode::Coherence);
     let param_env = ty::ParamEnv::empty();
     let fresh_args = infcx.fresh_args_for_item(tcx.def_span(impl_def_id), impl_def_id);
 
diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs
index 12e00ec79ac..954dfe93387 100644
--- a/compiler/rustc_trait_selection/src/traits/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/normalize.rs
@@ -1,15 +1,16 @@
 //! Deeply normalize types using the old trait solver.
 
 use rustc_data_structures::stack::ensure_sufficient_stack;
-use rustc_infer::infer::InferOk;
 use rustc_infer::infer::at::At;
+use rustc_infer::infer::{InferCtxt, InferOk};
 use rustc_infer::traits::{
     FromSolverError, Normalized, Obligation, PredicateObligations, TraitEngine,
 };
 use rustc_macros::extension;
-use rustc_middle::traits::{ObligationCause, ObligationCauseCode, Reveal};
+use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
 use rustc_middle::ty::{
     self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, TypeVisitableExt,
+    TypingMode,
 };
 use tracing::{debug, instrument};
 
@@ -109,16 +110,19 @@ where
 }
 
 pub(super) fn needs_normalization<'tcx, T: TypeVisitable<TyCtxt<'tcx>>>(
+    infcx: &InferCtxt<'tcx>,
+    param_env_for_debug_assertion: ty::ParamEnv<'tcx>,
     value: &T,
-    reveal: Reveal,
 ) -> bool {
     let mut flags = ty::TypeFlags::HAS_ALIAS;
 
     // Opaques are treated as rigid with `Reveal::UserFacing`,
     // so we can ignore those.
-    match reveal {
-        Reveal::UserFacing => flags.remove(ty::TypeFlags::HAS_TY_OPAQUE),
-        Reveal::All => {}
+    match infcx.typing_mode(param_env_for_debug_assertion) {
+        TypingMode::Coherence | TypingMode::Analysis { defining_opaque_types: _ } => {
+            flags.remove(ty::TypeFlags::HAS_TY_OPAQUE)
+        }
+        TypingMode::PostAnalysis => {}
     }
 
     value.has_type_flags(flags)
@@ -154,7 +158,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
             "Normalizing {value:?} without wrapping in a `Binder`"
         );
 
-        if !needs_normalization(&value, self.param_env.reveal()) {
+        if !needs_normalization(self.selcx.infcx, self.param_env, &value) {
             value
         } else {
             value.fold_with(self)
@@ -178,7 +182,7 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
     }
 
     fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        if !needs_normalization(&ty, self.param_env.reveal()) {
+        if !needs_normalization(self.selcx.infcx, self.param_env, &ty) {
             return ty;
         }
 
@@ -213,10 +217,11 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
         match kind {
             ty::Opaque => {
                 // Only normalize `impl Trait` outside of type inference, usually in codegen.
-                match self.param_env.reveal() {
-                    Reveal::UserFacing => ty.super_fold_with(self),
-
-                    Reveal::All => {
+                match self.selcx.infcx.typing_mode(self.param_env) {
+                    TypingMode::Coherence | TypingMode::Analysis { defining_opaque_types: _ } => {
+                        ty.super_fold_with(self)
+                    }
+                    TypingMode::PostAnalysis => {
                         let recursion_limit = self.cx().recursion_limit();
                         if !recursion_limit.value_within_limit(self.depth) {
                             self.selcx.infcx.err_ctxt().report_overflow_error(
@@ -403,7 +408,7 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
     fn fold_const(&mut self, constant: ty::Const<'tcx>) -> ty::Const<'tcx> {
         let tcx = self.selcx.tcx();
         if tcx.features().generic_const_exprs()
-            || !needs_normalization(&constant, self.param_env.reveal())
+            || !needs_normalization(self.selcx.infcx, self.param_env, &constant)
         {
             constant
         } else {
@@ -420,7 +425,7 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
 
     #[inline]
     fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
-        if p.allow_normalization() && needs_normalization(&p, self.param_env.reveal()) {
+        if p.allow_normalization() && needs_normalization(self.selcx.infcx, self.param_env, &p) {
             p.super_fold_with(self)
         } else {
             p
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 0803dd74b89..aab854e9caf 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -16,7 +16,7 @@ use rustc_middle::traits::{BuiltinImplSource, ImplSource, ImplSourceUserDefinedD
 use rustc_middle::ty::fast_reject::DeepRejectCtxt;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable, TypeVisitableExt};
-use rustc_middle::ty::{self, Term, Ty, TyCtxt, Upcast};
+use rustc_middle::ty::{self, Term, Ty, TyCtxt, TypingMode, Upcast};
 use rustc_middle::{bug, span_bug};
 use rustc_span::symbol::sym;
 use tracing::{debug, instrument};
@@ -334,11 +334,6 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>(
 ) -> Result<Option<Term<'tcx>>, InProgress> {
     let infcx = selcx.infcx;
     debug_assert!(!selcx.infcx.next_trait_solver());
-    // Don't use the projection cache in intercrate mode -
-    // the `infcx` may be re-used between intercrate in non-intercrate
-    // mode, which could lead to using incorrect cache results.
-    let use_cache = !selcx.is_intercrate();
-
     let projection_term = infcx.resolve_vars_if_possible(projection_term);
     let cache_key = ProjectionCacheKey::new(projection_term, param_env);
 
@@ -349,13 +344,8 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>(
     // would not benefit from caching when proving `T: Trait<U=Foo>`
     // bounds. It might be the case that we want two distinct caches,
     // or else another kind of cache entry.
-
-    let cache_result = if use_cache {
-        infcx.inner.borrow_mut().projection_cache().try_start(cache_key)
-    } else {
-        Ok(())
-    };
-    match cache_result {
+    let cache_entry = infcx.inner.borrow_mut().projection_cache().try_start(cache_key);
+    match cache_entry {
         Ok(()) => debug!("no cache"),
         Err(ProjectionCacheEntry::Ambiguous) => {
             // If we found ambiguity the last time, that means we will continue
@@ -378,10 +368,7 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>(
             // Cache that normalizing this projection resulted in a cycle. This
             // should ensure that, unless this happens within a snapshot that's
             // rolled back, fulfillment or evaluation will notice the cycle.
-
-            if use_cache {
-                infcx.inner.borrow_mut().projection_cache().recur(cache_key);
-            }
+            infcx.inner.borrow_mut().projection_cache().recur(cache_key);
             return Err(InProgress);
         }
         Err(ProjectionCacheEntry::Recur) => {
@@ -445,26 +432,20 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>(
             let mut deduped = SsoHashSet::with_capacity(result.obligations.len());
             result.obligations.retain(|obligation| deduped.insert(obligation.clone()));
 
-            if use_cache {
-                infcx.inner.borrow_mut().projection_cache().insert_term(cache_key, result.clone());
-            }
+            infcx.inner.borrow_mut().projection_cache().insert_term(cache_key, result.clone());
             obligations.extend(result.obligations);
             Ok(Some(result.value))
         }
         Ok(Projected::NoProgress(projected_ty)) => {
             let result =
                 Normalized { value: projected_ty, obligations: PredicateObligations::new() };
-            if use_cache {
-                infcx.inner.borrow_mut().projection_cache().insert_term(cache_key, result.clone());
-            }
+            infcx.inner.borrow_mut().projection_cache().insert_term(cache_key, result.clone());
             // No need to extend `obligations`.
             Ok(Some(result.value))
         }
         Err(ProjectionError::TooManyCandidates) => {
             debug!("opt_normalize_projection_type: too many candidates");
-            if use_cache {
-                infcx.inner.borrow_mut().projection_cache().ambiguous(cache_key);
-            }
+            infcx.inner.borrow_mut().projection_cache().ambiguous(cache_key);
             Ok(None)
         }
         Err(ProjectionError::TraitSelectionError(_)) => {
@@ -473,10 +454,7 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>(
             // just return `ty::err` but add the obligation `T :
             // Trait`, which when processed will cause the error to be
             // reported later
-
-            if use_cache {
-                infcx.inner.borrow_mut().projection_cache().error(cache_key);
-            }
+            infcx.inner.borrow_mut().projection_cache().error(cache_key);
             let result = normalize_to_error(selcx, param_env, projection_term, cause, depth);
             obligations.extend(result.obligations);
             Ok(Some(result.value))
@@ -997,18 +975,21 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                     // and the obligation is monomorphic, otherwise passes such as
                     // transmute checking and polymorphic MIR optimizations could
                     // get a result which isn't correct for all monomorphizations.
-                    if obligation.param_env.reveal() == Reveal::All {
-                        // NOTE(eddyb) inference variables can resolve to parameters, so
-                        // assume `poly_trait_ref` isn't monomorphic, if it contains any.
-                        let poly_trait_ref = selcx.infcx.resolve_vars_if_possible(trait_ref);
-                        !poly_trait_ref.still_further_specializable()
-                    } else {
-                        debug!(
-                            assoc_ty = ?selcx.tcx().def_path_str(node_item.item.def_id),
-                            ?obligation.predicate,
-                            "assemble_candidates_from_impls: not eligible due to default",
-                        );
-                        false
+                    match selcx.infcx.typing_mode(obligation.param_env) {
+                        TypingMode::Coherence | TypingMode::Analysis { .. } => {
+                            debug!(
+                                assoc_ty = ?selcx.tcx().def_path_str(node_item.item.def_id),
+                                ?obligation.predicate,
+                                "assemble_candidates_from_impls: not eligible due to default",
+                            );
+                            false
+                        }
+                        TypingMode::PostAnalysis => {
+                            // NOTE(eddyb) inference variables can resolve to parameters, so
+                            // assume `poly_trait_ref` isn't monomorphic, if it contains any.
+                            let poly_trait_ref = selcx.infcx.resolve_vars_if_possible(trait_ref);
+                            !poly_trait_ref.still_further_specializable()
+                        }
                     }
                 }
             }
diff --git a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
index bb44645a4ce..9e1a2a3e7d2 100644
--- a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
@@ -87,7 +87,6 @@ impl<'tcx> InferCtxt<'tcx> {
                 Ok(result)
             })
         } else {
-            assert!(!self.intercrate);
             let c_pred =
                 self.canonicalize_query(param_env.and(obligation.predicate), &mut _orig_values);
             self.tcx.at(obligation.cause.span).evaluate_obligation(c_pred)
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index 01e6516302c..a8d701a750d 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -9,7 +9,7 @@ use rustc_macros::extension;
 pub use rustc_middle::traits::query::NormalizationResult;
 use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
 use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt};
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor, TypingMode};
 use rustc_span::DUMMY_SP;
 use tracing::{debug, info, instrument};
 
@@ -21,7 +21,7 @@ use crate::infer::canonical::OriginalQueryValues;
 use crate::infer::{InferCtxt, InferOk};
 use crate::traits::normalize::needs_normalization;
 use crate::traits::{
-    BoundVarReplacer, Normalized, ObligationCause, PlaceholderReplacer, Reveal, ScrubbedTraitError,
+    BoundVarReplacer, Normalized, ObligationCause, PlaceholderReplacer, ScrubbedTraitError,
 };
 
 #[extension(pub trait QueryNormalizeExt<'tcx>)]
@@ -89,7 +89,7 @@ impl<'a, 'tcx> At<'a, 'tcx> {
             }
         }
 
-        if !needs_normalization(&value, self.param_env.reveal()) {
+        if !needs_normalization(self.infcx, self.param_env, &value) {
             return Ok(Normalized { value, obligations: PredicateObligations::new() });
         }
 
@@ -191,7 +191,7 @@ impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'a, 'tcx> {
 
     #[instrument(level = "debug", skip(self))]
     fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
-        if !needs_normalization(&ty, self.param_env.reveal()) {
+        if !needs_normalization(self.infcx, self.param_env, &ty) {
             return Ok(ty);
         }
 
@@ -215,10 +215,12 @@ impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'a, 'tcx> {
         let res = match kind {
             ty::Opaque => {
                 // Only normalize `impl Trait` outside of type inference, usually in codegen.
-                match self.param_env.reveal() {
-                    Reveal::UserFacing => ty.try_super_fold_with(self)?,
+                match self.infcx.typing_mode(self.param_env) {
+                    TypingMode::Coherence | TypingMode::Analysis { defining_opaque_types: _ } => {
+                        ty.try_super_fold_with(self)?
+                    }
 
-                    Reveal::All => {
+                    TypingMode::PostAnalysis => {
                         let args = data.args.try_fold_with(self)?;
                         let recursion_limit = self.cx().recursion_limit();
 
@@ -332,7 +334,7 @@ impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'a, 'tcx> {
         &mut self,
         constant: ty::Const<'tcx>,
     ) -> Result<ty::Const<'tcx>, Self::Error> {
-        if !needs_normalization(&constant, self.param_env.reveal()) {
+        if !needs_normalization(self.infcx, self.param_env, &constant) {
             return Ok(constant);
         }
 
@@ -351,7 +353,7 @@ impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'a, 'tcx> {
         &mut self,
         p: ty::Predicate<'tcx>,
     ) -> Result<ty::Predicate<'tcx>, Self::Error> {
-        if p.allow_normalization() && needs_normalization(&p, self.param_env.reveal()) {
+        if p.allow_normalization() && needs_normalization(self.infcx, self.param_env, &p) {
             p.try_super_fold_with(self)
         } else {
             Ok(p)
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index e027586563e..03fde1d1598 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -16,7 +16,7 @@ use rustc_infer::traits::{
     Obligation, ObligationCause, PolyTraitObligation, PredicateObligations, SelectionError,
 };
 use rustc_middle::ty::fast_reject::DeepRejectCtxt;
-use rustc_middle::ty::{self, ToPolyTraitRef, Ty, TypeVisitableExt};
+use rustc_middle::ty::{self, ToPolyTraitRef, Ty, TypeVisitableExt, TypingMode};
 use rustc_middle::{bug, span_bug};
 use tracing::{debug, instrument, trace};
 
@@ -790,7 +790,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                         //
                         // Note that this is only sound as projection candidates of opaque types
                         // are always applicable for auto traits.
-                    } else if self.infcx.intercrate {
+                    } else if let TypingMode::Coherence =
+                        self.infcx.typing_mode(obligation.param_env)
+                    {
                         // We do not emit auto trait candidates for opaque types in coherence.
                         // Doing so can result in weird dependency cycles.
                         candidates.ambiguous = true;
@@ -930,7 +932,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     ) -> Option<ty::PolyExistentialTraitRef<'tcx>> {
         // Don't drop any candidates in intercrate mode, as it's incomplete.
         // (Not that it matters, since `Unsize` is not a stable trait.)
-        if self.infcx.intercrate {
+        //
+        // FIXME(@lcnr): This should probably only trigger during analysis,
+        // disabling candidates during codegen is also questionable.
+        if let TypingMode::Coherence = self.infcx.typing_mode(param_env) {
             return None;
         }
 
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index ec4114fd9d7..b1e5e526315 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -2,6 +2,7 @@
 //!
 //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html#selection
 
+use std::assert_matches::assert_matches;
 use std::cell::{Cell, RefCell};
 use std::fmt::{self, Display};
 use std::ops::ControlFlow;
@@ -28,7 +29,7 @@ use rustc_middle::ty::error::TypeErrorToStringExt;
 use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths};
 use rustc_middle::ty::{
     self, GenericArgsRef, PolyProjectionPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitableExt,
-    Upcast,
+    TypingMode, Upcast,
 };
 use rustc_span::Symbol;
 use rustc_span::symbol::sym;
@@ -49,7 +50,7 @@ use crate::infer::{InferCtxt, InferOk, TypeFreshener};
 use crate::solve::InferCtxtSelectExt as _;
 use crate::traits::normalize::{normalize_with_depth, normalize_with_depth_to};
 use crate::traits::project::{ProjectAndUnifyResult, ProjectionCacheKeyExt};
-use crate::traits::{ProjectionCacheKey, Unimplemented};
+use crate::traits::{ProjectionCacheKey, Unimplemented, effects};
 
 mod _match;
 mod candidate_assembly;
@@ -222,7 +223,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     /// Enables tracking of intercrate ambiguity causes. See
     /// the documentation of [`Self::intercrate_ambiguity_causes`] for more.
     pub fn enable_tracking_intercrate_ambiguity_causes(&mut self) {
-        assert!(self.is_intercrate());
+        assert_matches!(self.infcx.typing_mode_unchecked(), TypingMode::Coherence);
         assert!(self.intercrate_ambiguity_causes.is_none());
         self.intercrate_ambiguity_causes = Some(FxIndexSet::default());
         debug!("selcx: enable_tracking_intercrate_ambiguity_causes");
@@ -234,7 +235,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     pub fn take_intercrate_ambiguity_causes(
         &mut self,
     ) -> FxIndexSet<IntercrateAmbiguityCause<'tcx>> {
-        assert!(self.is_intercrate());
+        assert_matches!(self.infcx.typing_mode_unchecked(), TypingMode::Coherence);
         self.intercrate_ambiguity_causes.take().unwrap_or_default()
     }
 
@@ -242,10 +243,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         self.infcx.tcx
     }
 
-    pub fn is_intercrate(&self) -> bool {
-        self.infcx.intercrate
-    }
-
     ///////////////////////////////////////////////////////////////////////////
     // Selection
     //
@@ -645,11 +642,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     self.evaluate_trait_predicate_recursively(previous_stack, obligation)
                 }
 
-                ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..)) => {
-                    // FIXME(effects): It should be relatively straightforward to implement
-                    // old trait solver support for `HostEffect` bounds; or at least basic
-                    // support for them.
-                    todo!()
+                ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(data)) => {
+                    self.infcx.enter_forall(bound_predicate.rebind(data), |data| {
+                        match effects::evaluate_host_effect_obligation(
+                            self,
+                            &obligation.with(self.tcx(), data),
+                        ) {
+                            Ok(nested) => {
+                                self.evaluate_predicates_recursively(previous_stack, nested)
+                            }
+                            Err(effects::EvaluationFailure::Ambiguous) => Ok(EvaluatedToAmbig),
+                            Err(effects::EvaluationFailure::NoSolution) => Ok(EvaluatedToErr),
+                        }
+                    })
                 }
 
                 ty::PredicateKind::Subtype(p) => {
@@ -1021,7 +1026,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         previous_stack: TraitObligationStackList<'o, 'tcx>,
         mut obligation: PolyTraitObligation<'tcx>,
     ) -> Result<EvaluationResult, OverflowError> {
-        if !self.is_intercrate()
+        if !matches!(self.infcx.typing_mode(obligation.param_env), TypingMode::Coherence)
             && obligation.is_global()
             && obligation.param_env.caller_bounds().iter().all(|bound| bound.has_param())
         {
@@ -1304,14 +1309,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         param_env: ty::ParamEnv<'tcx>,
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) -> Option<EvaluationResult> {
-        // Neither the global nor local cache is aware of intercrate
-        // mode, so don't do any caching. In particular, we might
-        // re-use the same `InferCtxt` with both an intercrate
-        // and non-intercrate `SelectionContext`
-        if self.is_intercrate() {
-            return None;
-        }
-
         let tcx = self.tcx();
         if self.can_use_global_caches(param_env) {
             if let Some(res) = tcx.evaluation_cache.get(&(param_env, trait_pred), tcx) {
@@ -1334,14 +1331,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             return;
         }
 
-        // Neither the global nor local cache is aware of intercrate
-        // mode, so don't do any caching. In particular, we might
-        // re-use the same `InferCtxt` with both an intercrate
-        // and non-intercrate `SelectionContext`
-        if self.is_intercrate() {
-            return;
-        }
-
         if self.can_use_global_caches(param_env) && !trait_pred.has_infer() {
             debug!(?trait_pred, ?result, "insert_evaluation_cache global");
             // This may overwrite the cache with the same value
@@ -1468,13 +1457,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     }
 
     fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Result<(), Conflict> {
-        debug!("is_knowable(intercrate={:?})", self.is_intercrate());
-
-        if !self.is_intercrate() {
-            return Ok(());
+        let obligation = &stack.obligation;
+        match self.infcx.typing_mode(obligation.param_env) {
+            TypingMode::Coherence => {}
+            TypingMode::Analysis { .. } | TypingMode::PostAnalysis => return Ok(()),
         }
 
-        let obligation = &stack.obligation;
+        debug!("is_knowable()");
+
         let predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);
 
         // Okay to skip binder because of the nature of the
@@ -1494,25 +1484,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             return false;
         }
 
-        // Avoid using the global cache during coherence and just rely
-        // on the local cache. This effectively disables caching
-        // during coherence. It is really just a simplification to
-        // avoid us having to fear that coherence results "pollute"
-        // the master cache. Since coherence executes pretty quickly,
-        // it's not worth going to more trouble to increase the
-        // hit-rate, I don't think.
-        if self.is_intercrate() {
-            return false;
-        }
-
-        // Avoid using the global cache when we're defining opaque types
-        // as their hidden type may impact the result of candidate selection.
-        if !self.infcx.defining_opaque_types().is_empty() {
-            return false;
+        match self.infcx.typing_mode(param_env) {
+            // Avoid using the global cache during coherence and just rely
+            // on the local cache. It is really just a simplification to
+            // avoid us having to fear that coherence results "pollute"
+            // the master cache. Since coherence executes pretty quickly,
+            // it's not worth going to more trouble to increase the
+            // hit-rate, I don't think.
+            TypingMode::Coherence => false,
+            // Avoid using the global cache when we're defining opaque types
+            // as their hidden type may impact the result of candidate selection.
+            TypingMode::Analysis { defining_opaque_types } => defining_opaque_types.is_empty(),
+            // The global cache is only used if there are no opaque types in
+            // the defining scope or we're outside of analysis.
+            //
+            // FIXME(#132279): This is still incorrect as we treat opaque types
+            // and default associated items differently between these two modes.
+            TypingMode::PostAnalysis => true,
         }
-
-        // Otherwise, we can use the global cache.
-        true
     }
 
     fn check_candidate_cache(
@@ -1520,13 +1509,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         param_env: ty::ParamEnv<'tcx>,
         cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) -> Option<SelectionResult<'tcx, SelectionCandidate<'tcx>>> {
-        // Neither the global nor local cache is aware of intercrate
-        // mode, so don't do any caching. In particular, we might
-        // re-use the same `InferCtxt` with both an intercrate
-        // and non-intercrate `SelectionContext`
-        if self.is_intercrate() {
-            return None;
-        }
         let tcx = self.tcx();
         let pred = cache_fresh_trait_pred.skip_binder();
 
@@ -1558,13 +1540,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         &self,
         result: &SelectionResult<'tcx, SelectionCandidate<'tcx>>,
     ) -> bool {
-        // Neither the global nor local cache is aware of intercrate
-        // mode, so don't do any caching. In particular, we might
-        // re-use the same `InferCtxt` with both an intercrate
-        // and non-intercrate `SelectionContext`
-        if self.is_intercrate() {
-            return false;
-        }
         match result {
             Ok(Some(SelectionCandidate::ParamCandidate(trait_ref))) => !trait_ref.has_infer(),
             _ => true,
@@ -2533,7 +2508,9 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
             })?;
         nested_obligations.extend(obligations);
 
-        if !self.is_intercrate() && impl_trait_header.polarity == ty::ImplPolarity::Reservation {
+        if impl_trait_header.polarity == ty::ImplPolarity::Reservation
+            && !matches!(self.infcx.typing_mode(obligation.param_env), TypingMode::Coherence)
+        {
             debug!("reservation impls only apply in intercrate mode");
             return Err(());
         }
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index 0e45f7a195f..5bf3dbcbc32 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -19,7 +19,9 @@ use rustc_infer::infer::DefineOpaqueTypes;
 use rustc_middle::bug;
 use rustc_middle::query::LocalCrate;
 use rustc_middle::ty::print::PrintTraitRefExt as _;
-use rustc_middle::ty::{self, GenericArgsRef, ImplSubject, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{
+    self, GenericArgsRef, ImplSubject, Ty, TyCtxt, TypeVisitableExt, TypingMode,
+};
 use rustc_session::lint::builtin::{COHERENCE_LEAK_CHECK, ORDER_DEPENDENT_TRAIT_OBJECTS};
 use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, sym};
 use specialization_graph::GraphExt;
@@ -184,7 +186,7 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId,
     let penv = tcx.param_env(impl1_def_id);
 
     // Create an infcx, taking the predicates of impl1 as assumptions:
-    let infcx = tcx.infer_ctxt().build();
+    let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
 
     // Attempt to prove that impl2 applies, given all of the above.
     fulfill_implication(
diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs
index ed221e2a183..bb56d6eaf54 100644
--- a/compiler/rustc_trait_selection/src/traits/vtable.rs
+++ b/compiler/rustc_trait_selection/src/traits/vtable.rs
@@ -9,7 +9,8 @@ use rustc_infer::traits::util::PredicateSet;
 use rustc_middle::bug;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{
-    self, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeVisitableExt, Upcast, VtblEntry,
+    self, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeVisitableExt, TypingMode, Upcast,
+    VtblEntry,
 };
 use rustc_span::{DUMMY_SP, Span, sym};
 use smallvec::{SmallVec, smallvec};
@@ -439,7 +440,7 @@ fn trait_refs_are_compatible<'tcx>(
         return false;
     }
 
-    let infcx = tcx.infer_ctxt().build();
+    let infcx = tcx.infer_ctxt().build(TypingMode::PostAnalysis);
     let param_env = ty::ParamEnv::reveal_all();
     let ocx = ObligationCtxt::new(&infcx);
     let hr_source_principal =
diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs
index 11182198246..d8c1c50d79a 100644
--- a/compiler/rustc_traits/src/codegen.rs
+++ b/compiler/rustc_traits/src/codegen.rs
@@ -6,7 +6,7 @@
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::bug;
 use rustc_middle::traits::CodegenObligationError;
-use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt, TypingMode};
 use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::traits::{
     ImplSource, Obligation, ObligationCause, ObligationCtxt, ScrubbedTraitError, SelectionContext,
@@ -30,7 +30,7 @@ pub(crate) fn codegen_select_candidate<'tcx>(
 
     // Do the initial selection for the obligation. This yields the
     // shallow result we are looking for -- that is, what specific impl.
-    let infcx = tcx.infer_ctxt().ignoring_regions().build();
+    let infcx = tcx.infer_ctxt().ignoring_regions().build(TypingMode::from_param_env(param_env));
     let mut selcx = SelectionContext::new(&infcx);
 
     let obligation_cause = ObligationCause::dummy();
diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs
index 3e2794f6489..d79059a39a1 100644
--- a/compiler/rustc_traits/src/normalize_erasing_regions.rs
+++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs
@@ -1,7 +1,7 @@
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::query::Providers;
 use rustc_middle::traits::query::NoSolution;
-use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt, TypeFoldable, TypeVisitableExt};
+use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt, TypeFoldable, TypeVisitableExt, TypingMode};
 use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
 use rustc_trait_selection::traits::{Normalized, ObligationCause};
 use tracing::debug;
@@ -22,7 +22,7 @@ fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable<TyCtxt<'tcx>> + Par
     goal: ParamEnvAnd<'tcx, T>,
 ) -> Result<T, NoSolution> {
     let ParamEnvAnd { param_env, value } = goal;
-    let infcx = tcx.infer_ctxt().build();
+    let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env));
     let cause = ObligationCause::dummy();
     match infcx.at(&cause, param_env).query_normalize(value) {
         Ok(Normalized { value: normalized_value, obligations: normalized_obligations }) => {
diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs
index 94ca4c13d08..f19a567cd84 100644
--- a/compiler/rustc_transmute/src/layout/tree.rs
+++ b/compiler/rustc_transmute/src/layout/tree.rs
@@ -339,9 +339,7 @@ pub(crate) mod rustc {
             // 2. enums that delegate their layout to a variant
             // 3. enums with multiple variants
             match layout.variants() {
-                Variants::Single { .. }
-                    if layout.abi.is_uninhabited() && layout.size == Size::ZERO =>
-                {
+                Variants::Single { .. } if layout.is_uninhabited() && layout.size == Size::ZERO => {
                     // The layout representation of uninhabited, ZST enums is
                     // defined to be like that of the `!` type, as opposed of a
                     // typical enum. Consequently, they cannot be descended into
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index 48149a08de8..722ef5f4569 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -1,7 +1,7 @@
 use std::iter;
 
 use rustc_abi::Primitive::Pointer;
-use rustc_abi::{Abi, PointerKind, Scalar, Size};
+use rustc_abi::{BackendRepr, PointerKind, Scalar, Size};
 use rustc_hir as hir;
 use rustc_hir::lang_items::LangItem;
 use rustc_middle::bug;
@@ -469,7 +469,7 @@ fn fn_abi_sanity_check<'tcx>(
                 // careful. Scalar/ScalarPair is fine, since backends will generally use
                 // `layout.abi` and ignore everything else. We should just reject `Aggregate`
                 // entirely here, but some targets need to be fixed first.
-                if matches!(arg.layout.abi, Abi::Aggregate { .. }) {
+                if matches!(arg.layout.backend_repr, BackendRepr::Memory { .. }) {
                     // For an unsized type we'd only pass the sized prefix, so there is no universe
                     // in which we ever want to allow this.
                     assert!(
@@ -500,7 +500,7 @@ fn fn_abi_sanity_check<'tcx>(
                 // Similar to `Direct`, we need to make sure that backends use `layout.abi` and
                 // ignore the rest of the layout.
                 assert!(
-                    matches!(arg.layout.abi, Abi::ScalarPair(..)),
+                    matches!(arg.layout.backend_repr, BackendRepr::ScalarPair(..)),
                     "PassMode::Pair for type {}",
                     arg.layout.ty
                 );
@@ -658,9 +658,9 @@ fn fn_abi_adjust_for_abi<'tcx>(
         fn unadjust<'tcx>(arg: &mut ArgAbi<'tcx, Ty<'tcx>>) {
             // This still uses `PassMode::Pair` for ScalarPair types. That's unlikely to be intended,
             // but who knows what breaks if we change this now.
-            if matches!(arg.layout.abi, Abi::Aggregate { .. }) {
+            if matches!(arg.layout.backend_repr, BackendRepr::Memory { .. }) {
                 assert!(
-                    arg.layout.abi.is_sized(),
+                    arg.layout.backend_repr.is_sized(),
                     "'unadjusted' ABI does not support unsized arguments"
                 );
             }
@@ -731,8 +731,8 @@ fn make_thin_self_ptr<'tcx>(
         // FIXME (mikeyhew) change this to use &own if it is ever added to the language
         Ty::new_mut_ptr(tcx, layout.ty)
     } else {
-        match layout.abi {
-            Abi::ScalarPair(..) | Abi::Scalar(..) => (),
+        match layout.backend_repr {
+            BackendRepr::ScalarPair(..) | BackendRepr::Scalar(..) => (),
             _ => bug!("receiver type has unsupported layout: {:?}", layout),
         }
 
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index 16fd28201c2..3655fa5ae0e 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -143,7 +143,6 @@ fn associated_item_from_trait_item_ref(trait_item_ref: &hir::TraitItemRef) -> ty
         container: ty::TraitContainer,
         fn_has_self_parameter: has_self,
         opt_rpitit_info: None,
-        is_effects_desugaring: false,
     }
 }
 
@@ -163,7 +162,6 @@ fn associated_item_from_impl_item_ref(impl_item_ref: &hir::ImplItemRef) -> ty::A
         container: ty::ImplContainer,
         fn_has_self_parameter: has_self,
         opt_rpitit_info: None,
-        is_effects_desugaring: false,
     }
 }
 
@@ -190,7 +188,7 @@ fn associated_types_for_impl_traits_in_associated_fn(
 
             impl<'tcx> Visitor<'tcx> for RPITVisitor {
                 fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
-                    if let hir::TyKind::OpaqueDef(opaq, _) = ty.kind
+                    if let hir::TyKind::OpaqueDef(opaq) = ty.kind
                         && self.rpits.insert(opaq.def_id)
                     {
                         for bound in opaq.bounds {
@@ -246,7 +244,7 @@ fn associated_type_for_impl_trait_in_trait(
 ) -> LocalDefId {
     let (hir::OpaqueTyOrigin::FnReturn { parent: fn_def_id, .. }
     | hir::OpaqueTyOrigin::AsyncFn { parent: fn_def_id, .. }) =
-        tcx.opaque_type_origin(opaque_ty_def_id)
+        tcx.local_opaque_ty_origin(opaque_ty_def_id)
     else {
         bug!("expected opaque for {opaque_ty_def_id:?}");
     };
@@ -275,7 +273,6 @@ fn associated_type_for_impl_trait_in_trait(
             fn_def_id: fn_def_id.to_def_id(),
             opaque_def_id: opaque_ty_def_id.to_def_id(),
         }),
-        is_effects_desugaring: false,
     });
 
     // Copy visility of the containing function.
@@ -284,8 +281,6 @@ fn associated_type_for_impl_trait_in_trait(
     // Copy defaultness of the containing function.
     trait_assoc_ty.defaultness(tcx.defaultness(fn_def_id));
 
-    trait_assoc_ty.is_type_alias_impl_trait(false);
-
     // There are no inferred outlives for the synthesized associated type.
     trait_assoc_ty.inferred_outlives_of(&[]);
 
@@ -327,7 +322,6 @@ fn associated_type_for_impl_trait_in_impl(
         container: ty::ImplContainer,
         fn_has_self_parameter: false,
         opt_rpitit_info: Some(ImplTraitInTraitData::Impl { fn_def_id: impl_fn_def_id.to_def_id() }),
-        is_effects_desugaring: false,
     });
 
     // Copy visility of the containing function.
diff --git a/compiler/rustc_ty_utils/src/common_traits.rs b/compiler/rustc_ty_utils/src/common_traits.rs
index 51b908881eb..c26b41d8960 100644
--- a/compiler/rustc_ty_utils/src/common_traits.rs
+++ b/compiler/rustc_ty_utils/src/common_traits.rs
@@ -3,7 +3,7 @@
 use rustc_hir::lang_items::LangItem;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::query::Providers;
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypingMode};
 use rustc_trait_selection::traits;
 
 fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
@@ -29,7 +29,7 @@ fn is_item_raw<'tcx>(
 ) -> bool {
     let (param_env, ty) = query.into_parts();
     let trait_def_id = tcx.require_lang_item(item, None);
-    let infcx = tcx.infer_ctxt().build();
+    let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env));
     traits::type_known_to_meet_bound_modulo_regions(&infcx, param_env, ty, trait_def_id)
 }
 
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 9b764133f2c..e258b6dae0b 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -6,7 +6,7 @@ use rustc_middle::bug;
 use rustc_middle::query::Providers;
 use rustc_middle::traits::{BuiltinImplSource, CodegenObligationError};
 use rustc_middle::ty::util::AsyncDropGlueMorphology;
-use rustc_middle::ty::{self, GenericArgsRef, Instance, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{self, GenericArgsRef, Instance, TyCtxt, TypeVisitableExt, TypingMode};
 use rustc_span::sym;
 use rustc_trait_selection::traits;
 use rustc_type_ir::ClosureKind;
@@ -130,7 +130,7 @@ fn resolve_associated_item<'tcx>(
                 .unwrap_or_else(|| {
                     bug!("{:?} not found in {:?}", trait_item_id, impl_data.impl_def_id);
                 });
-            let infcx = tcx.infer_ctxt().build();
+            let infcx = tcx.infer_ctxt().build(TypingMode::PostAnalysis);
             let param_env = param_env.with_reveal_all_normalized(tcx);
             let args = rcvr_args.rebase_onto(tcx, trait_def_id, impl_data.args);
             let args = translate_args(
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 94b80e2694d..5ca7afe2453 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -5,8 +5,9 @@ use hir::def_id::DefId;
 use rustc_abi::Integer::{I8, I32};
 use rustc_abi::Primitive::{self, Float, Int, Pointer};
 use rustc_abi::{
-    Abi, AbiAndPrefAlign, AddressSpace, Align, FieldsShape, HasDataLayout, LayoutCalculatorError,
-    LayoutData, Niche, ReprOptions, Scalar, Size, StructKind, TagEncoding, Variants, WrappingRange,
+    AbiAndPrefAlign, AddressSpace, Align, BackendRepr, FieldsShape, HasDataLayout,
+    LayoutCalculatorError, LayoutData, Niche, ReprOptions, Scalar, Size, StructKind, TagEncoding,
+    Variants, WrappingRange,
 };
 use rustc_index::bit_set::BitSet;
 use rustc_index::{IndexSlice, IndexVec};
@@ -173,7 +174,9 @@ fn layout_of_uncached<'tcx>(
             let mut layout = LayoutData::clone(&layout.0);
             match *pat {
                 ty::PatternKind::Range { start, end, include_end } => {
-                    if let Abi::Scalar(scalar) | Abi::ScalarPair(scalar, _) = &mut layout.abi {
+                    if let BackendRepr::Scalar(scalar) | BackendRepr::ScalarPair(scalar, _) =
+                        &mut layout.backend_repr
+                    {
                         if let Some(start) = start {
                             scalar.valid_range_mut().start = start
                                 .try_to_bits(tcx, param_env)
@@ -275,7 +278,7 @@ fn layout_of_uncached<'tcx>(
                     return Ok(tcx.mk_layout(LayoutData::scalar(cx, data_ptr)));
                 }
 
-                let Abi::Scalar(metadata) = metadata_layout.abi else {
+                let BackendRepr::Scalar(metadata) = metadata_layout.backend_repr else {
                     return Err(error(cx, LayoutError::Unknown(pointee)));
                 };
 
@@ -330,9 +333,9 @@ fn layout_of_uncached<'tcx>(
                 .ok_or_else(|| error(cx, LayoutError::SizeOverflow(ty)))?;
 
             let abi = if count != 0 && ty.is_privately_uninhabited(tcx, param_env) {
-                Abi::Uninhabited
+                BackendRepr::Uninhabited
             } else {
-                Abi::Aggregate { sized: true }
+                BackendRepr::Memory { sized: true }
             };
 
             let largest_niche = if count != 0 { element.largest_niche } else { None };
@@ -340,7 +343,7 @@ fn layout_of_uncached<'tcx>(
             tcx.mk_layout(LayoutData {
                 variants: Variants::Single { index: FIRST_VARIANT },
                 fields: FieldsShape::Array { stride: element.size, count },
-                abi,
+                backend_repr: abi,
                 largest_niche,
                 align: element.align,
                 size,
@@ -353,7 +356,7 @@ fn layout_of_uncached<'tcx>(
             tcx.mk_layout(LayoutData {
                 variants: Variants::Single { index: FIRST_VARIANT },
                 fields: FieldsShape::Array { stride: element.size, count: 0 },
-                abi: Abi::Aggregate { sized: false },
+                backend_repr: BackendRepr::Memory { sized: false },
                 largest_niche: None,
                 align: element.align,
                 size: Size::ZERO,
@@ -364,7 +367,7 @@ fn layout_of_uncached<'tcx>(
         ty::Str => tcx.mk_layout(LayoutData {
             variants: Variants::Single { index: FIRST_VARIANT },
             fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 },
-            abi: Abi::Aggregate { sized: false },
+            backend_repr: BackendRepr::Memory { sized: false },
             largest_niche: None,
             align: dl.i8_align,
             size: Size::ZERO,
@@ -384,8 +387,8 @@ fn layout_of_uncached<'tcx>(
                 &ReprOptions::default(),
                 StructKind::AlwaysSized,
             )?;
-            match unit.abi {
-                Abi::Aggregate { ref mut sized } => *sized = false,
+            match unit.backend_repr {
+                BackendRepr::Memory { ref mut sized } => *sized = false,
                 _ => bug!(),
             }
             tcx.mk_layout(unit)
@@ -500,7 +503,7 @@ fn layout_of_uncached<'tcx>(
 
             // Compute the ABI of the element type:
             let e_ly = cx.layout_of(e_ty)?;
-            let Abi::Scalar(e_abi) = e_ly.abi else {
+            let BackendRepr::Scalar(e_abi) = e_ly.backend_repr else {
                 // This error isn't caught in typeck, e.g., if
                 // the element type of the vector is generic.
                 tcx.dcx().emit_fatal(NonPrimitiveSimdType { ty, e_ty });
@@ -516,12 +519,12 @@ fn layout_of_uncached<'tcx>(
                 // Non-power-of-two vectors have padding up to the next power-of-two.
                 // If we're a packed repr, remove the padding while keeping the alignment as close
                 // to a vector as possible.
-                (Abi::Aggregate { sized: true }, AbiAndPrefAlign {
+                (BackendRepr::Memory { sized: true }, AbiAndPrefAlign {
                     abi: Align::max_for_offset(size),
                     pref: dl.vector_align(size).pref,
                 })
             } else {
-                (Abi::Vector { element: e_abi, count: e_len }, dl.vector_align(size))
+                (BackendRepr::Vector { element: e_abi, count: e_len }, dl.vector_align(size))
             };
             let size = size.align_to(align.abi);
 
@@ -535,7 +538,7 @@ fn layout_of_uncached<'tcx>(
             tcx.mk_layout(LayoutData {
                 variants: Variants::Single { index: FIRST_VARIANT },
                 fields,
-                abi,
+                backend_repr: abi,
                 largest_niche: e_ly.largest_niche,
                 size,
                 align,
@@ -985,10 +988,12 @@ fn coroutine_layout<'tcx>(
 
     size = size.align_to(align.abi);
 
-    let abi = if prefix.abi.is_uninhabited() || variants.iter().all(|v| v.abi.is_uninhabited()) {
-        Abi::Uninhabited
+    let abi = if prefix.backend_repr.is_uninhabited()
+        || variants.iter().all(|v| v.backend_repr.is_uninhabited())
+    {
+        BackendRepr::Uninhabited
     } else {
-        Abi::Aggregate { sized: true }
+        BackendRepr::Memory { sized: true }
     };
 
     let layout = tcx.mk_layout(LayoutData {
@@ -999,7 +1004,7 @@ fn coroutine_layout<'tcx>(
             variants,
         },
         fields: outer_fields,
-        abi,
+        backend_repr: abi,
         // Suppress niches inside coroutines. If the niche is inside a field that is aliased (due to
         // self-referentiality), getting the discriminant can cause aliasing violations.
         // `UnsafeCell` blocks niches for the same reason, but we don't yet have `UnsafePinned` that
diff --git a/compiler/rustc_ty_utils/src/layout/invariant.rs b/compiler/rustc_ty_utils/src/layout/invariant.rs
index 6cf114b74c1..f43feb552b2 100644
--- a/compiler/rustc_ty_utils/src/layout/invariant.rs
+++ b/compiler/rustc_ty_utils/src/layout/invariant.rs
@@ -10,7 +10,7 @@ pub(super) fn partially_check_layout<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLa
 
     // Type-level uninhabitedness should always imply ABI uninhabitedness.
     if layout.ty.is_privately_uninhabited(tcx, cx.param_env) {
-        assert!(layout.abi.is_uninhabited());
+        assert!(layout.is_uninhabited());
     }
 
     if layout.size.bytes() % layout.align.abi.bytes() != 0 {
@@ -66,12 +66,12 @@ pub(super) fn partially_check_layout<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLa
 
     fn check_layout_abi<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayout<'tcx>) {
         // Verify the ABI mandated alignment and size.
-        let align = layout.abi.inherent_align(cx).map(|align| align.abi);
-        let size = layout.abi.inherent_size(cx);
+        let align = layout.backend_repr.inherent_align(cx).map(|align| align.abi);
+        let size = layout.backend_repr.inherent_size(cx);
         let Some((align, size)) = align.zip(size) else {
             assert_matches!(
-                layout.layout.abi(),
-                Abi::Uninhabited | Abi::Aggregate { .. },
+                layout.layout.backend_repr(),
+                BackendRepr::Uninhabited | BackendRepr::Memory { .. },
                 "ABI unexpectedly missing alignment and/or size in {layout:#?}"
             );
             return;
@@ -88,12 +88,12 @@ pub(super) fn partially_check_layout<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLa
         );
 
         // Verify per-ABI invariants
-        match layout.layout.abi() {
-            Abi::Scalar(_) => {
+        match layout.layout.backend_repr() {
+            BackendRepr::Scalar(_) => {
                 // Check that this matches the underlying field.
                 let inner = skip_newtypes(cx, layout);
                 assert!(
-                    matches!(inner.layout.abi(), Abi::Scalar(_)),
+                    matches!(inner.layout.backend_repr(), BackendRepr::Scalar(_)),
                     "`Scalar` type {} is newtype around non-`Scalar` type {}",
                     layout.ty,
                     inner.ty
@@ -132,7 +132,7 @@ pub(super) fn partially_check_layout<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLa
                             "`Scalar` field with bad align in {inner:#?}",
                         );
                         assert!(
-                            matches!(field.abi, Abi::Scalar(_)),
+                            matches!(field.backend_repr, BackendRepr::Scalar(_)),
                             "`Scalar` field with bad ABI in {inner:#?}",
                         );
                     }
@@ -141,11 +141,11 @@ pub(super) fn partially_check_layout<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLa
                     }
                 }
             }
-            Abi::ScalarPair(scalar1, scalar2) => {
+            BackendRepr::ScalarPair(scalar1, scalar2) => {
                 // Check that the underlying pair of fields matches.
                 let inner = skip_newtypes(cx, layout);
                 assert!(
-                    matches!(inner.layout.abi(), Abi::ScalarPair(..)),
+                    matches!(inner.layout.backend_repr(), BackendRepr::ScalarPair(..)),
                     "`ScalarPair` type {} is newtype around non-`ScalarPair` type {}",
                     layout.ty,
                     inner.ty
@@ -208,8 +208,8 @@ pub(super) fn partially_check_layout<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLa
                     "`ScalarPair` first field with bad align in {inner:#?}",
                 );
                 assert_matches!(
-                    field1.abi,
-                    Abi::Scalar(_),
+                    field1.backend_repr,
+                    BackendRepr::Scalar(_),
                     "`ScalarPair` first field with bad ABI in {inner:#?}",
                 );
                 let field2_offset = size1.align_to(align2);
@@ -226,16 +226,16 @@ pub(super) fn partially_check_layout<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLa
                     "`ScalarPair` second field with bad align in {inner:#?}",
                 );
                 assert_matches!(
-                    field2.abi,
-                    Abi::Scalar(_),
+                    field2.backend_repr,
+                    BackendRepr::Scalar(_),
                     "`ScalarPair` second field with bad ABI in {inner:#?}",
                 );
             }
-            Abi::Vector { element, .. } => {
+            BackendRepr::Vector { element, .. } => {
                 assert!(align >= element.align(cx).abi); // just sanity-checking `vector_align`.
                 // FIXME: Do some kind of check of the inner type, like for Scalar and ScalarPair.
             }
-            Abi::Uninhabited | Abi::Aggregate { .. } => {} // Nothing to check.
+            BackendRepr::Uninhabited | BackendRepr::Memory { .. } => {} // Nothing to check.
         }
     }
 
@@ -262,9 +262,7 @@ pub(super) fn partially_check_layout<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLa
                 )
             }
             // Skip empty variants.
-            if variant.size == Size::ZERO
-                || variant.fields.count() == 0
-                || variant.abi.is_uninhabited()
+            if variant.size == Size::ZERO || variant.fields.count() == 0 || variant.is_uninhabited()
             {
                 // These are never actually accessed anyway, so we can skip the coherence check
                 // for them. They also fail that check, since they have
@@ -276,13 +274,13 @@ pub(super) fn partially_check_layout<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLa
             // The top-level ABI and the ABI of the variants should be coherent.
             let scalar_coherent =
                 |s1: Scalar, s2: Scalar| s1.size(cx) == s2.size(cx) && s1.align(cx) == s2.align(cx);
-            let abi_coherent = match (layout.abi, variant.abi) {
-                (Abi::Scalar(s1), Abi::Scalar(s2)) => scalar_coherent(s1, s2),
-                (Abi::ScalarPair(a1, b1), Abi::ScalarPair(a2, b2)) => {
+            let abi_coherent = match (layout.backend_repr, variant.backend_repr) {
+                (BackendRepr::Scalar(s1), BackendRepr::Scalar(s2)) => scalar_coherent(s1, s2),
+                (BackendRepr::ScalarPair(a1, b1), BackendRepr::ScalarPair(a2, b2)) => {
                     scalar_coherent(a1, a2) && scalar_coherent(b1, b2)
                 }
-                (Abi::Uninhabited, _) => true,
-                (Abi::Aggregate { .. }, _) => true,
+                (BackendRepr::Uninhabited, _) => true,
+                (BackendRepr::Memory { .. }, _) => true,
                 _ => false,
             };
             if !abi_coherent {
diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs
index 5e2232ff47d..34f461aac58 100644
--- a/compiler/rustc_ty_utils/src/opaque_types.rs
+++ b/compiler/rustc_ty_utils/src/opaque_types.rs
@@ -139,7 +139,7 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
         }
 
         // TAITs outside their defining scopes are ignored.
-        let origin = self.tcx.opaque_type_origin(alias_ty.def_id.expect_local());
+        let origin = self.tcx.local_opaque_ty_origin(alias_ty.def_id.expect_local());
         trace!(?origin);
         match origin {
             rustc_hir::OpaqueTyOrigin::FnReturn { .. }
diff --git a/compiler/rustc_ty_utils/src/structural_match.rs b/compiler/rustc_ty_utils/src/structural_match.rs
index 1ead7b731e7..0b4efab1d9c 100644
--- a/compiler/rustc_ty_utils/src/structural_match.rs
+++ b/compiler/rustc_ty_utils/src/structural_match.rs
@@ -1,7 +1,7 @@
 use rustc_hir::lang_items::LangItem;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::query::Providers;
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypingMode};
 use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt};
 
 /// This method returns true if and only if `adt_ty` itself has been marked as
@@ -11,7 +11,7 @@ use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt};
 /// Note that this does *not* recursively check if the substructure of `adt_ty`
 /// implements the trait.
 fn has_structural_eq_impl<'tcx>(tcx: TyCtxt<'tcx>, adt_ty: Ty<'tcx>) -> bool {
-    let infcx = &tcx.infer_ctxt().build();
+    let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
     let cause = ObligationCause::dummy();
 
     let ocx = ObligationCtxt::new(infcx);
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index aa499995bcb..731d42fc006 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -155,7 +155,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
     if tcx.is_conditionally_const(def_id) {
         predicates.extend(
             tcx.const_conditions(def_id).instantiate_identity(tcx).into_iter().map(
-                |(trait_ref, _)| trait_ref.to_host_effect_clause(tcx, ty::HostPolarity::Maybe),
+                |(trait_ref, _)| trait_ref.to_host_effect_clause(tcx, ty::BoundConstness::Maybe),
             ),
         );
     }
diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs
index 3fb7d87bcc4..24b2ebc1fbe 100644
--- a/compiler/rustc_type_ir/src/canonical.rs
+++ b/compiler/rustc_type_ir/src/canonical.rs
@@ -8,7 +8,7 @@ use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
 use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
 
 use crate::inherent::*;
-use crate::{self as ty, Interner, UniverseIndex};
+use crate::{self as ty, Interner, TypingMode, UniverseIndex};
 
 #[derive_where(Clone; I: Interner, V: Clone)]
 #[derive_where(Hash; I: Interner, V: Hash)]
@@ -19,7 +19,7 @@ use crate::{self as ty, Interner, UniverseIndex};
 #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
 pub struct CanonicalQueryInput<I: Interner, V> {
     pub canonical: Canonical<I, V>,
-    pub defining_opaque_types: I::DefiningOpaqueTypes,
+    pub typing_mode: TypingMode<I>,
 }
 
 /// A "canonicalized" type `V` is one where all free inference
diff --git a/compiler/rustc_type_ir/src/elaborate.rs b/compiler/rustc_type_ir/src/elaborate.rs
index 72d392ecd7b..3fbce7886ed 100644
--- a/compiler/rustc_type_ir/src/elaborate.rs
+++ b/compiler/rustc_type_ir/src/elaborate.rs
@@ -160,7 +160,7 @@ impl<I: Interner, O: Elaboratable<I>> Elaborator<I, O> {
                 cx.implied_const_bounds(data.def_id()).iter_identity().map(|trait_ref| {
                     elaboratable.child(
                         trait_ref
-                            .to_host_effect_clause(cx, data.host)
+                            .to_host_effect_clause(cx, data.constness)
                             .instantiate_supertrait(cx, bound_clause.rebind(data.trait_ref)),
                     )
                 }),
diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs
index 7c6a3c65ebf..aadb64f45d7 100644
--- a/compiler/rustc_type_ir/src/infer_ctxt.rs
+++ b/compiler/rustc_type_ir/src/infer_ctxt.rs
@@ -1,9 +1,75 @@
+use derive_where::derive_where;
+#[cfg(feature = "nightly")]
+use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
+
 use crate::fold::TypeFoldable;
+use crate::inherent::*;
 use crate::relate::RelateResult;
 use crate::relate::combine::PredicateEmittingRelation;
-use crate::solve::SolverMode;
+use crate::solve::Reveal;
 use crate::{self as ty, Interner};
 
+/// The current typing mode of an inference context. We unfortunately have some
+/// slightly different typing rules depending on the current context. See the
+/// doc comment for each variant for how and why they are used.
+///
+/// In most cases you can get the correct typing mode automically via:
+/// - `mir::Body::typing_mode`
+/// - `rustc_lint::LateContext::typing_mode`
+///
+/// If neither of these functions are available, feel free to reach out to
+/// t-types for help.
+#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
+#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
+pub enum TypingMode<I: Interner> {
+    /// When checking whether impls overlap, we check whether any obligations
+    /// are guaranteed to never hold when unifying the impls. This requires us
+    /// to be complete: we must never fail to prove something which may actually
+    /// hold.
+    ///
+    /// In this typing mode we bail with ambiguity in case its not knowable
+    /// whether a trait goal may hold, e.g. because the trait may get implemented
+    /// in a downstream or sibling crate.
+    ///
+    /// We also have to be careful when generalizing aliases inside of higher-ranked
+    /// types to not unnecessarily constrain any inference variables.
+    Coherence,
+    /// Analysis includes type inference, checking that items are well-formed, and
+    /// pretty much everything else which may emit proper type errors to the user.
+    ///
+    /// We only normalize opaque types which may get defined by the current body,
+    /// which are stored in `defining_opaque_types`.
+    Analysis { defining_opaque_types: I::DefiningOpaqueTypes },
+    /// After analysis, mostly during codegen and MIR optimizations, we're able to
+    /// reveal all opaque types.
+    PostAnalysis,
+}
+
+impl<I: Interner> TypingMode<I> {
+    /// Analysis outside of a body does not define any opaque types.
+    pub fn non_body_analysis() -> TypingMode<I> {
+        TypingMode::Analysis { defining_opaque_types: Default::default() }
+    }
+
+    /// While typechecking a body, we need to be able to define the opaque
+    /// types defined by that body.
+    pub fn analysis_in_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
+        TypingMode::Analysis { defining_opaque_types: cx.opaque_types_defined_by(body_def_id) }
+    }
+
+    /// FIXME(#132279): Using this function is questionable as the `param_env`
+    /// does not track `defining_opaque_types` and whether we're in coherence mode.
+    /// Many uses of this function should also use a not-yet implemented typing mode
+    /// which reveals already defined opaque types in the future. This function will
+    /// get completely removed at some point.
+    pub fn from_param_env(param_env: I::ParamEnv) -> TypingMode<I> {
+        match param_env.reveal() {
+            Reveal::UserFacing => TypingMode::non_body_analysis(),
+            Reveal::All => TypingMode::PostAnalysis,
+        }
+    }
+}
+
 pub trait InferCtxtLike: Sized {
     type Interner: Interner;
     fn cx(&self) -> Self::Interner;
@@ -16,7 +82,10 @@ pub trait InferCtxtLike: Sized {
         true
     }
 
-    fn solver_mode(&self) -> SolverMode;
+    fn typing_mode(
+        &self,
+        param_env_for_debug_assertion: <Self::Interner as Interner>::ParamEnv,
+    ) -> TypingMode<Self::Interner>;
 
     fn universe(&self) -> ty::UniverseIndex;
     fn create_next_universe(&self) -> ty::UniverseIndex;
@@ -43,8 +112,6 @@ pub trait InferCtxtLike: Sized {
         vid: ty::RegionVid,
     ) -> <Self::Interner as Interner>::Region;
 
-    fn defining_opaque_types(&self) -> <Self::Interner as Interner>::DefiningOpaqueTypes;
-
     fn next_ty_infer(&self) -> <Self::Interner as Interner>::Ty;
     fn next_const_infer(&self) -> <Self::Interner as Interner>::Const;
     fn fresh_args_for_item(
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index 6a8113b38b7..36ddddccfa2 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -11,9 +11,7 @@ use crate::inherent::*;
 use crate::ir_print::IrPrint;
 use crate::lang_items::TraitSolverLangItem;
 use crate::relate::Relate;
-use crate::solve::{
-    CanonicalInput, ExternalConstraintsData, PredefinedOpaquesData, QueryResult, SolverMode,
-};
+use crate::solve::{CanonicalInput, ExternalConstraintsData, PredefinedOpaquesData, QueryResult};
 use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
 use crate::{self as ty, search_graph};
 
@@ -130,11 +128,7 @@ pub trait Interner:
     type Clause: Clause<Self>;
     type Clauses: Copy + Debug + Hash + Eq + TypeSuperVisitable<Self> + Flags;
 
-    fn with_global_cache<R>(
-        self,
-        mode: SolverMode,
-        f: impl FnOnce(&mut search_graph::GlobalCache<Self>) -> R,
-    ) -> R;
+    fn with_global_cache<R>(self, f: impl FnOnce(&mut search_graph::GlobalCache<Self>) -> R) -> R;
 
     fn evaluation_is_concurrent(&self) -> bool;
 
@@ -298,6 +292,11 @@ pub trait Interner:
         self,
         binder: ty::Binder<Self, T>,
     ) -> ty::Binder<Self, T>;
+
+    fn opaque_types_defined_by(
+        self,
+        defining_anchor: Self::LocalDefId,
+    ) -> Self::DefiningOpaqueTypes;
 }
 
 /// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter`
@@ -414,12 +413,8 @@ impl<I: Interner> search_graph::Cx for I {
     fn with_cached_task<T>(self, task: impl FnOnce() -> T) -> (T, I::DepNodeIndex) {
         I::with_cached_task(self, task)
     }
-    fn with_global_cache<R>(
-        self,
-        mode: SolverMode,
-        f: impl FnOnce(&mut search_graph::GlobalCache<Self>) -> R,
-    ) -> R {
-        I::with_global_cache(self, mode, f)
+    fn with_global_cache<R>(self, f: impl FnOnce(&mut search_graph::GlobalCache<Self>) -> R) -> R {
+        I::with_global_cache(self, f)
     }
     fn evaluation_is_concurrent(&self) -> bool {
         self.evaluation_is_concurrent()
diff --git a/compiler/rustc_type_ir/src/outlives.rs b/compiler/rustc_type_ir/src/outlives.rs
index ac35215fbaa..0e94e989b97 100644
--- a/compiler/rustc_type_ir/src/outlives.rs
+++ b/compiler/rustc_type_ir/src/outlives.rs
@@ -110,6 +110,18 @@ impl<I: Interner> TypeVisitor<I> for OutlivesCollector<'_, I> {
             ty::Coroutine(_, args) => {
                 args.as_coroutine().tupled_upvars_ty().visit_with(self);
 
+                // Coroutines may not outlive a region unless the resume
+                // ty outlives a region. This is because the resume ty may
+                // store data that lives shorter than this outlives region
+                // across yield points, which may subsequently be accessed
+                // after the coroutine is resumed again.
+                //
+                // Conceptually, you may think of the resume arg as an upvar
+                // of `&mut Option<ResumeArgTy>`, since it is kinda like
+                // storage shared between the callee of the coroutine and the
+                // coroutine body.
+                args.as_coroutine().resume_ty().visit_with(self);
+
                 // We ignore regions in the coroutine interior as we don't
                 // want these to affect region inference
             }
diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs
index c3164550348..0cade1d6885 100644
--- a/compiler/rustc_type_ir/src/predicate.rs
+++ b/compiler/rustc_type_ir/src/predicate.rs
@@ -112,9 +112,9 @@ impl<I: Interner> ty::Binder<I, TraitRef<I>> {
         self.skip_binder().def_id
     }
 
-    pub fn to_host_effect_clause(self, cx: I, host: HostPolarity) -> I::Clause {
+    pub fn to_host_effect_clause(self, cx: I, constness: BoundConstness) -> I::Clause {
         self.map_bound(|trait_ref| {
-            ty::ClauseKind::HostEffect(HostEffectPredicate { trait_ref, host })
+            ty::ClauseKind::HostEffect(HostEffectPredicate { trait_ref, constness })
         })
         .upcast(cx)
     }
@@ -757,7 +757,7 @@ impl<I: Interner> fmt::Debug for NormalizesTo<I> {
 #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
 pub struct HostEffectPredicate<I: Interner> {
     pub trait_ref: ty::TraitRef<I>,
-    pub host: HostPolarity,
+    pub constness: BoundConstness,
 }
 
 impl<I: Interner> HostEffectPredicate<I> {
@@ -785,28 +785,8 @@ impl<I: Interner> ty::Binder<I, HostEffectPredicate<I>> {
     }
 
     #[inline]
-    pub fn host(self) -> HostPolarity {
-        self.skip_binder().host
-    }
-}
-
-#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
-#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
-#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
-pub enum HostPolarity {
-    /// May be called in const environments if the callee is const.
-    Maybe,
-    /// Always allowed to be called in const environments.
-    Const,
-}
-
-impl HostPolarity {
-    pub fn satisfies(self, goal: HostPolarity) -> bool {
-        match (self, goal) {
-            (HostPolarity::Const, HostPolarity::Const | HostPolarity::Maybe) => true,
-            (HostPolarity::Maybe, HostPolarity::Maybe) => true,
-            (HostPolarity::Maybe, HostPolarity::Const) => false,
-        }
+    pub fn constness(self) -> BoundConstness {
+        self.skip_binder().constness
     }
 }
 
@@ -831,8 +811,8 @@ pub struct CoercePredicate<I: Interner> {
     pub b: I::Ty,
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
-#[cfg_attr(feature = "nightly", derive(HashStable_NoContext, TyEncodable, TyDecodable))]
+#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
+#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
 pub enum BoundConstness {
     /// `Type: const Trait`
     ///
@@ -841,14 +821,22 @@ pub enum BoundConstness {
     /// `Type: ~const Trait`
     ///
     /// Requires resolving to const only when we are in a const context.
-    ConstIfConst,
+    Maybe,
 }
 
 impl BoundConstness {
+    pub fn satisfies(self, goal: BoundConstness) -> bool {
+        match (self, goal) {
+            (BoundConstness::Const, BoundConstness::Const | BoundConstness::Maybe) => true,
+            (BoundConstness::Maybe, BoundConstness::Maybe) => true,
+            (BoundConstness::Maybe, BoundConstness::Const) => false,
+        }
+    }
+
     pub fn as_str(self) -> &'static str {
         match self {
             Self::Const => "const",
-            Self::ConstIfConst => "~const",
+            Self::Maybe => "~const",
         }
     }
 }
@@ -857,14 +845,7 @@ impl fmt::Display for BoundConstness {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
             Self::Const => f.write_str("const"),
-            Self::ConstIfConst => f.write_str("~const"),
+            Self::Maybe => f.write_str("~const"),
         }
     }
 }
-
-impl<I> Lift<I> for BoundConstness {
-    type Lifted = BoundConstness;
-    fn lift_to_interner(self, _: I) -> Option<Self::Lifted> {
-        Some(self)
-    }
-}
diff --git a/compiler/rustc_type_ir/src/relate/combine.rs b/compiler/rustc_type_ir/src/relate/combine.rs
index 17a3912730f..53751f7711a 100644
--- a/compiler/rustc_type_ir/src/relate/combine.rs
+++ b/compiler/rustc_type_ir/src/relate/combine.rs
@@ -6,9 +6,9 @@ use super::{
 };
 use crate::error::TypeError;
 use crate::inherent::*;
-use crate::solve::{Goal, SolverMode};
+use crate::solve::Goal;
 use crate::visit::TypeVisitableExt as _;
-use crate::{self as ty, InferCtxtLike, Interner, Upcast};
+use crate::{self as ty, InferCtxtLike, Interner, TypingMode, Upcast};
 
 pub trait PredicateEmittingRelation<Infcx, I = <Infcx as InferCtxtLike>::Interner>:
     TypeRelation<I>
@@ -128,19 +128,19 @@ where
         }
 
         (ty::Alias(ty::Opaque, _), _) | (_, ty::Alias(ty::Opaque, _)) => {
-            match infcx.solver_mode() {
-                SolverMode::Normal => {
-                    assert!(!infcx.next_trait_solver());
-                    structurally_relate_tys(relation, a, b)
-                }
+            assert!(!infcx.next_trait_solver());
+            match infcx.typing_mode(relation.param_env()) {
                 // During coherence, opaque types should be treated as *possibly*
-                // equal to any other type (except for possibly itinfcx). This is an
+                // equal to any other type. This is an
                 // extremely heavy hammer, but can be relaxed in a forwards-compatible
                 // way later.
-                SolverMode::Coherence => {
+                TypingMode::Coherence => {
                     relation.register_predicates([ty::Binder::dummy(ty::PredicateKind::Ambiguous)]);
                     Ok(a)
                 }
+                TypingMode::Analysis { .. } | TypingMode::PostAnalysis => {
+                    structurally_relate_tys(relation, a, b)
+                }
             }
         }
 
diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs
index 3fd2bb61ba5..5010fc09adc 100644
--- a/compiler/rustc_type_ir/src/search_graph/mod.rs
+++ b/compiler/rustc_type_ir/src/search_graph/mod.rs
@@ -22,7 +22,6 @@ use rustc_index::{Idx, IndexVec};
 use tracing::debug;
 
 use crate::data_structures::HashMap;
-use crate::solve::SolverMode;
 
 mod global_cache;
 use global_cache::CacheData;
@@ -48,11 +47,7 @@ pub trait Cx: Copy {
     fn get_tracked<T: Debug + Clone>(self, tracked: &Self::Tracked<T>) -> T;
     fn with_cached_task<T>(self, task: impl FnOnce() -> T) -> (T, Self::DepNodeIndex);
 
-    fn with_global_cache<R>(
-        self,
-        mode: SolverMode,
-        f: impl FnOnce(&mut GlobalCache<Self>) -> R,
-    ) -> R;
+    fn with_global_cache<R>(self, f: impl FnOnce(&mut GlobalCache<Self>) -> R) -> R;
 
     fn evaluation_is_concurrent(&self) -> bool;
 }
@@ -358,7 +353,6 @@ struct ProvisionalCacheEntry<X: Cx> {
 }
 
 pub struct SearchGraph<D: Delegate<Cx = X>, X: Cx = <D as Delegate>::Cx> {
-    mode: SolverMode,
     root_depth: AvailableDepth,
     /// The stack of goals currently being computed.
     ///
@@ -374,9 +368,8 @@ pub struct SearchGraph<D: Delegate<Cx = X>, X: Cx = <D as Delegate>::Cx> {
 }
 
 impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
-    pub fn new(mode: SolverMode, root_depth: usize) -> SearchGraph<D> {
+    pub fn new(root_depth: usize) -> SearchGraph<D> {
         Self {
-            mode,
             root_depth: AvailableDepth(root_depth),
             stack: Default::default(),
             provisional_cache: Default::default(),
@@ -384,10 +377,6 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
         }
     }
 
-    pub fn solver_mode(&self) -> SolverMode {
-        self.mode
-    }
-
     /// Lazily update the stack entry for the parent goal.
     /// This behavior is shared between actually evaluating goals
     /// and using existing global cache entries to make sure they
@@ -829,7 +818,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
         input: X::Input,
         available_depth: AvailableDepth,
     ) -> Option<X::Result> {
-        cx.with_global_cache(self.mode, |cache| {
+        cx.with_global_cache(|cache| {
             cache
                 .get(cx, input, available_depth, |nested_goals| {
                     Self::candidate_is_applicable(
@@ -852,7 +841,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
         input: X::Input,
         available_depth: AvailableDepth,
     ) -> Option<X::Result> {
-        cx.with_global_cache(self.mode, |cache| {
+        cx.with_global_cache(|cache| {
             let CacheData { result, additional_depth, encountered_overflow, nested_goals } = cache
                 .get(cx, input, available_depth, |nested_goals| {
                     Self::candidate_is_applicable(
@@ -1041,7 +1030,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
     ) {
         let additional_depth = final_entry.reached_depth.as_usize() - self.stack.len();
         debug!(?final_entry, ?result, "insert global cache");
-        cx.with_global_cache(self.mode, |cache| {
+        cx.with_global_cache(|cache| {
             cache.insert(
                 cx,
                 input,
diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs
index b3f8390bbf0..fe455873051 100644
--- a/compiler/rustc_type_ir/src/solve/mod.rs
+++ b/compiler/rustc_type_ir/src/solve/mod.rs
@@ -58,19 +58,6 @@ pub enum Reveal {
     All,
 }
 
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub enum SolverMode {
-    /// Ordinary trait solving, using everywhere except for coherence.
-    Normal,
-    /// Trait solving during coherence. There are a few notable differences
-    /// between coherence and ordinary trait solving.
-    ///
-    /// Most importantly, trait solving during coherence must not be incomplete,
-    /// i.e. return `Err(NoSolution)` for goals for which a solution exists.
-    /// This means that we must not make any guesses or arbitrary choices.
-    Coherence,
-}
-
 pub type CanonicalInput<I, T = <I as Interner>::Predicate> =
     ty::CanonicalQueryInput<I, QueryInput<I, T>>;
 pub type CanonicalResponse<I> = Canonical<I, Response<I>>;
diff --git a/config.example.toml b/config.example.toml
index d5b904ebf3d..9072a83551a 100644
--- a/config.example.toml
+++ b/config.example.toml
@@ -497,11 +497,12 @@
 #debug = false
 
 # Whether to download the stage 1 and 2 compilers from CI.
-# This is mostly useful for tools; if you have changes to `compiler/` or `library/` they will be ignored.
+# This is useful if you are working on tools, doc-comments, or library (you will be able to build
+# the standard library without needing to build the compiler).
 #
-# Set this to "if-unchanged" to only download if the compiler and standard library have not been modified.
-# Set this to `true` to download unconditionally. This is useful if you are working on tools, doc-comments,
-# or library (you will be able to build the standard library without needing to build the compiler).
+# Set this to "if-unchanged" to only download if the compiler (and library if running on CI) have
+# not been modified.
+# Set this to `true` to download unconditionally.
 #download-rustc = false
 
 # Number of codegen units to use for each compiler invocation. A value of 0
diff --git a/library/Cargo.lock b/library/Cargo.lock
index db60a484081..5defd2950e8 100644
--- a/library/Cargo.lock
+++ b/library/Cargo.lock
@@ -61,9 +61,9 @@ dependencies = [
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.134"
+version = "0.1.136"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f743e6f7410a78c261505c729f389583de40eec62332cc8cdf2c8b9bf73049a"
+checksum = "33ccee9dd499d7ada4c81533382ce87e88c52b0676c7320b2e617d29e1bb3a3f"
 dependencies = [
  "cc",
  "rustc-std-workspace-core",
diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml
index 6301ade2775..a9c375b62bd 100644
--- a/library/alloc/Cargo.toml
+++ b/library/alloc/Cargo.toml
@@ -10,7 +10,7 @@ edition = "2021"
 
 [dependencies]
 core = { path = "../core" }
-compiler_builtins = { version = "0.1.134", features = ['rustc-dep-of-std'] }
+compiler_builtins = { version = "0.1.136", features = ['rustc-dep-of-std'] }
 
 [dev-dependencies]
 rand = { version = "0.8.5", default-features = false, features = ["alloc"] }
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index bc354650a8e..e4956c7c53c 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -183,15 +183,14 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use core::any::Any;
-use core::async_iter::AsyncIterator;
+use core::borrow::{Borrow, BorrowMut};
 #[cfg(not(no_global_oom_handling))]
 use core::clone::CloneToUninit;
 use core::cmp::Ordering;
-use core::error::Error;
+use core::error::{self, Error};
+use core::fmt;
 use core::future::Future;
 use core::hash::{Hash, Hasher};
-use core::iter::FusedIterator;
 use core::marker::{Tuple, Unsize};
 use core::mem::{self, SizedTypeProperties};
 use core::ops::{
@@ -201,27 +200,24 @@ use core::ops::{
 use core::pin::{Pin, PinCoerceUnsized};
 use core::ptr::{self, NonNull, Unique};
 use core::task::{Context, Poll};
-use core::{borrow, fmt, slice};
-
-#[unstable(feature = "thin_box", issue = "92791")]
-pub use thin::ThinBox;
 
 #[cfg(not(no_global_oom_handling))]
 use crate::alloc::handle_alloc_error;
 use crate::alloc::{AllocError, Allocator, Global, Layout};
-#[cfg(not(no_global_oom_handling))]
-use crate::borrow::Cow;
 use crate::raw_vec::RawVec;
 #[cfg(not(no_global_oom_handling))]
 use crate::str::from_boxed_utf8_unchecked;
-#[cfg(not(no_global_oom_handling))]
-use crate::string::String;
-use crate::vec;
-#[cfg(not(no_global_oom_handling))]
-use crate::vec::Vec;
 
+/// Conversion related impls for `Box<_>` (`From`, `downcast`, etc)
+mod convert;
+/// Iterator related impls for `Box<_>`.
+mod iter;
+/// [`ThinBox`] implementation.
 mod thin;
 
+#[unstable(feature = "thin_box", issue = "92791")]
+pub use thin::ThinBox;
+
 /// A pointer type that uniquely owns a heap allocation of type `T`.
 ///
 /// See the [module-level documentation](../../std/boxed/index.html) for more.
@@ -1768,6 +1764,41 @@ impl<T: Clone, A: Allocator + Clone> Clone for Box<T, A> {
 
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "box_slice_clone", since = "1.3.0")]
+impl<T: Clone, A: Allocator + Clone> Clone for Box<[T], A> {
+    fn clone(&self) -> Self {
+        let alloc = Box::allocator(self).clone();
+        self.to_vec_in(alloc).into_boxed_slice()
+    }
+
+    /// Copies `source`'s contents into `self` without creating a new allocation,
+    /// so long as the two are of the same length.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = Box::new([5, 6, 7]);
+    /// let mut y = Box::new([8, 9, 10]);
+    /// let yp: *const [i32] = &*y;
+    ///
+    /// y.clone_from(&x);
+    ///
+    /// // The value is the same
+    /// assert_eq!(x, y);
+    ///
+    /// // And no allocation occurred
+    /// assert_eq!(yp, &*y);
+    /// ```
+    fn clone_from(&mut self, source: &Self) {
+        if self.len() == source.len() {
+            self.clone_from_slice(&source);
+        } else {
+            *self = source.clone();
+        }
+    }
+}
+
+#[cfg(not(no_global_oom_handling))]
+#[stable(feature = "box_slice_clone", since = "1.3.0")]
 impl Clone for Box<str> {
     fn clone(&self) -> Self {
         // this makes a copy of the data
@@ -1787,6 +1818,7 @@ impl<T: ?Sized + PartialEq, A: Allocator> PartialEq for Box<T, A> {
         PartialEq::ne(&**self, &**other)
     }
 }
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized + PartialOrd, A: Allocator> PartialOrd for Box<T, A> {
     #[inline]
@@ -1810,6 +1842,7 @@ impl<T: ?Sized + PartialOrd, A: Allocator> PartialOrd for Box<T, A> {
         PartialOrd::gt(&**self, &**other)
     }
 }
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized + Ord, A: Allocator> Ord for Box<T, A> {
     #[inline]
@@ -1817,6 +1850,7 @@ impl<T: ?Sized + Ord, A: Allocator> Ord for Box<T, A> {
         Ord::cmp(&**self, &**other)
     }
 }
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized + Eq, A: Allocator> Eq for Box<T, A> {}
 
@@ -1879,462 +1913,6 @@ impl<T: ?Sized + Hasher, A: Allocator> Hasher for Box<T, A> {
     }
 }
 
-#[cfg(not(no_global_oom_handling))]
-#[stable(feature = "from_for_ptrs", since = "1.6.0")]
-impl<T> From<T> for Box<T> {
-    /// Converts a `T` into a `Box<T>`
-    ///
-    /// The conversion allocates on the heap and moves `t`
-    /// from the stack into it.
-    ///
-    /// # Examples
-    ///
-    /// ```rust
-    /// let x = 5;
-    /// let boxed = Box::new(5);
-    ///
-    /// assert_eq!(Box::from(x), boxed);
-    /// ```
-    fn from(t: T) -> Self {
-        Box::new(t)
-    }
-}
-
-#[stable(feature = "pin", since = "1.33.0")]
-impl<T: ?Sized, A: Allocator> From<Box<T, A>> for Pin<Box<T, A>>
-where
-    A: 'static,
-{
-    /// Converts a `Box<T>` into a `Pin<Box<T>>`. If `T` does not implement [`Unpin`], then
-    /// `*boxed` will be pinned in memory and unable to be moved.
-    ///
-    /// This conversion does not allocate on the heap and happens in place.
-    ///
-    /// This is also available via [`Box::into_pin`].
-    ///
-    /// Constructing and pinning a `Box` with <code><Pin<Box\<T>>>::from([Box::new]\(x))</code>
-    /// can also be written more concisely using <code>[Box::pin]\(x)</code>.
-    /// This `From` implementation is useful if you already have a `Box<T>`, or you are
-    /// constructing a (pinned) `Box` in a different way than with [`Box::new`].
-    fn from(boxed: Box<T, A>) -> Self {
-        Box::into_pin(boxed)
-    }
-}
-
-/// Specialization trait used for `From<&[T]>`.
-#[cfg(not(no_global_oom_handling))]
-trait BoxFromSlice<T> {
-    fn from_slice(slice: &[T]) -> Self;
-}
-
-#[cfg(not(no_global_oom_handling))]
-impl<T: Clone> BoxFromSlice<T> for Box<[T]> {
-    #[inline]
-    default fn from_slice(slice: &[T]) -> Self {
-        slice.to_vec().into_boxed_slice()
-    }
-}
-
-#[cfg(not(no_global_oom_handling))]
-impl<T: Copy> BoxFromSlice<T> for Box<[T]> {
-    #[inline]
-    fn from_slice(slice: &[T]) -> Self {
-        let len = slice.len();
-        let buf = RawVec::with_capacity(len);
-        unsafe {
-            ptr::copy_nonoverlapping(slice.as_ptr(), buf.ptr(), len);
-            buf.into_box(slice.len()).assume_init()
-        }
-    }
-}
-
-#[cfg(not(no_global_oom_handling))]
-#[stable(feature = "box_from_slice", since = "1.17.0")]
-impl<T: Clone> From<&[T]> for Box<[T]> {
-    /// Converts a `&[T]` into a `Box<[T]>`
-    ///
-    /// This conversion allocates on the heap
-    /// and performs a copy of `slice` and its contents.
-    ///
-    /// # Examples
-    /// ```rust
-    /// // create a &[u8] which will be used to create a Box<[u8]>
-    /// let slice: &[u8] = &[104, 101, 108, 108, 111];
-    /// let boxed_slice: Box<[u8]> = Box::from(slice);
-    ///
-    /// println!("{boxed_slice:?}");
-    /// ```
-    #[inline]
-    fn from(slice: &[T]) -> Box<[T]> {
-        <Self as BoxFromSlice<T>>::from_slice(slice)
-    }
-}
-
-#[cfg(not(no_global_oom_handling))]
-#[stable(feature = "box_from_cow", since = "1.45.0")]
-impl<T: Clone> From<Cow<'_, [T]>> for Box<[T]> {
-    /// Converts a `Cow<'_, [T]>` into a `Box<[T]>`
-    ///
-    /// When `cow` is the `Cow::Borrowed` variant, this
-    /// conversion allocates on the heap and copies the
-    /// underlying slice. Otherwise, it will try to reuse the owned
-    /// `Vec`'s allocation.
-    #[inline]
-    fn from(cow: Cow<'_, [T]>) -> Box<[T]> {
-        match cow {
-            Cow::Borrowed(slice) => Box::from(slice),
-            Cow::Owned(slice) => Box::from(slice),
-        }
-    }
-}
-
-#[cfg(not(no_global_oom_handling))]
-#[stable(feature = "box_from_slice", since = "1.17.0")]
-impl From<&str> for Box<str> {
-    /// Converts a `&str` into a `Box<str>`
-    ///
-    /// This conversion allocates on the heap
-    /// and performs a copy of `s`.
-    ///
-    /// # Examples
-    ///
-    /// ```rust
-    /// let boxed: Box<str> = Box::from("hello");
-    /// println!("{boxed}");
-    /// ```
-    #[inline]
-    fn from(s: &str) -> Box<str> {
-        unsafe { from_boxed_utf8_unchecked(Box::from(s.as_bytes())) }
-    }
-}
-
-#[cfg(not(no_global_oom_handling))]
-#[stable(feature = "box_from_cow", since = "1.45.0")]
-impl From<Cow<'_, str>> for Box<str> {
-    /// Converts a `Cow<'_, str>` into a `Box<str>`
-    ///
-    /// When `cow` is the `Cow::Borrowed` variant, this
-    /// conversion allocates on the heap and copies the
-    /// underlying `str`. Otherwise, it will try to reuse the owned
-    /// `String`'s allocation.
-    ///
-    /// # Examples
-    ///
-    /// ```rust
-    /// use std::borrow::Cow;
-    ///
-    /// let unboxed = Cow::Borrowed("hello");
-    /// let boxed: Box<str> = Box::from(unboxed);
-    /// println!("{boxed}");
-    /// ```
-    ///
-    /// ```rust
-    /// # use std::borrow::Cow;
-    /// let unboxed = Cow::Owned("hello".to_string());
-    /// let boxed: Box<str> = Box::from(unboxed);
-    /// println!("{boxed}");
-    /// ```
-    #[inline]
-    fn from(cow: Cow<'_, str>) -> Box<str> {
-        match cow {
-            Cow::Borrowed(s) => Box::from(s),
-            Cow::Owned(s) => Box::from(s),
-        }
-    }
-}
-
-#[stable(feature = "boxed_str_conv", since = "1.19.0")]
-impl<A: Allocator> From<Box<str, A>> for Box<[u8], A> {
-    /// Converts a `Box<str>` into a `Box<[u8]>`
-    ///
-    /// This conversion does not allocate on the heap and happens in place.
-    ///
-    /// # Examples
-    /// ```rust
-    /// // create a Box<str> which will be used to create a Box<[u8]>
-    /// let boxed: Box<str> = Box::from("hello");
-    /// let boxed_str: Box<[u8]> = Box::from(boxed);
-    ///
-    /// // create a &[u8] which will be used to create a Box<[u8]>
-    /// let slice: &[u8] = &[104, 101, 108, 108, 111];
-    /// let boxed_slice = Box::from(slice);
-    ///
-    /// assert_eq!(boxed_slice, boxed_str);
-    /// ```
-    #[inline]
-    fn from(s: Box<str, A>) -> Self {
-        let (raw, alloc) = Box::into_raw_with_allocator(s);
-        unsafe { Box::from_raw_in(raw as *mut [u8], alloc) }
-    }
-}
-
-#[cfg(not(no_global_oom_handling))]
-#[stable(feature = "box_from_array", since = "1.45.0")]
-impl<T, const N: usize> From<[T; N]> for Box<[T]> {
-    /// Converts a `[T; N]` into a `Box<[T]>`
-    ///
-    /// This conversion moves the array to newly heap-allocated memory.
-    ///
-    /// # Examples
-    ///
-    /// ```rust
-    /// let boxed: Box<[u8]> = Box::from([4, 2]);
-    /// println!("{boxed:?}");
-    /// ```
-    fn from(array: [T; N]) -> Box<[T]> {
-        Box::new(array)
-    }
-}
-
-/// Casts a boxed slice to a boxed array.
-///
-/// # Safety
-///
-/// `boxed_slice.len()` must be exactly `N`.
-unsafe fn boxed_slice_as_array_unchecked<T, A: Allocator, const N: usize>(
-    boxed_slice: Box<[T], A>,
-) -> Box<[T; N], A> {
-    debug_assert_eq!(boxed_slice.len(), N);
-
-    let (ptr, alloc) = Box::into_raw_with_allocator(boxed_slice);
-    // SAFETY: Pointer and allocator came from an existing box,
-    // and our safety condition requires that the length is exactly `N`
-    unsafe { Box::from_raw_in(ptr as *mut [T; N], alloc) }
-}
-
-#[stable(feature = "boxed_slice_try_from", since = "1.43.0")]
-impl<T, const N: usize> TryFrom<Box<[T]>> for Box<[T; N]> {
-    type Error = Box<[T]>;
-
-    /// Attempts to convert a `Box<[T]>` into a `Box<[T; N]>`.
-    ///
-    /// The conversion occurs in-place and does not require a
-    /// new memory allocation.
-    ///
-    /// # Errors
-    ///
-    /// Returns the old `Box<[T]>` in the `Err` variant if
-    /// `boxed_slice.len()` does not equal `N`.
-    fn try_from(boxed_slice: Box<[T]>) -> Result<Self, Self::Error> {
-        if boxed_slice.len() == N {
-            Ok(unsafe { boxed_slice_as_array_unchecked(boxed_slice) })
-        } else {
-            Err(boxed_slice)
-        }
-    }
-}
-
-#[cfg(not(no_global_oom_handling))]
-#[stable(feature = "boxed_array_try_from_vec", since = "1.66.0")]
-impl<T, const N: usize> TryFrom<Vec<T>> for Box<[T; N]> {
-    type Error = Vec<T>;
-
-    /// Attempts to convert a `Vec<T>` into a `Box<[T; N]>`.
-    ///
-    /// Like [`Vec::into_boxed_slice`], this is in-place if `vec.capacity() == N`,
-    /// but will require a reallocation otherwise.
-    ///
-    /// # Errors
-    ///
-    /// Returns the original `Vec<T>` in the `Err` variant if
-    /// `boxed_slice.len()` does not equal `N`.
-    ///
-    /// # Examples
-    ///
-    /// This can be used with [`vec!`] to create an array on the heap:
-    ///
-    /// ```
-    /// let state: Box<[f32; 100]> = vec![1.0; 100].try_into().unwrap();
-    /// assert_eq!(state.len(), 100);
-    /// ```
-    fn try_from(vec: Vec<T>) -> Result<Self, Self::Error> {
-        if vec.len() == N {
-            let boxed_slice = vec.into_boxed_slice();
-            Ok(unsafe { boxed_slice_as_array_unchecked(boxed_slice) })
-        } else {
-            Err(vec)
-        }
-    }
-}
-
-impl<A: Allocator> Box<dyn Any, A> {
-    /// Attempts to downcast the box to a concrete type.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::any::Any;
-    ///
-    /// fn print_if_string(value: Box<dyn Any>) {
-    ///     if let Ok(string) = value.downcast::<String>() {
-    ///         println!("String ({}): {}", string.len(), string);
-    ///     }
-    /// }
-    ///
-    /// let my_string = "Hello World".to_string();
-    /// print_if_string(Box::new(my_string));
-    /// print_if_string(Box::new(0i8));
-    /// ```
-    #[inline]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn downcast<T: Any>(self) -> Result<Box<T, A>, Self> {
-        if self.is::<T>() { unsafe { Ok(self.downcast_unchecked::<T>()) } } else { Err(self) }
-    }
-
-    /// Downcasts the box to a concrete type.
-    ///
-    /// For a safe alternative see [`downcast`].
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(downcast_unchecked)]
-    ///
-    /// use std::any::Any;
-    ///
-    /// let x: Box<dyn Any> = Box::new(1_usize);
-    ///
-    /// unsafe {
-    ///     assert_eq!(*x.downcast_unchecked::<usize>(), 1);
-    /// }
-    /// ```
-    ///
-    /// # Safety
-    ///
-    /// The contained value must be of type `T`. Calling this method
-    /// with the incorrect type is *undefined behavior*.
-    ///
-    /// [`downcast`]: Self::downcast
-    #[inline]
-    #[unstable(feature = "downcast_unchecked", issue = "90850")]
-    pub unsafe fn downcast_unchecked<T: Any>(self) -> Box<T, A> {
-        debug_assert!(self.is::<T>());
-        unsafe {
-            let (raw, alloc): (*mut dyn Any, _) = Box::into_raw_with_allocator(self);
-            Box::from_raw_in(raw as *mut T, alloc)
-        }
-    }
-}
-
-impl<A: Allocator> Box<dyn Any + Send, A> {
-    /// Attempts to downcast the box to a concrete type.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::any::Any;
-    ///
-    /// fn print_if_string(value: Box<dyn Any + Send>) {
-    ///     if let Ok(string) = value.downcast::<String>() {
-    ///         println!("String ({}): {}", string.len(), string);
-    ///     }
-    /// }
-    ///
-    /// let my_string = "Hello World".to_string();
-    /// print_if_string(Box::new(my_string));
-    /// print_if_string(Box::new(0i8));
-    /// ```
-    #[inline]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn downcast<T: Any>(self) -> Result<Box<T, A>, Self> {
-        if self.is::<T>() { unsafe { Ok(self.downcast_unchecked::<T>()) } } else { Err(self) }
-    }
-
-    /// Downcasts the box to a concrete type.
-    ///
-    /// For a safe alternative see [`downcast`].
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(downcast_unchecked)]
-    ///
-    /// use std::any::Any;
-    ///
-    /// let x: Box<dyn Any + Send> = Box::new(1_usize);
-    ///
-    /// unsafe {
-    ///     assert_eq!(*x.downcast_unchecked::<usize>(), 1);
-    /// }
-    /// ```
-    ///
-    /// # Safety
-    ///
-    /// The contained value must be of type `T`. Calling this method
-    /// with the incorrect type is *undefined behavior*.
-    ///
-    /// [`downcast`]: Self::downcast
-    #[inline]
-    #[unstable(feature = "downcast_unchecked", issue = "90850")]
-    pub unsafe fn downcast_unchecked<T: Any>(self) -> Box<T, A> {
-        debug_assert!(self.is::<T>());
-        unsafe {
-            let (raw, alloc): (*mut (dyn Any + Send), _) = Box::into_raw_with_allocator(self);
-            Box::from_raw_in(raw as *mut T, alloc)
-        }
-    }
-}
-
-impl<A: Allocator> Box<dyn Any + Send + Sync, A> {
-    /// Attempts to downcast the box to a concrete type.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::any::Any;
-    ///
-    /// fn print_if_string(value: Box<dyn Any + Send + Sync>) {
-    ///     if let Ok(string) = value.downcast::<String>() {
-    ///         println!("String ({}): {}", string.len(), string);
-    ///     }
-    /// }
-    ///
-    /// let my_string = "Hello World".to_string();
-    /// print_if_string(Box::new(my_string));
-    /// print_if_string(Box::new(0i8));
-    /// ```
-    #[inline]
-    #[stable(feature = "box_send_sync_any_downcast", since = "1.51.0")]
-    pub fn downcast<T: Any>(self) -> Result<Box<T, A>, Self> {
-        if self.is::<T>() { unsafe { Ok(self.downcast_unchecked::<T>()) } } else { Err(self) }
-    }
-
-    /// Downcasts the box to a concrete type.
-    ///
-    /// For a safe alternative see [`downcast`].
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(downcast_unchecked)]
-    ///
-    /// use std::any::Any;
-    ///
-    /// let x: Box<dyn Any + Send + Sync> = Box::new(1_usize);
-    ///
-    /// unsafe {
-    ///     assert_eq!(*x.downcast_unchecked::<usize>(), 1);
-    /// }
-    /// ```
-    ///
-    /// # Safety
-    ///
-    /// The contained value must be of type `T`. Calling this method
-    /// with the incorrect type is *undefined behavior*.
-    ///
-    /// [`downcast`]: Self::downcast
-    #[inline]
-    #[unstable(feature = "downcast_unchecked", issue = "90850")]
-    pub unsafe fn downcast_unchecked<T: Any>(self) -> Box<T, A> {
-        debug_assert!(self.is::<T>());
-        unsafe {
-            let (raw, alloc): (*mut (dyn Any + Send + Sync), _) =
-                Box::into_raw_with_allocator(self);
-            Box::from_raw_in(raw as *mut T, alloc)
-        }
-    }
-}
-
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: fmt::Display + ?Sized, A: Allocator> fmt::Display for Box<T, A> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -2381,71 +1959,6 @@ unsafe impl<T: ?Sized, A: Allocator> DerefPure for Box<T, A> {}
 #[unstable(feature = "legacy_receiver_trait", issue = "none")]
 impl<T: ?Sized, A: Allocator> LegacyReceiver for Box<T, A> {}
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<I: Iterator + ?Sized, A: Allocator> Iterator for Box<I, A> {
-    type Item = I::Item;
-    fn next(&mut self) -> Option<I::Item> {
-        (**self).next()
-    }
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        (**self).size_hint()
-    }
-    fn nth(&mut self, n: usize) -> Option<I::Item> {
-        (**self).nth(n)
-    }
-    fn last(self) -> Option<I::Item> {
-        BoxIter::last(self)
-    }
-}
-
-trait BoxIter {
-    type Item;
-    fn last(self) -> Option<Self::Item>;
-}
-
-impl<I: Iterator + ?Sized, A: Allocator> BoxIter for Box<I, A> {
-    type Item = I::Item;
-    default fn last(self) -> Option<I::Item> {
-        #[inline]
-        fn some<T>(_: Option<T>, x: T) -> Option<T> {
-            Some(x)
-        }
-
-        self.fold(None, some)
-    }
-}
-
-/// Specialization for sized `I`s that uses `I`s implementation of `last()`
-/// instead of the default.
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<I: Iterator, A: Allocator> BoxIter for Box<I, A> {
-    fn last(self) -> Option<I::Item> {
-        (*self).last()
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<I: DoubleEndedIterator + ?Sized, A: Allocator> DoubleEndedIterator for Box<I, A> {
-    fn next_back(&mut self) -> Option<I::Item> {
-        (**self).next_back()
-    }
-    fn nth_back(&mut self, n: usize) -> Option<I::Item> {
-        (**self).nth_back(n)
-    }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<I: ExactSizeIterator + ?Sized, A: Allocator> ExactSizeIterator for Box<I, A> {
-    fn len(&self) -> usize {
-        (**self).len()
-    }
-    fn is_empty(&self) -> bool {
-        (**self).is_empty()
-    }
-}
-
-#[stable(feature = "fused", since = "1.26.0")]
-impl<I: FusedIterator + ?Sized, A: Allocator> FusedIterator for Box<I, A> {}
-
 #[stable(feature = "boxed_closure_impls", since = "1.35.0")]
 impl<Args: Tuple, F: FnOnce<Args> + ?Sized, A: Allocator> FnOnce<Args> for Box<F, A> {
     type Output = <F as FnOnce<Args>>::Output;
@@ -2501,157 +2014,24 @@ impl<Args: Tuple, F: AsyncFn<Args> + ?Sized, A: Allocator> AsyncFn<Args> for Box
 #[unstable(feature = "coerce_unsized", issue = "18598")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Box<U, A>> for Box<T, A> {}
 
+#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
+unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for Box<T, A> {}
+
 // It is quite crucial that we only allow the `Global` allocator here.
 // Handling arbitrary custom allocators (which can affect the `Box` layout heavily!)
 // would need a lot of codegen and interpreter adjustments.
 #[unstable(feature = "dispatch_from_dyn", issue = "none")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Box<U>> for Box<T, Global> {}
 
-#[cfg(not(no_global_oom_handling))]
-#[stable(feature = "boxed_slice_from_iter", since = "1.32.0")]
-impl<I> FromIterator<I> for Box<[I]> {
-    fn from_iter<T: IntoIterator<Item = I>>(iter: T) -> Self {
-        iter.into_iter().collect::<Vec<_>>().into_boxed_slice()
-    }
-}
-
-/// This implementation is required to make sure that the `Box<[I]>: IntoIterator`
-/// implementation doesn't overlap with `IntoIterator for T where T: Iterator` blanket.
-#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")]
-impl<I, A: Allocator> !Iterator for Box<[I], A> {}
-
-/// This implementation is required to make sure that the `&Box<[I]>: IntoIterator`
-/// implementation doesn't overlap with `IntoIterator for T where T: Iterator` blanket.
-#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")]
-impl<'a, I, A: Allocator> !Iterator for &'a Box<[I], A> {}
-
-/// This implementation is required to make sure that the `&mut Box<[I]>: IntoIterator`
-/// implementation doesn't overlap with `IntoIterator for T where T: Iterator` blanket.
-#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")]
-impl<'a, I, A: Allocator> !Iterator for &'a mut Box<[I], A> {}
-
-// Note: the `#[rustc_skip_during_method_dispatch(boxed_slice)]` on `trait IntoIterator`
-// hides this implementation from explicit `.into_iter()` calls on editions < 2024,
-// so those calls will still resolve to the slice implementation, by reference.
-#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")]
-impl<I, A: Allocator> IntoIterator for Box<[I], A> {
-    type IntoIter = vec::IntoIter<I, A>;
-    type Item = I;
-    fn into_iter(self) -> vec::IntoIter<I, A> {
-        self.into_vec().into_iter()
-    }
-}
-
-#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")]
-impl<'a, I, A: Allocator> IntoIterator for &'a Box<[I], A> {
-    type IntoIter = slice::Iter<'a, I>;
-    type Item = &'a I;
-    fn into_iter(self) -> slice::Iter<'a, I> {
-        self.iter()
-    }
-}
-
-#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")]
-impl<'a, I, A: Allocator> IntoIterator for &'a mut Box<[I], A> {
-    type IntoIter = slice::IterMut<'a, I>;
-    type Item = &'a mut I;
-    fn into_iter(self) -> slice::IterMut<'a, I> {
-        self.iter_mut()
-    }
-}
-
-#[cfg(not(no_global_oom_handling))]
-#[stable(feature = "boxed_str_from_iter", since = "1.80.0")]
-impl FromIterator<char> for Box<str> {
-    fn from_iter<T: IntoIterator<Item = char>>(iter: T) -> Self {
-        String::from_iter(iter).into_boxed_str()
-    }
-}
-
-#[cfg(not(no_global_oom_handling))]
-#[stable(feature = "boxed_str_from_iter", since = "1.80.0")]
-impl<'a> FromIterator<&'a char> for Box<str> {
-    fn from_iter<T: IntoIterator<Item = &'a char>>(iter: T) -> Self {
-        String::from_iter(iter).into_boxed_str()
-    }
-}
-
-#[cfg(not(no_global_oom_handling))]
-#[stable(feature = "boxed_str_from_iter", since = "1.80.0")]
-impl<'a> FromIterator<&'a str> for Box<str> {
-    fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> Self {
-        String::from_iter(iter).into_boxed_str()
-    }
-}
-
-#[cfg(not(no_global_oom_handling))]
-#[stable(feature = "boxed_str_from_iter", since = "1.80.0")]
-impl FromIterator<String> for Box<str> {
-    fn from_iter<T: IntoIterator<Item = String>>(iter: T) -> Self {
-        String::from_iter(iter).into_boxed_str()
-    }
-}
-
-#[cfg(not(no_global_oom_handling))]
-#[stable(feature = "boxed_str_from_iter", since = "1.80.0")]
-impl<A: Allocator> FromIterator<Box<str, A>> for Box<str> {
-    fn from_iter<T: IntoIterator<Item = Box<str, A>>>(iter: T) -> Self {
-        String::from_iter(iter).into_boxed_str()
-    }
-}
-
-#[cfg(not(no_global_oom_handling))]
-#[stable(feature = "boxed_str_from_iter", since = "1.80.0")]
-impl<'a> FromIterator<Cow<'a, str>> for Box<str> {
-    fn from_iter<T: IntoIterator<Item = Cow<'a, str>>>(iter: T) -> Self {
-        String::from_iter(iter).into_boxed_str()
-    }
-}
-
-#[cfg(not(no_global_oom_handling))]
-#[stable(feature = "box_slice_clone", since = "1.3.0")]
-impl<T: Clone, A: Allocator + Clone> Clone for Box<[T], A> {
-    fn clone(&self) -> Self {
-        let alloc = Box::allocator(self).clone();
-        self.to_vec_in(alloc).into_boxed_slice()
-    }
-
-    /// Copies `source`'s contents into `self` without creating a new allocation,
-    /// so long as the two are of the same length.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let x = Box::new([5, 6, 7]);
-    /// let mut y = Box::new([8, 9, 10]);
-    /// let yp: *const [i32] = &*y;
-    ///
-    /// y.clone_from(&x);
-    ///
-    /// // The value is the same
-    /// assert_eq!(x, y);
-    ///
-    /// // And no allocation occurred
-    /// assert_eq!(yp, &*y);
-    /// ```
-    fn clone_from(&mut self, source: &Self) {
-        if self.len() == source.len() {
-            self.clone_from_slice(&source);
-        } else {
-            *self = source.clone();
-        }
-    }
-}
-
 #[stable(feature = "box_borrow", since = "1.1.0")]
-impl<T: ?Sized, A: Allocator> borrow::Borrow<T> for Box<T, A> {
+impl<T: ?Sized, A: Allocator> Borrow<T> for Box<T, A> {
     fn borrow(&self) -> &T {
         &**self
     }
 }
 
 #[stable(feature = "box_borrow", since = "1.1.0")]
-impl<T: ?Sized, A: Allocator> borrow::BorrowMut<T> for Box<T, A> {
+impl<T: ?Sized, A: Allocator> BorrowMut<T> for Box<T, A> {
     fn borrow_mut(&mut self) -> &mut T {
         &mut **self
     }
@@ -2728,311 +2108,23 @@ impl<F: ?Sized + Future + Unpin, A: Allocator> Future for Box<F, A> {
     }
 }
 
-#[unstable(feature = "async_iterator", issue = "79024")]
-impl<S: ?Sized + AsyncIterator + Unpin> AsyncIterator for Box<S> {
-    type Item = S::Item;
-
-    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
-        Pin::new(&mut **self).poll_next(cx)
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        (**self).size_hint()
-    }
-}
-
-impl dyn Error {
-    #[inline]
-    #[stable(feature = "error_downcast", since = "1.3.0")]
-    #[rustc_allow_incoherent_impl]
-    /// Attempts to downcast the box to a concrete type.
-    pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error>> {
-        if self.is::<T>() {
-            unsafe {
-                let raw: *mut dyn Error = Box::into_raw(self);
-                Ok(Box::from_raw(raw as *mut T))
-            }
-        } else {
-            Err(self)
-        }
-    }
-}
-
-impl dyn Error + Send {
-    #[inline]
-    #[stable(feature = "error_downcast", since = "1.3.0")]
-    #[rustc_allow_incoherent_impl]
-    /// Attempts to downcast the box to a concrete type.
-    pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error + Send>> {
-        let err: Box<dyn Error> = self;
-        <dyn Error>::downcast(err).map_err(|s| unsafe {
-            // Reapply the `Send` marker.
-            mem::transmute::<Box<dyn Error>, Box<dyn Error + Send>>(s)
-        })
-    }
-}
-
-impl dyn Error + Send + Sync {
-    #[inline]
-    #[stable(feature = "error_downcast", since = "1.3.0")]
-    #[rustc_allow_incoherent_impl]
-    /// Attempts to downcast the box to a concrete type.
-    pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<Self>> {
-        let err: Box<dyn Error> = self;
-        <dyn Error>::downcast(err).map_err(|s| unsafe {
-            // Reapply the `Send + Sync` markers.
-            mem::transmute::<Box<dyn Error>, Box<dyn Error + Send + Sync>>(s)
-        })
-    }
-}
-
-#[cfg(not(no_global_oom_handling))]
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, E: Error + 'a> From<E> for Box<dyn Error + 'a> {
-    /// Converts a type of [`Error`] into a box of dyn [`Error`].
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::error::Error;
-    /// use std::fmt;
-    /// use std::mem;
-    ///
-    /// #[derive(Debug)]
-    /// struct AnError;
-    ///
-    /// impl fmt::Display for AnError {
-    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-    ///         write!(f, "An error")
-    ///     }
-    /// }
-    ///
-    /// impl Error for AnError {}
-    ///
-    /// let an_error = AnError;
-    /// assert!(0 == mem::size_of_val(&an_error));
-    /// let a_boxed_error = Box::<dyn Error>::from(an_error);
-    /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
-    /// ```
-    fn from(err: E) -> Box<dyn Error + 'a> {
-        Box::new(err)
-    }
-}
-
-#[cfg(not(no_global_oom_handling))]
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync + 'a> {
-    /// Converts a type of [`Error`] + [`Send`] + [`Sync`] into a box of
-    /// dyn [`Error`] + [`Send`] + [`Sync`].
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::error::Error;
-    /// use std::fmt;
-    /// use std::mem;
-    ///
-    /// #[derive(Debug)]
-    /// struct AnError;
-    ///
-    /// impl fmt::Display for AnError {
-    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-    ///         write!(f, "An error")
-    ///     }
-    /// }
-    ///
-    /// impl Error for AnError {}
-    ///
-    /// unsafe impl Send for AnError {}
-    ///
-    /// unsafe impl Sync for AnError {}
-    ///
-    /// let an_error = AnError;
-    /// assert!(0 == mem::size_of_val(&an_error));
-    /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(an_error);
-    /// assert!(
-    ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
-    /// ```
-    fn from(err: E) -> Box<dyn Error + Send + Sync + 'a> {
-        Box::new(err)
-    }
-}
-
-#[cfg(not(no_global_oom_handling))]
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a> From<String> for Box<dyn Error + Send + Sync + 'a> {
-    /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::error::Error;
-    /// use std::mem;
-    ///
-    /// let a_string_error = "a string error".to_string();
-    /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(a_string_error);
-    /// assert!(
-    ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
-    /// ```
-    #[inline]
-    fn from(err: String) -> Box<dyn Error + Send + Sync + 'a> {
-        struct StringError(String);
-
-        impl Error for StringError {
-            #[allow(deprecated)]
-            fn description(&self) -> &str {
-                &self.0
-            }
-        }
-
-        impl fmt::Display for StringError {
-            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-                fmt::Display::fmt(&self.0, f)
-            }
-        }
-
-        // Purposefully skip printing "StringError(..)"
-        impl fmt::Debug for StringError {
-            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-                fmt::Debug::fmt(&self.0, f)
-            }
-        }
-
-        Box::new(StringError(err))
-    }
-}
-
-#[cfg(not(no_global_oom_handling))]
-#[stable(feature = "string_box_error", since = "1.6.0")]
-impl<'a> From<String> for Box<dyn Error + 'a> {
-    /// Converts a [`String`] into a box of dyn [`Error`].
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::error::Error;
-    /// use std::mem;
-    ///
-    /// let a_string_error = "a string error".to_string();
-    /// let a_boxed_error = Box::<dyn Error>::from(a_string_error);
-    /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
-    /// ```
-    fn from(str_err: String) -> Box<dyn Error + 'a> {
-        let err1: Box<dyn Error + Send + Sync> = From::from(str_err);
-        let err2: Box<dyn Error> = err1;
-        err2
-    }
-}
-
-#[cfg(not(no_global_oom_handling))]
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a> From<&str> for Box<dyn Error + Send + Sync + 'a> {
-    /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
-    ///
-    /// [`str`]: prim@str
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::error::Error;
-    /// use std::mem;
-    ///
-    /// let a_str_error = "a str error";
-    /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(a_str_error);
-    /// assert!(
-    ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
-    /// ```
-    #[inline]
-    fn from(err: &str) -> Box<dyn Error + Send + Sync + 'a> {
-        From::from(String::from(err))
-    }
-}
-
-#[cfg(not(no_global_oom_handling))]
-#[stable(feature = "string_box_error", since = "1.6.0")]
-impl<'a> From<&str> for Box<dyn Error + 'a> {
-    /// Converts a [`str`] into a box of dyn [`Error`].
-    ///
-    /// [`str`]: prim@str
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::error::Error;
-    /// use std::mem;
-    ///
-    /// let a_str_error = "a str error";
-    /// let a_boxed_error = Box::<dyn Error>::from(a_str_error);
-    /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
-    /// ```
-    fn from(err: &str) -> Box<dyn Error + 'a> {
-        From::from(String::from(err))
-    }
-}
-
-#[cfg(not(no_global_oom_handling))]
-#[stable(feature = "cow_box_error", since = "1.22.0")]
-impl<'a, 'b> From<Cow<'b, str>> for Box<dyn Error + Send + Sync + 'a> {
-    /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::error::Error;
-    /// use std::mem;
-    /// use std::borrow::Cow;
-    ///
-    /// let a_cow_str_error = Cow::from("a str error");
-    /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(a_cow_str_error);
-    /// assert!(
-    ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
-    /// ```
-    fn from(err: Cow<'b, str>) -> Box<dyn Error + Send + Sync + 'a> {
-        From::from(String::from(err))
-    }
-}
-
-#[cfg(not(no_global_oom_handling))]
-#[stable(feature = "cow_box_error", since = "1.22.0")]
-impl<'a, 'b> From<Cow<'b, str>> for Box<dyn Error + 'a> {
-    /// Converts a [`Cow`] into a box of dyn [`Error`].
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::error::Error;
-    /// use std::mem;
-    /// use std::borrow::Cow;
-    ///
-    /// let a_cow_str_error = Cow::from("a str error");
-    /// let a_boxed_error = Box::<dyn Error>::from(a_cow_str_error);
-    /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
-    /// ```
-    fn from(err: Cow<'b, str>) -> Box<dyn Error + 'a> {
-        From::from(String::from(err))
-    }
-}
-
 #[stable(feature = "box_error", since = "1.8.0")]
-impl<T: core::error::Error> core::error::Error for Box<T> {
+impl<E: Error> Error for Box<E> {
     #[allow(deprecated, deprecated_in_future)]
     fn description(&self) -> &str {
-        core::error::Error::description(&**self)
+        Error::description(&**self)
     }
 
     #[allow(deprecated)]
-    fn cause(&self) -> Option<&dyn core::error::Error> {
-        core::error::Error::cause(&**self)
+    fn cause(&self) -> Option<&dyn Error> {
+        Error::cause(&**self)
     }
 
-    fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
-        core::error::Error::source(&**self)
+    fn source(&self) -> Option<&(dyn Error + 'static)> {
+        Error::source(&**self)
     }
 
-    fn provide<'b>(&'b self, request: &mut core::error::Request<'b>) {
-        core::error::Error::provide(&**self, request);
+    fn provide<'b>(&'b self, request: &mut error::Request<'b>) {
+        Error::provide(&**self, request);
     }
 }
-
-#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
-unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for Box<T, A> {}
diff --git a/library/alloc/src/boxed/convert.rs b/library/alloc/src/boxed/convert.rs
new file mode 100644
index 00000000000..19a583ca546
--- /dev/null
+++ b/library/alloc/src/boxed/convert.rs
@@ -0,0 +1,747 @@
+use core::any::Any;
+use core::error::Error;
+use core::mem;
+use core::pin::Pin;
+#[cfg(not(no_global_oom_handling))]
+use core::{fmt, ptr};
+
+use crate::alloc::Allocator;
+#[cfg(not(no_global_oom_handling))]
+use crate::borrow::Cow;
+use crate::boxed::Box;
+#[cfg(not(no_global_oom_handling))]
+use crate::raw_vec::RawVec;
+#[cfg(not(no_global_oom_handling))]
+use crate::str::from_boxed_utf8_unchecked;
+#[cfg(not(no_global_oom_handling))]
+use crate::string::String;
+#[cfg(not(no_global_oom_handling))]
+use crate::vec::Vec;
+
+#[cfg(not(no_global_oom_handling))]
+#[stable(feature = "from_for_ptrs", since = "1.6.0")]
+impl<T> From<T> for Box<T> {
+    /// Converts a `T` into a `Box<T>`
+    ///
+    /// The conversion allocates on the heap and moves `t`
+    /// from the stack into it.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// let x = 5;
+    /// let boxed = Box::new(5);
+    ///
+    /// assert_eq!(Box::from(x), boxed);
+    /// ```
+    fn from(t: T) -> Self {
+        Box::new(t)
+    }
+}
+
+#[stable(feature = "pin", since = "1.33.0")]
+impl<T: ?Sized, A: Allocator> From<Box<T, A>> for Pin<Box<T, A>>
+where
+    A: 'static,
+{
+    /// Converts a `Box<T>` into a `Pin<Box<T>>`. If `T` does not implement [`Unpin`], then
+    /// `*boxed` will be pinned in memory and unable to be moved.
+    ///
+    /// This conversion does not allocate on the heap and happens in place.
+    ///
+    /// This is also available via [`Box::into_pin`].
+    ///
+    /// Constructing and pinning a `Box` with <code><Pin<Box\<T>>>::from([Box::new]\(x))</code>
+    /// can also be written more concisely using <code>[Box::pin]\(x)</code>.
+    /// This `From` implementation is useful if you already have a `Box<T>`, or you are
+    /// constructing a (pinned) `Box` in a different way than with [`Box::new`].
+    fn from(boxed: Box<T, A>) -> Self {
+        Box::into_pin(boxed)
+    }
+}
+
+/// Specialization trait used for `From<&[T]>`.
+#[cfg(not(no_global_oom_handling))]
+trait BoxFromSlice<T> {
+    fn from_slice(slice: &[T]) -> Self;
+}
+
+#[cfg(not(no_global_oom_handling))]
+impl<T: Clone> BoxFromSlice<T> for Box<[T]> {
+    #[inline]
+    default fn from_slice(slice: &[T]) -> Self {
+        slice.to_vec().into_boxed_slice()
+    }
+}
+
+#[cfg(not(no_global_oom_handling))]
+impl<T: Copy> BoxFromSlice<T> for Box<[T]> {
+    #[inline]
+    fn from_slice(slice: &[T]) -> Self {
+        let len = slice.len();
+        let buf = RawVec::with_capacity(len);
+        unsafe {
+            ptr::copy_nonoverlapping(slice.as_ptr(), buf.ptr(), len);
+            buf.into_box(slice.len()).assume_init()
+        }
+    }
+}
+
+#[cfg(not(no_global_oom_handling))]
+#[stable(feature = "box_from_slice", since = "1.17.0")]
+impl<T: Clone> From<&[T]> for Box<[T]> {
+    /// Converts a `&[T]` into a `Box<[T]>`
+    ///
+    /// This conversion allocates on the heap
+    /// and performs a copy of `slice` and its contents.
+    ///
+    /// # Examples
+    /// ```rust
+    /// // create a &[u8] which will be used to create a Box<[u8]>
+    /// let slice: &[u8] = &[104, 101, 108, 108, 111];
+    /// let boxed_slice: Box<[u8]> = Box::from(slice);
+    ///
+    /// println!("{boxed_slice:?}");
+    /// ```
+    #[inline]
+    fn from(slice: &[T]) -> Box<[T]> {
+        <Self as BoxFromSlice<T>>::from_slice(slice)
+    }
+}
+
+#[cfg(not(no_global_oom_handling))]
+#[stable(feature = "box_from_cow", since = "1.45.0")]
+impl<T: Clone> From<Cow<'_, [T]>> for Box<[T]> {
+    /// Converts a `Cow<'_, [T]>` into a `Box<[T]>`
+    ///
+    /// When `cow` is the `Cow::Borrowed` variant, this
+    /// conversion allocates on the heap and copies the
+    /// underlying slice. Otherwise, it will try to reuse the owned
+    /// `Vec`'s allocation.
+    #[inline]
+    fn from(cow: Cow<'_, [T]>) -> Box<[T]> {
+        match cow {
+            Cow::Borrowed(slice) => Box::from(slice),
+            Cow::Owned(slice) => Box::from(slice),
+        }
+    }
+}
+
+#[cfg(not(no_global_oom_handling))]
+#[stable(feature = "box_from_slice", since = "1.17.0")]
+impl From<&str> for Box<str> {
+    /// Converts a `&str` into a `Box<str>`
+    ///
+    /// This conversion allocates on the heap
+    /// and performs a copy of `s`.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// let boxed: Box<str> = Box::from("hello");
+    /// println!("{boxed}");
+    /// ```
+    #[inline]
+    fn from(s: &str) -> Box<str> {
+        unsafe { from_boxed_utf8_unchecked(Box::from(s.as_bytes())) }
+    }
+}
+
+#[cfg(not(no_global_oom_handling))]
+#[stable(feature = "box_from_cow", since = "1.45.0")]
+impl From<Cow<'_, str>> for Box<str> {
+    /// Converts a `Cow<'_, str>` into a `Box<str>`
+    ///
+    /// When `cow` is the `Cow::Borrowed` variant, this
+    /// conversion allocates on the heap and copies the
+    /// underlying `str`. Otherwise, it will try to reuse the owned
+    /// `String`'s allocation.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// use std::borrow::Cow;
+    ///
+    /// let unboxed = Cow::Borrowed("hello");
+    /// let boxed: Box<str> = Box::from(unboxed);
+    /// println!("{boxed}");
+    /// ```
+    ///
+    /// ```rust
+    /// # use std::borrow::Cow;
+    /// let unboxed = Cow::Owned("hello".to_string());
+    /// let boxed: Box<str> = Box::from(unboxed);
+    /// println!("{boxed}");
+    /// ```
+    #[inline]
+    fn from(cow: Cow<'_, str>) -> Box<str> {
+        match cow {
+            Cow::Borrowed(s) => Box::from(s),
+            Cow::Owned(s) => Box::from(s),
+        }
+    }
+}
+
+#[stable(feature = "boxed_str_conv", since = "1.19.0")]
+impl<A: Allocator> From<Box<str, A>> for Box<[u8], A> {
+    /// Converts a `Box<str>` into a `Box<[u8]>`
+    ///
+    /// This conversion does not allocate on the heap and happens in place.
+    ///
+    /// # Examples
+    /// ```rust
+    /// // create a Box<str> which will be used to create a Box<[u8]>
+    /// let boxed: Box<str> = Box::from("hello");
+    /// let boxed_str: Box<[u8]> = Box::from(boxed);
+    ///
+    /// // create a &[u8] which will be used to create a Box<[u8]>
+    /// let slice: &[u8] = &[104, 101, 108, 108, 111];
+    /// let boxed_slice = Box::from(slice);
+    ///
+    /// assert_eq!(boxed_slice, boxed_str);
+    /// ```
+    #[inline]
+    fn from(s: Box<str, A>) -> Self {
+        let (raw, alloc) = Box::into_raw_with_allocator(s);
+        unsafe { Box::from_raw_in(raw as *mut [u8], alloc) }
+    }
+}
+
+#[cfg(not(no_global_oom_handling))]
+#[stable(feature = "box_from_array", since = "1.45.0")]
+impl<T, const N: usize> From<[T; N]> for Box<[T]> {
+    /// Converts a `[T; N]` into a `Box<[T]>`
+    ///
+    /// This conversion moves the array to newly heap-allocated memory.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// let boxed: Box<[u8]> = Box::from([4, 2]);
+    /// println!("{boxed:?}");
+    /// ```
+    fn from(array: [T; N]) -> Box<[T]> {
+        Box::new(array)
+    }
+}
+
+/// Casts a boxed slice to a boxed array.
+///
+/// # Safety
+///
+/// `boxed_slice.len()` must be exactly `N`.
+unsafe fn boxed_slice_as_array_unchecked<T, A: Allocator, const N: usize>(
+    boxed_slice: Box<[T], A>,
+) -> Box<[T; N], A> {
+    debug_assert_eq!(boxed_slice.len(), N);
+
+    let (ptr, alloc) = Box::into_raw_with_allocator(boxed_slice);
+    // SAFETY: Pointer and allocator came from an existing box,
+    // and our safety condition requires that the length is exactly `N`
+    unsafe { Box::from_raw_in(ptr as *mut [T; N], alloc) }
+}
+
+#[stable(feature = "boxed_slice_try_from", since = "1.43.0")]
+impl<T, const N: usize> TryFrom<Box<[T]>> for Box<[T; N]> {
+    type Error = Box<[T]>;
+
+    /// Attempts to convert a `Box<[T]>` into a `Box<[T; N]>`.
+    ///
+    /// The conversion occurs in-place and does not require a
+    /// new memory allocation.
+    ///
+    /// # Errors
+    ///
+    /// Returns the old `Box<[T]>` in the `Err` variant if
+    /// `boxed_slice.len()` does not equal `N`.
+    fn try_from(boxed_slice: Box<[T]>) -> Result<Self, Self::Error> {
+        if boxed_slice.len() == N {
+            Ok(unsafe { boxed_slice_as_array_unchecked(boxed_slice) })
+        } else {
+            Err(boxed_slice)
+        }
+    }
+}
+
+#[cfg(not(no_global_oom_handling))]
+#[stable(feature = "boxed_array_try_from_vec", since = "1.66.0")]
+impl<T, const N: usize> TryFrom<Vec<T>> for Box<[T; N]> {
+    type Error = Vec<T>;
+
+    /// Attempts to convert a `Vec<T>` into a `Box<[T; N]>`.
+    ///
+    /// Like [`Vec::into_boxed_slice`], this is in-place if `vec.capacity() == N`,
+    /// but will require a reallocation otherwise.
+    ///
+    /// # Errors
+    ///
+    /// Returns the original `Vec<T>` in the `Err` variant if
+    /// `boxed_slice.len()` does not equal `N`.
+    ///
+    /// # Examples
+    ///
+    /// This can be used with [`vec!`] to create an array on the heap:
+    ///
+    /// ```
+    /// let state: Box<[f32; 100]> = vec![1.0; 100].try_into().unwrap();
+    /// assert_eq!(state.len(), 100);
+    /// ```
+    fn try_from(vec: Vec<T>) -> Result<Self, Self::Error> {
+        if vec.len() == N {
+            let boxed_slice = vec.into_boxed_slice();
+            Ok(unsafe { boxed_slice_as_array_unchecked(boxed_slice) })
+        } else {
+            Err(vec)
+        }
+    }
+}
+
+impl<A: Allocator> Box<dyn Any, A> {
+    /// Attempts to downcast the box to a concrete type.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::any::Any;
+    ///
+    /// fn print_if_string(value: Box<dyn Any>) {
+    ///     if let Ok(string) = value.downcast::<String>() {
+    ///         println!("String ({}): {}", string.len(), string);
+    ///     }
+    /// }
+    ///
+    /// let my_string = "Hello World".to_string();
+    /// print_if_string(Box::new(my_string));
+    /// print_if_string(Box::new(0i8));
+    /// ```
+    #[inline]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn downcast<T: Any>(self) -> Result<Box<T, A>, Self> {
+        if self.is::<T>() { unsafe { Ok(self.downcast_unchecked::<T>()) } } else { Err(self) }
+    }
+
+    /// Downcasts the box to a concrete type.
+    ///
+    /// For a safe alternative see [`downcast`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(downcast_unchecked)]
+    ///
+    /// use std::any::Any;
+    ///
+    /// let x: Box<dyn Any> = Box::new(1_usize);
+    ///
+    /// unsafe {
+    ///     assert_eq!(*x.downcast_unchecked::<usize>(), 1);
+    /// }
+    /// ```
+    ///
+    /// # Safety
+    ///
+    /// The contained value must be of type `T`. Calling this method
+    /// with the incorrect type is *undefined behavior*.
+    ///
+    /// [`downcast`]: Self::downcast
+    #[inline]
+    #[unstable(feature = "downcast_unchecked", issue = "90850")]
+    pub unsafe fn downcast_unchecked<T: Any>(self) -> Box<T, A> {
+        debug_assert!(self.is::<T>());
+        unsafe {
+            let (raw, alloc): (*mut dyn Any, _) = Box::into_raw_with_allocator(self);
+            Box::from_raw_in(raw as *mut T, alloc)
+        }
+    }
+}
+
+impl<A: Allocator> Box<dyn Any + Send, A> {
+    /// Attempts to downcast the box to a concrete type.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::any::Any;
+    ///
+    /// fn print_if_string(value: Box<dyn Any + Send>) {
+    ///     if let Ok(string) = value.downcast::<String>() {
+    ///         println!("String ({}): {}", string.len(), string);
+    ///     }
+    /// }
+    ///
+    /// let my_string = "Hello World".to_string();
+    /// print_if_string(Box::new(my_string));
+    /// print_if_string(Box::new(0i8));
+    /// ```
+    #[inline]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn downcast<T: Any>(self) -> Result<Box<T, A>, Self> {
+        if self.is::<T>() { unsafe { Ok(self.downcast_unchecked::<T>()) } } else { Err(self) }
+    }
+
+    /// Downcasts the box to a concrete type.
+    ///
+    /// For a safe alternative see [`downcast`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(downcast_unchecked)]
+    ///
+    /// use std::any::Any;
+    ///
+    /// let x: Box<dyn Any + Send> = Box::new(1_usize);
+    ///
+    /// unsafe {
+    ///     assert_eq!(*x.downcast_unchecked::<usize>(), 1);
+    /// }
+    /// ```
+    ///
+    /// # Safety
+    ///
+    /// The contained value must be of type `T`. Calling this method
+    /// with the incorrect type is *undefined behavior*.
+    ///
+    /// [`downcast`]: Self::downcast
+    #[inline]
+    #[unstable(feature = "downcast_unchecked", issue = "90850")]
+    pub unsafe fn downcast_unchecked<T: Any>(self) -> Box<T, A> {
+        debug_assert!(self.is::<T>());
+        unsafe {
+            let (raw, alloc): (*mut (dyn Any + Send), _) = Box::into_raw_with_allocator(self);
+            Box::from_raw_in(raw as *mut T, alloc)
+        }
+    }
+}
+
+impl<A: Allocator> Box<dyn Any + Send + Sync, A> {
+    /// Attempts to downcast the box to a concrete type.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::any::Any;
+    ///
+    /// fn print_if_string(value: Box<dyn Any + Send + Sync>) {
+    ///     if let Ok(string) = value.downcast::<String>() {
+    ///         println!("String ({}): {}", string.len(), string);
+    ///     }
+    /// }
+    ///
+    /// let my_string = "Hello World".to_string();
+    /// print_if_string(Box::new(my_string));
+    /// print_if_string(Box::new(0i8));
+    /// ```
+    #[inline]
+    #[stable(feature = "box_send_sync_any_downcast", since = "1.51.0")]
+    pub fn downcast<T: Any>(self) -> Result<Box<T, A>, Self> {
+        if self.is::<T>() { unsafe { Ok(self.downcast_unchecked::<T>()) } } else { Err(self) }
+    }
+
+    /// Downcasts the box to a concrete type.
+    ///
+    /// For a safe alternative see [`downcast`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(downcast_unchecked)]
+    ///
+    /// use std::any::Any;
+    ///
+    /// let x: Box<dyn Any + Send + Sync> = Box::new(1_usize);
+    ///
+    /// unsafe {
+    ///     assert_eq!(*x.downcast_unchecked::<usize>(), 1);
+    /// }
+    /// ```
+    ///
+    /// # Safety
+    ///
+    /// The contained value must be of type `T`. Calling this method
+    /// with the incorrect type is *undefined behavior*.
+    ///
+    /// [`downcast`]: Self::downcast
+    #[inline]
+    #[unstable(feature = "downcast_unchecked", issue = "90850")]
+    pub unsafe fn downcast_unchecked<T: Any>(self) -> Box<T, A> {
+        debug_assert!(self.is::<T>());
+        unsafe {
+            let (raw, alloc): (*mut (dyn Any + Send + Sync), _) =
+                Box::into_raw_with_allocator(self);
+            Box::from_raw_in(raw as *mut T, alloc)
+        }
+    }
+}
+
+#[cfg(not(no_global_oom_handling))]
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, E: Error + 'a> From<E> for Box<dyn Error + 'a> {
+    /// Converts a type of [`Error`] into a box of dyn [`Error`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::error::Error;
+    /// use std::fmt;
+    /// use std::mem;
+    ///
+    /// #[derive(Debug)]
+    /// struct AnError;
+    ///
+    /// impl fmt::Display for AnError {
+    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+    ///         write!(f, "An error")
+    ///     }
+    /// }
+    ///
+    /// impl Error for AnError {}
+    ///
+    /// let an_error = AnError;
+    /// assert!(0 == mem::size_of_val(&an_error));
+    /// let a_boxed_error = Box::<dyn Error>::from(an_error);
+    /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
+    /// ```
+    fn from(err: E) -> Box<dyn Error + 'a> {
+        Box::new(err)
+    }
+}
+
+#[cfg(not(no_global_oom_handling))]
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync + 'a> {
+    /// Converts a type of [`Error`] + [`Send`] + [`Sync`] into a box of
+    /// dyn [`Error`] + [`Send`] + [`Sync`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::error::Error;
+    /// use std::fmt;
+    /// use std::mem;
+    ///
+    /// #[derive(Debug)]
+    /// struct AnError;
+    ///
+    /// impl fmt::Display for AnError {
+    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+    ///         write!(f, "An error")
+    ///     }
+    /// }
+    ///
+    /// impl Error for AnError {}
+    ///
+    /// unsafe impl Send for AnError {}
+    ///
+    /// unsafe impl Sync for AnError {}
+    ///
+    /// let an_error = AnError;
+    /// assert!(0 == mem::size_of_val(&an_error));
+    /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(an_error);
+    /// assert!(
+    ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
+    /// ```
+    fn from(err: E) -> Box<dyn Error + Send + Sync + 'a> {
+        Box::new(err)
+    }
+}
+
+#[cfg(not(no_global_oom_handling))]
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a> From<String> for Box<dyn Error + Send + Sync + 'a> {
+    /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::error::Error;
+    /// use std::mem;
+    ///
+    /// let a_string_error = "a string error".to_string();
+    /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(a_string_error);
+    /// assert!(
+    ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
+    /// ```
+    #[inline]
+    fn from(err: String) -> Box<dyn Error + Send + Sync + 'a> {
+        struct StringError(String);
+
+        impl Error for StringError {
+            #[allow(deprecated)]
+            fn description(&self) -> &str {
+                &self.0
+            }
+        }
+
+        impl fmt::Display for StringError {
+            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+                fmt::Display::fmt(&self.0, f)
+            }
+        }
+
+        // Purposefully skip printing "StringError(..)"
+        impl fmt::Debug for StringError {
+            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+                fmt::Debug::fmt(&self.0, f)
+            }
+        }
+
+        Box::new(StringError(err))
+    }
+}
+
+#[cfg(not(no_global_oom_handling))]
+#[stable(feature = "string_box_error", since = "1.6.0")]
+impl<'a> From<String> for Box<dyn Error + 'a> {
+    /// Converts a [`String`] into a box of dyn [`Error`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::error::Error;
+    /// use std::mem;
+    ///
+    /// let a_string_error = "a string error".to_string();
+    /// let a_boxed_error = Box::<dyn Error>::from(a_string_error);
+    /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
+    /// ```
+    fn from(str_err: String) -> Box<dyn Error + 'a> {
+        let err1: Box<dyn Error + Send + Sync> = From::from(str_err);
+        let err2: Box<dyn Error> = err1;
+        err2
+    }
+}
+
+#[cfg(not(no_global_oom_handling))]
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a> From<&str> for Box<dyn Error + Send + Sync + 'a> {
+    /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
+    ///
+    /// [`str`]: prim@str
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::error::Error;
+    /// use std::mem;
+    ///
+    /// let a_str_error = "a str error";
+    /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(a_str_error);
+    /// assert!(
+    ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
+    /// ```
+    #[inline]
+    fn from(err: &str) -> Box<dyn Error + Send + Sync + 'a> {
+        From::from(String::from(err))
+    }
+}
+
+#[cfg(not(no_global_oom_handling))]
+#[stable(feature = "string_box_error", since = "1.6.0")]
+impl<'a> From<&str> for Box<dyn Error + 'a> {
+    /// Converts a [`str`] into a box of dyn [`Error`].
+    ///
+    /// [`str`]: prim@str
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::error::Error;
+    /// use std::mem;
+    ///
+    /// let a_str_error = "a str error";
+    /// let a_boxed_error = Box::<dyn Error>::from(a_str_error);
+    /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
+    /// ```
+    fn from(err: &str) -> Box<dyn Error + 'a> {
+        From::from(String::from(err))
+    }
+}
+
+#[cfg(not(no_global_oom_handling))]
+#[stable(feature = "cow_box_error", since = "1.22.0")]
+impl<'a, 'b> From<Cow<'b, str>> for Box<dyn Error + Send + Sync + 'a> {
+    /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::error::Error;
+    /// use std::mem;
+    /// use std::borrow::Cow;
+    ///
+    /// let a_cow_str_error = Cow::from("a str error");
+    /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(a_cow_str_error);
+    /// assert!(
+    ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
+    /// ```
+    fn from(err: Cow<'b, str>) -> Box<dyn Error + Send + Sync + 'a> {
+        From::from(String::from(err))
+    }
+}
+
+#[cfg(not(no_global_oom_handling))]
+#[stable(feature = "cow_box_error", since = "1.22.0")]
+impl<'a, 'b> From<Cow<'b, str>> for Box<dyn Error + 'a> {
+    /// Converts a [`Cow`] into a box of dyn [`Error`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::error::Error;
+    /// use std::mem;
+    /// use std::borrow::Cow;
+    ///
+    /// let a_cow_str_error = Cow::from("a str error");
+    /// let a_boxed_error = Box::<dyn Error>::from(a_cow_str_error);
+    /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
+    /// ```
+    fn from(err: Cow<'b, str>) -> Box<dyn Error + 'a> {
+        From::from(String::from(err))
+    }
+}
+
+impl dyn Error {
+    /// Attempts to downcast the box to a concrete type.
+    #[inline]
+    #[stable(feature = "error_downcast", since = "1.3.0")]
+    #[rustc_allow_incoherent_impl]
+    pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error>> {
+        if self.is::<T>() {
+            unsafe {
+                let raw: *mut dyn Error = Box::into_raw(self);
+                Ok(Box::from_raw(raw as *mut T))
+            }
+        } else {
+            Err(self)
+        }
+    }
+}
+
+impl dyn Error + Send {
+    /// Attempts to downcast the box to a concrete type.
+    #[inline]
+    #[stable(feature = "error_downcast", since = "1.3.0")]
+    #[rustc_allow_incoherent_impl]
+    pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error + Send>> {
+        let err: Box<dyn Error> = self;
+        <dyn Error>::downcast(err).map_err(|s| unsafe {
+            // Reapply the `Send` marker.
+            mem::transmute::<Box<dyn Error>, Box<dyn Error + Send>>(s)
+        })
+    }
+}
+
+impl dyn Error + Send + Sync {
+    /// Attempts to downcast the box to a concrete type.
+    #[inline]
+    #[stable(feature = "error_downcast", since = "1.3.0")]
+    #[rustc_allow_incoherent_impl]
+    pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<Self>> {
+        let err: Box<dyn Error> = self;
+        <dyn Error>::downcast(err).map_err(|s| unsafe {
+            // Reapply the `Send + Sync` markers.
+            mem::transmute::<Box<dyn Error>, Box<dyn Error + Send + Sync>>(s)
+        })
+    }
+}
diff --git a/library/alloc/src/boxed/iter.rs b/library/alloc/src/boxed/iter.rs
new file mode 100644
index 00000000000..90582aa49c6
--- /dev/null
+++ b/library/alloc/src/boxed/iter.rs
@@ -0,0 +1,194 @@
+use core::async_iter::AsyncIterator;
+use core::iter::FusedIterator;
+use core::pin::Pin;
+use core::slice;
+use core::task::{Context, Poll};
+
+use crate::alloc::Allocator;
+#[cfg(not(no_global_oom_handling))]
+use crate::borrow::Cow;
+use crate::boxed::Box;
+#[cfg(not(no_global_oom_handling))]
+use crate::string::String;
+use crate::vec;
+#[cfg(not(no_global_oom_handling))]
+use crate::vec::Vec;
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<I: Iterator + ?Sized, A: Allocator> Iterator for Box<I, A> {
+    type Item = I::Item;
+    fn next(&mut self) -> Option<I::Item> {
+        (**self).next()
+    }
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        (**self).size_hint()
+    }
+    fn nth(&mut self, n: usize) -> Option<I::Item> {
+        (**self).nth(n)
+    }
+    fn last(self) -> Option<I::Item> {
+        BoxIter::last(self)
+    }
+}
+
+trait BoxIter {
+    type Item;
+    fn last(self) -> Option<Self::Item>;
+}
+
+impl<I: Iterator + ?Sized, A: Allocator> BoxIter for Box<I, A> {
+    type Item = I::Item;
+    default fn last(self) -> Option<I::Item> {
+        #[inline]
+        fn some<T>(_: Option<T>, x: T) -> Option<T> {
+            Some(x)
+        }
+
+        self.fold(None, some)
+    }
+}
+
+/// Specialization for sized `I`s that uses `I`s implementation of `last()`
+/// instead of the default.
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<I: Iterator, A: Allocator> BoxIter for Box<I, A> {
+    fn last(self) -> Option<I::Item> {
+        (*self).last()
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<I: DoubleEndedIterator + ?Sized, A: Allocator> DoubleEndedIterator for Box<I, A> {
+    fn next_back(&mut self) -> Option<I::Item> {
+        (**self).next_back()
+    }
+    fn nth_back(&mut self, n: usize) -> Option<I::Item> {
+        (**self).nth_back(n)
+    }
+}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<I: ExactSizeIterator + ?Sized, A: Allocator> ExactSizeIterator for Box<I, A> {
+    fn len(&self) -> usize {
+        (**self).len()
+    }
+    fn is_empty(&self) -> bool {
+        (**self).is_empty()
+    }
+}
+
+#[stable(feature = "fused", since = "1.26.0")]
+impl<I: FusedIterator + ?Sized, A: Allocator> FusedIterator for Box<I, A> {}
+
+#[unstable(feature = "async_iterator", issue = "79024")]
+impl<S: ?Sized + AsyncIterator + Unpin> AsyncIterator for Box<S> {
+    type Item = S::Item;
+
+    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
+        Pin::new(&mut **self).poll_next(cx)
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        (**self).size_hint()
+    }
+}
+
+/// This implementation is required to make sure that the `Box<[I]>: IntoIterator`
+/// implementation doesn't overlap with `IntoIterator for T where T: Iterator` blanket.
+#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")]
+impl<I, A: Allocator> !Iterator for Box<[I], A> {}
+
+/// This implementation is required to make sure that the `&Box<[I]>: IntoIterator`
+/// implementation doesn't overlap with `IntoIterator for T where T: Iterator` blanket.
+#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")]
+impl<'a, I, A: Allocator> !Iterator for &'a Box<[I], A> {}
+
+/// This implementation is required to make sure that the `&mut Box<[I]>: IntoIterator`
+/// implementation doesn't overlap with `IntoIterator for T where T: Iterator` blanket.
+#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")]
+impl<'a, I, A: Allocator> !Iterator for &'a mut Box<[I], A> {}
+
+// Note: the `#[rustc_skip_during_method_dispatch(boxed_slice)]` on `trait IntoIterator`
+// hides this implementation from explicit `.into_iter()` calls on editions < 2024,
+// so those calls will still resolve to the slice implementation, by reference.
+#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")]
+impl<I, A: Allocator> IntoIterator for Box<[I], A> {
+    type IntoIter = vec::IntoIter<I, A>;
+    type Item = I;
+    fn into_iter(self) -> vec::IntoIter<I, A> {
+        self.into_vec().into_iter()
+    }
+}
+
+#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")]
+impl<'a, I, A: Allocator> IntoIterator for &'a Box<[I], A> {
+    type IntoIter = slice::Iter<'a, I>;
+    type Item = &'a I;
+    fn into_iter(self) -> slice::Iter<'a, I> {
+        self.iter()
+    }
+}
+
+#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")]
+impl<'a, I, A: Allocator> IntoIterator for &'a mut Box<[I], A> {
+    type IntoIter = slice::IterMut<'a, I>;
+    type Item = &'a mut I;
+    fn into_iter(self) -> slice::IterMut<'a, I> {
+        self.iter_mut()
+    }
+}
+
+#[cfg(not(no_global_oom_handling))]
+#[stable(feature = "boxed_slice_from_iter", since = "1.32.0")]
+impl<I> FromIterator<I> for Box<[I]> {
+    fn from_iter<T: IntoIterator<Item = I>>(iter: T) -> Self {
+        iter.into_iter().collect::<Vec<_>>().into_boxed_slice()
+    }
+}
+
+#[cfg(not(no_global_oom_handling))]
+#[stable(feature = "boxed_str_from_iter", since = "1.80.0")]
+impl FromIterator<char> for Box<str> {
+    fn from_iter<T: IntoIterator<Item = char>>(iter: T) -> Self {
+        String::from_iter(iter).into_boxed_str()
+    }
+}
+
+#[cfg(not(no_global_oom_handling))]
+#[stable(feature = "boxed_str_from_iter", since = "1.80.0")]
+impl<'a> FromIterator<&'a char> for Box<str> {
+    fn from_iter<T: IntoIterator<Item = &'a char>>(iter: T) -> Self {
+        String::from_iter(iter).into_boxed_str()
+    }
+}
+
+#[cfg(not(no_global_oom_handling))]
+#[stable(feature = "boxed_str_from_iter", since = "1.80.0")]
+impl<'a> FromIterator<&'a str> for Box<str> {
+    fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> Self {
+        String::from_iter(iter).into_boxed_str()
+    }
+}
+
+#[cfg(not(no_global_oom_handling))]
+#[stable(feature = "boxed_str_from_iter", since = "1.80.0")]
+impl FromIterator<String> for Box<str> {
+    fn from_iter<T: IntoIterator<Item = String>>(iter: T) -> Self {
+        String::from_iter(iter).into_boxed_str()
+    }
+}
+
+#[cfg(not(no_global_oom_handling))]
+#[stable(feature = "boxed_str_from_iter", since = "1.80.0")]
+impl<A: Allocator> FromIterator<Box<str, A>> for Box<str> {
+    fn from_iter<T: IntoIterator<Item = Box<str, A>>>(iter: T) -> Self {
+        String::from_iter(iter).into_boxed_str()
+    }
+}
+
+#[cfg(not(no_global_oom_handling))]
+#[stable(feature = "boxed_str_from_iter", since = "1.80.0")]
+impl<'a> FromIterator<Cow<'a, str>> for Box<str> {
+    fn from_iter<T: IntoIterator<Item = Cow<'a, str>>>(iter: T) -> Self {
+        String::from_iter(iter).into_boxed_str()
+    }
+}
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index 9fdd51ce331..fc8646e96d9 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -376,6 +376,21 @@ impl<T: ?Sized, A: Allocator> Rc<T, A> {
     unsafe fn from_ptr_in(ptr: *mut RcInner<T>, alloc: A) -> Self {
         unsafe { Self::from_inner_in(NonNull::new_unchecked(ptr), alloc) }
     }
+
+    // Non-inlined part of `drop`.
+    #[inline(never)]
+    unsafe fn drop_slow(&mut self) {
+        // Reconstruct the "strong weak" pointer and drop it when this
+        // variable goes out of scope. This ensures that the memory is
+        // deallocated even if the destructor of `T` panics.
+        let _weak = Weak { ptr: self.ptr, alloc: &self.alloc };
+
+        // Destroy the contained object.
+        // We cannot use `get_mut_unchecked` here, because `self.alloc` is borrowed.
+        unsafe {
+            ptr::drop_in_place(&mut (*self.ptr.as_ptr()).value);
+        }
+    }
 }
 
 impl<T> Rc<T> {
@@ -2252,21 +2267,12 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Rc<T, A> {
     /// drop(foo);    // Doesn't print anything
     /// drop(foo2);   // Prints "dropped!"
     /// ```
+    #[inline]
     fn drop(&mut self) {
         unsafe {
             self.inner().dec_strong();
             if self.inner().strong() == 0 {
-                // destroy the contained object
-                ptr::drop_in_place(Self::get_mut_unchecked(self));
-
-                // remove the implicit "strong weak" pointer now that we've
-                // destroyed the contents.
-                self.inner().dec_weak();
-
-                if self.inner().weak() == 0 {
-                    self.alloc
-                        .deallocate(self.ptr.cast(), Layout::for_value_raw(self.ptr.as_ptr()));
-                }
+                self.drop_slow();
             }
         }
     }
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 15a1b0f2834..98a2fe24257 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -1872,15 +1872,17 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> {
     // Non-inlined part of `drop`.
     #[inline(never)]
     unsafe fn drop_slow(&mut self) {
+        // Drop the weak ref collectively held by all strong references when this
+        // variable goes out of scope. This ensures that the memory is deallocated
+        // even if the destructor of `T` panics.
+        // Take a reference to `self.alloc` instead of cloning because 1. it'll last long
+        // enough, and 2. you should be able to drop `Arc`s with unclonable allocators
+        let _weak = Weak { ptr: self.ptr, alloc: &self.alloc };
+
         // Destroy the data at this time, even though we must not free the box
         // allocation itself (there might still be weak pointers lying around).
-        unsafe { ptr::drop_in_place(Self::get_mut_unchecked(self)) };
-
-        // Drop the weak ref collectively held by all strong references
-        // Take a reference to `self.alloc` instead of cloning because 1. it'll
-        // last long enough, and 2. you should be able to drop `Arc`s with
-        // unclonable allocators
-        drop(Weak { ptr: self.ptr, alloc: &self.alloc });
+        // We cannot use `get_mut_unchecked` here, because `self.alloc` is borrowed.
+        unsafe { ptr::drop_in_place(&mut (*self.ptr.as_ptr()).data) };
     }
 
     /// Returns `true` if the two `Arc`s point to the same allocation in a vein similar to
diff --git a/library/alloc/tests/arc.rs b/library/alloc/tests/arc.rs
index dc27c578b57..a259c0131ec 100644
--- a/library/alloc/tests/arc.rs
+++ b/library/alloc/tests/arc.rs
@@ -1,5 +1,5 @@
 use std::any::Any;
-use std::cell::RefCell;
+use std::cell::{Cell, RefCell};
 use std::iter::TrustedLen;
 use std::mem;
 use std::sync::{Arc, Weak};
@@ -89,7 +89,7 @@ fn eq() {
 
 // The test code below is identical to that in `rc.rs`.
 // For better maintainability we therefore define this type alias.
-type Rc<T> = Arc<T>;
+type Rc<T, A = std::alloc::Global> = Arc<T, A>;
 
 const SHARED_ITER_MAX: u16 = 100;
 
@@ -210,6 +210,42 @@ fn weak_may_dangle() {
     // borrow might be used here, when `val` is dropped and runs the `Drop` code for type `std::sync::Weak`
 }
 
+/// Test that a panic from a destructor does not leak the allocation.
+#[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
+fn panic_no_leak() {
+    use std::alloc::{AllocError, Allocator, Global, Layout};
+    use std::panic::{AssertUnwindSafe, catch_unwind};
+    use std::ptr::NonNull;
+
+    struct AllocCount(Cell<i32>);
+    unsafe impl Allocator for AllocCount {
+        fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
+            self.0.set(self.0.get() + 1);
+            Global.allocate(layout)
+        }
+        unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
+            self.0.set(self.0.get() - 1);
+            unsafe { Global.deallocate(ptr, layout) }
+        }
+    }
+
+    struct PanicOnDrop;
+    impl Drop for PanicOnDrop {
+        fn drop(&mut self) {
+            panic!("PanicOnDrop");
+        }
+    }
+
+    let alloc = AllocCount(Cell::new(0));
+    let rc = Rc::new_in(PanicOnDrop, &alloc);
+    assert_eq!(alloc.0.get(), 1);
+
+    let panic_message = catch_unwind(AssertUnwindSafe(|| drop(rc))).unwrap_err();
+    assert_eq!(*panic_message.downcast_ref::<&'static str>().unwrap(), "PanicOnDrop");
+    assert_eq!(alloc.0.get(), 0);
+}
+
 /// This is similar to the doc-test for `Arc::make_mut()`, but on an unsized type (slice).
 #[test]
 fn make_mut_unsized() {
diff --git a/library/alloc/tests/boxed.rs b/library/alloc/tests/boxed.rs
index 544f60da587..6a8ba5c92fb 100644
--- a/library/alloc/tests/boxed.rs
+++ b/library/alloc/tests/boxed.rs
@@ -60,6 +60,44 @@ fn box_deref_lval() {
     assert_eq!(x.get(), 1000);
 }
 
+/// Test that a panic from a destructor does not leak the allocation.
+#[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
+fn panic_no_leak() {
+    use std::alloc::{AllocError, Allocator, Global, Layout};
+    use std::panic::{AssertUnwindSafe, catch_unwind};
+    use std::ptr::NonNull;
+
+    struct AllocCount(Cell<i32>);
+    unsafe impl Allocator for AllocCount {
+        fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
+            self.0.set(self.0.get() + 1);
+            Global.allocate(layout)
+        }
+        unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
+            self.0.set(self.0.get() - 1);
+            unsafe { Global.deallocate(ptr, layout) }
+        }
+    }
+
+    struct PanicOnDrop {
+        _data: u8,
+    }
+    impl Drop for PanicOnDrop {
+        fn drop(&mut self) {
+            panic!("PanicOnDrop");
+        }
+    }
+
+    let alloc = AllocCount(Cell::new(0));
+    let b = Box::new_in(PanicOnDrop { _data: 42 }, &alloc);
+    assert_eq!(alloc.0.get(), 1);
+
+    let panic_message = catch_unwind(AssertUnwindSafe(|| drop(b))).unwrap_err();
+    assert_eq!(*panic_message.downcast_ref::<&'static str>().unwrap(), "PanicOnDrop");
+    assert_eq!(alloc.0.get(), 0);
+}
+
 #[allow(unused)]
 pub struct ConstAllocator;
 
diff --git a/library/alloc/tests/rc.rs b/library/alloc/tests/rc.rs
index 29dbdcf225e..451765d7242 100644
--- a/library/alloc/tests/rc.rs
+++ b/library/alloc/tests/rc.rs
@@ -1,5 +1,5 @@
 use std::any::Any;
-use std::cell::RefCell;
+use std::cell::{Cell, RefCell};
 use std::iter::TrustedLen;
 use std::mem;
 use std::rc::{Rc, Weak};
@@ -206,6 +206,42 @@ fn weak_may_dangle() {
     // borrow might be used here, when `val` is dropped and runs the `Drop` code for type `std::rc::Weak`
 }
 
+/// Test that a panic from a destructor does not leak the allocation.
+#[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
+fn panic_no_leak() {
+    use std::alloc::{AllocError, Allocator, Global, Layout};
+    use std::panic::{AssertUnwindSafe, catch_unwind};
+    use std::ptr::NonNull;
+
+    struct AllocCount(Cell<i32>);
+    unsafe impl Allocator for AllocCount {
+        fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
+            self.0.set(self.0.get() + 1);
+            Global.allocate(layout)
+        }
+        unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
+            self.0.set(self.0.get() - 1);
+            unsafe { Global.deallocate(ptr, layout) }
+        }
+    }
+
+    struct PanicOnDrop;
+    impl Drop for PanicOnDrop {
+        fn drop(&mut self) {
+            panic!("PanicOnDrop");
+        }
+    }
+
+    let alloc = AllocCount(Cell::new(0));
+    let rc = Rc::new_in(PanicOnDrop, &alloc);
+    assert_eq!(alloc.0.get(), 1);
+
+    let panic_message = catch_unwind(AssertUnwindSafe(|| drop(rc))).unwrap_err();
+    assert_eq!(*panic_message.downcast_ref::<&'static str>().unwrap(), "PanicOnDrop");
+    assert_eq!(alloc.0.get(), 0);
+}
+
 #[allow(unused)]
 mod pin_coerce_unsized {
     use alloc::rc::{Rc, UniqueRc};
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index 302720eddef..ffaf1bc56e9 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -106,7 +106,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[unstable(feature = "iter_next_chunk", reason = "recently added", issue = "98326")]
-    #[rustc_do_not_const_check]
     fn next_chunk<const N: usize>(
         &mut self,
     ) -> Result<[Self::Item; N], array::IntoIter<Self::Item, N>>
@@ -184,7 +183,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_do_not_const_check]
     fn size_hint(&self) -> (usize, Option<usize>) {
         (0, None)
     }
@@ -220,7 +218,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_do_not_const_check]
     fn count(self) -> usize
     where
         Self: Sized,
@@ -249,7 +246,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_do_not_const_check]
     fn last(self) -> Option<Self::Item>
     where
         Self: Sized,
@@ -297,7 +293,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[unstable(feature = "iter_advance_by", reason = "recently added", issue = "77404")]
-    #[rustc_do_not_const_check]
     fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
         for i in 0..n {
             if self.next().is_none() {
@@ -349,7 +344,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_do_not_const_check]
     fn nth(&mut self, n: usize) -> Option<Self::Item> {
         self.advance_by(n).ok()?;
         self.next()
@@ -400,7 +394,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[stable(feature = "iterator_step_by", since = "1.28.0")]
-    #[rustc_do_not_const_check]
     fn step_by(self, step: usize) -> StepBy<Self>
     where
         Self: Sized,
@@ -472,7 +465,6 @@ pub trait Iterator {
     /// [`OsStr`]: ../../std/ffi/struct.OsStr.html
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_do_not_const_check]
     fn chain<U>(self, other: U) -> Chain<Self, U::IntoIter>
     where
         Self: Sized,
@@ -591,7 +583,6 @@ pub trait Iterator {
     /// [`zip`]: crate::iter::zip
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_do_not_const_check]
     fn zip<U>(self, other: U) -> Zip<Self, U::IntoIter>
     where
         Self: Sized,
@@ -634,7 +625,6 @@ pub trait Iterator {
     /// [`intersperse_with`]: Iterator::intersperse_with
     #[inline]
     #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
-    #[rustc_do_not_const_check]
     fn intersperse(self, separator: Self::Item) -> Intersperse<Self>
     where
         Self: Sized,
@@ -693,7 +683,6 @@ pub trait Iterator {
     /// [`intersperse`]: Iterator::intersperse
     #[inline]
     #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
-    #[rustc_do_not_const_check]
     fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G>
     where
         Self: Sized,
@@ -753,7 +742,6 @@ pub trait Iterator {
     #[rustc_diagnostic_item = "IteratorMap"]
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_do_not_const_check]
     fn map<B, F>(self, f: F) -> Map<Self, F>
     where
         Self: Sized,
@@ -799,7 +787,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[stable(feature = "iterator_for_each", since = "1.21.0")]
-    #[rustc_do_not_const_check]
     fn for_each<F>(self, f: F)
     where
         Self: Sized,
@@ -875,7 +862,6 @@ pub trait Iterator {
     /// Note that `iter.filter(f).next()` is equivalent to `iter.find(f)`.
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_do_not_const_check]
     #[cfg_attr(not(test), rustc_diagnostic_item = "iter_filter")]
     fn filter<P>(self, predicate: P) -> Filter<Self, P>
     where
@@ -922,7 +908,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_do_not_const_check]
     fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F>
     where
         Self: Sized,
@@ -969,7 +954,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_do_not_const_check]
     #[cfg_attr(not(test), rustc_diagnostic_item = "enumerate_method")]
     fn enumerate(self) -> Enumerate<Self>
     where
@@ -1042,7 +1026,6 @@ pub trait Iterator {
     /// [`next`]: Iterator::next
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_do_not_const_check]
     fn peekable(self) -> Peekable<Self>
     where
         Self: Sized,
@@ -1108,7 +1091,6 @@ pub trait Iterator {
     #[inline]
     #[doc(alias = "drop_while")]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_do_not_const_check]
     fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P>
     where
         Self: Sized,
@@ -1190,7 +1172,6 @@ pub trait Iterator {
     /// the iteration should stop, but wasn't placed back into the iterator.
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_do_not_const_check]
     fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P>
     where
         Self: Sized,
@@ -1279,7 +1260,6 @@ pub trait Iterator {
     /// [`fuse`]: Iterator::fuse
     #[inline]
     #[stable(feature = "iter_map_while", since = "1.57.0")]
-    #[rustc_do_not_const_check]
     fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P>
     where
         Self: Sized,
@@ -1309,7 +1289,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_do_not_const_check]
     fn skip(self, n: usize) -> Skip<Self>
     where
         Self: Sized,
@@ -1363,7 +1342,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_do_not_const_check]
     fn take(self, n: usize) -> Take<Self>
     where
         Self: Sized,
@@ -1411,7 +1389,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_do_not_const_check]
     fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F>
     where
         Self: Sized,
@@ -1450,7 +1427,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_do_not_const_check]
     fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F>
     where
         Self: Sized,
@@ -1535,7 +1511,6 @@ pub trait Iterator {
     /// [`flat_map()`]: Iterator::flat_map
     #[inline]
     #[stable(feature = "iterator_flatten", since = "1.29.0")]
-    #[rustc_do_not_const_check]
     fn flatten(self) -> Flatten<Self>
     where
         Self: Sized,
@@ -1692,7 +1667,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[unstable(feature = "iter_map_windows", reason = "recently added", issue = "87155")]
-    #[rustc_do_not_const_check]
     fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N>
     where
         Self: Sized,
@@ -1759,7 +1733,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_do_not_const_check]
     fn fuse(self) -> Fuse<Self>
     where
         Self: Sized,
@@ -1844,7 +1817,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_do_not_const_check]
     fn inspect<F>(self, f: F) -> Inspect<Self, F>
     where
         Self: Sized,
@@ -1873,7 +1845,6 @@ pub trait Iterator {
     /// assert_eq!(of_rust, vec!["of", "Rust"]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_do_not_const_check]
     fn by_ref(&mut self) -> &mut Self
     where
         Self: Sized,
@@ -1993,7 +1964,6 @@ pub trait Iterator {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead"]
     #[cfg_attr(not(test), rustc_diagnostic_item = "iterator_collect_fn")]
-    #[rustc_do_not_const_check]
     fn collect<B: FromIterator<Self::Item>>(self) -> B
     where
         Self: Sized,
@@ -2072,7 +2042,6 @@ pub trait Iterator {
     /// [`collect`]: Iterator::collect
     #[inline]
     #[unstable(feature = "iterator_try_collect", issue = "94047")]
-    #[rustc_do_not_const_check]
     fn try_collect<B>(&mut self) -> ChangeOutputType<Self::Item, B>
     where
         Self: Sized,
@@ -2145,7 +2114,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[unstable(feature = "iter_collect_into", reason = "new API", issue = "94780")]
-    #[rustc_do_not_const_check]
     fn collect_into<E: Extend<Self::Item>>(self, collection: &mut E) -> &mut E
     where
         Self: Sized,
@@ -2178,7 +2146,6 @@ pub trait Iterator {
     /// assert_eq!(odd, vec![1, 3]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_do_not_const_check]
     fn partition<B, F>(self, f: F) -> (B, B)
     where
         Self: Sized,
@@ -2241,7 +2208,6 @@ pub trait Iterator {
     /// assert!(a[i..].iter().all(|&n| n % 2 == 1)); // odds
     /// ```
     #[unstable(feature = "iter_partition_in_place", reason = "new API", issue = "62543")]
-    #[rustc_do_not_const_check]
     fn partition_in_place<'a, T: 'a, P>(mut self, ref mut predicate: P) -> usize
     where
         Self: Sized + DoubleEndedIterator<Item = &'a mut T>,
@@ -2299,7 +2265,6 @@ pub trait Iterator {
     /// assert!(!"IntoIterator".chars().is_partitioned(char::is_uppercase));
     /// ```
     #[unstable(feature = "iter_is_partitioned", reason = "new API", issue = "62544")]
-    #[rustc_do_not_const_check]
     fn is_partitioned<P>(mut self, mut predicate: P) -> bool
     where
         Self: Sized,
@@ -2394,7 +2359,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[stable(feature = "iterator_try_fold", since = "1.27.0")]
-    #[rustc_do_not_const_check]
     fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
     where
         Self: Sized,
@@ -2453,7 +2417,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[stable(feature = "iterator_try_fold", since = "1.27.0")]
-    #[rustc_do_not_const_check]
     fn try_for_each<F, R>(&mut self, f: F) -> R
     where
         Self: Sized,
@@ -2573,7 +2536,6 @@ pub trait Iterator {
     #[doc(alias = "inject", alias = "foldl")]
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_do_not_const_check]
     fn fold<B, F>(mut self, init: B, mut f: F) -> B
     where
         Self: Sized,
@@ -2611,7 +2573,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[stable(feature = "iterator_fold_self", since = "1.51.0")]
-    #[rustc_do_not_const_check]
     fn reduce<F>(mut self, f: F) -> Option<Self::Item>
     where
         Self: Sized,
@@ -2683,7 +2644,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[unstable(feature = "iterator_try_reduce", reason = "new API", issue = "87053")]
-    #[rustc_do_not_const_check]
     fn try_reduce<R>(
         &mut self,
         f: impl FnMut(Self::Item, Self::Item) -> R,
@@ -2742,7 +2702,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_do_not_const_check]
     fn all<F>(&mut self, f: F) -> bool
     where
         Self: Sized,
@@ -2796,7 +2755,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_do_not_const_check]
     fn any<F>(&mut self, f: F) -> bool
     where
         Self: Sized,
@@ -2860,7 +2818,6 @@ pub trait Iterator {
     /// Note that `iter.find(f)` is equivalent to `iter.filter(f).next()`.
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_do_not_const_check]
     fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
     where
         Self: Sized,
@@ -2892,7 +2849,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[stable(feature = "iterator_find_map", since = "1.30.0")]
-    #[rustc_do_not_const_check]
     fn find_map<B, F>(&mut self, f: F) -> Option<B>
     where
         Self: Sized,
@@ -2951,7 +2907,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[unstable(feature = "try_find", reason = "new API", issue = "63178")]
-    #[rustc_do_not_const_check]
     fn try_find<R>(
         &mut self,
         f: impl FnMut(&Self::Item) -> R,
@@ -3035,7 +2990,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_do_not_const_check]
     fn position<P>(&mut self, predicate: P) -> Option<usize>
     where
         Self: Sized,
@@ -3100,7 +3054,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_do_not_const_check]
     fn rposition<P>(&mut self, predicate: P) -> Option<usize>
     where
         P: FnMut(Self::Item) -> bool,
@@ -3150,7 +3103,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_do_not_const_check]
     fn max(self) -> Option<Self::Item>
     where
         Self: Sized,
@@ -3187,7 +3139,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_do_not_const_check]
     fn min(self) -> Option<Self::Item>
     where
         Self: Sized,
@@ -3210,7 +3161,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[stable(feature = "iter_cmp_by_key", since = "1.6.0")]
-    #[rustc_do_not_const_check]
     fn max_by_key<B: Ord, F>(self, f: F) -> Option<Self::Item>
     where
         Self: Sized,
@@ -3244,7 +3194,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[stable(feature = "iter_max_by", since = "1.15.0")]
-    #[rustc_do_not_const_check]
     fn max_by<F>(self, compare: F) -> Option<Self::Item>
     where
         Self: Sized,
@@ -3272,7 +3221,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[stable(feature = "iter_cmp_by_key", since = "1.6.0")]
-    #[rustc_do_not_const_check]
     fn min_by_key<B: Ord, F>(self, f: F) -> Option<Self::Item>
     where
         Self: Sized,
@@ -3306,7 +3254,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[stable(feature = "iter_min_by", since = "1.15.0")]
-    #[rustc_do_not_const_check]
     fn min_by<F>(self, compare: F) -> Option<Self::Item>
     where
         Self: Sized,
@@ -3344,7 +3291,6 @@ pub trait Iterator {
     #[inline]
     #[doc(alias = "reverse")]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_do_not_const_check]
     fn rev(self) -> Rev<Self>
     where
         Self: Sized + DoubleEndedIterator,
@@ -3381,7 +3327,6 @@ pub trait Iterator {
     /// assert_eq!(z, [3, 6]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_do_not_const_check]
     fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB)
     where
         FromA: Default + Extend<A>,
@@ -3412,7 +3357,6 @@ pub trait Iterator {
     /// assert_eq!(v_map, vec![1, 2, 3]);
     /// ```
     #[stable(feature = "iter_copied", since = "1.36.0")]
-    #[rustc_do_not_const_check]
     #[cfg_attr(not(test), rustc_diagnostic_item = "iter_copied")]
     fn copied<'a, T: 'a>(self) -> Copied<Self>
     where
@@ -3461,7 +3405,6 @@ pub trait Iterator {
     /// assert_eq!(&[vec![23]], &faster[..]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_do_not_const_check]
     #[cfg_attr(not(test), rustc_diagnostic_item = "iter_cloned")]
     fn cloned<'a, T: 'a>(self) -> Cloned<Self>
     where
@@ -3495,7 +3438,6 @@ pub trait Iterator {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    #[rustc_do_not_const_check]
     fn cycle(self) -> Cycle<Self>
     where
         Self: Sized + Clone,
@@ -3539,7 +3481,6 @@ pub trait Iterator {
     /// ```
     #[track_caller]
     #[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")]
-    #[rustc_do_not_const_check]
     fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N>
     where
         Self: Sized,
@@ -3571,7 +3512,6 @@ pub trait Iterator {
     /// assert_eq!(sum, 6);
     /// ```
     #[stable(feature = "iter_arith", since = "1.11.0")]
-    #[rustc_do_not_const_check]
     fn sum<S>(self) -> S
     where
         Self: Sized,
@@ -3604,7 +3544,6 @@ pub trait Iterator {
     /// assert_eq!(factorial(5), 120);
     /// ```
     #[stable(feature = "iter_arith", since = "1.11.0")]
-    #[rustc_do_not_const_check]
     fn product<P>(self) -> P
     where
         Self: Sized,
@@ -3626,7 +3565,6 @@ pub trait Iterator {
     /// assert_eq!([1, 2].iter().cmp([1].iter()), Ordering::Greater);
     /// ```
     #[stable(feature = "iter_order", since = "1.5.0")]
-    #[rustc_do_not_const_check]
     fn cmp<I>(self, other: I) -> Ordering
     where
         I: IntoIterator<Item = Self::Item>,
@@ -3654,7 +3592,6 @@ pub trait Iterator {
     /// assert_eq!(xs.iter().cmp_by(&ys, |&x, &y| (2 * x).cmp(&y)), Ordering::Greater);
     /// ```
     #[unstable(feature = "iter_order_by", issue = "64295")]
-    #[rustc_do_not_const_check]
     fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering
     where
         Self: Sized,
@@ -3711,7 +3648,6 @@ pub trait Iterator {
     /// ```
     ///
     #[stable(feature = "iter_order", since = "1.5.0")]
-    #[rustc_do_not_const_check]
     fn partial_cmp<I>(self, other: I) -> Option<Ordering>
     where
         I: IntoIterator,
@@ -3748,7 +3684,6 @@ pub trait Iterator {
     /// );
     /// ```
     #[unstable(feature = "iter_order_by", issue = "64295")]
-    #[rustc_do_not_const_check]
     fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering>
     where
         Self: Sized,
@@ -3782,7 +3717,6 @@ pub trait Iterator {
     /// assert_eq!([1].iter().eq([1, 2].iter()), false);
     /// ```
     #[stable(feature = "iter_order", since = "1.5.0")]
-    #[rustc_do_not_const_check]
     fn eq<I>(self, other: I) -> bool
     where
         I: IntoIterator,
@@ -3806,7 +3740,6 @@ pub trait Iterator {
     /// assert!(xs.iter().eq_by(&ys, |&x, &y| x * x == y));
     /// ```
     #[unstable(feature = "iter_order_by", issue = "64295")]
-    #[rustc_do_not_const_check]
     fn eq_by<I, F>(self, other: I, eq: F) -> bool
     where
         Self: Sized,
@@ -3839,7 +3772,6 @@ pub trait Iterator {
     /// assert_eq!([1].iter().ne([1, 2].iter()), true);
     /// ```
     #[stable(feature = "iter_order", since = "1.5.0")]
-    #[rustc_do_not_const_check]
     fn ne<I>(self, other: I) -> bool
     where
         I: IntoIterator,
@@ -3861,7 +3793,6 @@ pub trait Iterator {
     /// assert_eq!([1, 2].iter().lt([1, 2].iter()), false);
     /// ```
     #[stable(feature = "iter_order", since = "1.5.0")]
-    #[rustc_do_not_const_check]
     fn lt<I>(self, other: I) -> bool
     where
         I: IntoIterator,
@@ -3883,7 +3814,6 @@ pub trait Iterator {
     /// assert_eq!([1, 2].iter().le([1, 2].iter()), true);
     /// ```
     #[stable(feature = "iter_order", since = "1.5.0")]
-    #[rustc_do_not_const_check]
     fn le<I>(self, other: I) -> bool
     where
         I: IntoIterator,
@@ -3905,7 +3835,6 @@ pub trait Iterator {
     /// assert_eq!([1, 2].iter().gt([1, 2].iter()), false);
     /// ```
     #[stable(feature = "iter_order", since = "1.5.0")]
-    #[rustc_do_not_const_check]
     fn gt<I>(self, other: I) -> bool
     where
         I: IntoIterator,
@@ -3927,7 +3856,6 @@ pub trait Iterator {
     /// assert_eq!([1, 2].iter().ge([1, 2].iter()), true);
     /// ```
     #[stable(feature = "iter_order", since = "1.5.0")]
-    #[rustc_do_not_const_check]
     fn ge<I>(self, other: I) -> bool
     where
         I: IntoIterator,
@@ -3957,7 +3885,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[stable(feature = "is_sorted", since = "1.82.0")]
-    #[rustc_do_not_const_check]
     fn is_sorted(self) -> bool
     where
         Self: Sized,
@@ -3984,7 +3911,6 @@ pub trait Iterator {
     /// assert!(std::iter::empty::<i32>().is_sorted_by(|a, b| true));
     /// ```
     #[stable(feature = "is_sorted", since = "1.82.0")]
-    #[rustc_do_not_const_check]
     fn is_sorted_by<F>(mut self, compare: F) -> bool
     where
         Self: Sized,
@@ -4029,7 +3955,6 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[stable(feature = "is_sorted", since = "1.82.0")]
-    #[rustc_do_not_const_check]
     fn is_sorted_by_key<F, K>(self, f: F) -> bool
     where
         Self: Sized,
@@ -4045,7 +3970,6 @@ pub trait Iterator {
     #[inline]
     #[doc(hidden)]
     #[unstable(feature = "trusted_random_access", issue = "none")]
-    #[rustc_do_not_const_check]
     unsafe fn __iterator_get_unchecked(&mut self, _idx: usize) -> Self::Item
     where
         Self: TrustedRandomAccessNoCoerce,
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 74f79059fe4..115fdd7a140 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -185,7 +185,9 @@
 #![feature(cfg_target_has_atomic_equal_alignment)]
 #![feature(cfg_ub_checks)]
 #![feature(const_for)]
+#![feature(const_is_char_boundary)]
 #![feature(const_precise_live_drops)]
+#![feature(const_str_split_at)]
 #![feature(decl_macro)]
 #![feature(deprecated_suggestion)]
 #![feature(doc_cfg)]
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index 9a5e211dd60..6a0b40ff517 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -429,7 +429,7 @@ impl i64 {
         from_xe_bytes_doc = "",
         bound_condition = "",
     }
-    midpoint_impl! { i64, i128, signed }
+    midpoint_impl! { i64, signed }
 }
 
 impl i128 {
@@ -530,7 +530,7 @@ impl isize {
         from_xe_bytes_doc = usize_isize_from_xe_bytes_doc!(),
         bound_condition = " on 64-bit targets",
     }
-    midpoint_impl! { isize, i128, signed }
+    midpoint_impl! { isize, signed }
 }
 
 /// If the 6th bit is set ascii is lower case.
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index 89addc4cb74..9ef99e9dae8 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -185,8 +185,9 @@ impl str {
     /// ```
     #[must_use]
     #[stable(feature = "is_char_boundary", since = "1.9.0")]
+    #[rustc_const_unstable(feature = "const_is_char_boundary", issue = "131516")]
     #[inline]
-    pub fn is_char_boundary(&self, index: usize) -> bool {
+    pub const fn is_char_boundary(&self, index: usize) -> bool {
         // 0 is always ok.
         // Test for 0 explicitly so that it can optimize out the check
         // easily and skip reading string data for that case.
@@ -195,8 +196,8 @@ impl str {
             return true;
         }
 
-        match self.as_bytes().get(index) {
-            // For `None` we have two options:
+        if index >= self.len() {
+            // For `true` we have two options:
             //
             // - index == self.len()
             //   Empty strings are valid, so return true
@@ -205,9 +206,9 @@ impl str {
             //
             // The check is placed exactly here, because it improves generated
             // code on higher opt-levels. See PR #84751 for more details.
-            None => index == self.len(),
-
-            Some(&b) => b.is_utf8_char_boundary(),
+            index == self.len()
+        } else {
+            self.as_bytes()[index].is_utf8_char_boundary()
         }
     }
 
@@ -637,7 +638,8 @@ impl str {
     #[inline]
     #[must_use]
     #[stable(feature = "str_split_at", since = "1.4.0")]
-    pub fn split_at(&self, mid: usize) -> (&str, &str) {
+    #[rustc_const_unstable(feature = "const_str_split_at", issue = "131518")]
+    pub const fn split_at(&self, mid: usize) -> (&str, &str) {
         match self.split_at_checked(mid) {
             None => slice_error_fail(self, 0, mid),
             Some(pair) => pair,
@@ -677,7 +679,8 @@ impl str {
     #[inline]
     #[must_use]
     #[stable(feature = "str_split_at", since = "1.4.0")]
-    pub fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str) {
+    #[rustc_const_unstable(feature = "const_str_split_at", issue = "131518")]
+    pub const fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str) {
         // is_char_boundary checks that the index is in [0, .len()]
         if self.is_char_boundary(mid) {
             // SAFETY: just checked that `mid` is on a char boundary.
@@ -716,11 +719,12 @@ impl str {
     #[inline]
     #[must_use]
     #[stable(feature = "split_at_checked", since = "1.80.0")]
-    pub fn split_at_checked(&self, mid: usize) -> Option<(&str, &str)> {
+    #[rustc_const_unstable(feature = "const_str_split_at", issue = "131518")]
+    pub const fn split_at_checked(&self, mid: usize) -> Option<(&str, &str)> {
         // is_char_boundary checks that the index is in [0, .len()]
         if self.is_char_boundary(mid) {
             // SAFETY: just checked that `mid` is on a char boundary.
-            Some(unsafe { (self.get_unchecked(0..mid), self.get_unchecked(mid..self.len())) })
+            Some(unsafe { self.split_at_unchecked(mid) })
         } else {
             None
         }
@@ -756,7 +760,9 @@ impl str {
     #[inline]
     #[must_use]
     #[stable(feature = "split_at_checked", since = "1.80.0")]
-    pub fn split_at_mut_checked(&mut self, mid: usize) -> Option<(&mut str, &mut str)> {
+    #[rustc_const_unstable(feature = "const_str_split_at", issue = "131518")]
+    #[rustc_allow_const_fn_unstable(const_is_char_boundary)]
+    pub const fn split_at_mut_checked(&mut self, mid: usize) -> Option<(&mut str, &mut str)> {
         // is_char_boundary checks that the index is in [0, .len()]
         if self.is_char_boundary(mid) {
             // SAFETY: just checked that `mid` is on a char boundary.
@@ -772,7 +778,25 @@ impl str {
     ///
     /// The caller must ensure that `mid` is a valid byte offset from the start
     /// of the string and falls on the boundary of a UTF-8 code point.
-    unsafe fn split_at_mut_unchecked(&mut self, mid: usize) -> (&mut str, &mut str) {
+    const unsafe fn split_at_unchecked(&self, mid: usize) -> (&str, &str) {
+        let len = self.len();
+        let ptr = self.as_ptr();
+        // SAFETY: caller guarantees `mid` is on a char boundary.
+        unsafe {
+            (
+                from_utf8_unchecked(slice::from_raw_parts(ptr, mid)),
+                from_utf8_unchecked(slice::from_raw_parts(ptr.add(mid), len - mid)),
+            )
+        }
+    }
+
+    /// Divides one string slice into two at an index.
+    ///
+    /// # Safety
+    ///
+    /// The caller must ensure that `mid` is a valid byte offset from the start
+    /// of the string and falls on the boundary of a UTF-8 code point.
+    const unsafe fn split_at_mut_unchecked(&mut self, mid: usize) -> (&mut str, &mut str) {
         let len = self.len();
         let ptr = self.as_mut_ptr();
         // SAFETY: caller guarantees `mid` is on a char boundary.
diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs
index ae47bb7adf4..15770248b31 100644
--- a/library/proc_macro/src/lib.rs
+++ b/library/proc_macro/src/lib.rs
@@ -32,6 +32,7 @@
 #![feature(restricted_std)]
 #![feature(rustc_attrs)]
 #![feature(min_specialization)]
+#![feature(extend_one)]
 #![recursion_limit = "256"]
 #![allow(internal_features)]
 #![deny(ffi_unwind_calls)]
@@ -43,6 +44,7 @@ pub mod bridge;
 
 mod diagnostic;
 mod escape;
+mod to_tokens;
 
 use std::ffi::CStr;
 use std::ops::{Range, RangeBounds};
@@ -52,6 +54,8 @@ use std::{error, fmt};
 
 #[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
 pub use diagnostic::{Diagnostic, Level, MultiSpan};
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+pub use to_tokens::ToTokens;
 
 use crate::escape::{EscapeOptions, escape_bytes};
 
diff --git a/library/proc_macro/src/to_tokens.rs b/library/proc_macro/src/to_tokens.rs
new file mode 100644
index 00000000000..8f697b416d5
--- /dev/null
+++ b/library/proc_macro/src/to_tokens.rs
@@ -0,0 +1,310 @@
+use std::borrow::Cow;
+use std::ffi::{CStr, CString};
+use std::rc::Rc;
+
+use crate::{ConcatTreesHelper, Group, Ident, Literal, Punct, Span, TokenStream, TokenTree};
+
+/// Types that can be interpolated inside a [`quote!`] invocation.
+///
+/// [`quote!`]: crate::quote!
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+pub trait ToTokens {
+    /// Write `self` to the given `TokenStream`.
+    ///
+    /// # Example
+    ///
+    /// Example implementation for a struct representing Rust paths like
+    /// `std::cmp::PartialEq`:
+    ///
+    /// ```
+    /// #![feature(proc_macro_totokens)]
+    ///
+    /// use std::iter;
+    /// use proc_macro::{Spacing, Punct, TokenStream, TokenTree, ToTokens};
+    ///
+    /// pub struct Path {
+    ///     pub global: bool,
+    ///     pub segments: Vec<PathSegment>,
+    /// }
+    ///
+    /// impl ToTokens for Path {
+    ///     fn to_tokens(&self, tokens: &mut TokenStream) {
+    ///         for (i, segment) in self.segments.iter().enumerate() {
+    ///             if i > 0 || self.global {
+    ///                 // Double colon `::`
+    ///                 tokens.extend(iter::once(TokenTree::from(Punct::new(':', Spacing::Joint))));
+    ///                 tokens.extend(iter::once(TokenTree::from(Punct::new(':', Spacing::Alone))));
+    ///             }
+    ///             segment.to_tokens(tokens);
+    ///         }
+    ///     }
+    /// }
+    /// #
+    /// # pub struct PathSegment;
+    /// #
+    /// # impl ToTokens for PathSegment {
+    /// #     fn to_tokens(&self, tokens: &mut TokenStream) {
+    /// #         unimplemented!()
+    /// #     }
+    /// # }
+    /// ```
+    fn to_tokens(&self, tokens: &mut TokenStream);
+
+    /// Convert `self` directly into a `TokenStream` object.
+    ///
+    /// This method is implicitly implemented using `to_tokens`, and acts as a
+    /// convenience method for consumers of the `ToTokens` trait.
+    fn to_token_stream(&self) -> TokenStream {
+        let mut tokens = TokenStream::new();
+        self.to_tokens(&mut tokens);
+        tokens
+    }
+
+    /// Convert `self` directly into a `TokenStream` object.
+    ///
+    /// This method is implicitly implemented using `to_tokens`, and acts as a
+    /// convenience method for consumers of the `ToTokens` trait.
+    fn into_token_stream(self) -> TokenStream
+    where
+        Self: Sized,
+    {
+        self.to_token_stream()
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for TokenTree {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        tokens.extend_one(self.clone());
+    }
+
+    fn into_token_stream(self) -> TokenStream {
+        let mut builder = ConcatTreesHelper::new(1);
+        builder.push(self);
+        builder.build()
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for TokenStream {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        tokens.extend(self.clone());
+    }
+
+    fn into_token_stream(self) -> TokenStream {
+        self
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for Literal {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        tokens.extend_one(TokenTree::from(self.clone()));
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for Ident {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        tokens.extend_one(TokenTree::from(self.clone()));
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for Punct {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        tokens.extend_one(TokenTree::from(self.clone()));
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for Group {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        tokens.extend_one(TokenTree::from(self.clone()));
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl<T: ToTokens + ?Sized> ToTokens for &T {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        (**self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl<T: ToTokens + ?Sized> ToTokens for &mut T {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        (**self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl<T: ToTokens + ?Sized> ToTokens for Box<T> {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        (**self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl<T: ToTokens + ?Sized> ToTokens for Rc<T> {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        (**self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl<T: ToTokens + ToOwned + ?Sized> ToTokens for Cow<'_, T> {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        (**self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl<T: ToTokens> ToTokens for Option<T> {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        if let Some(t) = self {
+            t.to_tokens(tokens);
+        }
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for u8 {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::u8_suffixed(*self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for u16 {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::u16_suffixed(*self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for u32 {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::u32_suffixed(*self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for u64 {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::u64_suffixed(*self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for u128 {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::u128_suffixed(*self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for i8 {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::i8_suffixed(*self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for i16 {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::i16_suffixed(*self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for i32 {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::i32_suffixed(*self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for i64 {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::i64_suffixed(*self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for i128 {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::i128_suffixed(*self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for f32 {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::f32_suffixed(*self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for f64 {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::f64_suffixed(*self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for usize {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::usize_suffixed(*self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for isize {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::isize_suffixed(*self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for bool {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        let word = if *self { "true" } else { "false" };
+        Ident::new(word, Span::call_site()).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for char {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::character(*self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for str {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::string(self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for String {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::string(self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for CStr {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::c_string(self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for CString {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::c_string(self).to_tokens(tokens)
+    }
+}
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index bfb9df7d781..9b66fc8f921 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -17,7 +17,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
 panic_unwind = { path = "../panic_unwind", optional = true }
 panic_abort = { path = "../panic_abort" }
 core = { path = "../core", public = true }
-compiler_builtins = { version = "0.1.134" }
+compiler_builtins = { version = "0.1.136" }
 unwind = { path = "../unwind" }
 hashbrown = { version = "0.15", default-features = false, features = [
     'rustc-dep-of-std',
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 8a0d2a7f5cf..3079c8b1d90 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -1197,7 +1197,7 @@ impl OpenOptions {
 
     /// Sets the option for truncating a previous file.
     ///
-    /// If a file is successfully opened with this option set it will truncate
+    /// If a file is successfully opened with this option set to true, it will truncate
     /// the file to 0 length if it already exists.
     ///
     /// The file must be opened with write access for truncate to work.
diff --git a/library/std/src/sys/sync/condvar/xous.rs b/library/std/src/sys/sync/condvar/xous.rs
index cb55a3e3369..b9e5f47abfc 100644
--- a/library/std/src/sys/sync/condvar/xous.rs
+++ b/library/std/src/sys/sync/condvar/xous.rs
@@ -20,7 +20,6 @@ unsafe impl Sync for Condvar {}
 
 impl Condvar {
     #[inline]
-    #[rustc_const_stable(feature = "const_locks", since = "1.63.0")]
     pub const fn new() -> Condvar {
         Condvar { counter: AtomicUsize::new(0), timed_out: AtomicUsize::new(0) }
     }
diff --git a/library/std/src/sys/sync/mutex/xous.rs b/library/std/src/sys/sync/mutex/xous.rs
index 233e638f913..c6b954c1711 100644
--- a/library/std/src/sys/sync/mutex/xous.rs
+++ b/library/std/src/sys/sync/mutex/xous.rs
@@ -24,7 +24,6 @@ pub struct Mutex {
 
 impl Mutex {
     #[inline]
-    #[rustc_const_stable(feature = "const_locks", since = "1.63.0")]
     pub const fn new() -> Mutex {
         Mutex { locked: AtomicUsize::new(0), contended: AtomicBool::new(false) }
     }
diff --git a/src/bootstrap/src/bin/rustc.rs b/src/bootstrap/src/bin/rustc.rs
index 18f5a1a58db..88595ff7e51 100644
--- a/src/bootstrap/src/bin/rustc.rs
+++ b/src/bootstrap/src/bin/rustc.rs
@@ -175,9 +175,7 @@ fn main() {
         // Find any host flags that were passed by bootstrap.
         // The flags are stored in a RUSTC_HOST_FLAGS variable, separated by spaces.
         if let Ok(flags) = std::env::var("RUSTC_HOST_FLAGS") {
-            for flag in flags.split(' ') {
-                cmd.arg(flag);
-            }
+            cmd.args(flags.split(' '));
         }
     }
 
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index e13d4ccc618..4ab4e60773f 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -153,7 +153,6 @@ impl Step for Std {
             // NOTE: the beta compiler may generate different artifacts than the downloaded compiler, so
             // its artifacts can't be reused.
             && compiler.stage != 0
-            // This check is specific to testing std itself; see `test::Std` for more details.
             && !self.force_recompile
         {
             let sysroot = builder.ensure(Sysroot { compiler, force_recompile: false });
@@ -1057,6 +1056,14 @@ pub fn rustc_cargo(
         cargo.rustflag("-l").rustflag("Enzyme-19");
     }
 
+    // Building with protected visibility reduces the number of dynamic relocations needed, giving
+    // us a faster startup time. However GNU ld < 2.40 will error if we try to link a shared object
+    // with direct references to protected symbols, so for now we only use protected symbols if
+    // linking with LLD is enabled.
+    if builder.build.config.lld_mode.is_used() {
+        cargo.rustflag("-Zdefault-visibility=protected");
+    }
+
     // We currently don't support cross-crate LTO in stage0. This also isn't hugely necessary
     // and may just be a time sink.
     if compiler.stage != 0 {
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index 2ad1b39a87c..0a290a697e6 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -1725,6 +1725,11 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
         cmd.arg("--run-lib-path").arg(builder.sysroot_libdir(compiler, target));
         cmd.arg("--rustc-path").arg(builder.rustc(compiler));
 
+        // Minicore auxiliary lib for `no_core` tests that need `core` stubs in cross-compilation
+        // scenarios.
+        cmd.arg("--minicore-path")
+            .arg(builder.src.join("tests").join("auxiliary").join("minicore.rs"));
+
         let is_rustdoc = suite.ends_with("rustdoc-ui") || suite.ends_with("rustdoc-js");
 
         if mode == "run-make" {
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index 139ca7eb52e..8115aea033d 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -2767,25 +2767,32 @@ impl Config {
             }
         };
 
-        let files_to_track =
-            &["compiler", "library", "src/version", "src/stage0", "src/ci/channel"];
+        let mut files_to_track = vec!["compiler", "src/version", "src/stage0", "src/ci/channel"];
+
+        // In CI, disable ci-rustc if there are changes in the library tree. But for non-CI, ignore
+        // these changes to speed up the build process for library developers. This provides consistent
+        // functionality for library developers between `download-rustc=true` and `download-rustc="if-unchanged"`
+        // options.
+        if CiEnv::is_ci() {
+            files_to_track.push("library");
+        }
 
         // Look for a version to compare to based on the current commit.
         // Only commits merged by bors will have CI artifacts.
-        let commit = match self.last_modified_commit(files_to_track, "download-rustc", if_unchanged)
-        {
-            Some(commit) => commit,
-            None => {
-                if if_unchanged {
-                    return None;
+        let commit =
+            match self.last_modified_commit(&files_to_track, "download-rustc", if_unchanged) {
+                Some(commit) => commit,
+                None => {
+                    if if_unchanged {
+                        return None;
+                    }
+                    println!("ERROR: could not find commit hash for downloading rustc");
+                    println!("HELP: maybe your repository history is too shallow?");
+                    println!("HELP: consider disabling `download-rustc`");
+                    println!("HELP: or fetch enough history to include one upstream commit");
+                    crate::exit!(1);
                 }
-                println!("ERROR: could not find commit hash for downloading rustc");
-                println!("HELP: maybe your repository history is too shallow?");
-                println!("HELP: consider disabling `download-rustc`");
-                println!("HELP: or fetch enough history to include one upstream commit");
-                crate::exit!(1);
-            }
-        };
+            };
 
         if CiEnv::is_ci() && {
             let head_sha =
diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile
index 0f8ebb987c3..fdc8a7310c8 100644
--- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile
+++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile
@@ -51,7 +51,8 @@ ENV SCRIPT \
            /scripts/check-default-config-profiles.sh && \
            python3 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \
            python3 ../x.py clippy bootstrap -Dwarnings && \
-           python3 ../x.py clippy compiler library -Aclippy::all -Dclippy::correctness && \
+           python3 ../x.py clippy library -Aclippy::all -Dclippy::correctness && \
+           python3 ../x.py clippy compiler -Aclippy::all -Dclippy::correctness -Dclippy::clone_on_ref_ptr && \
            python3 ../x.py build --stage 0 src/tools/build-manifest && \
            python3 ../x.py test --stage 0 src/tools/compiletest && \
            python3 ../x.py test --stage 0 core alloc std test proc_macro && \
diff --git a/src/ci/docker/host-x86_64/x86_64-fuchsia/build-fuchsia.sh b/src/ci/docker/host-x86_64/x86_64-fuchsia/build-fuchsia.sh
index 1a0b141e984..969389f92f7 100755
--- a/src/ci/docker/host-x86_64/x86_64-fuchsia/build-fuchsia.sh
+++ b/src/ci/docker/host-x86_64/x86_64-fuchsia/build-fuchsia.sh
@@ -35,7 +35,7 @@ PICK_REFS=()
 # commit hash of fuchsia.git and some other repos in the "monorepo" checkout, in
 # addition to versions of prebuilts. It should be bumped regularly by the
 # Fuchsia team – we aim for every 1-2 months.
-INTEGRATION_SHA=1c5b42266fbfefb2337c6b2f0030a91bde15f9e9
+INTEGRATION_SHA=9f632bb7446d5a6af2998f1a0ebdb4b8ea2f4511
 
 checkout=fuchsia
 jiri=.jiri_root/bin/jiri
diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml
index a401092a3a7..8b7126d81d0 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -232,7 +232,7 @@ auto:
   # Tests integration with Rust for Linux.
   # Builds stage 1 compiler and tries to compile a few RfL examples with it.
   - image: x86_64-rust-for-linux
-    <<: *job-linux-8c
+    <<: *job-linux-4c
 
   - image: x86_64-gnu
     <<: *job-linux-4c
@@ -280,7 +280,7 @@ auto:
   - image: x86_64-gnu-tools
     env:
       DEPLOY_TOOLSTATES_JSON: toolstates-linux.json
-    <<: *job-linux-8c
+    <<: *job-linux-4c
 
   ####################
   #  macOS Builders  #
@@ -488,7 +488,7 @@ auto:
       SCRIPT: python x.py dist bootstrap --include-default-paths
       DIST_REQUIRE_ALL_TOOLS: 1
       CODEGEN_BACKENDS: llvm,cranelift
-    <<: *job-windows-8c
+    <<: *job-windows
 
   - image: dist-x86_64-mingw
     env:
@@ -501,10 +501,10 @@ auto:
       NO_DOWNLOAD_CI_LLVM: 1
       DIST_REQUIRE_ALL_TOOLS: 1
       CODEGEN_BACKENDS: llvm,cranelift
-    <<: *job-windows-8c
+    <<: *job-windows
 
   - image: dist-x86_64-msvc-alt
     env:
       RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler
       SCRIPT: python x.py dist bootstrap --include-default-paths
-    <<: *job-windows-8c
+    <<: *job-windows
diff --git a/src/doc/rustc/src/platform-support/aix.md b/src/doc/rustc/src/platform-support/aix.md
index c3ce71a1835..5a198062b95 100644
--- a/src/doc/rustc/src/platform-support/aix.md
+++ b/src/doc/rustc/src/platform-support/aix.md
@@ -6,8 +6,8 @@ Rust for AIX operating system, currently only 64-bit PowerPC is supported.
 
 ## Target maintainers
 
-- QIU Chaofan `qiucofan@cn.ibm.com`, https://github.com/ecnelises
-- Kai LUO, `lkail@cn.ibm.com`, https://github.com/bzEq
+- David Tenty `daltenty@ibm.com`, https://github.com/daltenty
+- Chris Cambly, `ccambly@ca.ibm.com`, https://github.com/gilamn5tr
 
 ## Requirements
 
diff --git a/src/doc/rustc/src/platform-support/apple-darwin.md b/src/doc/rustc/src/platform-support/apple-darwin.md
index c3a7b81f411..17ea225805b 100644
--- a/src/doc/rustc/src/platform-support/apple-darwin.md
+++ b/src/doc/rustc/src/platform-support/apple-darwin.md
@@ -52,5 +52,10 @@ Cross-compilation of these targets are supported using Clang, but may require
 Xcode or the macOS SDK (`MacOSX.sdk`) to be available to compile C code and
 to link.
 
+The Clang target is suffixed with `-macosx`. Clang's `-darwin` target refers
+to Darwin platforms in general (macOS/iOS/tvOS/watchOS/visionOS), and requires
+the `-mmacosx-version-min=...`, `-miphoneos-version-min=...` or similar flags
+to disambiguate.
+
 The path to the SDK can be passed to `rustc` using the common `SDKROOT`
 environment variable.
diff --git a/src/doc/rustc/src/platform-support/fuchsia.md b/src/doc/rustc/src/platform-support/fuchsia.md
index 5643c6a0188..489f46e1cb9 100644
--- a/src/doc/rustc/src/platform-support/fuchsia.md
+++ b/src/doc/rustc/src/platform-support/fuchsia.md
@@ -7,17 +7,9 @@ updatable, and performant.
 
 ## Target maintainers
 
-The [Fuchsia team]:
+See [`fuchsia.toml`] in the `team` repository for current target maintainers.
 
-- Tyler Mandry ([@tmandry](https://github.com/tmandry))
-- David Koloski ([@djkoloski](https://github.com/djkoloski))
-- Julia Ryan ([@P1n3appl3](https://github.com/P1n3appl3))
-- Erick Tryzelaar ([@erickt](https://github.com/erickt))
-
-As the team evolves over time, the specific members listed here may differ from
-the members reported by the API. The API should be considered to be
-authoritative if this occurs. Instead of pinging individual members, use
-`@rustbot ping fuchsia` to contact the team on GitHub.
+[`fuchsia.toml`]: https://github.com/rust-lang/team/blob/master/teams/fuchsia.toml
 
 ## Table of contents
 
@@ -525,14 +517,6 @@ ${SDK_PATH}/tools/${ARCH}/ffx repository publish \
     pkg/repo
 ```
 
-Then we can add the repository to `ffx`'s package server as `hello-fuchsia` using:
-
-```sh
-${SDK_PATH}/tools/${ARCH}/ffx repository add-from-pm \
-    --repository hello-fuchsia \
-    pkg/repo
-```
-
 ## Running a Fuchsia component on an emulator
 
 At this point, we are ready to run our Fuchsia
@@ -590,7 +574,8 @@ Now, start a package repository server to serve our
 package to the emulator:
 
 ```sh
-${SDK_PATH}/tools/${ARCH}/ffx repository server start
+${SDK_PATH}/tools/${ARCH}/ffx repository server start \
+    --background --repository hello-fuchsia --repo-path pkg-repo
 ```
 
 Once the repository server is up and running, register it with the target Fuchsia system running in the emulator:
diff --git a/src/etc/htmldocck.py b/src/etc/htmldocck.py
index 599e1e8102c..851b01a7458 100755
--- a/src/etc/htmldocck.py
+++ b/src/etc/htmldocck.py
@@ -250,7 +250,7 @@ def get_known_directive_names():
         os.path.join(
             # We go back to `src`.
             os.path.dirname(os.path.dirname(__file__)),
-            "tools/compiletest/src/command-list.rs",
+            "tools/compiletest/src/directive-list.rs",
         ),
         "r",
         encoding="utf8"
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index 1f3cb4a61b8..a6d9676dd84 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -1,7 +1,7 @@
 use rustc_hir as hir;
 use rustc_infer::infer::{DefineOpaqueTypes, InferOk, TyCtxtInferExt};
 use rustc_infer::traits;
-use rustc_middle::ty::{self, Upcast};
+use rustc_middle::ty::{self, TypingMode, Upcast};
 use rustc_span::DUMMY_SP;
 use rustc_span::def_id::DefId;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
@@ -38,7 +38,7 @@ pub(crate) fn synthesize_blanket_impls(
             if !matches!(trait_ref.skip_binder().self_ty().kind(), ty::Param(_)) {
                 continue;
             }
-            let infcx = tcx.infer_ctxt().build();
+            let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
             let args = infcx.fresh_args_for_item(DUMMY_SP, item_def_id);
             let impl_ty = ty.instantiate(tcx, args);
             let param_env = ty::ParamEnv::empty();
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index ea349f878e0..58663fcbafe 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -45,7 +45,7 @@ use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LOCAL_CRATE, LocalDefId};
 use rustc_hir_analysis::lower_ty;
 use rustc_middle::metadata::Reexport;
 use rustc_middle::middle::resolve_bound_vars as rbv;
-use rustc_middle::ty::{self, AdtKind, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{self, AdtKind, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt, TypingMode};
 use rustc_middle::{bug, span_bug};
 use rustc_span::ExpnKind;
 use rustc_span::hygiene::{AstPass, MacroKind};
@@ -1829,7 +1829,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
             Array(Box::new(clean_ty(ty, cx)), length.into())
         }
         TyKind::Tup(tys) => Tuple(tys.iter().map(|ty| clean_ty(ty, cx)).collect()),
-        TyKind::OpaqueDef(ty, _) => {
+        TyKind::OpaqueDef(ty) => {
             ImplTrait(ty.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect())
         }
         TyKind::Path(_) => clean_qpath(ty, cx),
@@ -1863,7 +1863,7 @@ fn normalize<'tcx>(
     use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
 
     // Try to normalize `<X as Y>::T` to a type
-    let infcx = cx.tcx.infer_ctxt().build();
+    let infcx = cx.tcx.infer_ctxt().build(TypingMode::non_body_analysis());
     let normalized = infcx
         .at(&ObligationCause::dummy(), cx.param_env)
         .query_normalize(ty)
@@ -2399,7 +2399,7 @@ pub(crate) fn clean_variant_def_with_args<'tcx>(
     use rustc_trait_selection::infer::TyCtxtInferExt;
     use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
 
-    let infcx = cx.tcx.infer_ctxt().build();
+    let infcx = cx.tcx.infer_ctxt().build(TypingMode::non_body_analysis());
     let kind = match variant.ctor_kind() {
         Some(CtorKind::Const) => VariantKind::CLike,
         Some(CtorKind::Fn) => VariantKind::Tuple(
diff --git a/src/librustdoc/doctest/runner.rs b/src/librustdoc/doctest/runner.rs
index 093755103f3..234f40c6c1a 100644
--- a/src/librustdoc/doctest/runner.rs
+++ b/src/librustdoc/doctest/runner.rs
@@ -198,10 +198,6 @@ fn generate_mergeable_doctest(
     } else {
         writeln!(output, "mod {test_id} {{\n{}{}", doctest.crates, doctest.maybe_crate_attrs)
             .unwrap();
-        if scraped_test.langstr.no_run {
-            // To prevent having warnings about unused items since they're not called.
-            writeln!(output, "#![allow(unused)]").unwrap();
-        }
         if doctest.has_main_fn {
             output.push_str(&doctest.everything_else);
         } else {
diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs
index a9ab02e29cd..27d0be133fe 100644
--- a/src/librustdoc/doctest/rust.rs
+++ b/src/librustdoc/doctest/rust.rs
@@ -113,7 +113,19 @@ impl<'tcx> HirCollector<'tcx> {
         let attrs = Attributes::from_ast(ast_attrs);
         if let Some(doc) = attrs.opt_doc_value() {
             let span = span_of_fragments(&attrs.doc_strings).unwrap_or(sp);
-            self.collector.position = span;
+            self.collector.position = if span.edition().at_least_rust_2024() {
+                span
+            } else {
+                // this span affects filesystem path resolution,
+                // so we need to keep it the same as it was previously
+                ast_attrs
+                    .iter()
+                    .find(|attr| attr.doc_str().is_some())
+                    .map(|attr| {
+                        attr.span.ctxt().outer_expn().expansion_cause().unwrap_or(attr.span)
+                    })
+                    .unwrap_or(DUMMY_SP)
+            };
             markdown::find_testable_code(
                 &doc,
                 &mut self.collector,
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 8e8e5c6ade8..47c21d89177 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -20,8 +20,7 @@ use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_metadata::creader::{CStore, LoadedMacro};
-use rustc_middle::ty;
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::{self, TyCtxt, TypingMode};
 use rustc_span::symbol::kw;
 use rustc_span::{Symbol, sym};
 use rustc_target::spec::abi::Abi;
@@ -613,7 +612,7 @@ fn generate_item_def_id_path(
     // No need to try to infer the actual parent item if it's not an associated item from the `impl`
     // block.
     if def_id != original_def_id && matches!(tcx.def_kind(def_id), DefKind::Impl { .. }) {
-        let infcx = tcx.infer_ctxt().build();
+        let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
         def_id = infcx
             .at(&ObligationCause::dummy(), tcx.param_env(def_id))
             .query_normalize(ty::Binder::dummy(tcx.type_of(def_id).instantiate_identity()))
diff --git a/src/librustdoc/html/render/type_layout.rs b/src/librustdoc/html/render/type_layout.rs
index cd4e597ff28..79209cee94f 100644
--- a/src/librustdoc/html/render/type_layout.rs
+++ b/src/librustdoc/html/render/type_layout.rs
@@ -60,8 +60,8 @@ pub(crate) fn document_type_layout<'a, 'cx: 'a>(
                         span_bug!(tcx.def_span(ty_def_id), "not an adt")
                     };
                     let name = adt.variant(variant_idx).name;
-                    let is_unsized = variant_layout.abi.is_unsized();
-                    let is_uninhabited = variant_layout.abi.is_uninhabited();
+                    let is_unsized = variant_layout.is_unsized();
+                    let is_uninhabited = variant_layout.is_uninhabited();
                     let size = variant_layout.size.bytes() - tag_size;
                     let type_layout_size = TypeLayoutSize { is_unsized, is_uninhabited, size };
                     (name, type_layout_size)
@@ -72,8 +72,8 @@ pub(crate) fn document_type_layout<'a, 'cx: 'a>(
         };
 
         let type_layout_size = tcx.layout_of(param_env.and(ty)).map(|layout| {
-            let is_unsized = layout.abi.is_unsized();
-            let is_uninhabited = layout.abi.is_uninhabited();
+            let is_unsized = layout.is_unsized();
+            let is_uninhabited = layout.is_uninhabited();
             let size = layout.size.bytes();
             TypeLayoutSize { is_unsized, is_uninhabited, size }
         });
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 97e8b8f5b5f..1042d254749 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -230,7 +230,7 @@ h4.code-header {
 	padding: 0;
 	white-space: pre-wrap;
 }
-.structfield {
+.structfield, .sub-variant-field {
 	margin: 0.6em 0;
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index f34f5e05606..b167d7f2208 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -418,7 +418,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
                         let (required_refs, msg) = if can_auto_borrow {
                             (1, if deref_count == 1 { borrow_msg } else { deref_msg })
                         } else if let Some(&Adjustment {
-                            kind: Adjust::Borrow(AutoBorrow::Ref(_, mutability)),
+                            kind: Adjust::Borrow(AutoBorrow::Ref(mutability)),
                             ..
                         }) = next_adjust
                             && matches!(mutability, AutoBorrowMutability::Mut { .. })
diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
index cabc6592258..6ca599ed361 100644
--- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs
+++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
@@ -9,7 +9,8 @@ use rustc_hir::{BindingMode, Expr, ExprKind, FnRetTy, Param, PatKind, QPath, Saf
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::{
-    self, Binder, ClosureKind, FnSig, GenericArg, GenericArgKind, List, Region, Ty, TypeVisitableExt, TypeckResults,
+    self, Binder, ClosureKind, FnSig, GenericArg, GenericArgKind, List, Region, Ty, TypeVisitableExt,
+    TypeckResults,
 };
 use rustc_session::declare_lint_pass;
 use rustc_span::symbol::sym;
@@ -203,7 +204,7 @@ fn check_clousure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tc
                             // 'cuz currently nothing changes after deleting this check.
                             local_used_in(cx, l, args) || local_used_after_expr(cx, l, expr)
                         }) {
-                            match cx.tcx.infer_ctxt().build().err_ctxt().type_implements_fn_trait(
+                            match cx.tcx.infer_ctxt().build(cx.typing_mode()).err_ctxt().type_implements_fn_trait(
                                 cx.param_env,
                                 Binder::bind_with_vars(callee_ty_adjusted, List::empty()),
                                 ty::PredicatePolarity::Positive,
diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
index cfd11e9339f..c74ba088b78 100644
--- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
@@ -117,7 +117,7 @@ fn check_needless_must_use(
     } else if attr.value_str().is_none() && is_must_use_ty(cx, return_ty(cx, item_id)) {
         // Ignore async functions unless Future::Output type is a must_use type
         if sig.header.is_async() {
-            let infcx = cx.tcx.infer_ctxt().build();
+            let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode());
             if let Some(future_ty) = infcx.err_ctxt().get_impl_future_output_ty(return_ty(cx, item_id))
                 && !is_must_use_ty(cx, future_ty)
             {
diff --git a/src/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs
index a4dbe134f36..cf08c16458b 100644
--- a/src/tools/clippy/clippy_lints/src/future_not_send.rs
+++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs
@@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
             if is_future {
                 let send_trait = cx.tcx.get_diagnostic_item(sym::Send).unwrap();
                 let span = decl.output.span();
-                let infcx = cx.tcx.infer_ctxt().build();
+                let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode());
                 let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
                 let cause = traits::ObligationCause::misc(span, fn_def_id);
                 ocx.register_bound(cause, cx.param_env, ret_ty, send_trait);
diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs
index 5a3930b8bb8..d55be2b036a 100644
--- a/src/tools/clippy/clippy_lints/src/lifetimes.rs
+++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs
@@ -420,15 +420,6 @@ impl<'tcx> Visitor<'tcx> for RefVisitor<'_, 'tcx> {
 
     fn visit_ty(&mut self, ty: &'tcx Ty<'_>) {
         match ty.kind {
-            TyKind::OpaqueDef(opaque, bounds) => {
-                let len = self.lts.len();
-                self.visit_opaque_ty(opaque);
-                self.lts.truncate(len);
-                self.lts.extend(bounds.iter().filter_map(|bound| match bound {
-                    GenericArg::Lifetime(&l) => Some(l),
-                    _ => None,
-                }));
-            },
             TyKind::BareFn(&BareFnTy { decl, .. }) => {
                 let mut sub_visitor = RefVisitor::new(self.cx);
                 sub_visitor.visit_fn_decl(decl);
diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_into_iter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_into_iter_loop.rs
index 93d6b808646..d5ddc33e928 100644
--- a/src/tools/clippy/clippy_lints/src/loops/explicit_into_iter_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/explicit_into_iter_loop.rs
@@ -53,7 +53,7 @@ pub(super) fn check(cx: &LateContext<'_>, self_arg: &Expr<'_>, call_expr: &Expr<
         [] => AdjustKind::None,
         &[
             Adjustment {
-                kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl)),
+                kind: Adjust::Borrow(AutoBorrow::Ref(mutbl)),
                 ..
             },
         ] => AdjustKind::borrow(mutbl),
@@ -62,7 +62,7 @@ pub(super) fn check(cx: &LateContext<'_>, self_arg: &Expr<'_>, call_expr: &Expr<
                 kind: Adjust::Deref(_), ..
             },
             Adjustment {
-                kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl)),
+                kind: Adjust::Borrow(AutoBorrow::Ref(mutbl)),
                 target,
             },
         ] => {
diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs
index 022c6bcc70b..119e410b91c 100644
--- a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs
@@ -199,7 +199,7 @@ fn is_ref_iterable<'tcx>(
                     kind: Adjust::Deref(_), ..
                 },
                 Adjustment {
-                    kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl)),
+                    kind: Adjust::Borrow(AutoBorrow::Ref(mutbl)),
                     target,
                 },
                 ..,
@@ -236,7 +236,7 @@ fn is_ref_iterable<'tcx>(
             },
             &[
                 Adjustment {
-                    kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl)),
+                    kind: Adjust::Borrow(AutoBorrow::Ref(mutbl)),
                     target,
                 },
                 ..,
diff --git a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
index 67255c1af79..c904137da1a 100644
--- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
@@ -4,9 +4,11 @@ use rustc_errors::Applicability;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{
     Block, Body, Closure, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, FnDecl,
-    FnRetTy, GenericArg, GenericBound, ImplItem, Item, LifetimeName, Node, TraitRef, Ty, TyKind,
+    FnRetTy, GenericBound, ImplItem, Item, Node, OpaqueTy, TraitRef, Ty, TyKind,
 };
 use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
+use rustc_middle::ty;
 use rustc_session::declare_lint_pass;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::{Span, sym};
@@ -44,21 +46,22 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn {
         decl: &'tcx FnDecl<'_>,
         body: &'tcx Body<'_>,
         span: Span,
-        def_id: LocalDefId,
+        fn_def_id: LocalDefId,
     ) {
         if let Some(header) = kind.header()
             && !header.asyncness.is_async()
             // Check that this function returns `impl Future`
             && let FnRetTy::Return(ret_ty) = decl.output
-            && let Some((trait_ref, output_lifetimes)) = future_trait_ref(cx, ret_ty)
+            && let TyKind::OpaqueDef(opaque) = ret_ty.kind
+            && let Some(trait_ref) = future_trait_ref(cx, opaque)
             && let Some(output) = future_output_ty(trait_ref)
-            && captures_all_lifetimes(decl.inputs, &output_lifetimes)
+            && captures_all_lifetimes(cx, fn_def_id, opaque.def_id)
             // Check that the body of the function consists of one async block
             && let ExprKind::Block(block, _) = body.value.kind
             && block.stmts.is_empty()
             && let Some(closure_body) = desugared_async_block(cx, block)
             && let Node::Item(Item {vis_span, ..}) | Node::ImplItem(ImplItem {vis_span, ..}) =
-                cx.tcx.hir_node_by_def_id(def_id)
+                cx.tcx.hir_node_by_def_id(fn_def_id)
         {
             let header_span = span.with_hi(ret_ty.span.hi());
 
@@ -101,12 +104,8 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn {
     }
 }
 
-fn future_trait_ref<'tcx>(
-    cx: &LateContext<'tcx>,
-    ty: &'tcx Ty<'tcx>,
-) -> Option<(&'tcx TraitRef<'tcx>, Vec<LifetimeName>)> {
-    if let TyKind::OpaqueDef(opaque, bounds) = ty.kind
-        && let Some(trait_ref) = opaque.bounds.iter().find_map(|bound| {
+fn future_trait_ref<'tcx>(cx: &LateContext<'tcx>, opaque: &'tcx OpaqueTy<'tcx>) -> Option<&'tcx TraitRef<'tcx>> {
+    if let Some(trait_ref) = opaque.bounds.iter().find_map(|bound| {
             if let GenericBound::Trait(poly) = bound {
                 Some(&poly.trait_ref)
             } else {
@@ -115,18 +114,7 @@ fn future_trait_ref<'tcx>(
         })
         && trait_ref.trait_def_id() == cx.tcx.lang_items().future_trait()
     {
-        let output_lifetimes = bounds
-            .iter()
-            .filter_map(|bound| {
-                if let GenericArg::Lifetime(lt) = bound {
-                    Some(lt.res)
-                } else {
-                    None
-                }
-            })
-            .collect();
-
-        return Some((trait_ref, output_lifetimes));
+        return Some(trait_ref);
     }
 
     None
@@ -145,27 +133,35 @@ fn future_output_ty<'tcx>(trait_ref: &'tcx TraitRef<'tcx>) -> Option<&'tcx Ty<'t
     None
 }
 
-fn captures_all_lifetimes(inputs: &[Ty<'_>], output_lifetimes: &[LifetimeName]) -> bool {
-    let input_lifetimes: Vec<LifetimeName> = inputs
+fn captures_all_lifetimes(cx: &LateContext<'_>, fn_def_id: LocalDefId, opaque_def_id: LocalDefId) -> bool {
+    let early_input_params = ty::GenericArgs::identity_for_item(cx.tcx, fn_def_id);
+    let late_input_params = cx.tcx.late_bound_vars(cx.tcx.local_def_id_to_hir_id(fn_def_id));
+
+    let num_early_lifetimes = early_input_params
         .iter()
-        .filter_map(|ty| {
-            if let TyKind::Ref(lt, _) = ty.kind {
-                Some(lt.res)
-            } else {
-                None
-            }
+        .filter(|param| param.as_region().is_some())
+        .count();
+    let num_late_lifetimes = late_input_params
+        .iter()
+        .filter(|param_kind| matches!(param_kind, ty::BoundVariableKind::Region(_)))
+        .count();
+
+    // There is no lifetime, so they are all captured.
+    if num_early_lifetimes == 0 && num_late_lifetimes == 0 {
+        return true;
+    }
+
+    // By construction, each captured lifetime only appears once in `opaque_captured_lifetimes`.
+    let num_captured_lifetimes = cx
+        .tcx
+        .opaque_captured_lifetimes(opaque_def_id)
+        .iter()
+        .filter(|&(lifetime, _)| match *lifetime {
+            ResolvedArg::EarlyBound(_) | ResolvedArg::LateBound(ty::INNERMOST, _, _) => true,
+            _ => false,
         })
-        .collect();
-
-    // The lint should trigger in one of these cases:
-    // - There are no input lifetimes
-    // - There's only one output lifetime bound using `+ '_`
-    // - All input lifetimes are explicitly bound to the output
-    input_lifetimes.is_empty()
-        || (output_lifetimes.len() == 1 && matches!(output_lifetimes[0], LifetimeName::Infer))
-        || input_lifetimes
-            .iter()
-            .all(|in_lt| output_lifetimes.iter().any(|out_lt| in_lt == out_lt))
+        .count();
+    num_captured_lifetimes == num_early_lifetimes + num_late_lifetimes
 }
 
 fn desugared_async_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) -> Option<&'tcx Body<'tcx>> {
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs b/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs
index 64c19c327b2..223b0630bfd 100644
--- a/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs
@@ -137,7 +137,7 @@ pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>, name:
                                 _ if matches!(
                                     typeck.expr_adjustments(prev_expr).first(),
                                     Some(Adjustment {
-                                        kind: Adjust::Borrow(AutoBorrow::Ref(_, AutoBorrowMutability::Not))
+                                        kind: Adjust::Borrow(AutoBorrow::Ref(AutoBorrowMutability::Not))
                                             | Adjust::Deref(_),
                                         ..
                                     })
@@ -230,7 +230,7 @@ fn check_use<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> (UseKind<'tcx>,
             if use_cx
                 .adjustments
                 .first()
-                .is_some_and(|a| matches!(a.kind, Adjust::Borrow(AutoBorrow::Ref(_, AutoBorrowMutability::Not)))) =>
+                .is_some_and(|a| matches!(a.kind, Adjust::Borrow(AutoBorrow::Ref(AutoBorrowMutability::Not)))) =>
         {
             UseKind::AutoBorrowed
         },
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
index cfa1fdb8137..82549413fa9 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -568,7 +568,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
                             let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), cx.param_env, predicate);
                             !cx.tcx
                                 .infer_ctxt()
-                                .build()
+                                .build(cx.typing_mode())
                                 .predicate_must_hold_modulo_regions(&obligation)
                         }) {
                             return false;
diff --git a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs
index f6db12ed84e..f7fa31d83aa 100644
--- a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs
@@ -278,7 +278,7 @@ fn needless_borrow_count<'tcx>(
 
             let predicate = EarlyBinder::bind(predicate).instantiate(cx.tcx, &args_with_referent_ty[..]);
             let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), cx.param_env, predicate);
-            let infcx = cx.tcx.infer_ctxt().build();
+            let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode());
             infcx.predicate_must_hold_modulo_regions(&obligation)
         })
     };
diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs
index 392cfcb813e..2e5195d459f 100644
--- a/src/tools/clippy/clippy_lints/src/no_effect.rs
+++ b/src/tools/clippy/clippy_lints/src/no_effect.rs
@@ -160,7 +160,7 @@ impl NoEffect {
                                 // Remove `impl Future<Output = T>` to get `T`
                                 if cx.tcx.ty_is_opaque_future(ret_ty)
                                     && let Some(true_ret_ty) =
-                                        cx.tcx.infer_ctxt().build().err_ctxt().get_impl_future_output_ty(ret_ty)
+                                        cx.tcx.infer_ctxt().build(cx.typing_mode()).err_ctxt().get_impl_future_output_ty(ret_ty)
                                 {
                                     ret_ty = true_ret_ty;
                                 }
diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs
index f5fcf521b96..a548c6ef3b1 100644
--- a/src/tools/clippy/clippy_lints/src/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -695,7 +695,7 @@ fn matches_preds<'tcx>(
     ty: Ty<'tcx>,
     preds: &'tcx [ty::PolyExistentialPredicate<'tcx>],
 ) -> bool {
-    let infcx = cx.tcx.infer_ctxt().build();
+    let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode());
     preds
         .iter()
         .all(|&p| match cx.tcx.instantiate_bound_regions_with_erased(p) {
diff --git a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
index 1c10e84d3ca..030df535c35 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
@@ -110,7 +110,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing {
                 ) || cx.typeck_results().expr_adjustments(expr).first().map_or(false, |a| {
                     matches!(
                         a.kind,
-                        Adjust::Borrow(AutoBorrow::Ref(_, AutoBorrowMutability::Mut { .. }))
+                        Adjust::Borrow(AutoBorrow::Ref(AutoBorrowMutability::Mut { .. }))
                     )
                 }) || (matches!(
                     cx.typeck_results().expr_ty(indexed).ref_mutability(),
diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
index ec3a693d2ef..3b05abc546f 100644
--- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs
+++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
@@ -114,7 +114,7 @@ fn into_iter_bound<'tcx>(
                     if !cx
                         .tcx
                         .infer_ctxt()
-                        .build()
+                        .build(cx.typing_mode())
                         .predicate_must_hold_modulo_regions(&obligation)
                     {
                         return None;
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index 181d414cbbd..8004bc68b2e 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -1231,16 +1231,13 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                 }
             },
             TyKind::Path(ref qpath) => self.hash_qpath(qpath),
-            TyKind::OpaqueDef(_, arg_list) => {
-                self.hash_generic_args(arg_list);
-            },
             TyKind::TraitObject(_, lifetime, _) => {
                 self.hash_lifetime(lifetime);
             },
             TyKind::Typeof(anon_const) => {
                 self.hash_body(anon_const.body);
             },
-            TyKind::Err(_) | TyKind::Infer | TyKind::Never | TyKind::InferDelegation(..) | TyKind::AnonAdt(_) => {},
+            TyKind::Err(_) | TyKind::Infer | TyKind::Never | TyKind::InferDelegation(..) | TyKind::OpaqueDef(_) | TyKind::AnonAdt(_) => {},
         }
     }
 
diff --git a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs
index a00196c4b51..6b3078f52af 100644
--- a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs
+++ b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs
@@ -185,9 +185,7 @@ impl<'b, 'tcx> PossibleBorrowerMap<'b, 'tcx> {
             vis.into_map(cx)
         };
         let maybe_storage_live_result = MaybeStorageLive::new(Cow::Owned(BitSet::new_empty(mir.local_decls.len())))
-            .into_engine(cx.tcx, mir)
-            .pass_name("redundant_clone")
-            .iterate_to_fixpoint()
+            .iterate_to_fixpoint(cx.tcx, mir, Some("redundant_clone"))
             .into_results_cursor(mir);
         let mut vis = PossibleBorrowerVisitor::new(cx, mir, possible_origin);
         vis.visit_body(mir);
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index 46739862de6..8f9f75d6824 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -420,7 +420,7 @@ fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx>
             TraitRef::new(tcx, tcx.require_lang_item(LangItem::Destruct, Some(body.span)), [ty]),
         );
 
-        let infcx = tcx.infer_ctxt().build();
+        let infcx = tcx.infer_ctxt().build(body.typing_mode(tcx));
         let mut selcx = SelectionContext::new(&infcx);
         let Some(impl_src) = selcx.select(&obligation).ok().flatten() else {
             return false;
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index 07c3d0eada0..41785e161d0 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -19,7 +19,7 @@ use rustc_middle::ty::layout::ValidityRequirement;
 use rustc_middle::ty::{
     self, AdtDef, AliasTy, AssocItem, AssocKind, Binder, BoundRegion, FnSig, GenericArg, GenericArgKind,
     GenericArgsRef, GenericParamDefKind, IntTy, ParamEnv, Region, RegionKind, TraitRef, Ty, TyCtxt, TypeSuperVisitable,
-    TypeVisitable, TypeVisitableExt, TypeVisitor, UintTy, Upcast, VariantDef, VariantDiscr,
+    TypeVisitable, TypeVisitableExt, TypeVisitor, UintTy, Upcast, VariantDef, VariantDiscr, TypingMode,
 };
 use rustc_span::symbol::Ident;
 use rustc_span::{DUMMY_SP, Span, Symbol, sym};
@@ -268,7 +268,7 @@ pub fn implements_trait_with_env_from_iter<'tcx>(
         return false;
     }
 
-    let infcx = tcx.infer_ctxt().build();
+    let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env));
     let args = args
         .into_iter()
         .map(|arg| arg.into().unwrap_or_else(|| infcx.next_ty_var(DUMMY_SP).into()))
@@ -362,7 +362,7 @@ fn is_normalizable_helper<'tcx>(
     }
     // prevent recursive loops, false-negative is better than endless loop leading to stack overflow
     cache.insert(ty, false);
-    let infcx = cx.tcx.infer_ctxt().build();
+    let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode());
     let cause = ObligationCause::dummy();
     let result = if infcx.at(&cause, param_env).query_normalize(ty).is_ok() {
         match ty.kind() {
@@ -1268,7 +1268,7 @@ pub fn make_normalized_projection_with_regions<'tcx>(
         let cause = ObligationCause::dummy();
         match tcx
             .infer_ctxt()
-            .build()
+            .build(TypingMode::from_param_env(param_env))
             .at(&cause, param_env)
             .query_normalize(Ty::new_projection_from_args(tcx, ty.def_id, ty.args))
         {
@@ -1284,7 +1284,7 @@ pub fn make_normalized_projection_with_regions<'tcx>(
 
 pub fn normalize_with_regions<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
     let cause = ObligationCause::dummy();
-    match tcx.infer_ctxt().build().at(&cause, param_env).query_normalize(ty) {
+    match tcx.infer_ctxt().build(TypingMode::from_param_env(param_env)).at(&cause, param_env).query_normalize(ty) {
         Ok(ty) => ty.value,
         Err(_) => ty,
     }
diff --git a/src/tools/clippy/tests/ui/issue_4266.stderr b/src/tools/clippy/tests/ui/issue_4266.stderr
index c0e81791589..63c568a153b 100644
--- a/src/tools/clippy/tests/ui/issue_4266.stderr
+++ b/src/tools/clippy/tests/ui/issue_4266.stderr
@@ -11,7 +11,7 @@ error: the following explicit lifetimes could be elided: 'a
   --> tests/ui/issue_4266.rs:10:21
    |
 LL | async fn one_to_one<'a>(s: &'a str) -> &'a str {
-   |                     ^^      ^^
+   |                     ^^      ^^          ^^
 
 error: methods called `new` usually take no `self`
   --> tests/ui/issue_4266.rs:31:22
diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml
index b6a89dd49e6..cef6b525a7b 100644
--- a/src/tools/compiletest/Cargo.toml
+++ b/src/tools/compiletest/Cargo.toml
@@ -18,6 +18,7 @@ build_helper = { path = "../build_helper" }
 tracing = "0.1"
 tracing-subscriber = { version = "0.3.3", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] }
 regex = "1.0"
+semver = { version = "1.0.23", features = ["serde"] }
 serde = { version = "1.0", features = ["derive"] }
 serde_json = "1.0"
 rustfix = "0.8.1"
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 69ac4644941..e4f2f95a91b 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -7,6 +7,7 @@ use std::sync::OnceLock;
 use std::{fmt, iter};
 
 use build_helper::git::GitConfig;
+use semver::Version;
 use serde::de::{Deserialize, Deserializer, Error as _};
 use test::{ColorConfig, OutputFormat};
 
@@ -298,7 +299,7 @@ pub struct Config {
     pub lldb_version: Option<u32>,
 
     /// Version of LLVM
-    pub llvm_version: Option<u32>,
+    pub llvm_version: Option<Version>,
 
     /// Is LLVM a system LLVM
     pub system_llvm: bool,
@@ -391,6 +392,11 @@ pub struct Config {
 
     /// Command for visual diff display, e.g. `diff-tool --color=always`.
     pub diff_command: Option<String>,
+
+    /// Path to minicore aux library, used for `no_core` tests that need `core` stubs in
+    /// cross-compilation scenarios that do not otherwise want/need to `-Zbuild-std`. Used in e.g.
+    /// ABI tests.
+    pub minicore_path: PathBuf,
 }
 
 impl Config {
diff --git a/src/tools/compiletest/src/command-list.rs b/src/tools/compiletest/src/directive-list.rs
index 4d57907f26f..980b3f6829a 100644
--- a/src/tools/compiletest/src/command-list.rs
+++ b/src/tools/compiletest/src/directive-list.rs
@@ -3,6 +3,7 @@
 /// a best-effort approximation for diagnostics. Add new headers to this list when needed.
 const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     // tidy-alphabetical-start
+    "add-core-stubs",
     "assembly-output",
     "aux-bin",
     "aux-build",
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index d75cdefe635..300a03e5f33 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -6,6 +6,7 @@ use std::io::prelude::*;
 use std::path::{Path, PathBuf};
 use std::process::Command;
 
+use semver::Version;
 use tracing::*;
 
 use crate::common::{Config, Debugger, FailMode, Mode, PassMode};
@@ -197,6 +198,9 @@ pub struct TestProps {
     pub no_auto_check_cfg: bool,
     /// Run tests which require enzyme being build
     pub has_enzyme: bool,
+    /// Build and use `minicore` as `core` stub for `no_core` tests in cross-compilation scenarios
+    /// that don't otherwise want/need `-Z build-std`.
+    pub add_core_stubs: bool,
 }
 
 mod directives {
@@ -242,6 +246,7 @@ mod directives {
     pub const LLVM_COV_FLAGS: &'static str = "llvm-cov-flags";
     pub const FILECHECK_FLAGS: &'static str = "filecheck-flags";
     pub const NO_AUTO_CHECK_CFG: &'static str = "no-auto-check-cfg";
+    pub const ADD_CORE_STUBS: &'static str = "add-core-stubs";
     // This isn't a real directive, just one that is probably mistyped often
     pub const INCORRECT_COMPILER_FLAGS: &'static str = "compiler-flags";
 }
@@ -299,6 +304,7 @@ impl TestProps {
             filecheck_flags: vec![],
             no_auto_check_cfg: false,
             has_enzyme: false,
+            add_core_stubs: false,
         }
     }
 
@@ -563,6 +569,8 @@ impl TestProps {
                     }
 
                     config.set_name_directive(ln, NO_AUTO_CHECK_CFG, &mut self.no_auto_check_cfg);
+
+                    self.update_add_core_stubs(ln, config);
                 },
             );
 
@@ -676,6 +684,27 @@ impl TestProps {
     pub fn local_pass_mode(&self) -> Option<PassMode> {
         self.pass_mode
     }
+
+    pub fn update_add_core_stubs(&mut self, ln: &str, config: &Config) {
+        let add_core_stubs = config.parse_name_directive(ln, directives::ADD_CORE_STUBS);
+        if add_core_stubs {
+            if !matches!(config.mode, Mode::Ui | Mode::Codegen | Mode::Assembly) {
+                panic!(
+                    "`add-core-stubs` is currently only supported for ui, codegen and assembly test modes"
+                );
+            }
+
+            // FIXME(jieyouxu): this check is currently order-dependent, but we should probably
+            // collect all directives in one go then perform a validation pass after that.
+            if self.local_pass_mode().is_some_and(|pm| pm == PassMode::Run) {
+                // `minicore` can only be used with non-run modes, because it's `core` prelude stubs
+                // and can't run.
+                panic!("`add-core-stubs` cannot be used to run the test binary");
+            }
+
+            self.add_core_stubs = add_core_stubs;
+        }
+    }
 }
 
 /// If the given line begins with the appropriate comment prefix for a directive,
@@ -709,11 +738,11 @@ fn line_directive<'line>(
     Some(DirectiveLine { line_number, revision, raw_directive })
 }
 
-// To prevent duplicating the list of commmands between `compiletest`,`htmldocck` and `jsondocck`,
+// To prevent duplicating the list of directives between `compiletest`,`htmldocck` and `jsondocck`,
 // we put it into a common file which is included in rust code and parsed here.
 // FIXME: This setup is temporary until we figure out how to improve this situation.
 //        See <https://github.com/rust-lang/rust/issues/125813#issuecomment-2141953780>.
-include!("command-list.rs");
+include!("directive-list.rs");
 
 const KNOWN_HTMLDOCCK_DIRECTIVE_NAMES: &[&str] = &[
     "count",
@@ -1113,26 +1142,39 @@ fn parse_normalize_rule(header: &str) -> Option<(String, String)> {
     Some((regex, replacement))
 }
 
-pub fn extract_llvm_version(version: &str) -> Option<u32> {
-    let pat = |c: char| !c.is_ascii_digit() && c != '.';
-    let version_without_suffix = match version.find(pat) {
-        Some(pos) => &version[..pos],
+/// Given an llvm version string that looks like `1.2.3-rc1`, extract as semver. Note that this
+/// accepts more than just strict `semver` syntax (as in `major.minor.patch`); this permits omitting
+/// minor and patch version components so users can write e.g. `//@ min-llvm-version: 19` instead of
+/// having to write `//@ min-llvm-version: 19.0.0`.
+///
+/// Currently panics if the input string is malformed, though we really should not use panic as an
+/// error handling strategy.
+///
+/// FIXME(jieyouxu): improve error handling
+pub fn extract_llvm_version(version: &str) -> Version {
+    // The version substring we're interested in usually looks like the `1.2.3`, without any of the
+    // fancy suffix like `-rc1` or `meow`.
+    let version = version.trim();
+    let uninterested = |c: char| !c.is_ascii_digit() && c != '.';
+    let version_without_suffix = match version.split_once(uninterested) {
+        Some((prefix, _suffix)) => prefix,
         None => version,
     };
-    let components: Vec<u32> = version_without_suffix
+
+    let components: Vec<u64> = version_without_suffix
         .split('.')
-        .map(|s| s.parse().expect("Malformed version component"))
+        .map(|s| s.parse().expect("llvm version component should consist of only digits"))
         .collect();
-    let version = match *components {
-        [a] => a * 10_000,
-        [a, b] => a * 10_000 + b * 100,
-        [a, b, c] => a * 10_000 + b * 100 + c,
-        _ => panic!("Malformed version"),
-    };
-    Some(version)
+
+    match &components[..] {
+        [major] => Version::new(*major, 0, 0),
+        [major, minor] => Version::new(*major, *minor, 0),
+        [major, minor, patch] => Version::new(*major, *minor, *patch),
+        _ => panic!("malformed llvm version string, expected only 1-3 components: {version}"),
+    }
 }
 
-pub fn extract_llvm_version_from_binary(binary_path: &str) -> Option<u32> {
+pub fn extract_llvm_version_from_binary(binary_path: &str) -> Option<Version> {
     let output = Command::new(binary_path).arg("--version").output().ok()?;
     if !output.status.success() {
         return None;
@@ -1140,7 +1182,7 @@ pub fn extract_llvm_version_from_binary(binary_path: &str) -> Option<u32> {
     let version = String::from_utf8(output.stdout).ok()?;
     for line in version.lines() {
         if let Some(version) = line.split("LLVM version ").nth(1) {
-            return extract_llvm_version(version);
+            return Some(extract_llvm_version(version));
         }
     }
     None
@@ -1247,15 +1289,17 @@ pub fn llvm_has_libzstd(config: &Config) -> bool {
     false
 }
 
-/// Takes a directive of the form `"<version1> [- <version2>]"`,
-/// returns the numeric representation of `<version1>` and `<version2>` as
-/// tuple: `(<version1> as u32, <version2> as u32)`.
+/// Takes a directive of the form `"<version1> [- <version2>]"`, returns the numeric representation
+/// of `<version1>` and `<version2>` as tuple: `(<version1>, <version2>)`.
 ///
-/// If the `<version2>` part is omitted, the second component of the tuple
-/// is the same as `<version1>`.
-fn extract_version_range<F>(line: &str, parse: F) -> Option<(u32, u32)>
+/// If the `<version2>` part is omitted, the second component of the tuple is the same as
+/// `<version1>`.
+fn extract_version_range<'a, F, VersionTy: Clone>(
+    line: &'a str,
+    parse: F,
+) -> Option<(VersionTy, VersionTy)>
 where
-    F: Fn(&str) -> Option<u32>,
+    F: Fn(&'a str) -> Option<VersionTy>,
 {
     let mut splits = line.splitn(2, "- ").map(str::trim);
     let min = splits.next().unwrap();
@@ -1273,7 +1317,7 @@ where
     let max = match max {
         Some("") => return None,
         Some(max) => parse(max)?,
-        _ => min,
+        _ => min.clone(),
     };
 
     Some((min, max))
@@ -1489,43 +1533,55 @@ fn ignore_llvm(config: &Config, line: &str) -> IgnoreDecision {
             };
         }
     }
-    if let Some(actual_version) = config.llvm_version {
-        if let Some(rest) = line.strip_prefix("min-llvm-version:").map(str::trim) {
-            let min_version = extract_llvm_version(rest).unwrap();
-            // Ignore if actual version is smaller the minimum required
-            // version
-            if actual_version < min_version {
+    if let Some(actual_version) = &config.llvm_version {
+        // Note that these `min` versions will check for not just major versions.
+
+        if let Some(version_string) = config.parse_name_value_directive(line, "min-llvm-version") {
+            let min_version = extract_llvm_version(&version_string);
+            // Ignore if actual version is smaller than the minimum required version.
+            if *actual_version < min_version {
                 return IgnoreDecision::Ignore {
-                    reason: format!("ignored when the LLVM version is older than {rest}"),
+                    reason: format!(
+                        "ignored when the LLVM version {actual_version} is older than {min_version}"
+                    ),
                 };
             }
-        } else if let Some(rest) = line.strip_prefix("min-system-llvm-version:").map(str::trim) {
-            let min_version = extract_llvm_version(rest).unwrap();
+        } else if let Some(version_string) =
+            config.parse_name_value_directive(line, "min-system-llvm-version")
+        {
+            let min_version = extract_llvm_version(&version_string);
             // Ignore if using system LLVM and actual version
             // is smaller the minimum required version
-            if config.system_llvm && actual_version < min_version {
+            if config.system_llvm && *actual_version < min_version {
                 return IgnoreDecision::Ignore {
-                    reason: format!("ignored when the system LLVM version is older than {rest}"),
+                    reason: format!(
+                        "ignored when the system LLVM version {actual_version} is older than {min_version}"
+                    ),
                 };
             }
-        } else if let Some(rest) = line.strip_prefix("ignore-llvm-version:").map(str::trim) {
+        } else if let Some(version_range) =
+            config.parse_name_value_directive(line, "ignore-llvm-version")
+        {
             // Syntax is: "ignore-llvm-version: <version1> [- <version2>]"
             let (v_min, v_max) =
-                extract_version_range(rest, extract_llvm_version).unwrap_or_else(|| {
-                    panic!("couldn't parse version range: {:?}", rest);
-                });
+                extract_version_range(&version_range, |s| Some(extract_llvm_version(s)))
+                    .unwrap_or_else(|| {
+                        panic!("couldn't parse version range: \"{version_range}\"");
+                    });
             if v_max < v_min {
-                panic!("Malformed LLVM version range: max < min")
+                panic!("malformed LLVM version range where {v_max} < {v_min}")
             }
             // Ignore if version lies inside of range.
-            if actual_version >= v_min && actual_version <= v_max {
+            if *actual_version >= v_min && *actual_version <= v_max {
                 if v_min == v_max {
                     return IgnoreDecision::Ignore {
-                        reason: format!("ignored when the LLVM version is {rest}"),
+                        reason: format!("ignored when the LLVM version is {actual_version}"),
                     };
                 } else {
                     return IgnoreDecision::Ignore {
-                        reason: format!("ignored when the LLVM version is between {rest}"),
+                        reason: format!(
+                            "ignored when the LLVM version is between {v_min} and {v_max}"
+                        ),
                     };
                 }
             }
diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs
index c3c9496c4d2..0e735dc77c4 100644
--- a/src/tools/compiletest/src/header/tests.rs
+++ b/src/tools/compiletest/src/header/tests.rs
@@ -1,9 +1,13 @@
 use std::io::Read;
 use std::path::Path;
 
-use super::iter_header;
+use semver::Version;
+
+use super::{
+    EarlyProps, HeadersCache, extract_llvm_version, extract_version_range, iter_header,
+    parse_normalize_rule,
+};
 use crate::common::{Config, Debugger, Mode};
-use crate::header::{EarlyProps, HeadersCache, parse_normalize_rule};
 
 fn make_test_description<R: Read>(
     config: &Config,
@@ -148,6 +152,7 @@ impl ConfigBuilder {
             "--git-repository=",
             "--nightly-branch=",
             "--git-merge-commit-email=",
+            "--minicore-path=",
         ];
         let mut args: Vec<String> = args.iter().map(ToString::to_string).collect();
 
@@ -408,18 +413,66 @@ fn channel() {
 }
 
 #[test]
+fn test_extract_llvm_version() {
+    // Note: officially, semver *requires* that versions at the minimum have all three
+    // `major.minor.patch` numbers, though for test-writer's convenience we allow omitting the minor
+    // and patch numbers (which will be stubbed out as 0).
+    assert_eq!(extract_llvm_version("0"), Version::new(0, 0, 0));
+    assert_eq!(extract_llvm_version("0.0"), Version::new(0, 0, 0));
+    assert_eq!(extract_llvm_version("0.0.0"), Version::new(0, 0, 0));
+    assert_eq!(extract_llvm_version("1"), Version::new(1, 0, 0));
+    assert_eq!(extract_llvm_version("1.2"), Version::new(1, 2, 0));
+    assert_eq!(extract_llvm_version("1.2.3"), Version::new(1, 2, 3));
+    assert_eq!(extract_llvm_version("4.5.6git"), Version::new(4, 5, 6));
+    assert_eq!(extract_llvm_version("4.5.6-rc1"), Version::new(4, 5, 6));
+    assert_eq!(extract_llvm_version("123.456.789-rc1"), Version::new(123, 456, 789));
+    assert_eq!(extract_llvm_version("8.1.2-rust"), Version::new(8, 1, 2));
+    assert_eq!(extract_llvm_version("9.0.1-rust-1.43.0-dev"), Version::new(9, 0, 1));
+    assert_eq!(extract_llvm_version("9.3.1-rust-1.43.0-dev"), Version::new(9, 3, 1));
+    assert_eq!(extract_llvm_version("10.0.0-rust"), Version::new(10, 0, 0));
+    assert_eq!(extract_llvm_version("11.1.0"), Version::new(11, 1, 0));
+    assert_eq!(extract_llvm_version("12.0.0libcxx"), Version::new(12, 0, 0));
+    assert_eq!(extract_llvm_version("12.0.0-rc3"), Version::new(12, 0, 0));
+    assert_eq!(extract_llvm_version("13.0.0git"), Version::new(13, 0, 0));
+}
+
+#[test]
+#[should_panic]
+fn test_llvm_version_invalid_components() {
+    extract_llvm_version("4.x.6");
+}
+
+#[test]
+#[should_panic]
+fn test_llvm_version_invalid_prefix() {
+    extract_llvm_version("meow4.5.6");
+}
+
+#[test]
+#[should_panic]
+fn test_llvm_version_too_many_components() {
+    extract_llvm_version("4.5.6.7");
+}
+
+#[test]
 fn test_extract_version_range() {
-    use super::{extract_llvm_version, extract_version_range};
-
-    assert_eq!(extract_version_range("1.2.3 - 4.5.6", extract_llvm_version), Some((10203, 40506)));
-    assert_eq!(extract_version_range("0   - 4.5.6", extract_llvm_version), Some((0, 40506)));
-    assert_eq!(extract_version_range("1.2.3 -", extract_llvm_version), None);
-    assert_eq!(extract_version_range("1.2.3 - ", extract_llvm_version), None);
-    assert_eq!(extract_version_range("- 4.5.6", extract_llvm_version), None);
-    assert_eq!(extract_version_range("-", extract_llvm_version), None);
-    assert_eq!(extract_version_range(" - 4.5.6", extract_llvm_version), None);
-    assert_eq!(extract_version_range("   - 4.5.6", extract_llvm_version), None);
-    assert_eq!(extract_version_range("0  -", extract_llvm_version), None);
+    let wrapped_extract = |s: &str| Some(extract_llvm_version(s));
+
+    assert_eq!(
+        extract_version_range("1.2.3 - 4.5.6", wrapped_extract),
+        Some((Version::new(1, 2, 3), Version::new(4, 5, 6)))
+    );
+    assert_eq!(
+        extract_version_range("0   - 4.5.6", wrapped_extract),
+        Some((Version::new(0, 0, 0), Version::new(4, 5, 6)))
+    );
+    assert_eq!(extract_version_range("1.2.3 -", wrapped_extract), None);
+    assert_eq!(extract_version_range("1.2.3 - ", wrapped_extract), None);
+    assert_eq!(extract_version_range("- 4.5.6", wrapped_extract), None);
+    assert_eq!(extract_version_range("-", wrapped_extract), None);
+    assert_eq!(extract_version_range(" - 4.5.6", wrapped_extract), None);
+    assert_eq!(extract_version_range("   - 4.5.6", wrapped_extract), None);
+    assert_eq!(extract_version_range("0  -", wrapped_extract), None);
 }
 
 #[test]
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
index 490df313228..5c06a39c477 100644
--- a/src/tools/compiletest/src/lib.rs
+++ b/src/tools/compiletest/src/lib.rs
@@ -181,7 +181,8 @@ pub fn parse_config(args: Vec<String>) -> Config {
             "compiletest-diff-tool",
             "What custom diff tool to use for displaying compiletest tests.",
             "COMMAND",
-        );
+        )
+        .reqopt("", "minicore-path", "path to minicore aux library", "PATH");
 
     let (argv0, args_) = args.split_first().unwrap();
     if args.len() == 1 || args[1] == "-h" || args[1] == "--help" {
@@ -228,7 +229,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
         Some(x) => panic!("argument for --color must be auto, always, or never, but found `{}`", x),
     };
     let llvm_version =
-        matches.opt_str("llvm-version").as_deref().and_then(header::extract_llvm_version).or_else(
+        matches.opt_str("llvm-version").as_deref().map(header::extract_llvm_version).or_else(
             || header::extract_llvm_version_from_binary(&matches.opt_str("llvm-filecheck")?),
         );
 
@@ -371,7 +372,10 @@ pub fn parse_config(args: Vec<String>) -> Config {
         git_merge_commit_email: matches.opt_str("git-merge-commit-email").unwrap(),
 
         profiler_runtime: matches.opt_present("profiler-runtime"),
+
         diff_command: matches.opt_str("compiletest-diff-tool"),
+
+        minicore_path: opt_path(matches, "minicore-path"),
     }
 }
 
@@ -409,6 +413,7 @@ pub fn log_config(config: &Config) {
     logv(c, format!("host-linker: {:?}", config.host_linker));
     logv(c, format!("verbose: {}", config.verbose));
     logv(c, format!("format: {:?}", config.format));
+    logv(c, format!("minicore_path: {:?}", config.minicore_path.display()));
     logv(c, "\n".to_string());
 }
 
@@ -885,6 +890,12 @@ fn files_related_to_test(
         related.push(path);
     }
 
+    // `minicore.rs` test auxiliary: we need to make sure tests get rerun if this changes.
+    //
+    // FIXME(jieyouxu): untangle these paths, we should provide both a path to root `tests/` or
+    // `tests/auxiliary/` and the test suite in question. `src_base` is also a terrible name.
+    related.push(config.src_base.parent().unwrap().join("auxiliary").join("minicore.rs"));
+
     related
 }
 
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index a8a71c196fc..b337458f943 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1150,14 +1150,20 @@ impl<'test> TestCx<'test> {
         }
     }
 
-    /// `root_testpaths` refers to the path of the original test.
-    /// the auxiliary and the test with an aux-build have the same `root_testpaths`.
+    /// `root_testpaths` refers to the path of the original test. the auxiliary and the test with an
+    /// aux-build have the same `root_testpaths`.
     fn compose_and_run_compiler(
         &self,
         mut rustc: Command,
         input: Option<String>,
         root_testpaths: &TestPaths,
     ) -> ProcRes {
+        if self.props.add_core_stubs {
+            let minicore_path = self.build_minicore();
+            rustc.arg("--extern");
+            rustc.arg(&format!("minicore={}", minicore_path.to_str().unwrap()));
+        }
+
         let aux_dir = self.aux_output_dir();
         self.build_all_auxiliary(root_testpaths, &aux_dir, &mut rustc);
 
@@ -1171,6 +1177,37 @@ impl<'test> TestCx<'test> {
         )
     }
 
+    /// Builds `minicore`. Returns the path to the minicore rlib within the base test output
+    /// directory.
+    fn build_minicore(&self) -> PathBuf {
+        let output_file_path = self.output_base_dir().join("libminicore.rlib");
+        let mut rustc = self.make_compile_args(
+            &self.config.minicore_path,
+            TargetLocation::ThisFile(output_file_path.clone()),
+            Emit::None,
+            AllowUnused::Yes,
+            LinkToAux::No,
+            vec![],
+        );
+
+        rustc.args(&["--crate-type", "rlib"]);
+        rustc.arg("-Cpanic=abort");
+
+        let res =
+            self.compose_and_run(rustc, self.config.compile_lib_path.to_str().unwrap(), None, None);
+        if !res.status.success() {
+            self.fatal_proc_rec(
+                &format!(
+                    "auxiliary build of {:?} failed to compile: ",
+                    self.config.minicore_path.display()
+                ),
+                &res,
+            );
+        }
+
+        output_file_path
+    }
+
     /// Builds an aux dependency.
     fn build_auxiliary(
         &self,
@@ -1662,6 +1699,15 @@ impl<'test> TestCx<'test> {
 
         rustc.args(&self.props.compile_flags);
 
+        // FIXME(jieyouxu): we should report a fatal error or warning if user wrote `-Cpanic=` with
+        // something that's not `abort`, however, by moving this last we should override previous
+        // `-Cpanic=`s
+        //
+        // `minicore` requires `#![no_std]` and `#![no_core]`, which means no unwinding panics.
+        if self.props.add_core_stubs {
+            rustc.arg("-Cpanic=abort");
+        }
+
         rustc
     }
 
@@ -1848,34 +1894,6 @@ impl<'test> TestCx<'test> {
         (proc_res, output_path)
     }
 
-    fn compile_test_and_save_assembly(&self) -> (ProcRes, PathBuf) {
-        // This works with both `--emit asm` (as default output name for the assembly)
-        // and `ptx-linker` because the latter can write output at requested location.
-        let output_path = self.output_base_name().with_extension("s");
-        let input_file = &self.testpaths.file;
-
-        // Use the `//@ assembly-output:` directive to determine how to emit assembly.
-        let emit = match self.props.assembly_output.as_deref() {
-            Some("emit-asm") => Emit::Asm,
-            Some("bpf-linker") => Emit::LinkArgsAsm,
-            Some("ptx-linker") => Emit::None, // No extra flags needed.
-            Some(other) => self.fatal(&format!("unknown 'assembly-output' directive: {other}")),
-            None => self.fatal("missing 'assembly-output' directive"),
-        };
-
-        let rustc = self.make_compile_args(
-            input_file,
-            TargetLocation::ThisFile(output_path.clone()),
-            emit,
-            AllowUnused::No,
-            LinkToAux::Yes,
-            Vec::new(),
-        );
-
-        let proc_res = self.compose_and_run_compiler(rustc, None, self.testpaths);
-        (proc_res, output_path)
-    }
-
     fn verify_with_filecheck(&self, output: &Path) -> ProcRes {
         let mut filecheck = Command::new(self.config.llvm_filecheck.as_ref().unwrap());
         filecheck.arg("--input-file").arg(output).arg(&self.testpaths.file);
diff --git a/src/tools/compiletest/src/runtest/assembly.rs b/src/tools/compiletest/src/runtest/assembly.rs
index 430a5534da1..89d7de58c20 100644
--- a/src/tools/compiletest/src/runtest/assembly.rs
+++ b/src/tools/compiletest/src/runtest/assembly.rs
@@ -1,4 +1,6 @@
-use super::TestCx;
+use std::path::PathBuf;
+
+use super::{AllowUnused, Emit, LinkToAux, ProcRes, TargetLocation, TestCx};
 
 impl TestCx<'_> {
     pub(super) fn run_assembly_test(&self) {
@@ -16,4 +18,32 @@ impl TestCx<'_> {
             self.fatal_proc_rec("verification with 'FileCheck' failed", &proc_res);
         }
     }
+
+    fn compile_test_and_save_assembly(&self) -> (ProcRes, PathBuf) {
+        // This works with both `--emit asm` (as default output name for the assembly)
+        // and `ptx-linker` because the latter can write output at requested location.
+        let output_path = self.output_base_name().with_extension("s");
+        let input_file = &self.testpaths.file;
+
+        // Use the `//@ assembly-output:` directive to determine how to emit assembly.
+        let emit = match self.props.assembly_output.as_deref() {
+            Some("emit-asm") => Emit::Asm,
+            Some("bpf-linker") => Emit::LinkArgsAsm,
+            Some("ptx-linker") => Emit::None, // No extra flags needed.
+            Some(other) => self.fatal(&format!("unknown 'assembly-output' directive: {other}")),
+            None => self.fatal("missing 'assembly-output' directive"),
+        };
+
+        let rustc = self.make_compile_args(
+            input_file,
+            TargetLocation::ThisFile(output_path.clone()),
+            emit,
+            AllowUnused::No,
+            LinkToAux::Yes,
+            Vec::new(),
+        );
+
+        let proc_res = self.compose_and_run_compiler(rustc, None, self.testpaths);
+        (proc_res, output_path)
+    }
 }
diff --git a/src/tools/compiletest/src/tests.rs b/src/tools/compiletest/src/tests.rs
index 680579c59ae..fec746904de 100644
--- a/src/tools/compiletest/src/tests.rs
+++ b/src/tools/compiletest/src/tests.rs
@@ -1,7 +1,6 @@
 use std::ffi::OsString;
 
 use crate::debuggers::{extract_gdb_version, extract_lldb_version};
-use crate::header::extract_llvm_version;
 use crate::is_test;
 
 #[test]
@@ -67,15 +66,3 @@ fn is_test_test() {
     assert!(!is_test(&OsString::from("#a_dog_gif")));
     assert!(!is_test(&OsString::from("~a_temp_file")));
 }
-
-#[test]
-fn test_extract_llvm_version() {
-    assert_eq!(extract_llvm_version("8.1.2-rust"), Some(80102));
-    assert_eq!(extract_llvm_version("9.0.1-rust-1.43.0-dev"), Some(90001));
-    assert_eq!(extract_llvm_version("9.3.1-rust-1.43.0-dev"), Some(90301));
-    assert_eq!(extract_llvm_version("10.0.0-rust"), Some(100000));
-    assert_eq!(extract_llvm_version("11.1.0"), Some(110100));
-    assert_eq!(extract_llvm_version("12.0.0libcxx"), Some(120000));
-    assert_eq!(extract_llvm_version("12.0.0-rc3"), Some(120000));
-    assert_eq!(extract_llvm_version("13.0.0git"), Some(130000));
-}
diff --git a/src/tools/jsondocck/src/main.rs b/src/tools/jsondocck/src/main.rs
index b264405ac3e..c08bbbc769a 100644
--- a/src/tools/jsondocck/src/main.rs
+++ b/src/tools/jsondocck/src/main.rs
@@ -123,7 +123,7 @@ fn print_err(msg: &str, lineno: usize) {
 
 // FIXME: This setup is temporary until we figure out how to improve this situation.
 //        See <https://github.com/rust-lang/rust/issues/125813#issuecomment-2141953780>.
-include!(concat!(env!("CARGO_MANIFEST_DIR"), "/../compiletest/src/command-list.rs"));
+include!(concat!(env!("CARGO_MANIFEST_DIR"), "/../compiletest/src/directive-list.rs"));
 
 /// Get a list of commands from a file. Does the work of ensuring the commands
 /// are syntactically valid.
diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
index fdc7a675fb7..47fe41d9ecd 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
@@ -9,11 +9,11 @@ use std::cell::RefCell;
 use std::fmt::Write;
 use std::{cmp, mem};
 
+use rustc_abi::{BackendRepr, Size};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_middle::mir::{Mutability, RetagKind};
 use rustc_middle::ty::layout::HasParamEnv;
 use rustc_middle::ty::{self, Ty};
-use rustc_target::abi::{Abi, Size};
 
 use self::diagnostics::{RetagCause, RetagInfo};
 pub use self::item::{Item, Permission};
@@ -972,7 +972,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                             RetagFields::OnlyScalar => {
                                 // Matching `ArgAbi::new` at the time of writing, only fields of
                                 // `Scalar` and `ScalarPair` ABI are considered.
-                                matches!(place.layout.abi, Abi::Scalar(..) | Abi::ScalarPair(..))
+                                matches!(
+                                    place.layout.backend_repr,
+                                    BackendRepr::Scalar(..) | BackendRepr::ScalarPair(..)
+                                )
                             }
                         };
                         if recurse {
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
index acfb76030f5..40467aa4bc1 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
@@ -1,8 +1,8 @@
+use rustc_abi::{BackendRepr, Size};
 use rustc_middle::mir::{Mutability, RetagKind};
 use rustc_middle::ty::layout::HasParamEnv;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::def_id::DefId;
-use rustc_target::abi::{Abi, Size};
 
 use crate::borrow_tracker::{GlobalState, GlobalStateInner, ProtectorKind};
 use crate::concurrency::data_race::NaReadType;
@@ -495,7 +495,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                             RetagFields::OnlyScalar => {
                                 // Matching `ArgAbi::new` at the time of writing, only fields of
                                 // `Scalar` and `ScalarPair` ABI are considered.
-                                matches!(place.layout.abi, Abi::Scalar(..) | Abi::ScalarPair(..))
+                                matches!(
+                                    place.layout.backend_repr,
+                                    BackendRepr::Scalar(..) | BackendRepr::ScalarPair(..)
+                                )
                             }
                         };
                         if recurse {
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index d35cbf242f5..17f664da853 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -349,8 +349,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         i: impl Into<i128>,
         dest: &impl Writeable<'tcx, Provenance>,
     ) -> InterpResult<'tcx> {
-        assert!(dest.layout().abi.is_scalar(), "write_int on non-scalar type {}", dest.layout().ty);
-        let val = if dest.layout().abi.is_signed() {
+        assert!(
+            dest.layout().backend_repr.is_scalar(),
+            "write_int on non-scalar type {}",
+            dest.layout().ty
+        );
+        let val = if dest.layout().backend_repr.is_signed() {
             Scalar::from_int(i, dest.layout().size)
         } else {
             // `unwrap` can only fail here if `i` is negative
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index 938d1ca319e..f903ccbc25a 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -55,6 +55,7 @@ extern crate either;
 extern crate tracing;
 
 // The rustc crates we need
+extern crate rustc_abi;
 extern crate rustc_apfloat;
 extern crate rustc_ast;
 extern crate rustc_attr;
diff --git a/src/tools/miri/src/operator.rs b/src/tools/miri/src/operator.rs
index 8e06f4258d6..608e23fc110 100644
--- a/src/tools/miri/src/operator.rs
+++ b/src/tools/miri/src/operator.rs
@@ -23,7 +23,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
         interp_ok(match bin_op {
             Eq | Ne | Lt | Le | Gt | Ge => {
-                assert_eq!(left.layout.abi, right.layout.abi); // types can differ, e.g. fn ptrs with different `for`
+                assert_eq!(left.layout.backend_repr, right.layout.backend_repr); // types can differ, e.g. fn ptrs with different `for`
                 let size = this.pointer_size();
                 // Just compare the bits. ScalarPairs are compared lexicographically.
                 // We thus always compare pairs and simply fill scalars up with 0.
diff --git a/src/tools/miri/src/shims/native_lib.rs b/src/tools/miri/src/shims/native_lib.rs
index 3f282017bb7..525bcd381d5 100644
--- a/src/tools/miri/src/shims/native_lib.rs
+++ b/src/tools/miri/src/shims/native_lib.rs
@@ -5,7 +5,7 @@ use libffi::high::call as ffi;
 use libffi::low::CodePtr;
 use rustc_middle::ty::{self as ty, IntTy, UintTy};
 use rustc_span::Symbol;
-use rustc_target::abi::{Abi, HasDataLayout};
+use rustc_abi::{BackendRepr, HasDataLayout};
 
 use crate::*;
 
@@ -149,7 +149,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         // Get the function arguments, and convert them to `libffi`-compatible form.
         let mut libffi_args = Vec::<CArg>::with_capacity(args.len());
         for arg in args.iter() {
-            if !matches!(arg.layout.abi, Abi::Scalar(_)) {
+            if !matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) {
                 throw_unsup_format!("only scalar argument types are support for native calls")
             }
             libffi_args.push(imm_to_carg(this.read_immediate(arg)?, this)?);
diff --git a/src/tools/miri/tests/fail/coroutine-pinned-moved.stderr b/src/tools/miri/tests/fail/coroutine-pinned-moved.stderr
index c2c6ce987e5..9b4890c7cc6 100644
--- a/src/tools/miri/tests/fail/coroutine-pinned-moved.stderr
+++ b/src/tools/miri/tests/fail/coroutine-pinned-moved.stderr
@@ -23,7 +23,7 @@ note: inside `<CoroutineIteratorAdapter<{static coroutine@tests/fail/coroutine-p
    |
 LL |         match me.resume(()) {
    |               ^^^^^^^^^^^^^
-   = note: inside `<std::boxed::Box<CoroutineIteratorAdapter<{static coroutine@tests/fail/coroutine-pinned-moved.rs:LL:CC}>> as std::iter::Iterator>::next` at RUSTLIB/alloc/src/boxed.rs:LL:CC
+   = note: inside `std::boxed::iter::<impl std::iter::Iterator for std::boxed::Box<CoroutineIteratorAdapter<{static coroutine@tests/fail/coroutine-pinned-moved.rs:LL:CC}>>>::next` at RUSTLIB/alloc/src/boxed/iter.rs:LL:CC
 note: inside `main`
   --> tests/fail/coroutine-pinned-moved.rs:LL:CC
    |
diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock
index 695c37f6d7b..55705de9b2c 100644
--- a/src/tools/rust-analyzer/Cargo.lock
+++ b/src/tools/rust-analyzer/Cargo.lock
@@ -1364,7 +1364,6 @@ dependencies = [
  "proc-macro-api",
  "proc-macro-test",
  "ra-ap-rustc_lexer",
- "snap",
  "span",
  "stdx",
  "syntax-bridge",
@@ -1493,9 +1492,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_abi"
-version = "0.75.0"
+version = "0.76.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d5bc2cfc7264d84215a08875ef90a1d35f76b5c9ad1993515d2da7e4e40b2b4b"
+checksum = "709fde78db053c78c87776ec738677649f791645883f82ff145f68caf9f18e1a"
 dependencies = [
  "bitflags 2.6.0",
  "ra-ap-rustc_index",
@@ -1504,9 +1503,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_index"
-version = "0.75.0"
+version = "0.76.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8929140697812e5dd09e19cf446d85146332363f0dbc125d4214834c34ead96"
+checksum = "da115d496e5abd65e2dceb6883d7597593badfe23fea3439202b8da5a11ea250"
 dependencies = [
  "arrayvec",
  "ra-ap-rustc_index_macros",
@@ -1515,9 +1514,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_index_macros"
-version = "0.75.0"
+version = "0.76.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "514a3f5d04c8b4a2750f29746cc9abb1f78deb7e72e4ad1dc95bbc608f3db157"
+checksum = "be86d06a75a8125c1ace197d5030e6e02721348d32e572baea35c891669ad1e2"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1526,9 +1525,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_lexer"
-version = "0.75.0"
+version = "0.76.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "276fcb1205da071a0cd64416f3f0e198043c11f176c5b501a45dbf0cb33979f2"
+checksum = "b64b46ae0d8f59acc32e64e0085532b831f0d6182d870a7cd86c046c2c46e722"
 dependencies = [
  "unicode-properties",
  "unicode-xid",
@@ -1536,9 +1535,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_parse_format"
-version = "0.75.0"
+version = "0.76.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "961b30b22cfac296b14b72e9f95e79c16cebc8c926872755fb1568a6c4243a62"
+checksum = "dbdaad19ddbd0ff46e947ca8dbb6ae678a112d3938669fb3ad6bfd244917e24b"
 dependencies = [
  "ra-ap-rustc_index",
  "ra-ap-rustc_lexer",
@@ -1546,9 +1545,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_pattern_analysis"
-version = "0.75.0"
+version = "0.76.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "614232513814a4b714fea7f11345d31c0c277bca3089bb6ca1ec20870bfc022a"
+checksum = "dc5761e37c78d98ede9f20f6b66526093d0be66aa256d5cbdf214495843ba74d"
 dependencies = [
  "ra-ap-rustc_index",
  "rustc-hash 2.0.0",
@@ -1889,12 +1888,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "snap"
-version = "1.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b"
-
-[[package]]
 name = "span"
 version = "0.0.0"
 dependencies = [
diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml
index 3aa93b7b7b4..94e7de553bf 100644
--- a/src/tools/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/Cargo.toml
@@ -84,11 +84,11 @@ tt = { path = "./crates/tt", version = "0.0.0" }
 vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" }
 vfs = { path = "./crates/vfs", version = "0.0.0" }
 
-ra-ap-rustc_lexer = { version = "0.75", default-features = false }
-ra-ap-rustc_parse_format = { version = "0.75", default-features = false }
-ra-ap-rustc_index = { version = "0.75", default-features = false }
-ra-ap-rustc_abi = { version = "0.75", default-features = false }
-ra-ap-rustc_pattern_analysis = { version = "0.75", default-features = false }
+ra-ap-rustc_lexer = { version = "0.76", default-features = false }
+ra-ap-rustc_parse_format = { version = "0.76", default-features = false }
+ra-ap-rustc_index = { version = "0.76", default-features = false }
+ra-ap-rustc_abi = { version = "0.76", default-features = false }
+ra-ap-rustc_pattern_analysis = { version = "0.76", default-features = false }
 
 # local crates that aren't published to crates.io. These should not have versions.
 test-fixture = { path = "./crates/test-fixture" }
@@ -145,7 +145,6 @@ smallvec = { version = "1.10.0", features = [
   "const_generics",
 ] }
 smol_str = "0.3.2"
-snap = "1.1.0"
 text-size = "1.1.1"
 tracing = "0.1.40"
 tracing-tree = "0.3.0"
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
index 9f4cc98993e..0c1f63880cd 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
@@ -6,8 +6,9 @@ use base_db::ra_salsa::Cycle;
 use chalk_ir::{AdtId, FloatTy, IntTy, TyKind, UintTy};
 use hir_def::{
     layout::{
-        Abi, FieldsShape, Float, Integer, LayoutCalculator, LayoutCalculatorError, LayoutData,
-        Primitive, ReprOptions, Scalar, Size, StructKind, TargetDataLayout, WrappingRange,
+        BackendRepr, FieldsShape, Float, Integer, LayoutCalculator, LayoutCalculatorError,
+        LayoutData, Primitive, ReprOptions, Scalar, Size, StructKind, TargetDataLayout,
+        WrappingRange,
     },
     LocalFieldId, StructId,
 };
@@ -168,7 +169,7 @@ fn layout_of_simd_ty(
 
     // Compute the ABI of the element type:
     let e_ly = db.layout_of_ty(e_ty, env)?;
-    let Abi::Scalar(e_abi) = e_ly.abi else {
+    let BackendRepr::Scalar(e_abi) = e_ly.backend_repr else {
         return Err(LayoutError::Unknown);
     };
 
@@ -190,7 +191,7 @@ fn layout_of_simd_ty(
     Ok(Arc::new(Layout {
         variants: Variants::Single { index: struct_variant_idx() },
         fields,
-        abi: Abi::Vector { element: e_abi, count: e_len },
+        backend_repr: BackendRepr::Vector { element: e_abi, count: e_len },
         largest_niche: e_ly.largest_niche,
         size,
         align,
@@ -294,18 +295,19 @@ pub fn layout_of_ty_query(
                 .checked_mul(count, dl)
                 .ok_or(LayoutError::BadCalc(LayoutCalculatorError::SizeOverflow))?;
 
-            let abi = if count != 0 && matches!(element.abi, Abi::Uninhabited) {
-                Abi::Uninhabited
-            } else {
-                Abi::Aggregate { sized: true }
-            };
+            let backend_repr =
+                if count != 0 && matches!(element.backend_repr, BackendRepr::Uninhabited) {
+                    BackendRepr::Uninhabited
+                } else {
+                    BackendRepr::Memory { sized: true }
+                };
 
             let largest_niche = if count != 0 { element.largest_niche } else { None };
 
             Layout {
                 variants: Variants::Single { index: struct_variant_idx() },
                 fields: FieldsShape::Array { stride: element.size, count },
-                abi,
+                backend_repr,
                 largest_niche,
                 align: element.align,
                 size,
@@ -318,7 +320,7 @@ pub fn layout_of_ty_query(
             Layout {
                 variants: Variants::Single { index: struct_variant_idx() },
                 fields: FieldsShape::Array { stride: element.size, count: 0 },
-                abi: Abi::Aggregate { sized: false },
+                backend_repr: BackendRepr::Memory { sized: false },
                 largest_niche: None,
                 align: element.align,
                 size: Size::ZERO,
@@ -329,7 +331,7 @@ pub fn layout_of_ty_query(
         TyKind::Str => Layout {
             variants: Variants::Single { index: struct_variant_idx() },
             fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 },
-            abi: Abi::Aggregate { sized: false },
+            backend_repr: BackendRepr::Memory { sized: false },
             largest_niche: None,
             align: dl.i8_align,
             size: Size::ZERO,
@@ -379,8 +381,8 @@ pub fn layout_of_ty_query(
         TyKind::Never => cx.calc.layout_of_never_type(),
         TyKind::Dyn(_) | TyKind::Foreign(_) => {
             let mut unit = layout_of_unit(&cx)?;
-            match &mut unit.abi {
-                Abi::Aggregate { sized } => *sized = false,
+            match &mut unit.backend_repr {
+                BackendRepr::Memory { sized } => *sized = false,
                 _ => return Err(LayoutError::Unknown),
             }
             unit
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml
index e8d9677c928..4fabcc90067 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml
@@ -16,7 +16,6 @@ doctest = false
 object.workspace = true
 libloading.workspace = true
 memmap2.workspace = true
-snap.workspace = true
 
 stdx.workspace = true
 tt.workspace = true
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib/version.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib/version.rs
index 1f7ef7914ba..7f0e95c50de 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib/version.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib/version.rs
@@ -8,7 +8,6 @@ use std::{
 use memmap2::Mmap;
 use object::read::{File as BinaryFile, Object, ObjectSection};
 use paths::AbsPath;
-use snap::read::FrameDecoder as SnapDecoder;
 
 #[derive(Debug)]
 #[allow(dead_code)]
@@ -123,9 +122,8 @@ pub fn read_version(dylib_path: &AbsPath) -> io::Result<String> {
     let version = u32::from_be_bytes([dot_rustc[4], dot_rustc[5], dot_rustc[6], dot_rustc[7]]);
     // Last supported version is:
     // https://github.com/rust-lang/rust/commit/b94cfefc860715fb2adf72a6955423d384c69318
-    let (snappy_portion, bytes_before_version) = match version {
-        5 | 6 => (&dot_rustc[8..], 13),
-        7 | 8 => {
+    let (mut metadata_portion, bytes_before_version) = match version {
+        8 => {
             let len_bytes = &dot_rustc[8..12];
             let data_len = u32::from_be_bytes(len_bytes.try_into().unwrap()) as usize;
             (&dot_rustc[12..data_len + 12], 13)
@@ -143,13 +141,6 @@ pub fn read_version(dylib_path: &AbsPath) -> io::Result<String> {
         }
     };
 
-    let mut uncompressed: Box<dyn Read> = if &snappy_portion[0..4] == b"rust" {
-        // Not compressed.
-        Box::new(snappy_portion)
-    } else {
-        Box::new(SnapDecoder::new(snappy_portion))
-    };
-
     // We're going to skip over the bytes before the version string, so basically:
     // 8 bytes for [b'r',b'u',b's',b't',0,0,0,5]
     // 4 or 8 bytes for [crate root bytes]
@@ -157,11 +148,11 @@ pub fn read_version(dylib_path: &AbsPath) -> io::Result<String> {
     // so 13 or 17 bytes in total, and we should check the last of those bytes
     // to know the length
     let mut bytes = [0u8; 17];
-    uncompressed.read_exact(&mut bytes[..bytes_before_version])?;
+    metadata_portion.read_exact(&mut bytes[..bytes_before_version])?;
     let length = bytes[bytes_before_version - 1];
 
     let mut version_string_utf8 = vec![0u8; length as usize];
-    uncompressed.read_exact(&mut version_string_utf8)?;
+    metadata_portion.read_exact(&mut version_string_utf8)?;
     let version_string = String::from_utf8(version_string_utf8);
     version_string.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
 }
diff --git a/src/tools/rust-analyzer/rust-version b/src/tools/rust-analyzer/rust-version
index ffb312d06e6..00f4f743a7c 100644
--- a/src/tools/rust-analyzer/rust-version
+++ b/src/tools/rust-analyzer/rust-version
@@ -1 +1 @@
-a9d17627d241645a54c1134a20f1596127fedb60
+145f9cf95de1fbde3fa11e98461310e0373253e6
diff --git a/src/tools/rust-analyzer/xtask/src/tidy.rs b/src/tools/rust-analyzer/xtask/src/tidy.rs
index c3d531344a1..35412be8764 100644
--- a/src/tools/rust-analyzer/xtask/src/tidy.rs
+++ b/src/tools/rust-analyzer/xtask/src/tidy.rs
@@ -135,7 +135,6 @@ Apache-2.0 WITH LLVM-exception
 Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT
 Apache-2.0/MIT
 BSD-2-Clause OR Apache-2.0 OR MIT
-BSD-3-Clause
 CC0-1.0
 ISC
 MIT
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 5163f039a23..f3bd72fe647 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -24,6 +24,7 @@ const LICENSES: &[&str] = &[
     "BSD-2-Clause OR Apache-2.0 OR MIT",                   // zerocopy
     "ISC",
     "MIT / Apache-2.0",
+    "MIT AND Apache-2.0 WITH LLVM-exception AND (MIT OR Apache-2.0)", // compiler-builtins
     "MIT OR Apache-2.0 OR LGPL-2.1-or-later",              // r-efi, r-efi-alloc
     "MIT OR Apache-2.0 OR Zlib",                           // tinyvec_macros
     "MIT OR Apache-2.0",
@@ -100,7 +101,6 @@ const EXCEPTIONS: ExceptionList = &[
     ("rustc_apfloat", "Apache-2.0 WITH LLVM-exception"),     // rustc (license is the same as LLVM uses)
     ("ryu", "Apache-2.0 OR BSL-1.0"), // BSL is not acceptble, but we use it under Apache-2.0                       // cargo/... (because of serde)
     ("self_cell", "Apache-2.0"),                             // rustc (fluent translations)
-    ("snap", "BSD-3-Clause"),                                // rustc
     ("wasi-preview1-component-adapter-provider", "Apache-2.0 WITH LLVM-exception"), // rustc
     // tidy-alphabetical-end
 ];
@@ -162,7 +162,6 @@ const EXCEPTIONS_RUST_ANALYZER: ExceptionList = &[
     ("rustc_apfloat", "Apache-2.0 WITH LLVM-exception"),
     ("ryu", "Apache-2.0 OR BSL-1.0"), // BSL is not acceptble, but we use it under Apache-2.0
     ("scip", "Apache-2.0"),
-    ("snap", "BSD-3-Clause"),
     // tidy-alphabetical-end
 ];
 
@@ -390,7 +389,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "sharded-slab",
     "shlex",
     "smallvec",
-    "snap",
     "stable_deref_trait",
     "stacker",
     "static_assertions",
diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt
index 94f8d23c158..932a58788e0 100644
--- a/src/tools/tidy/src/issues.txt
+++ b/src/tools/tidy/src/issues.txt
@@ -4102,7 +4102,6 @@ ui/type-alias-impl-trait/issue-53678-coroutine-and-const-fn.rs
 ui/type-alias-impl-trait/issue-55099-lifetime-inference.rs
 ui/type-alias-impl-trait/issue-57188-associate-impl-capture.rs
 ui/type-alias-impl-trait/issue-57611-trait-alias.rs
-ui/type-alias-impl-trait/issue-57700.rs
 ui/type-alias-impl-trait/issue-57807-associated-type.rs
 ui/type-alias-impl-trait/issue-57961.rs
 ui/type-alias-impl-trait/issue-58662-coroutine-with-lifetime.rs
diff --git a/tests/assembly/compiletest-self-test/use-minicore-no-run.rs b/tests/assembly/compiletest-self-test/use-minicore-no-run.rs
new file mode 100644
index 00000000000..0e4f05c4b37
--- /dev/null
+++ b/tests/assembly/compiletest-self-test/use-minicore-no-run.rs
@@ -0,0 +1,5 @@
+//! `compiletest` self-test to check that `add-core-stubs` is incompatible with run pass modes.
+
+//@ add-core-stubs
+//@ run-pass
+//@ should-fail
diff --git a/tests/assembly/riscv-soft-abi-with-float-features.rs b/tests/assembly/riscv-soft-abi-with-float-features.rs
index 733137f5700..6d6001af084 100644
--- a/tests/assembly/riscv-soft-abi-with-float-features.rs
+++ b/tests/assembly/riscv-soft-abi-with-float-features.rs
@@ -1,6 +1,9 @@
 //@ assembly-output: emit-asm
 //@ compile-flags: --target riscv64imac-unknown-none-elf -Ctarget-feature=+f,+d
 //@ needs-llvm-components: riscv
+//@ revisions: LLVM-PRE-20 LLVM-POST-20
+//@ [LLVM-PRE-20] ignore-llvm-version: 20 - 99
+//@ [LLVM-POST-20] min-llvm-version: 20
 
 #![feature(no_core, lang_items, f16)]
 #![crate_type = "lib"]
@@ -31,9 +34,11 @@ pub extern "C" fn read_f16(x: &f16) -> f16 {
 // CHECK-LABEL: read_f32
 #[no_mangle]
 pub extern "C" fn read_f32(x: &f32) -> f32 {
-    // CHECK: flw fa5, 0(a0)
-    // CHECK-NEXT: fmv.x.w a0, fa5
-    // CHECK-NEXT: ret
+    // LLVM-PRE-20: flw fa5, 0(a0)
+    // LLVM-PRE-20-NEXT: fmv.x.w a0, fa5
+    // LLVM-PRE-20-NEXT: ret
+    // LLVM-POST-20: lw a0, 0(a0)
+    // LLVM-POST-20-NEXT: ret
     *x
 }
 
diff --git a/tests/auxiliary/minicore.rs b/tests/auxiliary/minicore.rs
new file mode 100644
index 00000000000..49a7580eccc
--- /dev/null
+++ b/tests/auxiliary/minicore.rs
@@ -0,0 +1,72 @@
+//! Auxiliary `minicore` prelude which stubs out `core` items for `no_core` tests that need to work
+//! in cross-compilation scenarios where no `core` is available (that don't want nor need to
+//! `-Zbuild-std`).
+//!
+//! # Important notes
+//!
+//! - `minicore` is **only** intended for `core` items, and the stubs should match the actual `core`
+//!   items.
+//!
+//! # References
+//!
+//! This is partially adapted from `rustc_codegen_cranelift`:
+//! <https://github.com/rust-lang/rust/blob/c0b5cc9003f6464c11ae1c0662c6a7e06f6f5cab/compiler/rustc_codegen_cranelift/example/mini_core.rs>.
+// ignore-tidy-linelength
+
+#![feature(no_core, lang_items, rustc_attrs)]
+#![allow(unused, improper_ctypes_definitions, internal_features)]
+#![no_std]
+#![no_core]
+
+// `core` has some exotic `marker_impls!` macro for handling the with-generics cases, but for our
+// purposes, just use a simple macro_rules macro.
+macro_rules! impl_marker_trait {
+    ($Trait:ident => [$( $ty:ident ),* $(,)?] ) => {
+        $( impl $Trait for $ty {} )*
+    }
+}
+
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "legacy_receiver"]
+pub trait LegacyReceiver {}
+impl<T: ?Sized> LegacyReceiver for &T {}
+impl<T: ?Sized> LegacyReceiver for &mut T {}
+
+#[lang = "copy"]
+pub trait Copy: Sized {}
+
+impl_marker_trait!(Copy => [ bool, char, isize, usize, i8, i16, i32, i64, u8, u16, u32, u64 ]);
+impl<'a, T: ?Sized> Copy for &'a T {}
+impl<T: ?Sized> Copy for *const T {}
+impl<T: ?Sized> Copy for *mut T {}
+
+#[lang = "phantom_data"]
+pub struct PhantomData<T: ?Sized>;
+impl<T: ?Sized> Copy for PhantomData<T> {}
+
+pub enum Option<T> {
+    None,
+    Some(T),
+}
+impl<T: Copy> Copy for Option<T> {}
+
+pub enum Result<T, E> {
+    Ok(T),
+    Err(E),
+}
+impl<T: Copy, E: Copy> Copy for Result<T, E> {}
+
+#[lang = "manually_drop"]
+#[repr(transparent)]
+pub struct ManuallyDrop<T: ?Sized> {
+    value: T,
+}
+impl<T: Copy + ?Sized> Copy for ManuallyDrop<T> {}
+
+#[lang = "unsafe_cell"]
+#[repr(transparent)]
+pub struct UnsafeCell<T: ?Sized> {
+    value: T,
+}
diff --git a/tests/codegen/clone_as_copy.rs b/tests/codegen/clone_as_copy.rs
index 36a59ae56b7..6ba198297e2 100644
--- a/tests/codegen/clone_as_copy.rs
+++ b/tests/codegen/clone_as_copy.rs
@@ -1,4 +1,6 @@
 //@ revisions: DEBUGINFO NODEBUGINFO
+//@ compile-flags: -Zunsound-mir-opts
+// FIXME: see <https://github.com/rust-lang/rust/issues/132353>
 //@ compile-flags: -O -Cno-prepopulate-passes
 //@ [DEBUGINFO] compile-flags: -Cdebuginfo=full
 
diff --git a/tests/codegen/compiletest-self-test/minicore-smoke-test.rs b/tests/codegen/compiletest-self-test/minicore-smoke-test.rs
new file mode 100644
index 00000000000..9dd1bf29c6c
--- /dev/null
+++ b/tests/codegen/compiletest-self-test/minicore-smoke-test.rs
@@ -0,0 +1,20 @@
+//! Basic smoke test for `minicore` test auxiliary.
+
+//@ add-core-stubs
+//@ compile-flags: --target=x86_64-unknown-linux-gnu
+//@ needs-llvm-components: x86
+
+#![crate_type = "lib"]
+#![feature(no_core)]
+#![no_std]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
+
+struct Meow;
+impl Copy for Meow {}
+
+// CHECK-LABEL: meow
+#[no_mangle]
+fn meow() {}
diff --git a/tests/codegen/try_question_mark_nop.rs b/tests/codegen/try_question_mark_nop.rs
index 65167f5c5af..bbab0d9eb1d 100644
--- a/tests/codegen/try_question_mark_nop.rs
+++ b/tests/codegen/try_question_mark_nop.rs
@@ -1,10 +1,7 @@
 //@ compile-flags: -O -Z merge-functions=disabled --edition=2021
 //@ only-x86_64
 // FIXME: Remove the `min-llvm-version`.
-//@ revisions: NINETEEN TWENTY
-//@[NINETEEN] min-llvm-version: 19
-//@[NINETEEN] ignore-llvm-version: 20-99
-//@[TWENTY] min-llvm-version: 20
+//@ min-llvm-version: 19
 
 #![crate_type = "lib"]
 #![feature(try_blocks)]
@@ -16,12 +13,9 @@ use std::ptr::NonNull;
 #[no_mangle]
 pub fn option_nop_match_32(x: Option<u32>) -> Option<u32> {
     // CHECK: start:
-    // NINETEEN-NEXT: [[TRUNC:%.*]] = trunc nuw i32 %0 to i1
-    // NINETEEN-NEXT: [[FIRST:%.*]] = select i1 [[TRUNC]], i32 %0
-    // NINETEEN-NEXT: insertvalue { i32, i32 } poison, i32 [[FIRST]], 0
-    // TWENTY-NEXT: insertvalue { i32, i32 } poison, i32 %0, 0
-    // CHECK-NEXT: insertvalue { i32, i32 }
-    // CHECK-NEXT: ret { i32, i32 }
+    // CHECK-NEXT: [[REG1:%.*]] = insertvalue { i32, i32 } poison, i32 %0, 0
+    // CHECK-NEXT: [[REG2:%.*]] = insertvalue { i32, i32 } [[REG1]], i32 %1, 1
+    // CHECK-NEXT: ret { i32, i32 } [[REG2]]
     match x {
         Some(x) => Some(x),
         None => None,
diff --git a/tests/crashes/125249.rs b/tests/crashes/125249.rs
deleted file mode 100644
index 1cf6338a0d6..00000000000
--- a/tests/crashes/125249.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-//@ known-bug: rust-lang/rust#125185
-#![feature(return_position_impl_trait_in_trait, return_type_notation)]
-
-trait IntFactory {
-    fn stream(&self) -> impl IntFactory<stream(..): IntFactory<stream(..): Send> + Send>;
-}
-
-pub fn main() {}
diff --git a/tests/crashes/23707.rs b/tests/crashes/23707.rs
deleted file mode 100644
index 4105933c60f..00000000000
--- a/tests/crashes/23707.rs
+++ /dev/null
@@ -1,109 +0,0 @@
-//@ known-bug: #23707
-//@ compile-flags: -Copt-level=0 --edition=2021
-//@ only-x86_64
-#![recursion_limit="2048"]
-
-use std::marker::PhantomData;
-use std::fmt;
-use std::fmt::Debug;
-
-pub struct Z( () );
-pub struct S<T> (PhantomData<T>);
-
-
-pub trait Nat {
-    fn sing() -> Self;
-    fn get(&self) -> usize;
-}
-
-impl Nat for Z {
-    fn sing() -> Z { Z( () ) }
-    #[inline(always)]
-    fn get(&self) -> usize {
-        0
-    }
-}
-
-impl<T : Nat> Nat for S<T> {
-    fn sing() -> S<T> { S::<T>( PhantomData::<T> ) }
-    #[inline(always)]
-    fn get(&self) -> usize {
-        let prd : T = Nat::sing();
-        1 + prd.get()
-    }
-}
-
-pub type N0 = Z;
-pub type N1 = S<N0>;
-pub type N2 = S<N1>;
-pub type N3 = S<N2>;
-pub type N4 = S<N3>;
-pub type N5 = S<N4>;
-
-
-pub struct Node<D : Nat>(usize,PhantomData<D>);
-
-impl<D:Nat> Node<D> {
-    pub fn push(&self, c : usize) -> Node<S<D>> {
-        let Node(i,_) = *self;
-        Node(10*i+c, PhantomData::<S<D>>)
-    }
-}
-
-impl<D:Nat> Node<S<D>> {
-    pub fn pop(&self) -> (Node<D>,usize) {
-        let Node(i,_) = *self;
-        (Node(i/10, PhantomData::<D>), i-10*(i/10))
-    }
-}
-
-impl<D:Nat> Debug for Node<D> {
-    fn fmt(&self, f : &mut fmt::Formatter) -> fmt::Result {
-        let s : D = Nat::sing();
-        write!(f, "Node<{}>: i= {}",
-               s.get(), self.0)
-    }
-}
-pub trait Step {
-    fn step(&self, usize) -> Self;
-}
-
-impl Step for Node<N0> {
-    #[inline(always)]
-    fn step(&self, n : usize) -> Node<N0> {
-        println!("base case");
-        Node(n,PhantomData::<N0>)
-    }
-}
-
-impl<D:Nat> Step for Node<S<D>>
-    where Node<D> : Step {
-        #[inline(always)]
-        fn step(&self, n : usize) -> Node<S<D>> {
-            println!("rec");
-            let (par,c) = self.pop();
-            let cnew = c+n;
-            par.step(c).push(cnew)
-        }
-
-}
-
-fn tst<D:Nat>(ref p : &Node<D>, c : usize) -> usize
-    where Node<D> : Step {
-        let Node(i,_) = p.step(c);
-        i
-}
-
-
-
-fn main() {
-    let nd : Node<N3> = Node(555,PhantomData::<N3>);
-
-    // overflow...core::marker::Size
-    let Node(g,_) = tst(nd,1);
-
-    // ok
-    //let Node(g,_) = nd.step(1);
-
-    println!("{:?}", g);
-}
diff --git a/tests/mir-opt/gvn_clone.rs b/tests/mir-opt/gvn_clone.rs
index 08938c0e1b4..c16b665fbd3 100644
--- a/tests/mir-opt/gvn_clone.rs
+++ b/tests/mir-opt/gvn_clone.rs
@@ -1,3 +1,5 @@
+//@ compile-flags: -Zunsound-mir-opts
+// FIXME: see <https://github.com/rust-lang/rust/issues/132353>
 //@ test-mir-pass: GVN
 //@ compile-flags: -Zmir-enable-passes=+InstSimplify-before-inline
 
diff --git a/tests/mir-opt/gvn_clone.{impl#0}-clone.GVN.diff b/tests/mir-opt/gvn_clone.{impl#0}-clone.GVN.diff
index 57b0980a0bd..8d5991872e1 100644
--- a/tests/mir-opt/gvn_clone.{impl#0}-clone.GVN.diff
+++ b/tests/mir-opt/gvn_clone.{impl#0}-clone.GVN.diff
@@ -1,7 +1,7 @@
-- // MIR for `<impl at $DIR/gvn_clone.rs:12:10: 12:15>::clone` before GVN
-+ // MIR for `<impl at $DIR/gvn_clone.rs:12:10: 12:15>::clone` after GVN
+- // MIR for `<impl at $DIR/gvn_clone.rs:14:10: 14:15>::clone` before GVN
++ // MIR for `<impl at $DIR/gvn_clone.rs:14:10: 14:15>::clone` after GVN
   
-  fn <impl at $DIR/gvn_clone.rs:12:10: 12:15>::clone(_1: &AllCopy) -> AllCopy {
+  fn <impl at $DIR/gvn_clone.rs:14:10: 14:15>::clone(_1: &AllCopy) -> AllCopy {
       debug self => _1;
       let mut _0: AllCopy;
       let mut _2: i32;
diff --git a/tests/mir-opt/gvn_copy_aggregate.rs b/tests/mir-opt/gvn_copy_aggregate.rs
index c9473025a15..7c181d1ad37 100644
--- a/tests/mir-opt/gvn_copy_aggregate.rs
+++ b/tests/mir-opt/gvn_copy_aggregate.rs
@@ -1,3 +1,5 @@
+//@ compile-flags: -Zunsound-mir-opts
+// FIXME: see <https://github.com/rust-lang/rust/issues/132353.
 //@ test-mir-pass: GVN
 //@ compile-flags: -Cpanic=abort
 
diff --git a/tests/mir-opt/pre-codegen/clone_as_copy.rs b/tests/mir-opt/pre-codegen/clone_as_copy.rs
index f5ff1854d38..ae4661e93fd 100644
--- a/tests/mir-opt/pre-codegen/clone_as_copy.rs
+++ b/tests/mir-opt/pre-codegen/clone_as_copy.rs
@@ -1,3 +1,5 @@
+//@ compile-flags: -Zunsound-mir-opts
+// FIXME: see <https://github.com/rust-lang/rust/issues/132353>
 //@ compile-flags: -Cdebuginfo=full
 
 // Check if we have transformed the nested clone to the copy in the complete pipeline.
diff --git a/tests/mir-opt/pre-codegen/no_inlined_clone.{impl#0}-clone.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/no_inlined_clone.{impl#0}-clone.PreCodegen.after.mir
index 9020cf1ef37..62a9cd9131f 100644
--- a/tests/mir-opt/pre-codegen/no_inlined_clone.{impl#0}-clone.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/no_inlined_clone.{impl#0}-clone.PreCodegen.after.mir
@@ -3,9 +3,13 @@
 fn <impl at $DIR/no_inlined_clone.rs:9:10: 9:15>::clone(_1: &Foo) -> Foo {
     debug self => _1;
     let mut _0: Foo;
+    let mut _2: i32;
 
     bb0: {
-        _0 = copy (*_1);
+        StorageLive(_2);
+        _2 = copy ((*_1).0: i32);
+        _0 = Foo { a: move _2 };
+        StorageDead(_2);
         return;
     }
 }
diff --git a/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir
index 889e80d26e1..ac485f485b1 100644
--- a/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir
@@ -19,14 +19,14 @@ fn old(_1: Result<T, E>) -> Result<T, E> {
     }
 
     bb1: {
-        _3 = copy ((_1 as Ok).0: T);
-        _0 = copy _1;
+        _3 = move ((_1 as Ok).0: T);
+        _0 = Result::<T, E>::Ok(copy _3);
         goto -> bb3;
     }
 
     bb2: {
-        _4 = copy ((_1 as Err).0: E);
-        _0 = copy _1;
+        _4 = move ((_1 as Err).0: E);
+        _0 = Result::<T, E>::Err(copy _4);
         goto -> bb3;
     }
 
diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir
index 4d964b0afb7..c3091bd4395 100644
--- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir
@@ -7,7 +7,7 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
         debug self => _1;
         scope 2 (inlined Vec::<u8>::as_slice) {
             debug self => _1;
-            let mut _6: usize;
+            let mut _7: usize;
             scope 3 (inlined Vec::<u8>::as_ptr) {
                 debug self => _1;
                 let mut _2: &alloc::raw_vec::RawVec<u8>;
@@ -16,6 +16,7 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
                     let mut _3: &alloc::raw_vec::RawVecInner;
                     scope 5 (inlined alloc::raw_vec::RawVecInner::ptr::<u8>) {
                         debug self => _3;
+                        let mut _6: std::ptr::NonNull<u8>;
                         scope 6 (inlined alloc::raw_vec::RawVecInner::non_null::<u8>) {
                             debug self => _3;
                             let mut _4: std::ptr::NonNull<u8>;
@@ -31,20 +32,20 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
                                 }
                             }
                             scope 10 (inlined Unique::<u8>::as_non_null_ptr) {
-                                debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _4;
+                                debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _6;
                                 debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>;
                             }
                         }
                         scope 11 (inlined NonNull::<u8>::as_ptr) {
-                            debug self => _4;
+                            debug self => _6;
                         }
                     }
                 }
             }
             scope 12 (inlined std::slice::from_raw_parts::<'_, u8>) {
                 debug data => _5;
-                debug len => _6;
-                let _7: *const [u8];
+                debug len => _7;
+                let _8: *const [u8];
                 scope 13 (inlined core::ub_checks::check_language_ub) {
                     scope 14 (inlined core::ub_checks::check_language_ub::runtime) {
                     }
@@ -55,10 +56,10 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
                 }
                 scope 17 (inlined slice_from_raw_parts::<u8>) {
                     debug data => _5;
-                    debug len => _6;
+                    debug len => _7;
                     scope 18 (inlined std::ptr::from_raw_parts::<[u8], u8>) {
                         debug data_pointer => _5;
-                        debug metadata => _6;
+                        debug metadata => _7;
                     }
                 }
             }
@@ -70,17 +71,22 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
         _2 = &((*_1).0: alloc::raw_vec::RawVec<u8>);
         StorageLive(_3);
         _3 = &(((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner);
+        StorageLive(_6);
+        StorageLive(_4);
         _4 = copy (((((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>);
         _5 = copy (_4.0: *const u8);
+        _6 = NonNull::<u8> { pointer: copy _5 };
+        StorageDead(_4);
+        StorageDead(_6);
         StorageDead(_3);
         StorageDead(_2);
-        StorageLive(_6);
-        _6 = copy ((*_1).1: usize);
         StorageLive(_7);
-        _7 = *const [u8] from (copy _5, copy _6);
-        _0 = &(*_7);
+        _7 = copy ((*_1).1: usize);
+        StorageLive(_8);
+        _8 = *const [u8] from (copy _5, copy _7);
+        _0 = &(*_8);
+        StorageDead(_8);
         StorageDead(_7);
-        StorageDead(_6);
         return;
     }
 }
diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir
index 4d964b0afb7..c3091bd4395 100644
--- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir
@@ -7,7 +7,7 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
         debug self => _1;
         scope 2 (inlined Vec::<u8>::as_slice) {
             debug self => _1;
-            let mut _6: usize;
+            let mut _7: usize;
             scope 3 (inlined Vec::<u8>::as_ptr) {
                 debug self => _1;
                 let mut _2: &alloc::raw_vec::RawVec<u8>;
@@ -16,6 +16,7 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
                     let mut _3: &alloc::raw_vec::RawVecInner;
                     scope 5 (inlined alloc::raw_vec::RawVecInner::ptr::<u8>) {
                         debug self => _3;
+                        let mut _6: std::ptr::NonNull<u8>;
                         scope 6 (inlined alloc::raw_vec::RawVecInner::non_null::<u8>) {
                             debug self => _3;
                             let mut _4: std::ptr::NonNull<u8>;
@@ -31,20 +32,20 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
                                 }
                             }
                             scope 10 (inlined Unique::<u8>::as_non_null_ptr) {
-                                debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _4;
+                                debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _6;
                                 debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>;
                             }
                         }
                         scope 11 (inlined NonNull::<u8>::as_ptr) {
-                            debug self => _4;
+                            debug self => _6;
                         }
                     }
                 }
             }
             scope 12 (inlined std::slice::from_raw_parts::<'_, u8>) {
                 debug data => _5;
-                debug len => _6;
-                let _7: *const [u8];
+                debug len => _7;
+                let _8: *const [u8];
                 scope 13 (inlined core::ub_checks::check_language_ub) {
                     scope 14 (inlined core::ub_checks::check_language_ub::runtime) {
                     }
@@ -55,10 +56,10 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
                 }
                 scope 17 (inlined slice_from_raw_parts::<u8>) {
                     debug data => _5;
-                    debug len => _6;
+                    debug len => _7;
                     scope 18 (inlined std::ptr::from_raw_parts::<[u8], u8>) {
                         debug data_pointer => _5;
-                        debug metadata => _6;
+                        debug metadata => _7;
                     }
                 }
             }
@@ -70,17 +71,22 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
         _2 = &((*_1).0: alloc::raw_vec::RawVec<u8>);
         StorageLive(_3);
         _3 = &(((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner);
+        StorageLive(_6);
+        StorageLive(_4);
         _4 = copy (((((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>);
         _5 = copy (_4.0: *const u8);
+        _6 = NonNull::<u8> { pointer: copy _5 };
+        StorageDead(_4);
+        StorageDead(_6);
         StorageDead(_3);
         StorageDead(_2);
-        StorageLive(_6);
-        _6 = copy ((*_1).1: usize);
         StorageLive(_7);
-        _7 = *const [u8] from (copy _5, copy _6);
-        _0 = &(*_7);
+        _7 = copy ((*_1).1: usize);
+        StorageLive(_8);
+        _8 = *const [u8] from (copy _5, copy _7);
+        _0 = &(*_8);
+        StorageDead(_8);
         StorageDead(_7);
-        StorageDead(_6);
         return;
     }
 }
diff --git a/tests/mir-opt/simplify_aggregate_to_copy_miscompile.foo.GVN.diff b/tests/mir-opt/simplify_aggregate_to_copy_miscompile.foo.GVN.diff
new file mode 100644
index 00000000000..22d4277ee45
--- /dev/null
+++ b/tests/mir-opt/simplify_aggregate_to_copy_miscompile.foo.GVN.diff
@@ -0,0 +1,72 @@
+- // MIR for `foo` before GVN
++ // MIR for `foo` after GVN
+  
+  fn foo(_1: &mut Option<i32>) -> Option<i32> {
+      debug v => _1;
+      let mut _0: std::option::Option<i32>;
+      let mut _2: &std::option::Option<i32>;
+      let mut _3: &std::option::Option<i32>;
+      let _4: &&mut std::option::Option<i32>;
+      let mut _5: isize;
+      let mut _7: !;
+      let mut _8: std::option::Option<i32>;
+      let mut _9: i32;
+      let mut _10: !;
+      let mut _11: &mut std::option::Option<i32>;
+      scope 1 {
+          debug col => _6;
+          let _6: i32;
+      }
+  
+      bb0: {
+-         StorageLive(_2);
++         nop;
+          StorageLive(_3);
+          StorageLive(_4);
+          _4 = &_1;
+-         _11 = deref_copy (*_4);
+-         _3 = &(*_11);
++         _11 = copy _1;
++         _3 = &(*_1);
+          _2 = get(move _3) -> [return: bb1, unwind unreachable];
+      }
+  
+      bb1: {
+          StorageDead(_3);
+          _5 = discriminant((*_2));
+          switchInt(move _5) -> [1: bb2, otherwise: bb3];
+      }
+  
+      bb2: {
+-         StorageLive(_6);
++         nop;
+          _6 = copy (((*_2) as Some).0: i32);
+          StorageLive(_8);
+-         _8 = Option::<i32>::None;
+-         (*_1) = move _8;
++         _8 = const Option::<i32>::None;
++         (*_1) = const Option::<i32>::None;
+          StorageDead(_8);
+          StorageLive(_9);
+          _9 = copy _6;
+-         _0 = Option::<i32>::Some(move _9);
++         _0 = copy (*_2);
+          StorageDead(_9);
+-         StorageDead(_6);
++         nop;
+          StorageDead(_4);
+-         StorageDead(_2);
++         nop;
+          return;
+      }
+  
+      bb3: {
+          StorageLive(_10);
+          unreachable;
+      }
++ }
++ 
++ ALLOC0 (size: 8, align: 4) {
++     00 00 00 00 __ __ __ __                         │ ....░░░░
+  }
+  
diff --git a/tests/mir-opt/simplify_aggregate_to_copy_miscompile.rs b/tests/mir-opt/simplify_aggregate_to_copy_miscompile.rs
new file mode 100644
index 00000000000..47721b768be
--- /dev/null
+++ b/tests/mir-opt/simplify_aggregate_to_copy_miscompile.rs
@@ -0,0 +1,32 @@
+//! The `simplify_aggregate_to_copy` mir-opt introduced in
+//! <https://github.com/rust-lang/rust/pull/128299> caused a miscompile because the initial
+//! implementation
+//!
+//! > introduce[d] new dereferences without checking for aliasing
+//!
+//! This test demonstrates the behavior, and should be adjusted or removed when fixing and relanding
+//! the mir-opt.
+#![crate_type = "lib"]
+// skip-filecheck
+//@ compile-flags: -O -Zunsound-mir-opts
+//@ test-mir-pass: GVN
+#![allow(internal_features)]
+#![feature(rustc_attrs, core_intrinsics)]
+
+// EMIT_MIR simplify_aggregate_to_copy_miscompile.foo.GVN.diff
+#[no_mangle]
+fn foo(v: &mut Option<i32>) -> Option<i32> {
+    if let &Some(col) = get(&v) {
+        *v = None;
+        return Some(col);
+    } else {
+        unsafe { std::intrinsics::unreachable() }
+    }
+}
+
+#[no_mangle]
+#[inline(never)]
+#[rustc_nounwind]
+fn get(v: &Option<i32>) -> &Option<i32> {
+    v
+}
diff --git a/tests/rustdoc-gui/fields.goml b/tests/rustdoc-gui/fields.goml
index 5d13d7be2f9..dce9918c332 100644
--- a/tests/rustdoc-gui/fields.goml
+++ b/tests/rustdoc-gui/fields.goml
@@ -1,6 +1,7 @@
 // This test checks that fields are displayed as expected (one by line) and they are surrounded
 // by margins.
 
+store-value: (margin, "9.6px")
 define-function: (
     "check-fields",
     [path, selector_1, selector_2],
@@ -12,8 +13,8 @@ define-function: (
 
         // Check the margins.
         assert-css: (".structfield.section-header", {
-            "margin-top": "9.6px",
-            "margin-bottom": "9.6px",
+            "margin-top": |margin|,
+            "margin-bottom": |margin|,
             "margin-left": "0px",
             "margin-right": "0px",
         }, ALL)
@@ -41,9 +42,9 @@ store-position: ("#variant\.B\.field\.b", {"y": b_y})
 assert: |a_y| < |b_y|
 
 // Check the margins.
-assert-css: (".sub-variant-field .section-header", {
-    "margin-top": "0px",
-    "margin-bottom": "0px",
-    "margin-left": "0px",
+assert-css: (".sub-variant-field", {
+    "margin-top": |margin|,
+    "margin-bottom": |margin|,
+    "margin-left": "24px",
     "margin-right": "0px",
 }, ALL)
diff --git a/tests/rustdoc-ui/doctest/auxiliary/extern_macros_2024.rs b/tests/rustdoc-ui/doctest/auxiliary/extern_macros_2024.rs
new file mode 100644
index 00000000000..354427000bf
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/auxiliary/extern_macros_2024.rs
@@ -0,0 +1,10 @@
+//@ edition:2024
+//@ compile-flags:-Z unstable-options
+#![crate_name="extern_macros"]
+#[macro_export]
+macro_rules! attrs_on_struct {
+    ( $( #[$attr:meta] )* ) => {
+        $( #[$attr] )*
+        pub struct ExpandedStruct;
+    }
+}
diff --git a/tests/rustdoc-ui/doctest/auxiliary/relative-dir-empty-file b/tests/rustdoc-ui/doctest/auxiliary/relative-dir-empty-file
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/auxiliary/relative-dir-empty-file
diff --git a/tests/rustdoc-ui/doctest/auxiliary/relative-dir.md b/tests/rustdoc-ui/doctest/auxiliary/relative-dir.md
new file mode 100644
index 00000000000..90097ce82fb
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/auxiliary/relative-dir.md
@@ -0,0 +1,3 @@
+```rust
+let x = include_bytes!("relative-dir-empty-file");
+```
diff --git a/tests/rustdoc-ui/doctest/dead-code-2024.rs b/tests/rustdoc-ui/doctest/dead-code-2024.rs
new file mode 100644
index 00000000000..4c77112e61a
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/dead-code-2024.rs
@@ -0,0 +1,15 @@
+// This test ensures that the 2024 edition merged doctest will not use `#[allow(unused)]`.
+
+//@ compile-flags:--test -Zunstable-options --edition 2024
+//@ normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
+//@ normalize-stdout-test: "finished in \d+\.\d+s" -> "finished in $$TIME"
+//@ failure-status: 101
+
+#![doc(test(attr(allow(unused_variables), deny(warnings))))]
+
+/// Example
+///
+/// ```rust,no_run
+/// trait T { fn f(); }
+/// ```
+pub fn f() {}
diff --git a/tests/rustdoc-ui/doctest/dead-code-2024.stdout b/tests/rustdoc-ui/doctest/dead-code-2024.stdout
new file mode 100644
index 00000000000..69dd4e2ede1
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/dead-code-2024.stdout
@@ -0,0 +1,29 @@
+
+running 1 test
+test $DIR/dead-code-2024.rs - f (line 12) - compile ... FAILED
+
+failures:
+
+---- $DIR/dead-code-2024.rs - f (line 12) stdout ----
+error: trait `T` is never used
+  --> $DIR/dead-code-2024.rs:13:7
+   |
+LL | trait T { fn f(); }
+   |       ^
+   |
+note: the lint level is defined here
+  --> $DIR/dead-code-2024.rs:11:9
+   |
+LL | #![deny(warnings)]
+   |         ^^^^^^^^
+   = note: `#[deny(dead_code)]` implied by `#[deny(warnings)]`
+
+error: aborting due to 1 previous error
+
+Couldn't compile the test.
+
+failures:
+    $DIR/dead-code-2024.rs - f (line 12)
+
+test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/doctest/dead-code.rs b/tests/rustdoc-ui/doctest/dead-code.rs
new file mode 100644
index 00000000000..cb9b4c28f6c
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/dead-code.rs
@@ -0,0 +1,15 @@
+// This test ensures that the doctest will not use `#[allow(unused)]`.
+
+//@ compile-flags:--test
+//@ normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
+//@ normalize-stdout-test: "finished in \d+\.\d+s" -> "finished in $$TIME"
+//@ failure-status: 101
+
+#![doc(test(attr(allow(unused_variables), deny(warnings))))]
+
+/// Example
+///
+/// ```rust,no_run
+/// trait T { fn f(); }
+/// ```
+pub fn f() {}
diff --git a/tests/rustdoc-ui/doctest/dead-code.stdout b/tests/rustdoc-ui/doctest/dead-code.stdout
new file mode 100644
index 00000000000..38d15d5c1bc
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/dead-code.stdout
@@ -0,0 +1,29 @@
+
+running 1 test
+test $DIR/dead-code.rs - f (line 12) - compile ... FAILED
+
+failures:
+
+---- $DIR/dead-code.rs - f (line 12) stdout ----
+error: trait `T` is never used
+  --> $DIR/dead-code.rs:13:7
+   |
+LL | trait T { fn f(); }
+   |       ^
+   |
+note: the lint level is defined here
+  --> $DIR/dead-code.rs:11:9
+   |
+LL | #![deny(warnings)]
+   |         ^^^^^^^^
+   = note: `#[deny(dead_code)]` implied by `#[deny(warnings)]`
+
+error: aborting due to 1 previous error
+
+Couldn't compile the test.
+
+failures:
+    $DIR/dead-code.rs - f (line 12)
+
+test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/doctest/doctest-output-include-fail.rs b/tests/rustdoc-ui/doctest/doctest-output-include-fail.rs
index 4fc0674a0c9..bae61992eb2 100644
--- a/tests/rustdoc-ui/doctest/doctest-output-include-fail.rs
+++ b/tests/rustdoc-ui/doctest/doctest-output-include-fail.rs
@@ -1,4 +1,5 @@
-//@ compile-flags:--test --test-args=--test-threads=1
+//@ edition:2024
+//@ compile-flags:--test --test-args=--test-threads=1 -Z unstable-options
 //@ normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
 //@ normalize-stdout-test: "finished in \d+\.\d+s" -> "finished in $$TIME"
 //@ failure-status: 101
diff --git a/tests/rustdoc-ui/doctest/doctest-output.edition2015.stdout b/tests/rustdoc-ui/doctest/doctest-output.edition2015.stdout
new file mode 100644
index 00000000000..0e2e30390ad
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/doctest-output.edition2015.stdout
@@ -0,0 +1,8 @@
+
+running 3 tests
+test $DIR/doctest-output.rs - (line 12) ... ok
+test $DIR/doctest-output.rs - ExpandedStruct (line 28) ... ok
+test $DIR/doctest-output.rs - foo::bar (line 22) ... ok
+
+test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/doctest/doctest-output.edition2024.stdout b/tests/rustdoc-ui/doctest/doctest-output.edition2024.stdout
new file mode 100644
index 00000000000..0e2e30390ad
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/doctest-output.edition2024.stdout
@@ -0,0 +1,8 @@
+
+running 3 tests
+test $DIR/doctest-output.rs - (line 12) ... ok
+test $DIR/doctest-output.rs - ExpandedStruct (line 28) ... ok
+test $DIR/doctest-output.rs - foo::bar (line 22) ... ok
+
+test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/doctest/doctest-output.rs b/tests/rustdoc-ui/doctest/doctest-output.rs
index 72394a4bed3..0e5ccf0b090 100644
--- a/tests/rustdoc-ui/doctest/doctest-output.rs
+++ b/tests/rustdoc-ui/doctest/doctest-output.rs
@@ -1,6 +1,10 @@
-//@ edition:2018
-//@ aux-build:extern_macros.rs
-//@ compile-flags:--test --test-args=--test-threads=1
+//@ revisions: edition2015 edition2024
+//@[edition2015]edition:2015
+//@[edition2015]aux-build:extern_macros.rs
+//@[edition2015]compile-flags:--test --test-args=--test-threads=1
+//@[edition2024]edition:2015
+//@[edition2024]aux-build:extern_macros.rs
+//@[edition2024]compile-flags:--test --test-args=--test-threads=1 -Z unstable-options
 //@ normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
 //@ normalize-stdout-test: "finished in \d+\.\d+s" -> "finished in $$TIME"
 //@ check-pass
diff --git a/tests/rustdoc-ui/doctest/doctest-output.stdout b/tests/rustdoc-ui/doctest/doctest-output.stdout
deleted file mode 100644
index c3b1570c43e..00000000000
--- a/tests/rustdoc-ui/doctest/doctest-output.stdout
+++ /dev/null
@@ -1,8 +0,0 @@
-
-running 3 tests
-test $DIR/doctest-output.rs - (line 8) ... ok
-test $DIR/doctest-output.rs - ExpandedStruct (line 25) ... ok
-test $DIR/doctest-output.rs - foo::bar (line 18) ... ok
-
-test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
-
diff --git a/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.edition2015.stdout b/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.edition2015.stdout
new file mode 100644
index 00000000000..ca6e7750264
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.edition2015.stdout
@@ -0,0 +1,24 @@
+
+running 1 test
+test $DIR/relative-path-include-bytes-132203.rs - (line 18) ... FAILED
+
+failures:
+
+---- $DIR/relative-path-include-bytes-132203.rs - (line 18) stdout ----
+error: couldn't read `$DIR/relative-dir-empty-file`: No such file or directory (os error 2)
+  --> $DIR/relative-path-include-bytes-132203.rs:19:9
+   |
+LL | let x = include_bytes!("relative-dir-empty-file");
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in the macro `include_bytes` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 1 previous error
+
+Couldn't compile the test.
+
+failures:
+    $DIR/relative-path-include-bytes-132203.rs - (line 18)
+
+test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.edition2024.stdout b/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.edition2024.stdout
new file mode 100644
index 00000000000..e4c65703081
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.edition2024.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/auxiliary/relative-dir.md - (line 1) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.rs b/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.rs
new file mode 100644
index 00000000000..b393d126306
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.rs
@@ -0,0 +1,18 @@
+//@ ignore-windows
+//@ revisions: edition2015 edition2024
+//@[edition2015]edition:2015
+//@[edition2015]check-fail
+//@[edition2015]failure-status: 101
+//@[edition2015]compile-flags:--test --test-args=--test-threads=1
+//@[edition2024]edition:2024
+//@[edition2024]check-pass
+//@[edition2024]compile-flags:--test --test-args=--test-threads=1 -Z unstable-options
+//@ normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
+//@ normalize-stdout-test: "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+// https://github.com/rust-lang/rust/issues/132203
+// This version, because it's edition2024, passes thanks to the new
+// relative path. The edition2015 version fails, because paths are
+// resolved relative to the rs file instead of relative to the md file.
+
+#![doc=include_str!("auxiliary/relative-dir.md")]
diff --git a/tests/ui/abi/c-zst.other-linux.stderr b/tests/ui/abi/c-zst.aarch64-darwin.stderr
index 5a656e6ea66..7d384bc875f 100644
--- a/tests/ui/abi/c-zst.other-linux.stderr
+++ b/tests/ui/abi/c-zst.aarch64-darwin.stderr
@@ -9,7 +9,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                                abi: $SOME_ALIGN,
                                pref: $SOME_ALIGN,
                            },
-                           abi: Aggregate {
+                           abi: Memory {
                                sized: true,
                            },
                            fields: Arbitrary {
@@ -36,7 +36,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            abi: $SOME_ALIGN,
                            pref: $SOME_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -58,7 +58,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
            conv: C,
            can_unwind: false,
        }
-  --> $DIR/c-zst.rs:27:1
+  --> $DIR/c-zst.rs:63:1
    |
 LL | extern "C" fn pass_zst(_: ()) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/abi/c-zst.powerpc-linux.stderr b/tests/ui/abi/c-zst.powerpc-linux.stderr
index ba9738050d8..7980710bab6 100644
--- a/tests/ui/abi/c-zst.powerpc-linux.stderr
+++ b/tests/ui/abi/c-zst.powerpc-linux.stderr
@@ -9,7 +9,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                                abi: $SOME_ALIGN,
                                pref: $SOME_ALIGN,
                            },
-                           abi: Aggregate {
+                           abi: Memory {
                                sized: true,
                            },
                            fields: Arbitrary {
@@ -47,7 +47,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            abi: $SOME_ALIGN,
                            pref: $SOME_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -69,7 +69,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
            conv: C,
            can_unwind: false,
        }
-  --> $DIR/c-zst.rs:27:1
+  --> $DIR/c-zst.rs:63:1
    |
 LL | extern "C" fn pass_zst(_: ()) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/abi/c-zst.rs b/tests/ui/abi/c-zst.rs
index 0cfd653b37e..69ebefa09ac 100644
--- a/tests/ui/abi/c-zst.rs
+++ b/tests/ui/abi/c-zst.rs
@@ -1,27 +1,63 @@
-//@ revisions: other other-linux x86_64-pc-windows-gnu s390x-linux sparc64-linux powerpc-linux
 //@ normalize-stderr-test: "(abi|pref|unadjusted_abi_align): Align\([1-8] bytes\)" -> "$1: $$SOME_ALIGN"
-// ZSTs are only not ignored when the target_env is "gnu", "musl" or "uclibc". However, Rust does
-// not currently support any other target_env on these architectures.
-
-// Ignore the ZST revisions
-//@[other] ignore-x86_64-pc-windows-gnu
-//@[other] ignore-linux
-//@[other-linux] only-linux
-//@[other-linux] ignore-s390x
-//@[other-linux] ignore-sparc64
-//@[other-linux] ignore-powerpc
-
-// Pass the ZST indirectly revisions
-//@[x86_64-pc-windows-gnu] only-x86_64-pc-windows-gnu
-//@[s390x-linux] only-s390x
-//@[s390x-linux] only-linux
-//@[sparc64-linux] only-sparc64
-//@[sparc64-linux] only-linux
-//@[powerpc-linux] only-powerpc
-//@[powerpc-linux] only-linux
-
-#![feature(rustc_attrs)]
+/*!
+C doesn't have zero-sized types... except it does.
+
+Standard C doesn't, but some C compilers, like GCC, implement ZSTs as a compiler extension.
+This historically has wound up interacting with processor-specific ABIs in fairly ad-hoc ways.
+e.g. despite being "zero-sized", sometimes C compilers decide ZSTs consume registers.
+
+That means these two function signatures may not be compatible:
+
+```
+extern "C" fn((), i32, i32);
+extern "C" fn(i32, (), i32);
+```
+*/
+
+/*
+ * ZST IN "C" IS ZERO-SIZED
+ */
+
+//@ revisions: aarch64-darwin
+//@[aarch64-darwin] compile-flags: --target aarch64-apple-darwin
+//@[aarch64-darwin] needs-llvm-components: aarch64
+
+//@ revisions: x86_64-linux
+//@[x86_64-linux] compile-flags: --target x86_64-unknown-linux-gnu
+//@[x86_64-linux] needs-llvm-components: x86
+
+
+/*
+ * ZST IN "C" IS PASS-BY-POINTER
+ */
+
+// according to the SRV4 ABI, an aggregate is always passed in registers,
+// and it so happens the GCC extension for ZSTs considers them as structs.
+//@ revisions: powerpc-linux
+//@[powerpc-linux] compile-flags: --target powerpc-unknown-linux-gnu
+//@[powerpc-linux] needs-llvm-components: powerpc
+
+//@ revisions: s390x-linux
+//@[s390x-linux] compile-flags: --target s390x-unknown-linux-gnu
+//@[s390x-linux] needs-llvm-components: systemz
+
+//@ revisions: sparc64-linux
+//@[sparc64-linux] compile-flags: --target sparc64-unknown-linux-gnu
+//@[sparc64-linux] needs-llvm-components: sparc
+
+// The Win64 ABI uses slightly different handling for power-of-2 sizes in the ABI,
+// so GCC decided that ZSTs are pass-by-pointer, as `0.is_power_of_two() == false`
+//@ revisions: x86_64-pc-windows-gnu
+//@[x86_64-pc-windows-gnu] compile-flags: --target x86_64-pc-windows-gnu
+//@[x86_64-pc-windows-gnu] needs-llvm-components: x86
+
+
+#![feature(lang_items, no_core, rustc_attrs)]
+#![no_core]
 #![crate_type = "lib"]
 
+#[lang = "sized"]
+trait Sized {}
+
 #[rustc_abi(debug)]
 extern "C" fn pass_zst(_: ()) {} //~ ERROR: fn_abi
diff --git a/tests/ui/abi/c-zst.s390x-linux.stderr b/tests/ui/abi/c-zst.s390x-linux.stderr
index ba9738050d8..7980710bab6 100644
--- a/tests/ui/abi/c-zst.s390x-linux.stderr
+++ b/tests/ui/abi/c-zst.s390x-linux.stderr
@@ -9,7 +9,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                                abi: $SOME_ALIGN,
                                pref: $SOME_ALIGN,
                            },
-                           abi: Aggregate {
+                           abi: Memory {
                                sized: true,
                            },
                            fields: Arbitrary {
@@ -47,7 +47,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            abi: $SOME_ALIGN,
                            pref: $SOME_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -69,7 +69,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
            conv: C,
            can_unwind: false,
        }
-  --> $DIR/c-zst.rs:27:1
+  --> $DIR/c-zst.rs:63:1
    |
 LL | extern "C" fn pass_zst(_: ()) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/abi/c-zst.sparc64-linux.stderr b/tests/ui/abi/c-zst.sparc64-linux.stderr
index ba9738050d8..7980710bab6 100644
--- a/tests/ui/abi/c-zst.sparc64-linux.stderr
+++ b/tests/ui/abi/c-zst.sparc64-linux.stderr
@@ -9,7 +9,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                                abi: $SOME_ALIGN,
                                pref: $SOME_ALIGN,
                            },
-                           abi: Aggregate {
+                           abi: Memory {
                                sized: true,
                            },
                            fields: Arbitrary {
@@ -47,7 +47,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            abi: $SOME_ALIGN,
                            pref: $SOME_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -69,7 +69,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
            conv: C,
            can_unwind: false,
        }
-  --> $DIR/c-zst.rs:27:1
+  --> $DIR/c-zst.rs:63:1
    |
 LL | extern "C" fn pass_zst(_: ()) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/abi/c-zst.other.stderr b/tests/ui/abi/c-zst.x86_64-linux.stderr
index 5a656e6ea66..7d384bc875f 100644
--- a/tests/ui/abi/c-zst.other.stderr
+++ b/tests/ui/abi/c-zst.x86_64-linux.stderr
@@ -9,7 +9,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                                abi: $SOME_ALIGN,
                                pref: $SOME_ALIGN,
                            },
-                           abi: Aggregate {
+                           abi: Memory {
                                sized: true,
                            },
                            fields: Arbitrary {
@@ -36,7 +36,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            abi: $SOME_ALIGN,
                            pref: $SOME_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -58,7 +58,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
            conv: C,
            can_unwind: false,
        }
-  --> $DIR/c-zst.rs:27:1
+  --> $DIR/c-zst.rs:63:1
    |
 LL | extern "C" fn pass_zst(_: ()) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr
index ba9738050d8..7980710bab6 100644
--- a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr
+++ b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr
@@ -9,7 +9,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                                abi: $SOME_ALIGN,
                                pref: $SOME_ALIGN,
                            },
-                           abi: Aggregate {
+                           abi: Memory {
                                sized: true,
                            },
                            fields: Arbitrary {
@@ -47,7 +47,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            abi: $SOME_ALIGN,
                            pref: $SOME_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -69,7 +69,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
            conv: C,
            can_unwind: false,
        }
-  --> $DIR/c-zst.rs:27:1
+  --> $DIR/c-zst.rs:63:1
    |
 LL | extern "C" fn pass_zst(_: ()) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs
index 408dbea4ae8..01d90717107 100644
--- a/tests/ui/abi/compatibility.rs
+++ b/tests/ui/abi/compatibility.rs
@@ -1,4 +1,5 @@
 //@ check-pass
+//@ add-core-stubs
 //@ revisions: host
 //@ revisions: i686
 //@[i686] compile-flags: --target i686-unknown-linux-gnu
@@ -58,8 +59,10 @@
 //@ revisions: nvptx64
 //@[nvptx64] compile-flags: --target nvptx64-nvidia-cuda
 //@[nvptx64] needs-llvm-components: nvptx
-#![feature(rustc_attrs, unsized_fn_params, transparent_unions)]
-#![cfg_attr(not(host), feature(no_core, lang_items), no_std, no_core)]
+#![feature(no_core, rustc_attrs, lang_items)]
+#![feature(unsized_fn_params, transparent_unions)]
+#![no_std]
+#![no_core]
 #![allow(unused, improper_ctypes_definitions, internal_features)]
 
 // FIXME: some targets are broken in various ways.
@@ -67,67 +70,24 @@
 // sparc64: https://github.com/rust-lang/rust/issues/115336
 // mips64: https://github.com/rust-lang/rust/issues/115404
 
-#[cfg(host)]
-use std::{
-    any::Any, marker::PhantomData, mem::ManuallyDrop, num::NonZero, ptr::NonNull, rc::Rc, sync::Arc,
-};
+extern crate minicore;
+use minicore::*;
 
-/// To work cross-target this test must be no_core.
-/// This little prelude supplies what we need.
-#[cfg(not(host))]
+/// To work cross-target this test must be no_core. This little prelude supplies what we need.
+///
+/// Note that `minicore` provides a very minimal subset of `core` items (not yet complete). This
+/// prelude contains `alloc` and non-`core` (but in `std`) items that minicore does not stub out.
 mod prelude {
-    #[lang = "sized"]
-    pub trait Sized {}
+    use minicore::*;
 
-    #[lang = "legacy_receiver"]
-    pub trait LegacyReceiver {}
-    impl<T: ?Sized> LegacyReceiver for &T {}
-    impl<T: ?Sized> LegacyReceiver for &mut T {}
-
-    #[lang = "copy"]
-    pub trait Copy: Sized {}
-    impl Copy for i32 {}
-    impl Copy for f32 {}
-    impl<T: ?Sized> Copy for &T {}
-    impl<T: ?Sized> Copy for *const T {}
-    impl<T: ?Sized> Copy for *mut T {}
+    // Trait stub, no `type_id` method.
+    pub trait Any: 'static {}
 
     #[lang = "clone"]
     pub trait Clone: Sized {
         fn clone(&self) -> Self;
     }
 
-    #[lang = "phantom_data"]
-    pub struct PhantomData<T: ?Sized>;
-    impl<T: ?Sized> Copy for PhantomData<T> {}
-
-    #[lang = "unsafe_cell"]
-    #[repr(transparent)]
-    pub struct UnsafeCell<T: ?Sized> {
-        value: T,
-    }
-
-    pub trait Any: 'static {}
-
-    pub enum Option<T> {
-        None,
-        Some(T),
-    }
-    impl<T: Copy> Copy for Option<T> {}
-
-    pub enum Result<T, E> {
-        Ok(T),
-        Err(E),
-    }
-    impl<T: Copy, E: Copy> Copy for Result<T, E> {}
-
-    #[lang = "manually_drop"]
-    #[repr(transparent)]
-    pub struct ManuallyDrop<T: ?Sized> {
-        value: T,
-    }
-    impl<T: Copy + ?Sized> Copy for ManuallyDrop<T> {}
-
     #[repr(transparent)]
     #[rustc_layout_scalar_valid_range_start(1)]
     #[rustc_nonnull_optimization_guaranteed]
@@ -185,7 +145,6 @@ mod prelude {
         alloc: A,
     }
 }
-#[cfg(not(host))]
 use prelude::*;
 
 macro_rules! test_abi_compatible {
diff --git a/tests/ui/abi/debug.stderr b/tests/ui/abi/debug.stderr
index 7365839da89..aa51c42c58d 100644
--- a/tests/ui/abi/debug.stderr
+++ b/tests/ui/abi/debug.stderr
@@ -235,7 +235,7 @@ error: fn_abi_of(test_generic) = FnAbi {
                            abi: $SOME_ALIGN,
                            pref: $SOME_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -317,7 +317,7 @@ error: ABIs are not compatible
                            abi: $SOME_ALIGN,
                            pref: $SOME_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -387,7 +387,7 @@ error: ABIs are not compatible
                            abi: $SOME_ALIGN,
                            pref: $SOME_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -426,7 +426,7 @@ error: ABIs are not compatible
                                abi: $SOME_ALIGN,
                                pref: $SOME_ALIGN,
                            },
-                           abi: Aggregate {
+                           abi: Memory {
                                sized: true,
                            },
                            fields: Array {
@@ -464,7 +464,7 @@ error: ABIs are not compatible
                            abi: $SOME_ALIGN,
                            pref: $SOME_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -497,7 +497,7 @@ error: ABIs are not compatible
                                abi: $SOME_ALIGN,
                                pref: $SOME_ALIGN,
                            },
-                           abi: Aggregate {
+                           abi: Memory {
                                sized: true,
                            },
                            fields: Array {
@@ -535,7 +535,7 @@ error: ABIs are not compatible
                            abi: $SOME_ALIGN,
                            pref: $SOME_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -610,7 +610,7 @@ error: ABIs are not compatible
                            abi: $SOME_ALIGN,
                            pref: $SOME_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -680,7 +680,7 @@ error: ABIs are not compatible
                            abi: $SOME_ALIGN,
                            pref: $SOME_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -756,7 +756,7 @@ error: ABIs are not compatible
                            abi: $SOME_ALIGN,
                            pref: $SOME_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -826,7 +826,7 @@ error: ABIs are not compatible
                            abi: $SOME_ALIGN,
                            pref: $SOME_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -929,7 +929,7 @@ error: fn_abi_of(assoc_test) = FnAbi {
                            abi: $SOME_ALIGN,
                            pref: $SOME_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
diff --git a/tests/ui/abi/sysv64-zst.stderr b/tests/ui/abi/sysv64-zst.stderr
index 8b0b84dfa06..8e1791e27d2 100644
--- a/tests/ui/abi/sysv64-zst.stderr
+++ b/tests/ui/abi/sysv64-zst.stderr
@@ -9,7 +9,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                                abi: $SOME_ALIGN,
                                pref: $SOME_ALIGN,
                            },
-                           abi: Aggregate {
+                           abi: Memory {
                                sized: true,
                            },
                            fields: Arbitrary {
@@ -36,7 +36,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            abi: $SOME_ALIGN,
                            pref: $SOME_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
diff --git a/tests/ui/abi/win64-zst.rs b/tests/ui/abi/win64-zst.rs
index cae32795e16..a2f7d19eb45 100644
--- a/tests/ui/abi/win64-zst.rs
+++ b/tests/ui/abi/win64-zst.rs
@@ -1,11 +1,24 @@
-//@ only-x86_64
-//@ revisions: other windows-gnu
 //@ normalize-stderr-test: "(abi|pref|unadjusted_abi_align): Align\([1-8] bytes\)" -> "$1: $$SOME_ALIGN"
-//@[other] ignore-windows-gnu
-//@[windows-gnu] only-windows-gnu
+//@ only-x86_64
+
+//@ revisions: x86_64-linux
+//@[x86_64-linux] compile-flags: --target x86_64-unknown-linux-gnu
+//@[x86_64-linux] needs-llvm-components: x86
 
-#![feature(rustc_attrs)]
+//@ revisions: x86_64-windows-gnu
+//@[x86_64-windows-gnu] compile-flags: --target x86_64-pc-windows-gnu
+//@[x86_64-windows-gnu] needs-llvm-components: x86
+
+//@ revisions: x86_64-windows-msvc
+//@[x86_64-windows-msvc] compile-flags: --target x86_64-pc-windows-msvc
+//@[x86_64-windows-msvc] needs-llvm-components: x86
+
+#![feature(no_core, lang_items, rustc_attrs)]
+#![no_core]
 #![crate_type = "lib"]
 
+#[lang = "sized"]
+trait Sized {}
+
 #[rustc_abi(debug)]
 extern "win64" fn pass_zst(_: ()) {} //~ ERROR: fn_abi
diff --git a/tests/ui/abi/win64-zst.other.stderr b/tests/ui/abi/win64-zst.x86_64-linux.stderr
index 15db141cb57..76d90670eb1 100644
--- a/tests/ui/abi/win64-zst.other.stderr
+++ b/tests/ui/abi/win64-zst.x86_64-linux.stderr
@@ -9,7 +9,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                                abi: $SOME_ALIGN,
                                pref: $SOME_ALIGN,
                            },
-                           abi: Aggregate {
+                           abi: Memory {
                                sized: true,
                            },
                            fields: Arbitrary {
@@ -36,7 +36,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            abi: $SOME_ALIGN,
                            pref: $SOME_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -58,7 +58,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
            conv: X86_64Win64,
            can_unwind: false,
        }
-  --> $DIR/win64-zst.rs:11:1
+  --> $DIR/win64-zst.rs:24:1
    |
 LL | extern "win64" fn pass_zst(_: ()) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/abi/win64-zst.windows-gnu.stderr b/tests/ui/abi/win64-zst.x86_64-windows-gnu.stderr
index 7773e0aa2b5..7ee90e24744 100644
--- a/tests/ui/abi/win64-zst.windows-gnu.stderr
+++ b/tests/ui/abi/win64-zst.x86_64-windows-gnu.stderr
@@ -9,7 +9,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                                abi: $SOME_ALIGN,
                                pref: $SOME_ALIGN,
                            },
-                           abi: Aggregate {
+                           abi: Memory {
                                sized: true,
                            },
                            fields: Arbitrary {
@@ -47,7 +47,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            abi: $SOME_ALIGN,
                            pref: $SOME_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -69,7 +69,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
            conv: X86_64Win64,
            can_unwind: false,
        }
-  --> $DIR/win64-zst.rs:11:1
+  --> $DIR/win64-zst.rs:24:1
    |
 LL | extern "win64" fn pass_zst(_: ()) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/abi/win64-zst.x86_64-windows-msvc.stderr b/tests/ui/abi/win64-zst.x86_64-windows-msvc.stderr
new file mode 100644
index 00000000000..76d90670eb1
--- /dev/null
+++ b/tests/ui/abi/win64-zst.x86_64-windows-msvc.stderr
@@ -0,0 +1,67 @@
+error: fn_abi_of(pass_zst) = FnAbi {
+           args: [
+               ArgAbi {
+                   layout: TyAndLayout {
+                       ty: (),
+                       layout: Layout {
+                           size: Size(0 bytes),
+                           align: AbiAndPrefAlign {
+                               abi: $SOME_ALIGN,
+                               pref: $SOME_ALIGN,
+                           },
+                           abi: Memory {
+                               sized: true,
+                           },
+                           fields: Arbitrary {
+                               offsets: [],
+                               memory_index: [],
+                           },
+                           largest_niche: None,
+                           variants: Single {
+                               index: 0,
+                           },
+                           max_repr_align: None,
+                           unadjusted_abi_align: $SOME_ALIGN,
+                       },
+                   },
+                   mode: Ignore,
+               },
+           ],
+           ret: ArgAbi {
+               layout: TyAndLayout {
+                   ty: (),
+                   layout: Layout {
+                       size: Size(0 bytes),
+                       align: AbiAndPrefAlign {
+                           abi: $SOME_ALIGN,
+                           pref: $SOME_ALIGN,
+                       },
+                       abi: Memory {
+                           sized: true,
+                       },
+                       fields: Arbitrary {
+                           offsets: [],
+                           memory_index: [],
+                       },
+                       largest_niche: None,
+                       variants: Single {
+                           index: 0,
+                       },
+                       max_repr_align: None,
+                       unadjusted_abi_align: $SOME_ALIGN,
+                   },
+               },
+               mode: Ignore,
+           },
+           c_variadic: false,
+           fixed_count: 1,
+           conv: X86_64Win64,
+           can_unwind: false,
+       }
+  --> $DIR/win64-zst.rs:24:1
+   |
+LL | extern "win64" fn pass_zst(_: ()) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/array-slice-vec/vec-macro-with-comma-only.rs b/tests/ui/array-slice-vec/vec-macro-with-comma-only.rs
index 574a53c58fe..0f99f6b1b1e 100644
--- a/tests/ui/array-slice-vec/vec-macro-with-comma-only.rs
+++ b/tests/ui/array-slice-vec/vec-macro-with-comma-only.rs
@@ -1,3 +1,3 @@
 pub fn main() {
-    vec![,]; //~ ERROR no rules expected the token `,`
+    vec![,]; //~ ERROR no rules expected `,`
 }
diff --git a/tests/ui/array-slice-vec/vec-macro-with-comma-only.stderr b/tests/ui/array-slice-vec/vec-macro-with-comma-only.stderr
index b3f953af6d2..d76d493eca8 100644
--- a/tests/ui/array-slice-vec/vec-macro-with-comma-only.stderr
+++ b/tests/ui/array-slice-vec/vec-macro-with-comma-only.stderr
@@ -1,4 +1,4 @@
-error: no rules expected the token `,`
+error: no rules expected `,`
   --> $DIR/vec-macro-with-comma-only.rs:2:10
    |
 LL |     vec![,];
diff --git a/tests/ui/associated-consts/issue-58022.stderr b/tests/ui/associated-consts/issue-58022.stderr
index 6ce995eaab7..82cbc9ed3b0 100644
--- a/tests/ui/associated-consts/issue-58022.stderr
+++ b/tests/ui/associated-consts/issue-58022.stderr
@@ -13,7 +13,7 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation
 LL |     fn new(slice: &[u8; Self::SIZE]) -> Self {
    |                                         ^^^^ doesn't have a size known at compile-time
    |
-   = help: within `Bar<[u8]>`, the trait `Sized` is not implemented for `[u8]`, which is required by `Bar<[u8]>: Sized`
+   = help: within `Bar<[u8]>`, the trait `Sized` is not implemented for `[u8]`
 note: required because it appears within the type `Bar<[u8]>`
   --> $DIR/issue-58022.rs:8:12
    |
diff --git a/tests/ui/associated-type-bounds/implied-from-self-where-clause.rs b/tests/ui/associated-type-bounds/implied-from-self-where-clause.rs
new file mode 100644
index 00000000000..38f55696914
--- /dev/null
+++ b/tests/ui/associated-type-bounds/implied-from-self-where-clause.rs
@@ -0,0 +1,21 @@
+// Make sure that, like associated type where clauses on traits, we gather item
+// bounds for RPITITs from RTN where clauses.
+
+//@ check-pass
+
+#![feature(return_type_notation)]
+
+trait Foo
+where
+    Self::method(..): Send,
+{
+    fn method() -> impl Sized;
+}
+
+fn is_send(_: impl Send) {}
+
+fn test<T: Foo>() {
+    is_send(T::method());
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr b/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr
index 110d2a00583..0a31cc67533 100644
--- a/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr
+++ b/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr
@@ -4,7 +4,7 @@ error: future cannot be sent between threads safely
 LL |     is_send(foo::<T>());
    |             ^^^^^^^^^^ future returned by `foo` is not `Send`
    |
-   = help: within `impl Future<Output = Result<(), ()>>`, the trait `Send` is not implemented for `impl Future<Output = Result<(), ()>> { <T as Foo>::method(..) }`, which is required by `impl Future<Output = Result<(), ()>>: Send`
+   = help: within `impl Future<Output = Result<(), ()>>`, the trait `Send` is not implemented for `impl Future<Output = Result<(), ()>> { <T as Foo>::method(..) }`
 note: future is not `Send` as it awaits another future which is not `Send`
   --> $DIR/basic.rs:12:5
    |
diff --git a/tests/crashes/131648.rs b/tests/ui/associated-type-bounds/return-type-notation/impl-trait-in-trait.rs
index 68046ce2a1f..0d3e6f9c8e3 100644
--- a/tests/crashes/131648.rs
+++ b/tests/ui/associated-type-bounds/return-type-notation/impl-trait-in-trait.rs
@@ -1,7 +1,8 @@
-//@ known-bug: #131648
 #![feature(return_type_notation)]
 
 trait IntFactory {
     fn stream(self) -> impl IntFactory<stream(..): Send>;
+    //~^ ERROR cycle detected when resolving lifetimes for `IntFactory::stream`
 }
+
 fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/impl-trait-in-trait.stderr b/tests/ui/associated-type-bounds/return-type-notation/impl-trait-in-trait.stderr
new file mode 100644
index 00000000000..0ed54415b9e
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/impl-trait-in-trait.stderr
@@ -0,0 +1,27 @@
+error[E0391]: cycle detected when resolving lifetimes for `IntFactory::stream`
+  --> $DIR/impl-trait-in-trait.rs:4:5
+   |
+LL |     fn stream(self) -> impl IntFactory<stream(..): Send>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...which requires computing function signature of `IntFactory::stream`...
+  --> $DIR/impl-trait-in-trait.rs:4:5
+   |
+LL |     fn stream(self) -> impl IntFactory<stream(..): Send>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires looking up late bound vars inside `IntFactory::stream`...
+  --> $DIR/impl-trait-in-trait.rs:4:5
+   |
+LL |     fn stream(self) -> impl IntFactory<stream(..): Send>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which again requires resolving lifetimes for `IntFactory::stream`, completing the cycle
+note: cycle used when listing captured lifetimes for opaque `IntFactory::stream::{opaque#0}`
+  --> $DIR/impl-trait-in-trait.rs:4:24
+   |
+LL |     fn stream(self) -> impl IntFactory<stream(..): Send>;
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-unsatisfied.stderr b/tests/ui/associated-type-bounds/return-type-notation/path-unsatisfied.stderr
index 95810342d5a..90d0feb5217 100644
--- a/tests/ui/associated-type-bounds/return-type-notation/path-unsatisfied.stderr
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-unsatisfied.stderr
@@ -7,7 +7,7 @@ LL |     fn method() -> impl Sized {
 LL |     test::<DoesntWork>();
    |            ^^^^^^^^^^ `*mut ()` cannot be sent between threads safely
    |
-   = help: within `impl Sized`, the trait `Send` is not implemented for `*mut ()`, which is required by `impl Sized: Send`
+   = help: within `impl Sized`, the trait `Send` is not implemented for `*mut ()`
 note: required because it appears within the type `impl Sized`
   --> $DIR/path-unsatisfied.rs:9:20
    |
diff --git a/tests/ui/associated-types/defaults-suitability.current.stderr b/tests/ui/associated-types/defaults-suitability.current.stderr
index 3cdeaa93a34..9c0ae59ae43 100644
--- a/tests/ui/associated-types/defaults-suitability.current.stderr
+++ b/tests/ui/associated-types/defaults-suitability.current.stderr
@@ -39,7 +39,7 @@ error[E0277]: the trait bound `T: Clone` is not satisfied
   --> $DIR/defaults-suitability.rs:31:23
    |
 LL |     type Bar: Clone = Vec<T>;
-   |                       ^^^^^^ the trait `Clone` is not implemented for `T`, which is required by `Vec<T>: Clone`
+   |                       ^^^^^^ the trait `Clone` is not implemented for `T`
    |
    = note: required for `Vec<T>` to implement `Clone`
 note: required by a bound in `Foo::Bar`
@@ -88,7 +88,7 @@ error[E0277]: the trait bound `<Self as Foo2<T>>::Baz: Clone` is not satisfied
   --> $DIR/defaults-suitability.rs:68:23
    |
 LL |     type Bar: Clone = Vec<Self::Baz>;
-   |                       ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `<Self as Foo2<T>>::Baz`, which is required by `Vec<<Self as Foo2<T>>::Baz>: Clone`
+   |                       ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `<Self as Foo2<T>>::Baz`
    |
    = note: required for `Vec<<Self as Foo2<T>>::Baz>` to implement `Clone`
 note: required by a bound in `Foo2::Bar`
@@ -105,7 +105,7 @@ error[E0277]: the trait bound `<Self as Foo25<T>>::Baz: Clone` is not satisfied
   --> $DIR/defaults-suitability.rs:77:23
    |
 LL |     type Bar: Clone = Vec<Self::Baz>;
-   |                       ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `<Self as Foo25<T>>::Baz`, which is required by `Vec<<Self as Foo25<T>>::Baz>: Clone`
+   |                       ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `<Self as Foo25<T>>::Baz`
    |
    = note: required for `Vec<<Self as Foo25<T>>::Baz>` to implement `Clone`
 note: required by a bound in `Foo25::Bar`
diff --git a/tests/ui/associated-types/defaults-suitability.next.stderr b/tests/ui/associated-types/defaults-suitability.next.stderr
index 3cdeaa93a34..9c0ae59ae43 100644
--- a/tests/ui/associated-types/defaults-suitability.next.stderr
+++ b/tests/ui/associated-types/defaults-suitability.next.stderr
@@ -39,7 +39,7 @@ error[E0277]: the trait bound `T: Clone` is not satisfied
   --> $DIR/defaults-suitability.rs:31:23
    |
 LL |     type Bar: Clone = Vec<T>;
-   |                       ^^^^^^ the trait `Clone` is not implemented for `T`, which is required by `Vec<T>: Clone`
+   |                       ^^^^^^ the trait `Clone` is not implemented for `T`
    |
    = note: required for `Vec<T>` to implement `Clone`
 note: required by a bound in `Foo::Bar`
@@ -88,7 +88,7 @@ error[E0277]: the trait bound `<Self as Foo2<T>>::Baz: Clone` is not satisfied
   --> $DIR/defaults-suitability.rs:68:23
    |
 LL |     type Bar: Clone = Vec<Self::Baz>;
-   |                       ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `<Self as Foo2<T>>::Baz`, which is required by `Vec<<Self as Foo2<T>>::Baz>: Clone`
+   |                       ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `<Self as Foo2<T>>::Baz`
    |
    = note: required for `Vec<<Self as Foo2<T>>::Baz>` to implement `Clone`
 note: required by a bound in `Foo2::Bar`
@@ -105,7 +105,7 @@ error[E0277]: the trait bound `<Self as Foo25<T>>::Baz: Clone` is not satisfied
   --> $DIR/defaults-suitability.rs:77:23
    |
 LL |     type Bar: Clone = Vec<Self::Baz>;
-   |                       ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `<Self as Foo25<T>>::Baz`, which is required by `Vec<<Self as Foo25<T>>::Baz>: Clone`
+   |                       ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `<Self as Foo25<T>>::Baz`
    |
    = note: required for `Vec<<Self as Foo25<T>>::Baz>` to implement `Clone`
 note: required by a bound in `Foo25::Bar`
diff --git a/tests/ui/associated-types/hr-associated-type-bound-1.stderr b/tests/ui/associated-types/hr-associated-type-bound-1.stderr
index 8830048ed4e..5b00e714194 100644
--- a/tests/ui/associated-types/hr-associated-type-bound-1.stderr
+++ b/tests/ui/associated-types/hr-associated-type-bound-1.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
   --> $DIR/hr-associated-type-bound-1.rs:12:14
    |
 LL |     type U = str;
-   |              ^^^ the trait `Clone` is not implemented for `str`, which is required by `for<'b> <i32 as X<'b>>::U: Clone`
+   |              ^^^ the trait `Clone` is not implemented for `str`
    |
    = help: the trait `Clone` is implemented for `String`
 note: required by a bound in `X`
diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-1.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-1.stderr
index ad6d3e17684..07d3afb74e4 100644
--- a/tests/ui/associated-types/hr-associated-type-bound-param-1.stderr
+++ b/tests/ui/associated-types/hr-associated-type-bound-param-1.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
   --> $DIR/hr-associated-type-bound-param-1.rs:14:14
    |
 LL |     type V = str;
-   |              ^^^ the trait `Clone` is not implemented for `str`, which is required by `for<'b> <u8 as Y<'b, u8>>::V: Clone`
+   |              ^^^ the trait `Clone` is not implemented for `str`
    |
    = help: the trait `Clone` is implemented for `String`
 note: required by a bound in `Y`
diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-2.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-2.stderr
index 6a5729e7784..74cc2083d26 100644
--- a/tests/ui/associated-types/hr-associated-type-bound-param-2.stderr
+++ b/tests/ui/associated-types/hr-associated-type-bound-param-2.stderr
@@ -18,7 +18,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
   --> $DIR/hr-associated-type-bound-param-2.rs:17:14
    |
 LL |     type W = str;
-   |              ^^^ the trait `Clone` is not implemented for `str`, which is required by `for<'b> <u16 as Z<'b, u16>>::W: Clone`
+   |              ^^^ the trait `Clone` is not implemented for `str`
    |
    = help: the trait `Clone` is implemented for `String`
 note: required by a bound in `Z`
diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-3.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-3.stderr
index 70e030f2d1c..58b82fc9306 100644
--- a/tests/ui/associated-types/hr-associated-type-bound-param-3.stderr
+++ b/tests/ui/associated-types/hr-associated-type-bound-param-3.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
   --> $DIR/hr-associated-type-bound-param-3.rs:13:14
    |
 LL |     type U = str;
-   |              ^^^ the trait `Clone` is not implemented for `str`, which is required by `for<'b> <(T,) as X<'b, (T,)>>::U: Clone`
+   |              ^^^ the trait `Clone` is not implemented for `str`
    |
    = help: the trait `Clone` is implemented for `String`
 note: required by a bound in `X`
diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-4.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-4.stderr
index cba12afd674..6d6373a1918 100644
--- a/tests/ui/associated-types/hr-associated-type-bound-param-4.stderr
+++ b/tests/ui/associated-types/hr-associated-type-bound-param-4.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
   --> $DIR/hr-associated-type-bound-param-4.rs:13:14
    |
 LL |     type U = str;
-   |              ^^^ the trait `Clone` is not implemented for `str`, which is required by `for<'b> <(T,) as X<'b, T>>::U: Clone`
+   |              ^^^ the trait `Clone` is not implemented for `str`
    |
    = help: the trait `Clone` is implemented for `String`
 note: required by a bound in `X`
diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-5.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-5.stderr
index ac96187749a..44c446c599f 100644
--- a/tests/ui/associated-types/hr-associated-type-bound-param-5.stderr
+++ b/tests/ui/associated-types/hr-associated-type-bound-param-5.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
   --> $DIR/hr-associated-type-bound-param-5.rs:26:14
    |
 LL |     type U = str;
-   |              ^^^ the trait `Clone` is not implemented for `str`, which is required by `for<'b> <<Vec<T> as Cycle>::Next as X<'b, <Vec<T> as Cycle>::Next>>::U: Clone`
+   |              ^^^ the trait `Clone` is not implemented for `str`
    |
    = help: the trait `Clone` is implemented for `String`
 note: required by a bound in `X`
@@ -18,7 +18,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
   --> $DIR/hr-associated-type-bound-param-5.rs:31:14
    |
 LL |     type U = str;
-   |              ^^^ the trait `Clone` is not implemented for `str`, which is required by `for<'b> <<Box<T> as Cycle>::Next as X<'b, <Box<T> as Cycle>::Next>>::U: Clone`
+   |              ^^^ the trait `Clone` is not implemented for `str`
    |
    = help: the trait `Clone` is implemented for `String`
 note: required by a bound in `X`
diff --git a/tests/ui/associated-types/issue-38821.stderr b/tests/ui/associated-types/issue-38821.stderr
index f1c8f83e30c..58f019704e7 100644
--- a/tests/ui/associated-types/issue-38821.stderr
+++ b/tests/ui/associated-types/issue-38821.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not sat
   --> $DIR/issue-38821.rs:40:1
    |
 LL | pub enum ColumnInsertValue<Col, Expr> where
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`, which is required by `<Col as Expression>::SqlType: IntoNullable`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`
    |
 note: required for `<Col as Expression>::SqlType` to implement `IntoNullable`
   --> $DIR/issue-38821.rs:9:18
@@ -26,7 +26,7 @@ LL | |     Col: Column,
 ...  |
 LL | |     Default(Col),
 LL | | }
-   | |_^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`, which is required by `<Col as Expression>::SqlType: IntoNullable`
+   | |_^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`
    |
 note: required for `<Col as Expression>::SqlType` to implement `IntoNullable`
   --> $DIR/issue-38821.rs:9:18
@@ -44,7 +44,7 @@ error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not sat
   --> $DIR/issue-38821.rs:23:10
    |
 LL | #[derive(Debug, Copy, Clone)]
-   |          ^^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`, which is required by `<Col as Expression>::SqlType: IntoNullable`
+   |          ^^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`
    |
 note: required for `<Col as Expression>::SqlType` to implement `IntoNullable`
   --> $DIR/issue-38821.rs:9:18
@@ -63,7 +63,7 @@ error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not sat
   --> $DIR/issue-38821.rs:23:10
    |
 LL | #[derive(Debug, Copy, Clone)]
-   |          ^^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`, which is required by `<Col as Expression>::SqlType: IntoNullable`
+   |          ^^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`
    |
 note: required for `<Col as Expression>::SqlType` to implement `IntoNullable`
   --> $DIR/issue-38821.rs:9:18
@@ -83,7 +83,7 @@ error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not sat
   --> $DIR/issue-38821.rs:23:10
    |
 LL | #[derive(Debug, Copy, Clone)]
-   |          ^^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`, which is required by `<Col as Expression>::SqlType: IntoNullable`
+   |          ^^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`
    |
 note: required for `<Col as Expression>::SqlType` to implement `IntoNullable`
   --> $DIR/issue-38821.rs:9:18
@@ -98,7 +98,7 @@ error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not sat
   --> $DIR/issue-38821.rs:23:10
    |
 LL | #[derive(Debug, Copy, Clone)]
-   |          ^^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`, which is required by `<Col as Expression>::SqlType: IntoNullable`
+   |          ^^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`
    |
 note: required for `<Col as Expression>::SqlType` to implement `IntoNullable`
   --> $DIR/issue-38821.rs:9:18
@@ -114,7 +114,7 @@ error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not sat
   --> $DIR/issue-38821.rs:23:17
    |
 LL | #[derive(Debug, Copy, Clone)]
-   |                 ^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`, which is required by `<Col as Expression>::SqlType: IntoNullable`
+   |                 ^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`
    |
 note: required for `<Col as Expression>::SqlType` to implement `IntoNullable`
   --> $DIR/issue-38821.rs:9:18
@@ -133,7 +133,7 @@ error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not sat
   --> $DIR/issue-38821.rs:23:17
    |
 LL | #[derive(Debug, Copy, Clone)]
-   |                 ^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`, which is required by `<Col as Expression>::SqlType: IntoNullable`
+   |                 ^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`
    |
 note: required for `<Col as Expression>::SqlType` to implement `IntoNullable`
   --> $DIR/issue-38821.rs:9:18
@@ -153,7 +153,7 @@ error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not sat
   --> $DIR/issue-38821.rs:23:23
    |
 LL | #[derive(Debug, Copy, Clone)]
-   |                       ^^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`, which is required by `<Col as Expression>::SqlType: IntoNullable`
+   |                       ^^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`
    |
 note: required for `<Col as Expression>::SqlType` to implement `IntoNullable`
   --> $DIR/issue-38821.rs:9:18
@@ -172,7 +172,7 @@ error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not sat
   --> $DIR/issue-38821.rs:23:23
    |
 LL | #[derive(Debug, Copy, Clone)]
-   |                       ^^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`, which is required by `<Col as Expression>::SqlType: IntoNullable`
+   |                       ^^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`
    |
 note: required for `<Col as Expression>::SqlType` to implement `IntoNullable`
   --> $DIR/issue-38821.rs:9:18
@@ -192,7 +192,7 @@ error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not sat
   --> $DIR/issue-38821.rs:23:23
    |
 LL | #[derive(Debug, Copy, Clone)]
-   |                       ^^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`, which is required by `<Col as Expression>::SqlType: IntoNullable`
+   |                       ^^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`
    |
 note: required for `<Col as Expression>::SqlType` to implement `IntoNullable`
   --> $DIR/issue-38821.rs:9:18
@@ -207,7 +207,7 @@ error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not sat
   --> $DIR/issue-38821.rs:23:23
    |
 LL | #[derive(Debug, Copy, Clone)]
-   |                       ^^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`, which is required by `<Col as Expression>::SqlType: IntoNullable`
+   |                       ^^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`
    |
 note: required for `<Col as Expression>::SqlType` to implement `IntoNullable`
   --> $DIR/issue-38821.rs:9:18
@@ -223,7 +223,7 @@ error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not sat
   --> $DIR/issue-38821.rs:23:10
    |
 LL | #[derive(Debug, Copy, Clone)]
-   |          ^^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`, which is required by `<Col as Expression>::SqlType: IntoNullable`
+   |          ^^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`
    |
 note: required for `<Col as Expression>::SqlType` to implement `IntoNullable`
   --> $DIR/issue-38821.rs:9:18
@@ -239,7 +239,7 @@ error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not sat
   --> $DIR/issue-38821.rs:23:10
    |
 LL | #[derive(Debug, Copy, Clone)]
-   |          ^^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`, which is required by `<Col as Expression>::SqlType: IntoNullable`
+   |          ^^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`
    |
 note: required for `<Col as Expression>::SqlType` to implement `IntoNullable`
   --> $DIR/issue-38821.rs:9:18
@@ -255,7 +255,7 @@ error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not sat
   --> $DIR/issue-38821.rs:23:23
    |
 LL | #[derive(Debug, Copy, Clone)]
-   |                       ^^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`, which is required by `<Col as Expression>::SqlType: IntoNullable`
+   |                       ^^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`
    |
 note: required for `<Col as Expression>::SqlType` to implement `IntoNullable`
   --> $DIR/issue-38821.rs:9:18
@@ -271,7 +271,7 @@ error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not sat
   --> $DIR/issue-38821.rs:23:23
    |
 LL | #[derive(Debug, Copy, Clone)]
-   |                       ^^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`, which is required by `<Col as Expression>::SqlType: IntoNullable`
+   |                       ^^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`
    |
 note: required for `<Col as Expression>::SqlType` to implement `IntoNullable`
   --> $DIR/issue-38821.rs:9:18
@@ -287,7 +287,7 @@ error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not sat
   --> $DIR/issue-38821.rs:23:10
    |
 LL | #[derive(Debug, Copy, Clone)]
-   |          ^^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`, which is required by `<Col as Expression>::SqlType: IntoNullable`
+   |          ^^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`
    |
 note: required for `<Col as Expression>::SqlType` to implement `IntoNullable`
   --> $DIR/issue-38821.rs:9:18
@@ -303,7 +303,7 @@ error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not sat
   --> $DIR/issue-38821.rs:23:23
    |
 LL | #[derive(Debug, Copy, Clone)]
-   |                       ^^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`, which is required by `<Col as Expression>::SqlType: IntoNullable`
+   |                       ^^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`
    |
 note: required for `<Col as Expression>::SqlType` to implement `IntoNullable`
   --> $DIR/issue-38821.rs:9:18
diff --git a/tests/ui/associated-types/issue-43784-associated-type.stderr b/tests/ui/associated-types/issue-43784-associated-type.stderr
index b2cbe8ee86e..529fc1f119a 100644
--- a/tests/ui/associated-types/issue-43784-associated-type.stderr
+++ b/tests/ui/associated-types/issue-43784-associated-type.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `T: Copy` is not satisfied
   --> $DIR/issue-43784-associated-type.rs:14:18
    |
 LL |     type Assoc = T;
-   |                  ^ the trait `Copy` is not implemented for `T`, which is required by `<T as Complete>::Assoc: Partial<T>`
+   |                  ^ the trait `Copy` is not implemented for `T`
    |
 note: required for `<T as Complete>::Assoc` to implement `Partial<T>`
   --> $DIR/issue-43784-associated-type.rs:1:11
diff --git a/tests/ui/associated-types/issue-65774-1.stderr b/tests/ui/associated-types/issue-65774-1.stderr
index 9748a8fbbf4..9c77a25c432 100644
--- a/tests/ui/associated-types/issue-65774-1.stderr
+++ b/tests/ui/associated-types/issue-65774-1.stderr
@@ -15,7 +15,7 @@ error[E0277]: the trait bound `T: MyDisplay` is not satisfied
   --> $DIR/issue-65774-1.rs:44:76
    |
 LL |         let closure = |config: &mut <S as MPU>::MpuConfig| writer.my_write(&config);
-   |                                                                            ^^^^^^^ the trait `MyDisplay` is not implemented for `T`, which is required by `&mut T: MyDisplay`
+   |                                                                            ^^^^^^^ the trait `MyDisplay` is not implemented for `T`
    |
    = help: the trait `MyDisplay` is implemented for `&'a mut T`
 note: required for `&mut T` to implement `MyDisplay`
diff --git a/tests/ui/associated-types/substs-ppaux.normal.stderr b/tests/ui/associated-types/substs-ppaux.normal.stderr
index 8d3146be560..1ea8ab23556 100644
--- a/tests/ui/associated-types/substs-ppaux.normal.stderr
+++ b/tests/ui/associated-types/substs-ppaux.normal.stderr
@@ -80,7 +80,7 @@ error[E0277]: the trait bound `str: Foo<'_, '_, u8>` is not satisfied
   --> $DIR/substs-ppaux.rs:55:6
    |
 LL |     <str as Foo<u8>>::bar;
-   |      ^^^ the trait `Sized` is not implemented for `str`, which is required by `str: Foo<'_, '_, u8>`
+   |      ^^^ the trait `Sized` is not implemented for `str`
    |
 note: required for `str` to implement `Foo<'_, '_, u8>`
   --> $DIR/substs-ppaux.rs:15:20
diff --git a/tests/ui/associated-types/substs-ppaux.verbose.stderr b/tests/ui/associated-types/substs-ppaux.verbose.stderr
index 0b5f449e576..05cd971c882 100644
--- a/tests/ui/associated-types/substs-ppaux.verbose.stderr
+++ b/tests/ui/associated-types/substs-ppaux.verbose.stderr
@@ -80,7 +80,7 @@ error[E0277]: the trait bound `str: Foo<'?0, '?1, u8>` is not satisfied
   --> $DIR/substs-ppaux.rs:55:6
    |
 LL |     <str as Foo<u8>>::bar;
-   |      ^^^ the trait `Sized` is not implemented for `str`, which is required by `str: Foo<'?0, '?1, u8>`
+   |      ^^^ the trait `Sized` is not implemented for `str`
    |
 note: required for `str` to implement `Foo<'?0, '?1, u8>`
   --> $DIR/substs-ppaux.rs:15:20
diff --git a/tests/ui/async-await/async-await-let-else.stderr b/tests/ui/async-await/async-await-let-else.stderr
index 0952be2abe5..5883f34f87d 100644
--- a/tests/ui/async-await/async-await-let-else.stderr
+++ b/tests/ui/async-await/async-await-let-else.stderr
@@ -4,7 +4,7 @@ error: future cannot be sent between threads safely
 LL |     is_send(foo(Some(true)));
    |             ^^^^^^^^^^^^^^^ future returned by `foo` is not `Send`
    |
-   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`, which is required by `impl Future<Output = ()>: Send`
+   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
 note: future is not `Send` as this value is used across an await
   --> $DIR/async-await-let-else.rs:8:15
    |
@@ -29,7 +29,7 @@ LL |     is_send(foo2(Some(true)));
    |     |
    |     required by a bound introduced by this call
    |
-   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`, which is required by `impl Future<Output = ()>: Send`
+   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
 note: required because it's used within this `async` fn body
   --> $DIR/async-await-let-else.rs:24:29
    |
@@ -60,7 +60,7 @@ error: future cannot be sent between threads safely
 LL |     is_send(foo3(Some(true)));
    |             ^^^^^^^^^^^^^^^^ future returned by `foo3` is not `Send`
    |
-   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`, which is required by `impl Future<Output = ()>: Send`
+   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
 note: future is not `Send` as this value is used across an await
   --> $DIR/async-await-let-else.rs:30:29
    |
@@ -80,7 +80,7 @@ error: future cannot be sent between threads safely
 LL |     is_send(foo4(Some(true)));
    |             ^^^^^^^^^^^^^^^^ future returned by `foo4` is not `Send`
    |
-   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`, which is required by `impl Future<Output = ()>: Send`
+   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
 note: future is not `Send` as this value is used across an await
   --> $DIR/async-await-let-else.rs:38:15
    |
diff --git a/tests/ui/async-await/async-closures/not-clone-closure.stderr b/tests/ui/async-await/async-closures/not-clone-closure.stderr
index aea48a455c2..8d5612687db 100644
--- a/tests/ui/async-await/async-closures/not-clone-closure.stderr
+++ b/tests/ui/async-await/async-closures/not-clone-closure.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `NotClonableUpvar: Clone` is not satisfied in `{as
   --> $DIR/not-clone-closure.rs:32:15
    |
 LL |     not_clone.clone();
-   |               ^^^^^ within `{async closure@$DIR/not-clone-closure.rs:29:21: 29:34}`, the trait `Clone` is not implemented for `NotClonableUpvar`, which is required by `{async closure@$DIR/not-clone-closure.rs:29:21: 29:34}: Clone`
+   |               ^^^^^ within `{async closure@$DIR/not-clone-closure.rs:29:21: 29:34}`, the trait `Clone` is not implemented for `NotClonableUpvar`
    |
 note: required because it's used within this closure
   --> $DIR/not-clone-closure.rs:29:21
diff --git a/tests/ui/async-await/async-fn-nonsend.stderr b/tests/ui/async-await/async-fn-nonsend.stderr
index 8b245281da9..0ced6c36f47 100644
--- a/tests/ui/async-await/async-fn-nonsend.stderr
+++ b/tests/ui/async-await/async-fn-nonsend.stderr
@@ -4,7 +4,7 @@ error: future cannot be sent between threads safely
 LL |     assert_send(non_send_temporary_in_match());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_send_temporary_in_match` is not `Send`
    |
-   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`, which is required by `impl Future<Output = ()>: Send`
+   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
 note: future is not `Send` as this value is used across an await
   --> $DIR/async-fn-nonsend.rs:33:26
    |
@@ -24,7 +24,7 @@ error: future cannot be sent between threads safely
 LL |     assert_send(non_sync_with_method_call());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send`
    |
-   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `dyn std::fmt::Write`, which is required by `impl Future<Output = ()>: Send`
+   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `dyn std::fmt::Write`
 note: future is not `Send` as this value is used across an await
   --> $DIR/async-fn-nonsend.rs:46:15
    |
diff --git a/tests/ui/async-await/async-is-unwindsafe.stderr b/tests/ui/async-await/async-is-unwindsafe.stderr
index 9c5e8f0252c..9323ce25b77 100644
--- a/tests/ui/async-await/async-is-unwindsafe.stderr
+++ b/tests/ui/async-await/async-is-unwindsafe.stderr
@@ -13,7 +13,7 @@ LL | |         drop(cx_ref);
 LL | |     });
    | |______^ `&mut Context<'_>` may not be safely transferred across an unwind boundary
    |
-   = help: within `{async block@$DIR/async-is-unwindsafe.rs:12:19: 12:24}`, the trait `UnwindSafe` is not implemented for `&mut Context<'_>`, which is required by `{async block@$DIR/async-is-unwindsafe.rs:12:19: 12:24}: UnwindSafe`
+   = help: within `{async block@$DIR/async-is-unwindsafe.rs:12:19: 12:24}`, the trait `UnwindSafe` is not implemented for `&mut Context<'_>`
    = note: `UnwindSafe` is implemented for `&Context<'_>`, but not for `&mut Context<'_>`
 note: future does not implement `UnwindSafe` as this value is used across an await
   --> $DIR/async-is-unwindsafe.rs:25:18
diff --git a/tests/ui/async-await/debug-ice-attempted-to-add-with-overflow.stderr b/tests/ui/async-await/debug-ice-attempted-to-add-with-overflow.stderr
index eab5bea681c..8c9d06c79ca 100644
--- a/tests/ui/async-await/debug-ice-attempted-to-add-with-overflow.stderr
+++ b/tests/ui/async-await/debug-ice-attempted-to-add-with-overflow.stderr
@@ -7,7 +7,7 @@ LL |     [0usize; 0xffff_ffff_ffff_ffff].await;
    |                                    |`[usize; usize::MAX]` is not a future
    |                                    help: remove the `.await`
    |
-   = help: the trait `Future` is not implemented for `[usize; usize::MAX]`, which is required by `[usize; usize::MAX]: IntoFuture`
+   = help: the trait `Future` is not implemented for `[usize; usize::MAX]`
    = note: [usize; usize::MAX] must be a future or must implement `IntoFuture` to be awaited
    = note: required for `[usize; usize::MAX]` to implement `IntoFuture`
 
diff --git a/tests/ui/async-await/drop-track-bad-field-in-fru.stderr b/tests/ui/async-await/drop-track-bad-field-in-fru.stderr
index 53cdc9b61d3..721e0106293 100644
--- a/tests/ui/async-await/drop-track-bad-field-in-fru.stderr
+++ b/tests/ui/async-await/drop-track-bad-field-in-fru.stderr
@@ -15,7 +15,7 @@ LL |     None { value: (), ..Default::default() }.await;
    |                                             |`Option<_>` is not a future
    |                                             help: remove the `.await`
    |
-   = help: the trait `Future` is not implemented for `Option<_>`, which is required by `Option<_>: IntoFuture`
+   = help: the trait `Future` is not implemented for `Option<_>`
    = note: Option<_> must be a future or must implement `IntoFuture` to be awaited
    = note: required for `Option<_>` to implement `IntoFuture`
 
diff --git a/tests/ui/async-await/drop-track-field-assign-nonsend.stderr b/tests/ui/async-await/drop-track-field-assign-nonsend.stderr
index ce2cee6ed47..9fce4d61b3b 100644
--- a/tests/ui/async-await/drop-track-field-assign-nonsend.stderr
+++ b/tests/ui/async-await/drop-track-field-assign-nonsend.stderr
@@ -4,7 +4,7 @@ error: future cannot be sent between threads safely
 LL |     assert_send(agent.handle());
    |                 ^^^^^^^^^^^^^^ future returned by `handle` is not `Send`
    |
-   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<String>`, which is required by `impl Future<Output = ()>: Send`
+   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<String>`
 note: future is not `Send` as this value is used across an await
   --> $DIR/drop-track-field-assign-nonsend.rs:20:39
    |
diff --git a/tests/ui/async-await/field-assign-nonsend.stderr b/tests/ui/async-await/field-assign-nonsend.stderr
index 525a2cc78b4..418a0829c65 100644
--- a/tests/ui/async-await/field-assign-nonsend.stderr
+++ b/tests/ui/async-await/field-assign-nonsend.stderr
@@ -4,7 +4,7 @@ error: future cannot be sent between threads safely
 LL |     assert_send(agent.handle());
    |                 ^^^^^^^^^^^^^^ future returned by `handle` is not `Send`
    |
-   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<String>`, which is required by `impl Future<Output = ()>: Send`
+   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<String>`
 note: future is not `Send` as this value is used across an await
   --> $DIR/field-assign-nonsend.rs:20:39
    |
diff --git a/tests/ui/async-await/in-trait/missing-send-bound.stderr b/tests/ui/async-await/in-trait/missing-send-bound.stderr
index 93f37a9a8e9..aeabb5931df 100644
--- a/tests/ui/async-await/in-trait/missing-send-bound.stderr
+++ b/tests/ui/async-await/in-trait/missing-send-bound.stderr
@@ -4,7 +4,7 @@ error: future cannot be sent between threads safely
 LL |     assert_is_send(test::<T>());
    |                    ^^^^^^^^^^^ future returned by `test` is not `Send`
    |
-   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `impl Future<Output = ()>`, which is required by `impl Future<Output = ()>: Send`
+   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `impl Future<Output = ()>`
 note: future is not `Send` as it awaits another future which is not `Send`
   --> $DIR/missing-send-bound.rs:9:5
    |
diff --git a/tests/ui/async-await/issue-101715.stderr b/tests/ui/async-await/issue-101715.stderr
index 3b429793b78..f6af15c00d6 100644
--- a/tests/ui/async-await/issue-101715.stderr
+++ b/tests/ui/async-await/issue-101715.stderr
@@ -7,7 +7,7 @@ LL |         .await
    |         |`()` is not a future
    |         help: remove the `.await`
    |
-   = help: the trait `Future` is not implemented for `()`, which is required by `(): IntoFuture`
+   = help: the trait `Future` is not implemented for `()`
    = note: () must be a future or must implement `IntoFuture` to be awaited
    = note: required for `()` to implement `IntoFuture`
 
diff --git a/tests/ui/async-await/issue-64130-1-sync.stderr b/tests/ui/async-await/issue-64130-1-sync.stderr
index 15f49124f6f..5428d7ef71b 100644
--- a/tests/ui/async-await/issue-64130-1-sync.stderr
+++ b/tests/ui/async-await/issue-64130-1-sync.stderr
@@ -4,7 +4,7 @@ error: future cannot be shared between threads safely
 LL |     is_sync(bar());
    |             ^^^^^ future returned by `bar` is not `Sync`
    |
-   = help: within `impl Future<Output = ()>`, the trait `Sync` is not implemented for `Foo`, which is required by `impl Future<Output = ()>: Sync`
+   = help: within `impl Future<Output = ()>`, the trait `Sync` is not implemented for `Foo`
 note: future is not `Sync` as this value is used across an await
   --> $DIR/issue-64130-1-sync.rs:15:11
    |
diff --git a/tests/ui/async-await/issue-64130-2-send.stderr b/tests/ui/async-await/issue-64130-2-send.stderr
index 67368314b1b..f05e954d2d7 100644
--- a/tests/ui/async-await/issue-64130-2-send.stderr
+++ b/tests/ui/async-await/issue-64130-2-send.stderr
@@ -4,7 +4,7 @@ error: future cannot be sent between threads safely
 LL |     is_send(bar());
    |             ^^^^^ future returned by `bar` is not `Send`
    |
-   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Foo`, which is required by `impl Future<Output = ()>: Send`
+   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Foo`
 note: future is not `Send` as this value is used across an await
   --> $DIR/issue-64130-2-send.rs:15:11
    |
diff --git a/tests/ui/async-await/issue-64130-3-other.stderr b/tests/ui/async-await/issue-64130-3-other.stderr
index e3a73920c92..3ac30bdc23e 100644
--- a/tests/ui/async-await/issue-64130-3-other.stderr
+++ b/tests/ui/async-await/issue-64130-3-other.stderr
@@ -5,7 +5,7 @@ LL | async fn bar() {
    | -------------- within this `impl Future<Output = ()>`
 ...
 LL |     is_qux(bar());
-   |            ^^^^^ within `impl Future<Output = ()>`, the trait `Qux` is not implemented for `Foo`, which is required by `impl Future<Output = ()>: Qux`
+   |            ^^^^^ within `impl Future<Output = ()>`, the trait `Qux` is not implemented for `Foo`
    |
 note: future does not implement `Qux` as this value is used across an await
   --> $DIR/issue-64130-3-other.rs:18:11
diff --git a/tests/ui/async-await/issue-64130-non-send-future-diags.stderr b/tests/ui/async-await/issue-64130-non-send-future-diags.stderr
index bd890c83817..d28807e223b 100644
--- a/tests/ui/async-await/issue-64130-non-send-future-diags.stderr
+++ b/tests/ui/async-await/issue-64130-non-send-future-diags.stderr
@@ -4,7 +4,7 @@ error: future cannot be sent between threads safely
 LL |     is_send(foo());
    |             ^^^^^ future returned by `foo` is not `Send`
    |
-   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `MutexGuard<'_, u32>`, which is required by `impl Future<Output = ()>: Send`
+   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `MutexGuard<'_, u32>`
 note: future is not `Send` as this value is used across an await
   --> $DIR/issue-64130-non-send-future-diags.rs:17:11
    |
diff --git a/tests/ui/async-await/issue-67252-unnamed-future.stderr b/tests/ui/async-await/issue-67252-unnamed-future.stderr
index 2ed40284702..4ec6779dda8 100644
--- a/tests/ui/async-await/issue-67252-unnamed-future.stderr
+++ b/tests/ui/async-await/issue-67252-unnamed-future.stderr
@@ -8,7 +8,7 @@ LL | |         let _a = a;
 LL | |     });
    | |______^ future created by async block is not `Send`
    |
-   = help: within `{async block@$DIR/issue-67252-unnamed-future.rs:18:11: 18:16}`, the trait `Send` is not implemented for `*mut ()`, which is required by `{async block@$DIR/issue-67252-unnamed-future.rs:18:11: 18:16}: Send`
+   = help: within `{async block@$DIR/issue-67252-unnamed-future.rs:18:11: 18:16}`, the trait `Send` is not implemented for `*mut ()`
 note: future is not `Send` as this value is used across an await
   --> $DIR/issue-67252-unnamed-future.rs:20:17
    |
diff --git a/tests/ui/async-await/issue-68112.stderr b/tests/ui/async-await/issue-68112.stderr
index ca60079f3ef..f8889ebcca1 100644
--- a/tests/ui/async-await/issue-68112.stderr
+++ b/tests/ui/async-await/issue-68112.stderr
@@ -4,7 +4,7 @@ error: future cannot be sent between threads safely
 LL |     require_send(send_fut);
    |     ^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
    |
-   = help: the trait `Sync` is not implemented for `RefCell<i32>`, which is required by `{async block@$DIR/issue-68112.rs:29:20: 29:25}: Send`
+   = help: the trait `Sync` is not implemented for `RefCell<i32>`
    = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
 note: future is not `Send` as it awaits another future which is not `Send`
   --> $DIR/issue-68112.rs:31:17
@@ -23,7 +23,7 @@ error: future cannot be sent between threads safely
 LL |     require_send(send_fut);
    |     ^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
    |
-   = help: the trait `Sync` is not implemented for `RefCell<i32>`, which is required by `{async block@$DIR/issue-68112.rs:39:20: 39:25}: Send`
+   = help: the trait `Sync` is not implemented for `RefCell<i32>`
    = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
 note: future is not `Send` as it awaits another future which is not `Send`
   --> $DIR/issue-68112.rs:40:17
@@ -42,7 +42,7 @@ error[E0277]: `RefCell<i32>` cannot be shared between threads safely
 LL |     require_send(send_fut);
    |     ^^^^^^^^^^^^^^^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely
    |
-   = help: the trait `Sync` is not implemented for `RefCell<i32>`, which is required by `{async block@$DIR/issue-68112.rs:57:20: 57:25}: Send`
+   = help: the trait `Sync` is not implemented for `RefCell<i32>`
    = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
    = note: required for `Arc<RefCell<i32>>` to implement `Send`
 note: required because it's used within this `async` fn body
diff --git a/tests/ui/async-await/issue-70935-complex-spans.stderr b/tests/ui/async-await/issue-70935-complex-spans.stderr
index 1ca0b339c16..c6b7e21b9dd 100644
--- a/tests/ui/async-await/issue-70935-complex-spans.stderr
+++ b/tests/ui/async-await/issue-70935-complex-spans.stderr
@@ -4,7 +4,7 @@ error[E0277]: `*mut ()` cannot be shared between threads safely
 LL | fn foo(x: NotSync) -> impl Future + Send {
    |                       ^^^^^^^^^^^^^^^^^^ `*mut ()` cannot be shared between threads safely
    |
-   = help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()`, which is required by `{async block@$DIR/issue-70935-complex-spans.rs:18:5: 18:15}: Send`
+   = help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()`
 note: required because it appears within the type `PhantomData<*mut ()>`
   --> $SRC_DIR/core/src/marker.rs:LL:COL
 note: required because it appears within the type `NotSync`
@@ -37,7 +37,7 @@ error[E0277]: `*mut ()` cannot be shared between threads safely
 LL | fn foo(x: NotSync) -> impl Future + Send {
    |                       ^^^^^^^^^^^^^^^^^^ `*mut ()` cannot be shared between threads safely
    |
-   = help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()`, which is required by `{async block@$DIR/issue-70935-complex-spans.rs:18:5: 18:15}: Send`
+   = help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()`
 note: required because it appears within the type `PhantomData<*mut ()>`
   --> $SRC_DIR/core/src/marker.rs:LL:COL
 note: required because it appears within the type `NotSync`
diff --git a/tests/ui/async-await/issue-71137.stderr b/tests/ui/async-await/issue-71137.stderr
index 75d72e425f5..8739c22a310 100644
--- a/tests/ui/async-await/issue-71137.stderr
+++ b/tests/ui/async-await/issue-71137.stderr
@@ -4,7 +4,7 @@ error: future cannot be sent between threads safely
 LL |   fake_spawn(wrong_mutex());
    |              ^^^^^^^^^^^^^ future returned by `wrong_mutex` is not `Send`
    |
-   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `MutexGuard<'_, i32>`, which is required by `impl Future<Output = ()>: Send`
+   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `MutexGuard<'_, i32>`
 note: future is not `Send` as this value is used across an await
   --> $DIR/issue-71137.rs:14:26
    |
diff --git a/tests/ui/async-await/issue-72590-type-error-sized.stderr b/tests/ui/async-await/issue-72590-type-error-sized.stderr
index 1b822234d80..778423578e1 100644
--- a/tests/ui/async-await/issue-72590-type-error-sized.stderr
+++ b/tests/ui/async-await/issue-72590-type-error-sized.stderr
@@ -16,7 +16,7 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t
 LL |     async fn frob(self) {}
    |                   ^^^^ doesn't have a size known at compile-time
    |
-   = help: within `Foo`, the trait `Sized` is not implemented for `str`, which is required by `Foo: Sized`
+   = help: within `Foo`, the trait `Sized` is not implemented for `str`
 note: required because it appears within the type `Foo`
   --> $DIR/issue-72590-type-error-sized.rs:5:8
    |
diff --git a/tests/ui/async-await/issues/issue-67893.stderr b/tests/ui/async-await/issues/issue-67893.stderr
index 0c28aea44bb..c01237255b8 100644
--- a/tests/ui/async-await/issues/issue-67893.stderr
+++ b/tests/ui/async-await/issues/issue-67893.stderr
@@ -11,7 +11,7 @@ LL |     g(issue_67893::run())
 LL | pub async fn run() {
    | ------------------ within this `impl Future<Output = ()>`
    |
-   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `MutexGuard<'_, ()>`, which is required by `impl Future<Output = ()>: Send`
+   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `MutexGuard<'_, ()>`
 note: required because it's used within this `async` fn body
   --> $DIR/auxiliary/issue_67893.rs:9:20
    |
diff --git a/tests/ui/async-await/partial-drop-partial-reinit.stderr b/tests/ui/async-await/partial-drop-partial-reinit.stderr
index 0bd7d50b941..042ed18984e 100644
--- a/tests/ui/async-await/partial-drop-partial-reinit.stderr
+++ b/tests/ui/async-await/partial-drop-partial-reinit.stderr
@@ -9,7 +9,7 @@ LL |     gimme_send(foo());
 LL | async fn foo() {
    | -------------- within this `impl Future<Output = ()>`
    |
-   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `NotSend`, which is required by `impl Future<Output = ()>: Send`
+   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `NotSend`
    = note: required because it appears within the type `(NotSend,)`
 note: required because it's used within this `async` fn body
   --> $DIR/partial-drop-partial-reinit.rs:27:16
diff --git a/tests/ui/async-await/pin-needed-to-poll-2.stderr b/tests/ui/async-await/pin-needed-to-poll-2.stderr
index e22baabc25b..8eb671531e7 100644
--- a/tests/ui/async-await/pin-needed-to-poll-2.stderr
+++ b/tests/ui/async-await/pin-needed-to-poll-2.stderr
@@ -2,7 +2,7 @@ error[E0277]: `PhantomPinned` cannot be unpinned
   --> $DIR/pin-needed-to-poll-2.rs:43:18
    |
 LL |         Pin::new(&mut self.sleep).poll(cx)
-   |         -------- ^^^^^^^^^^^^^^^ within `Sleep`, the trait `Unpin` is not implemented for `PhantomPinned`, which is required by `Sleep: Unpin`
+   |         -------- ^^^^^^^^^^^^^^^ within `Sleep`, the trait `Unpin` is not implemented for `PhantomPinned`
    |         |
    |         required by a bound introduced by this call
    |
diff --git a/tests/ui/async-await/unnecessary-await.stderr b/tests/ui/async-await/unnecessary-await.stderr
index 8d819576532..620370a6113 100644
--- a/tests/ui/async-await/unnecessary-await.stderr
+++ b/tests/ui/async-await/unnecessary-await.stderr
@@ -6,7 +6,7 @@ LL |     boo().await;
    |     |
    |     this call returns `()`
    |
-   = help: the trait `Future` is not implemented for `()`, which is required by `(): IntoFuture`
+   = help: the trait `Future` is not implemented for `()`
    = note: () must be a future or must implement `IntoFuture` to be awaited
    = note: required for `()` to implement `IntoFuture`
 help: remove the `.await`
@@ -28,7 +28,7 @@ LL |     e!().await;
    |         |`()` is not a future
    |         help: remove the `.await`
    |
-   = help: the trait `Future` is not implemented for `()`, which is required by `(): IntoFuture`
+   = help: the trait `Future` is not implemented for `()`
    = note: () must be a future or must implement `IntoFuture` to be awaited
    = note: required for `()` to implement `IntoFuture`
 
@@ -44,7 +44,7 @@ LL |         $expr.await
 LL |     f!(());
    |     ------ in this macro invocation
    |
-   = help: the trait `Future` is not implemented for `()`, which is required by `(): IntoFuture`
+   = help: the trait `Future` is not implemented for `()`
    = note: () must be a future or must implement `IntoFuture` to be awaited
    = note: required for `()` to implement `IntoFuture`
    = note: this error originates in the macro `f` (in Nightly builds, run with -Z macro-backtrace for more info)
@@ -58,7 +58,7 @@ LL |     for x in [] {}.await
    |                   |`()` is not a future
    |                   help: remove the `.await`
    |
-   = help: the trait `Future` is not implemented for `()`, which is required by `(): IntoFuture`
+   = help: the trait `Future` is not implemented for `()`
    = note: () must be a future or must implement `IntoFuture` to be awaited
    = note: required for `()` to implement `IntoFuture`
 
diff --git a/tests/ui/auto-traits/issue-83857-ub.stderr b/tests/ui/auto-traits/issue-83857-ub.stderr
index 20bfe7e36ca..7c437b7e6c8 100644
--- a/tests/ui/auto-traits/issue-83857-ub.stderr
+++ b/tests/ui/auto-traits/issue-83857-ub.stderr
@@ -4,7 +4,7 @@ error[E0277]: `Foo<T, U>` cannot be sent between threads safely
 LL | fn generic<T, U>(v: Foo<T, U>, f: fn(<Foo<T, U> as WithAssoc>::Output) -> i32) {
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo<T, U>` cannot be sent between threads safely
    |
-   = help: the trait `Send` is not implemented for `Foo<T, U>`, which is required by `Foo<T, U>: WithAssoc`
+   = help: the trait `Send` is not implemented for `Foo<T, U>`
 note: required for `Foo<T, U>` to implement `WithAssoc`
   --> $DIR/issue-83857-ub.rs:14:15
    |
@@ -29,7 +29,7 @@ LL | |
 LL | | }
    | |_^ `Foo<T, U>` cannot be sent between threads safely
    |
-   = help: the trait `Send` is not implemented for `Foo<T, U>`, which is required by `Foo<T, U>: WithAssoc`
+   = help: the trait `Send` is not implemented for `Foo<T, U>`
 note: required for `Foo<T, U>` to implement `WithAssoc`
   --> $DIR/issue-83857-ub.rs:14:15
    |
diff --git a/tests/ui/auto-traits/str-contains-slice-conceptually.stderr b/tests/ui/auto-traits/str-contains-slice-conceptually.stderr
index ebd3a556e75..e1dae35be00 100644
--- a/tests/ui/auto-traits/str-contains-slice-conceptually.stderr
+++ b/tests/ui/auto-traits/str-contains-slice-conceptually.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `[u8]: AutoTrait` is not satisfied in `str`
   --> $DIR/str-contains-slice-conceptually.rs:11:22
    |
 LL |   needs_auto_trait::<str>();
-   |                      ^^^ within `str`, the trait `AutoTrait` is not implemented for `[u8]`, which is required by `str: AutoTrait`
+   |                      ^^^ within `str`, the trait `AutoTrait` is not implemented for `[u8]`
    |
    = note: `str` is considered to contain a `[u8]` slice for auto trait purposes
 note: required by a bound in `needs_auto_trait`
diff --git a/tests/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.stderr b/tests/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.stderr
index b7c97389912..aa5585a5371 100644
--- a/tests/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.stderr
+++ b/tests/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `MyS2: MyTrait` is not satisfied in `(MyS2, MyS)`
   --> $DIR/typeck-default-trait-impl-constituent-types-2.rs:17:18
    |
 LL |     is_mytrait::<(MyS2, MyS)>();
-   |                  ^^^^^^^^^^^ within `(MyS2, MyS)`, the trait `MyTrait` is not implemented for `MyS2`, which is required by `(MyS2, MyS): MyTrait`
+   |                  ^^^^^^^^^^^ within `(MyS2, MyS)`, the trait `MyTrait` is not implemented for `MyS2`
    |
    = note: required because it appears within the type `(MyS2, MyS)`
 note: required by a bound in `is_mytrait`
diff --git a/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr b/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr
index 4773ac4ccf7..fca01b3f48d 100644
--- a/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr
+++ b/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `&'static u32: Defaulted` is not satisfied
   --> $DIR/typeck-default-trait-impl-precedence.rs:19:20
    |
 LL |     is_defaulted::<&'static u32>();
-   |                    ^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32`, which is required by `&'static u32: Defaulted`
+   |                    ^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32`
    |
 note: required for `&'static u32` to implement `Defaulted`
   --> $DIR/typeck-default-trait-impl-precedence.rs:10:19
diff --git a/tests/ui/binop/binary-op-suggest-deref.stderr b/tests/ui/binop/binary-op-suggest-deref.stderr
index 01852fbc633..440625d8ccb 100644
--- a/tests/ui/binop/binary-op-suggest-deref.stderr
+++ b/tests/ui/binop/binary-op-suggest-deref.stderr
@@ -27,7 +27,7 @@ error[E0277]: can't compare `&{integer}` with `{integer}`
 LL |     _ = foo == &0;
    |             ^^ no implementation for `&{integer} == {integer}`
    |
-   = help: the trait `PartialEq<{integer}>` is not implemented for `&{integer}`, which is required by `&&{integer}: PartialEq<&{integer}>`
+   = help: the trait `PartialEq<{integer}>` is not implemented for `&{integer}`
    = note: required for `&&{integer}` to implement `PartialEq<&{integer}>`
 help: consider dereferencing here
    |
@@ -65,7 +65,7 @@ error[E0277]: can't compare `&&{integer}` with `{integer}`
 LL |     _ = &&foo == &&0;
    |               ^^ no implementation for `&&{integer} == {integer}`
    |
-   = help: the trait `PartialEq<{integer}>` is not implemented for `&&{integer}`, which is required by `&&&&{integer}: PartialEq<&&{integer}>`
+   = help: the trait `PartialEq<{integer}>` is not implemented for `&&{integer}`
    = note: required for `&&&{integer}` to implement `PartialEq<&{integer}>`
    = note: 1 redundant requirement hidden
    = note: required for `&&&&{integer}` to implement `PartialEq<&&{integer}>`
@@ -119,7 +119,7 @@ error[E0277]: can't compare `{integer}` with `&{integer}`
 LL |     _ = &0 == foo;
    |            ^^ no implementation for `{integer} == &{integer}`
    |
-   = help: the trait `PartialEq<&{integer}>` is not implemented for `{integer}`, which is required by `&{integer}: PartialEq<&&{integer}>`
+   = help: the trait `PartialEq<&{integer}>` is not implemented for `{integer}`
    = note: required for `&{integer}` to implement `PartialEq<&&{integer}>`
 help: consider dereferencing here
    |
@@ -157,7 +157,7 @@ error[E0277]: can't compare `{integer}` with `&&{integer}`
 LL |     _ = &&0 == &&foo;
    |             ^^ no implementation for `{integer} == &&{integer}`
    |
-   = help: the trait `PartialEq<&&{integer}>` is not implemented for `{integer}`, which is required by `&&{integer}: PartialEq<&&&&{integer}>`
+   = help: the trait `PartialEq<&&{integer}>` is not implemented for `{integer}`
    = note: required for `&{integer}` to implement `PartialEq<&&&{integer}>`
    = note: 1 redundant requirement hidden
    = note: required for `&&{integer}` to implement `PartialEq<&&&&{integer}>`
@@ -173,7 +173,7 @@ error[E0277]: can't compare `Box<Box<{integer}>>` with `&&{integer}`
 LL |     _ = &Box::new(Box::new(42)) == &foo;
    |                                 ^^ no implementation for `Box<Box<{integer}>> == &&{integer}`
    |
-   = help: the trait `PartialEq<&&{integer}>` is not implemented for `Box<Box<{integer}>>`, which is required by `&Box<Box<{integer}>>: PartialEq<&&&{integer}>`
+   = help: the trait `PartialEq<&&{integer}>` is not implemented for `Box<Box<{integer}>>`
    = note: required for `&Box<Box<{integer}>>` to implement `PartialEq<&&&{integer}>`
 help: consider dereferencing both sides of the expression
    |
@@ -187,7 +187,7 @@ error[E0277]: can't compare `Box<{integer}>` with `&&{integer}`
 LL |     _ = &Box::new(42) == &foo;
    |                       ^^ no implementation for `Box<{integer}> == &&{integer}`
    |
-   = help: the trait `PartialEq<&&{integer}>` is not implemented for `Box<{integer}>`, which is required by `&Box<{integer}>: PartialEq<&&&{integer}>`
+   = help: the trait `PartialEq<&&{integer}>` is not implemented for `Box<{integer}>`
    = note: required for `&Box<{integer}>` to implement `PartialEq<&&&{integer}>`
 help: consider dereferencing both sides of the expression
    |
@@ -201,7 +201,7 @@ error[E0277]: can't compare `Box<Box<Box<Box<{integer}>>>>` with `&&{integer}`
 LL |     _ = &Box::new(Box::new(Box::new(Box::new(42)))) == &foo;
    |                                                     ^^ no implementation for `Box<Box<Box<Box<{integer}>>>> == &&{integer}`
    |
-   = help: the trait `PartialEq<&&{integer}>` is not implemented for `Box<Box<Box<Box<{integer}>>>>`, which is required by `&Box<Box<Box<Box<{integer}>>>>: PartialEq<&&&{integer}>`
+   = help: the trait `PartialEq<&&{integer}>` is not implemented for `Box<Box<Box<Box<{integer}>>>>`
    = note: required for `&Box<Box<Box<Box<{integer}>>>>` to implement `PartialEq<&&&{integer}>`
 help: consider dereferencing both sides of the expression
    |
@@ -215,7 +215,7 @@ error[E0277]: can't compare `&&{integer}` with `Box<Box<Box<Box<{integer}>>>>`
 LL |     _ = &foo == &Box::new(Box::new(Box::new(Box::new(42))));
    |              ^^ no implementation for `&&{integer} == Box<Box<Box<Box<{integer}>>>>`
    |
-   = help: the trait `PartialEq<Box<Box<Box<Box<{integer}>>>>>` is not implemented for `&&{integer}`, which is required by `&&&{integer}: PartialEq<&Box<Box<Box<Box<{integer}>>>>>`
+   = help: the trait `PartialEq<Box<Box<Box<Box<{integer}>>>>>` is not implemented for `&&{integer}`
    = note: required for `&&&{integer}` to implement `PartialEq<&Box<Box<Box<Box<{integer}>>>>>`
 help: consider dereferencing both sides of the expression
    |
diff --git a/tests/ui/block-result/issue-22645.stderr b/tests/ui/block-result/issue-22645.stderr
index 2a267ce792f..1064848f513 100644
--- a/tests/ui/block-result/issue-22645.stderr
+++ b/tests/ui/block-result/issue-22645.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `{integer}: Scalar` is not satisfied
   --> $DIR/issue-22645.rs:15:5
    |
 LL |   b + 3
-   |     ^ the trait `Scalar` is not implemented for `{integer}`, which is required by `Bob: Add<_>`
+   |     ^ the trait `Scalar` is not implemented for `{integer}`
    |
    = help: the trait `Scalar` is implemented for `f64`
 note: required for `Bob` to implement `Add<{integer}>`
diff --git a/tests/ui/cast/unsized-union-ice.stderr b/tests/ui/cast/unsized-union-ice.stderr
index 05f86457829..1c9450b8e18 100644
--- a/tests/ui/cast/unsized-union-ice.stderr
+++ b/tests/ui/cast/unsized-union-ice.stderr
@@ -4,7 +4,7 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation
 LL |     val: std::mem::ManuallyDrop<[u8]>,
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = help: within `ManuallyDrop<[u8]>`, the trait `Sized` is not implemented for `[u8]`, which is required by `ManuallyDrop<[u8]>: Sized`
+   = help: within `ManuallyDrop<[u8]>`, the trait `Sized` is not implemented for `[u8]`
 note: required because it appears within the type `ManuallyDrop<[u8]>`
   --> $SRC_DIR/core/src/mem/manually_drop.rs:LL:COL
    = note: no field of a union may have a dynamically sized type
diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr
index b0ca09a59ed..37d2b0343c9 100644
--- a/tests/ui/check-cfg/well-known-values.stderr
+++ b/tests/ui/check-cfg/well-known-values.stderr
@@ -156,7 +156,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
 LL |     target_env = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `target_env` are: ``, `gnu`, `msvc`, `musl`, `newlib`, `nto70`, `nto71`, `ohos`, `p1`, `p2`, `psx`, `relibc`, `sgx`, and `uclibc`
+   = note: expected values for `target_env` are: ``, `gnu`, `msvc`, `musl`, `newlib`, `nto70`, `nto71`, `ohos`, `p1`, `p2`, `relibc`, `sgx`, and `uclibc`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -210,7 +210,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
 LL |     target_os = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm`
+   = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -294,7 +294,7 @@ LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux`
    |                   |
    |                   help: there is a expected value with a similar name: `"linux"`
    |
-   = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm`
+   = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: 30 warnings emitted
diff --git a/tests/ui/closures/closure-move-sync.stderr b/tests/ui/closures/closure-move-sync.stderr
index 6cade0c09dd..2bb26b0c0b7 100644
--- a/tests/ui/closures/closure-move-sync.stderr
+++ b/tests/ui/closures/closure-move-sync.stderr
@@ -10,7 +10,7 @@ LL | |
 LL | |     });
    | |_____^ `std::sync::mpsc::Receiver<()>` cannot be shared between threads safely
    |
-   = help: the trait `Sync` is not implemented for `std::sync::mpsc::Receiver<()>`, which is required by `{closure@$DIR/closure-move-sync.rs:6:27: 6:29}: Send`
+   = help: the trait `Sync` is not implemented for `std::sync::mpsc::Receiver<()>`
    = note: required for `&std::sync::mpsc::Receiver<()>` to implement `Send`
 note: required because it's used within this closure
   --> $DIR/closure-move-sync.rs:6:27
diff --git a/tests/ui/closures/closure-return-type-must-be-sized.stderr b/tests/ui/closures/closure-return-type-must-be-sized.stderr
index 167d326e26e..04ae7343bbe 100644
--- a/tests/ui/closures/closure-return-type-must-be-sized.stderr
+++ b/tests/ui/closures/closure-return-type-must-be-sized.stderr
@@ -4,7 +4,7 @@ error[E0277]: the size for values of type `dyn A` cannot be known at compilation
 LL |     a::foo::<fn() -> dyn A>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`, which is required by `fn() -> dyn A: FnOnce()`
+   = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`
    = note: required because it appears within the type `fn() -> dyn A`
 
 error[E0277]: the size for values of type `dyn A` cannot be known at compilation time
@@ -13,7 +13,7 @@ error[E0277]: the size for values of type `dyn A` cannot be known at compilation
 LL |     a::bar::<fn() -> dyn A, _>();
    |              ^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`, which is required by `fn() -> dyn A: FnOnce()`
+   = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`
    = note: required because it appears within the type `fn() -> dyn A`
 note: required by a bound in `a::bar`
   --> $DIR/closure-return-type-must-be-sized.rs:14:19
@@ -27,7 +27,7 @@ error[E0277]: the size for values of type `dyn A` cannot be known at compilation
 LL |     a::baz::<fn() -> dyn A>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`, which is required by `fn() -> dyn A: FnOnce()`
+   = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`
    = note: required because it appears within the type `fn() -> dyn A`
 
 error[E0277]: the size for values of type `dyn A` cannot be known at compilation time
@@ -36,7 +36,7 @@ error[E0277]: the size for values of type `dyn A` cannot be known at compilation
 LL |     b::foo::<fn() -> dyn A>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`, which is required by `fn() -> dyn A: FnOnce()`
+   = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`
    = note: required because it appears within the type `fn() -> dyn A`
 
 error[E0277]: the size for values of type `dyn A` cannot be known at compilation time
@@ -45,7 +45,7 @@ error[E0277]: the size for values of type `dyn A` cannot be known at compilation
 LL |     b::bar::<fn() -> dyn A, _>();
    |              ^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`, which is required by `fn() -> dyn A: Fn()`
+   = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`
    = note: required because it appears within the type `fn() -> dyn A`
 note: required by a bound in `b::bar`
   --> $DIR/closure-return-type-must-be-sized.rs:28:19
@@ -59,7 +59,7 @@ error[E0277]: the size for values of type `dyn A` cannot be known at compilation
 LL |     b::baz::<fn() -> dyn A>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`, which is required by `fn() -> dyn A: FnOnce()`
+   = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`
    = note: required because it appears within the type `fn() -> dyn A`
 
 error[E0277]: the size for values of type `dyn A` cannot be known at compilation time
@@ -68,7 +68,7 @@ error[E0277]: the size for values of type `dyn A` cannot be known at compilation
 LL |     c::foo::<fn() -> dyn A>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`, which is required by `fn() -> dyn A: FnOnce()`
+   = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`
    = note: required because it appears within the type `fn() -> dyn A`
 
 error[E0277]: the size for values of type `dyn A` cannot be known at compilation time
@@ -77,7 +77,7 @@ error[E0277]: the size for values of type `dyn A` cannot be known at compilation
 LL |     c::bar::<fn() -> dyn A, _>();
    |              ^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`, which is required by `fn() -> dyn A: FnMut()`
+   = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`
    = note: required because it appears within the type `fn() -> dyn A`
 note: required by a bound in `c::bar`
   --> $DIR/closure-return-type-must-be-sized.rs:42:19
@@ -91,7 +91,7 @@ error[E0277]: the size for values of type `dyn A` cannot be known at compilation
 LL |     c::baz::<fn() -> dyn A>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`, which is required by `fn() -> dyn A: FnOnce()`
+   = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`
    = note: required because it appears within the type `fn() -> dyn A`
 
 error: aborting due to 9 previous errors
diff --git a/tests/ui/coherence/deep-bad-copy-reason.stderr b/tests/ui/coherence/deep-bad-copy-reason.stderr
index fe5ae9b08b4..534f26c39c2 100644
--- a/tests/ui/coherence/deep-bad-copy-reason.stderr
+++ b/tests/ui/coherence/deep-bad-copy-reason.stderr
@@ -19,7 +19,7 @@ error[E0277]: the size for values of type `OpaqueListContents` cannot be known a
 LL | pub struct List<'tcx, T>(Interned<'tcx, ListS<T>>);
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = help: within `ListS<T>`, the trait `Sized` is not implemented for `OpaqueListContents`, which is required by `ListS<T>: Sized`
+   = help: within `ListS<T>`, the trait `Sized` is not implemented for `OpaqueListContents`
 note: required because it appears within the type `ListS<T>`
   --> $DIR/deep-bad-copy-reason.rs:7:12
    |
diff --git a/tests/ui/compiletest-self-test/minicore-smoke-test.rs b/tests/ui/compiletest-self-test/minicore-smoke-test.rs
new file mode 100644
index 00000000000..ec879f2852e
--- /dev/null
+++ b/tests/ui/compiletest-self-test/minicore-smoke-test.rs
@@ -0,0 +1,20 @@
+//! Basic smoke test for `minicore` test auxiliary.
+//!
+//! This test is duplicated between ui/codegen/assembly because they have different runtest
+//! codepaths.
+
+//@ add-core-stubs
+//@ check-pass
+//@ compile-flags: --target=x86_64-unknown-linux-gnu
+//@ needs-llvm-components: x86
+
+#![crate_type = "lib"]
+#![feature(no_core)]
+#![no_std]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
+
+struct Meow;
+impl Copy for Meow {}
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.stderr
index 9852e181b9a..9220cd1f94e 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.stderr
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.stderr
@@ -2,7 +2,7 @@ error[E0277]: `NotParam` can't be used as a const parameter type
   --> $DIR/const_param_ty_bad_empty_array.rs:10:13
    |
 LL |     check::<[NotParam; 0]>();
-   |             ^^^^^^^^^^^^^ the trait `ConstParamTy_` is not implemented for `NotParam`, which is required by `[NotParam; 0]: ConstParamTy_`
+   |             ^^^^^^^^^^^^^ the trait `ConstParamTy_` is not implemented for `NotParam`
    |
    = note: required for `[NotParam; 0]` to implement `ConstParamTy_`
 note: required by a bound in `check`
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.stderr
index e63ae582fd5..d01aaffe8ae 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.stderr
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.stderr
@@ -2,7 +2,7 @@ error[E0277]: `NotParam` can't be used as a const parameter type
   --> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:10:13
    |
 LL |     check::<&NotParam>();
-   |             ^^^^^^^^^ the trait `UnsizedConstParamTy` is not implemented for `NotParam`, which is required by `&NotParam: UnsizedConstParamTy`
+   |             ^^^^^^^^^ the trait `UnsizedConstParamTy` is not implemented for `NotParam`
    |
    = note: required for `&NotParam` to implement `UnsizedConstParamTy`
 note: required by a bound in `check`
@@ -15,7 +15,7 @@ error[E0277]: `NotParam` can't be used as a const parameter type
   --> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:11:13
    |
 LL |     check::<[NotParam]>();
-   |             ^^^^^^^^^^ the trait `UnsizedConstParamTy` is not implemented for `NotParam`, which is required by `[NotParam]: UnsizedConstParamTy`
+   |             ^^^^^^^^^^ the trait `UnsizedConstParamTy` is not implemented for `NotParam`
    |
    = note: required for `[NotParam]` to implement `UnsizedConstParamTy`
 note: required by a bound in `check`
@@ -28,7 +28,7 @@ error[E0277]: `NotParam` can't be used as a const parameter type
   --> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:12:13
    |
 LL |     check::<[NotParam; 17]>();
-   |             ^^^^^^^^^^^^^^ the trait `UnsizedConstParamTy` is not implemented for `NotParam`, which is required by `[NotParam; 17]: UnsizedConstParamTy`
+   |             ^^^^^^^^^^^^^^ the trait `UnsizedConstParamTy` is not implemented for `NotParam`
    |
    = note: required for `[NotParam; 17]` to implement `UnsizedConstParamTy`
 note: required by a bound in `check`
diff --git a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr
index 1c30aa68e85..72f3fd9de90 100644
--- a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr
+++ b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr
@@ -64,7 +64,7 @@ LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)]
 LL |     nested: &'static Bar<dyn std::fmt::Debug>,
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = help: the trait `Sized` is not implemented for `(dyn Debug + 'static)`, which is required by `&&'static Bar<(dyn Debug + 'static)>: Debug`
+   = help: the trait `Sized` is not implemented for `(dyn Debug + 'static)`
    = help: the trait `Debug` is implemented for `Bar<T>`
 note: required for `Bar<(dyn Debug + 'static)>` to implement `Debug`
   --> $DIR/unsizing-wfcheck-issue-126272.rs:20:10
@@ -96,7 +96,7 @@ LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)]
    |                            -- in this derive macro expansion
 ...
 LL |     nested: &'static Bar<dyn std::fmt::Debug>,
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `dyn Debug`, which is required by `&'static Bar<dyn Debug>: Eq`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `dyn Debug`
    |
    = help: the trait `Eq` is implemented for `Bar<T>`
 note: required for `Bar<dyn Debug>` to implement `Eq`
diff --git a/tests/ui/const-generics/generic_const_exprs/issue-85848.stderr b/tests/ui/const-generics/generic_const_exprs/issue-85848.stderr
index 4abe39eb598..6ff22ffa847 100644
--- a/tests/ui/const-generics/generic_const_exprs/issue-85848.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/issue-85848.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `(): _Contains<&C>` is not satisfied
   --> $DIR/issue-85848.rs:24:29
    |
 LL |     writes_to_specific_path(&cap);
-   |     ----------------------- ^^^^ the trait `_Contains<&C>` is not implemented for `()`, which is required by `&C: Delegates<()>`
+   |     ----------------------- ^^^^ the trait `_Contains<&C>` is not implemented for `()`
    |     |
    |     required by a bound introduced by this call
    |
diff --git a/tests/ui/const-generics/issues/issue-67185-2.stderr b/tests/ui/const-generics/issues/issue-67185-2.stderr
index 5cc3bb673bc..82813a24f99 100644
--- a/tests/ui/const-generics/issues/issue-67185-2.stderr
+++ b/tests/ui/const-generics/issues/issue-67185-2.stderr
@@ -32,7 +32,7 @@ error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied
   --> $DIR/issue-67185-2.rs:21:6
    |
 LL | impl Foo for FooImpl {}
-   |      ^^^ the trait `Bar` is not implemented for `[u16; 3]`, which is required by `<u8 as Baz>::Quaks: Bar`
+   |      ^^^ the trait `Bar` is not implemented for `[u16; 3]`
    |
    = help: the following other types implement trait `Bar`:
              [[u16; 3]; 3]
@@ -50,7 +50,7 @@ error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied
   --> $DIR/issue-67185-2.rs:21:6
    |
 LL | impl Foo for FooImpl {}
-   |      ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]`, which is required by `[<u8 as Baz>::Quaks; 2]: Bar`
+   |      ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]`
    |
    = help: the following other types implement trait `Bar`:
              [[u16; 3]; 3]
diff --git a/tests/ui/const-generics/kind_mismatch.stderr b/tests/ui/const-generics/kind_mismatch.stderr
index 80968ebea68..e13bc6ee058 100644
--- a/tests/ui/const-generics/kind_mismatch.stderr
+++ b/tests/ui/const-generics/kind_mismatch.stderr
@@ -18,7 +18,7 @@ error[E0277]: the trait bound `KeyHolder<0>: SubsetExcept<_>` is not satisfied
   --> $DIR/kind_mismatch.rs:22:45
    |
 LL |     let map: KeyHolder<0> = remove_key::<_, _>();
-   |                                             ^ the trait `ContainsKey<0>` is not implemented for `KeyHolder<0>`, which is required by `KeyHolder<0>: SubsetExcept<_>`
+   |                                             ^ the trait `ContainsKey<0>` is not implemented for `KeyHolder<0>`
    |
 note: required for `KeyHolder<0>` to implement `SubsetExcept<_>`
   --> $DIR/kind_mismatch.rs:15:28
diff --git a/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr b/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr
index 9dce29732ac..272c2f045e1 100644
--- a/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr
+++ b/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `Bar: Copy` is not satisfied
   --> $DIR/fn-call-in-non-const.rs:14:32
    |
 LL |     let _: [Option<Bar>; 2] = [no_copy(); 2];
-   |                                ^^^^^^^^^ the trait `Copy` is not implemented for `Bar`, which is required by `Option<Bar>: Copy`
+   |                                ^^^^^^^^^ the trait `Copy` is not implemented for `Bar`
    |
    = note: required for `Option<Bar>` to implement `Copy`
    = note: the `Copy` trait is required because this value will be copied for each element of the array
diff --git a/tests/ui/consts/const-blocks/migrate-fail.stderr b/tests/ui/consts/const-blocks/migrate-fail.stderr
index 3887658f748..3c116026e58 100644
--- a/tests/ui/consts/const-blocks/migrate-fail.stderr
+++ b/tests/ui/consts/const-blocks/migrate-fail.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `Bar: Copy` is not satisfied
   --> $DIR/migrate-fail.rs:11:38
    |
 LL |         let arr: [Option<Bar>; 2] = [x; 2];
-   |                                      ^ the trait `Copy` is not implemented for `Bar`, which is required by `Option<Bar>: Copy`
+   |                                      ^ the trait `Copy` is not implemented for `Bar`
    |
    = note: required for `Option<Bar>` to implement `Copy`
    = note: the `Copy` trait is required because this value will be copied for each element of the array
@@ -18,7 +18,7 @@ error[E0277]: the trait bound `Bar: Copy` is not satisfied
   --> $DIR/migrate-fail.rs:17:38
    |
 LL |         let arr: [Option<Bar>; 2] = [x; 2];
-   |                                      ^ the trait `Copy` is not implemented for `Bar`, which is required by `Option<Bar>: Copy`
+   |                                      ^ the trait `Copy` is not implemented for `Bar`
    |
    = note: required for `Option<Bar>` to implement `Copy`
    = note: the `Copy` trait is required because this value will be copied for each element of the array
diff --git a/tests/ui/consts/const-blocks/nll-fail.stderr b/tests/ui/consts/const-blocks/nll-fail.stderr
index a2ea833f650..ff2b62da668 100644
--- a/tests/ui/consts/const-blocks/nll-fail.stderr
+++ b/tests/ui/consts/const-blocks/nll-fail.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `Bar: Copy` is not satisfied
   --> $DIR/nll-fail.rs:11:38
    |
 LL |         let arr: [Option<Bar>; 2] = [x; 2];
-   |                                      ^ the trait `Copy` is not implemented for `Bar`, which is required by `Option<Bar>: Copy`
+   |                                      ^ the trait `Copy` is not implemented for `Bar`
    |
    = note: required for `Option<Bar>` to implement `Copy`
    = note: the `Copy` trait is required because this value will be copied for each element of the array
@@ -18,7 +18,7 @@ error[E0277]: the trait bound `Bar: Copy` is not satisfied
   --> $DIR/nll-fail.rs:17:38
    |
 LL |         let arr: [Option<Bar>; 2] = [x; 2];
-   |                                      ^ the trait `Copy` is not implemented for `Bar`, which is required by `Option<Bar>: Copy`
+   |                                      ^ the trait `Copy` is not implemented for `Bar`
    |
    = note: required for `Option<Bar>` to implement `Copy`
    = note: the `Copy` trait is required because this value will be copied for each element of the array
diff --git a/tests/ui/consts/const-blocks/trait-error.stderr b/tests/ui/consts/const-blocks/trait-error.stderr
index 8f00f14dfb9..068720a53f6 100644
--- a/tests/ui/consts/const-blocks/trait-error.stderr
+++ b/tests/ui/consts/const-blocks/trait-error.stderr
@@ -4,7 +4,7 @@ error[E0277]: the trait bound `String: Copy` is not satisfied
 LL |     [Foo(String::new()); 4];
    |      ^^^^^^^^^^^^^^^^^^
    |      |
-   |      the trait `Copy` is not implemented for `String`, which is required by `Foo<String>: Copy`
+   |      the trait `Copy` is not implemented for `String`
    |      help: create an inline `const` block: `const { Foo(String::new()) }`
    |
 note: required for `Foo<String>` to implement `Copy`
diff --git a/tests/ui/consts/const-fn-in-vec.stderr b/tests/ui/consts/const-fn-in-vec.stderr
index 7c6b3bee940..b31e180fea2 100644
--- a/tests/ui/consts/const-fn-in-vec.stderr
+++ b/tests/ui/consts/const-fn-in-vec.stderr
@@ -4,7 +4,7 @@ error[E0277]: the trait bound `String: Copy` is not satisfied
 LL | static _MAYBE_STRINGS: [Option<String>; 5] = [None; 5];
    |                                               ^^^^
    |                                               |
-   |                                               the trait `Copy` is not implemented for `String`, which is required by `Option<String>: Copy`
+   |                                               the trait `Copy` is not implemented for `String`
    |                                               help: create an inline `const` block: `const { None }`
    |
    = note: required for `Option<String>` to implement `Copy`
@@ -27,7 +27,7 @@ error[E0277]: the trait bound `String: Copy` is not satisfied
 LL |     let _maybe_strings: [Option<String>; 5] = [None; 5];
    |                                                ^^^^
    |                                                |
-   |                                                the trait `Copy` is not implemented for `String`, which is required by `Option<String>: Copy`
+   |                                                the trait `Copy` is not implemented for `String`
    |                                                help: create an inline `const` block: `const { None }`
    |
    = note: required for `Option<String>` to implement `Copy`
diff --git a/tests/ui/consts/constifconst-call-in-const-position.stderr b/tests/ui/consts/constifconst-call-in-const-position.stderr
index 2195cab3f4d..6add83dc52c 100644
--- a/tests/ui/consts/constifconst-call-in-const-position.stderr
+++ b/tests/ui/consts/constifconst-call-in-const-position.stderr
@@ -1,14 +1,15 @@
-error: using `#![feature(effects)]` without enabling next trait solver globally
-   |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
-
-error[E0080]: evaluation of `foo::<()>::{constant#0}` failed
+error[E0277]: the trait bound `T: const Tr` is not satisfied
   --> $DIR/constifconst-call-in-const-position.rs:17:38
    |
 LL | const fn foo<T: ~const Tr>() -> [u8; T::a()] {
-   |                                      ^^^^^^ calling non-const function `<() as Tr>::a`
+   |                                      ^^^^^^
+
+error[E0277]: the trait bound `T: const Tr` is not satisfied
+  --> $DIR/constifconst-call-in-const-position.rs:18:9
+   |
+LL |     [0; T::a()]
+   |         ^^^^^^
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0080`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/coroutine/clone-impl.stderr b/tests/ui/coroutine/clone-impl.stderr
index 5330d3bbd39..1256c97a02f 100644
--- a/tests/ui/coroutine/clone-impl.stderr
+++ b/tests/ui/coroutine/clone-impl.stderr
@@ -5,7 +5,7 @@ LL |     move || {
    |     ------- within this `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}`
 ...
 LL |     check_copy(&gen_clone_0);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}`, the trait `Copy` is not implemented for `Vec<u32>`, which is required by `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}: Copy`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}`, the trait `Copy` is not implemented for `Vec<u32>`
    |
 note: captured value does not implement `Copy`
   --> $DIR/clone-impl.rs:47:14
@@ -25,7 +25,7 @@ LL |     move || {
    |     ------- within this `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}`
 ...
 LL |     check_copy(&gen_clone_0);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}`, the trait `Copy` is not implemented for `Vec<char>`, which is required by `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}: Copy`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}`, the trait `Copy` is not implemented for `Vec<char>`
    |
 note: coroutine does not implement `Copy` as this value is used across a yield
   --> $DIR/clone-impl.rs:45:9
@@ -47,7 +47,7 @@ LL |     move || {
    |     ------- within this `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}`
 ...
 LL |     check_copy(&gen_clone_1);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}`, the trait `Copy` is not implemented for `Vec<u32>`, which is required by `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}: Copy`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}`, the trait `Copy` is not implemented for `Vec<u32>`
    |
 note: captured value does not implement `Copy`
   --> $DIR/clone-impl.rs:68:14
@@ -67,7 +67,7 @@ LL |     move || {
    |     ------- within this `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}`
 ...
 LL |     check_copy(&gen_clone_1);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}`, the trait `Copy` is not implemented for `Vec<char>`, which is required by `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}: Copy`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}`, the trait `Copy` is not implemented for `Vec<char>`
    |
 note: coroutine does not implement `Copy` as this value is used across a yield
   --> $DIR/clone-impl.rs:64:9
@@ -90,7 +90,7 @@ LL |     move || {
    |     ------- within this `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}`
 ...
 LL |     check_copy(&gen_non_clone);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}`, the trait `Copy` is not implemented for `NonClone`, which is required by `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}: Copy`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}`, the trait `Copy` is not implemented for `NonClone`
    |
 note: captured value does not implement `Copy`
   --> $DIR/clone-impl.rs:81:14
@@ -115,7 +115,7 @@ LL |     move || {
    |     ------- within this `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}`
 ...
 LL |     check_clone(&gen_non_clone);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}`, the trait `Clone` is not implemented for `NonClone`, which is required by `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}: Clone`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}`, the trait `Clone` is not implemented for `NonClone`
    |
 note: captured value does not implement `Clone`
   --> $DIR/clone-impl.rs:81:14
diff --git a/tests/ui/coroutine/drop-tracking-parent-expression.stderr b/tests/ui/coroutine/drop-tracking-parent-expression.stderr
index 5f8d8495e4f..51fc20070bf 100644
--- a/tests/ui/coroutine/drop-tracking-parent-expression.stderr
+++ b/tests/ui/coroutine/drop-tracking-parent-expression.stderr
@@ -13,7 +13,7 @@ LL | |         };
 LL | |     );
    | |_____- in this macro invocation
    |
-   = help: within `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:34: 17:41}`, the trait `Send` is not implemented for `derived_drop::Client`, which is required by `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:34: 17:41}: Send`
+   = help: within `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:34: 17:41}`, the trait `Send` is not implemented for `derived_drop::Client`
 note: coroutine is not `Send` as this value is used across a yield
   --> $DIR/drop-tracking-parent-expression.rs:21:22
    |
@@ -53,7 +53,7 @@ LL | |         };
 LL | |     );
    | |_____- in this macro invocation
    |
-   = help: within `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:34: 17:41}`, the trait `Send` is not implemented for `significant_drop::Client`, which is required by `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:34: 17:41}: Send`
+   = help: within `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:34: 17:41}`, the trait `Send` is not implemented for `significant_drop::Client`
 note: coroutine is not `Send` as this value is used across a yield
   --> $DIR/drop-tracking-parent-expression.rs:21:22
    |
@@ -93,7 +93,7 @@ LL | |         };
 LL | |     );
    | |_____- in this macro invocation
    |
-   = help: within `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:34: 17:41}`, the trait `Send` is not implemented for `insignificant_dtor::Client`, which is required by `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:34: 17:41}: Send`
+   = help: within `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:34: 17:41}`, the trait `Send` is not implemented for `insignificant_dtor::Client`
 note: coroutine is not `Send` as this value is used across a yield
   --> $DIR/drop-tracking-parent-expression.rs:21:22
    |
diff --git a/tests/ui/coroutine/drop-yield-twice.stderr b/tests/ui/coroutine/drop-yield-twice.stderr
index 362c6e943ad..c5da35d9736 100644
--- a/tests/ui/coroutine/drop-yield-twice.stderr
+++ b/tests/ui/coroutine/drop-yield-twice.stderr
@@ -9,7 +9,7 @@ LL | |         yield;
 LL | |     })
    | |______^ coroutine is not `Send`
    |
-   = help: within `{coroutine@$DIR/drop-yield-twice.rs:7:30: 7:32}`, the trait `Send` is not implemented for `Foo`, which is required by `{coroutine@$DIR/drop-yield-twice.rs:7:30: 7:32}: Send`
+   = help: within `{coroutine@$DIR/drop-yield-twice.rs:7:30: 7:32}`, the trait `Send` is not implemented for `Foo`
 note: coroutine is not `Send` as this value is used across a yield
   --> $DIR/drop-yield-twice.rs:9:9
    |
diff --git a/tests/ui/coroutine/issue-105084.stderr b/tests/ui/coroutine/issue-105084.stderr
index 6b1701f0c2a..11b5852b638 100644
--- a/tests/ui/coroutine/issue-105084.stderr
+++ b/tests/ui/coroutine/issue-105084.stderr
@@ -29,7 +29,7 @@ LL |     || {
    |     -- within this `{coroutine@$DIR/issue-105084.rs:15:5: 15:7}`
 ...
 LL |     let mut h = copy(g);
-   |                 ^^^^^^^ within `{coroutine@$DIR/issue-105084.rs:15:5: 15:7}`, the trait `Copy` is not implemented for `Box<(i32, ())>`, which is required by `{coroutine@$DIR/issue-105084.rs:15:5: 15:7}: Copy`
+   |                 ^^^^^^^ within `{coroutine@$DIR/issue-105084.rs:15:5: 15:7}`, the trait `Copy` is not implemented for `Box<(i32, ())>`
    |
 note: coroutine does not implement `Copy` as this value is used across a yield
   --> $DIR/issue-105084.rs:22:22
diff --git a/tests/ui/coroutine/issue-68112.stderr b/tests/ui/coroutine/issue-68112.stderr
index bcfcb5ec6e6..124537b971e 100644
--- a/tests/ui/coroutine/issue-68112.stderr
+++ b/tests/ui/coroutine/issue-68112.stderr
@@ -4,7 +4,7 @@ error: coroutine cannot be sent between threads safely
 LL |     require_send(send_gen);
    |     ^^^^^^^^^^^^^^^^^^^^^^ coroutine is not `Send`
    |
-   = help: the trait `Sync` is not implemented for `RefCell<i32>`, which is required by `{coroutine@$DIR/issue-68112.rs:33:33: 33:35}: Send`
+   = help: the trait `Sync` is not implemented for `RefCell<i32>`
    = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
 note: coroutine is not `Send` as this value is used across a yield
   --> $DIR/issue-68112.rs:36:9
@@ -26,7 +26,7 @@ error[E0277]: `RefCell<i32>` cannot be shared between threads safely
 LL |     require_send(send_gen);
    |     ^^^^^^^^^^^^^^^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely
    |
-   = help: the trait `Sync` is not implemented for `RefCell<i32>`, which is required by `{coroutine@$DIR/issue-68112.rs:60:33: 60:35}: Send`
+   = help: the trait `Sync` is not implemented for `RefCell<i32>`
    = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
    = note: required for `Arc<RefCell<i32>>` to implement `Send`
 note: required because it's used within this coroutine
diff --git a/tests/ui/coroutine/not-send-sync.stderr b/tests/ui/coroutine/not-send-sync.stderr
index 0f9cbdec130..c6d2ac0a557 100644
--- a/tests/ui/coroutine/not-send-sync.stderr
+++ b/tests/ui/coroutine/not-send-sync.stderr
@@ -9,7 +9,7 @@ LL | |         drop(a);
 LL | |     });
    | |______^ coroutine is not `Sync`
    |
-   = help: within `{coroutine@$DIR/not-send-sync.rs:14:30: 14:32}`, the trait `Sync` is not implemented for `NotSync`, which is required by `{coroutine@$DIR/not-send-sync.rs:14:30: 14:32}: Sync`
+   = help: within `{coroutine@$DIR/not-send-sync.rs:14:30: 14:32}`, the trait `Sync` is not implemented for `NotSync`
 note: coroutine is not `Sync` as this value is used across a yield
   --> $DIR/not-send-sync.rs:17:9
    |
@@ -34,7 +34,7 @@ LL | |         drop(a);
 LL | |     });
    | |______^ coroutine is not `Send`
    |
-   = help: within `{coroutine@$DIR/not-send-sync.rs:21:30: 21:32}`, the trait `Send` is not implemented for `NotSend`, which is required by `{coroutine@$DIR/not-send-sync.rs:21:30: 21:32}: Send`
+   = help: within `{coroutine@$DIR/not-send-sync.rs:21:30: 21:32}`, the trait `Send` is not implemented for `NotSend`
 note: coroutine is not `Send` as this value is used across a yield
   --> $DIR/not-send-sync.rs:24:9
    |
diff --git a/tests/ui/coroutine/parent-expression.stderr b/tests/ui/coroutine/parent-expression.stderr
index 2d817f1bfd9..770ffda7a26 100644
--- a/tests/ui/coroutine/parent-expression.stderr
+++ b/tests/ui/coroutine/parent-expression.stderr
@@ -13,7 +13,7 @@ LL | |         };
 LL | |     );
    | |_____- in this macro invocation
    |
-   = help: within `{coroutine@$DIR/parent-expression.rs:17:34: 17:41}`, the trait `Send` is not implemented for `derived_drop::Client`, which is required by `{coroutine@$DIR/parent-expression.rs:17:34: 17:41}: Send`
+   = help: within `{coroutine@$DIR/parent-expression.rs:17:34: 17:41}`, the trait `Send` is not implemented for `derived_drop::Client`
 note: coroutine is not `Send` as this value is used across a yield
   --> $DIR/parent-expression.rs:21:22
    |
@@ -53,7 +53,7 @@ LL | |         };
 LL | |     );
    | |_____- in this macro invocation
    |
-   = help: within `{coroutine@$DIR/parent-expression.rs:17:34: 17:41}`, the trait `Send` is not implemented for `significant_drop::Client`, which is required by `{coroutine@$DIR/parent-expression.rs:17:34: 17:41}: Send`
+   = help: within `{coroutine@$DIR/parent-expression.rs:17:34: 17:41}`, the trait `Send` is not implemented for `significant_drop::Client`
 note: coroutine is not `Send` as this value is used across a yield
   --> $DIR/parent-expression.rs:21:22
    |
@@ -93,7 +93,7 @@ LL | |         };
 LL | |     );
    | |_____- in this macro invocation
    |
-   = help: within `{coroutine@$DIR/parent-expression.rs:17:34: 17:41}`, the trait `Send` is not implemented for `insignificant_dtor::Client`, which is required by `{coroutine@$DIR/parent-expression.rs:17:34: 17:41}: Send`
+   = help: within `{coroutine@$DIR/parent-expression.rs:17:34: 17:41}`, the trait `Send` is not implemented for `insignificant_dtor::Client`
 note: coroutine is not `Send` as this value is used across a yield
   --> $DIR/parent-expression.rs:21:22
    |
diff --git a/tests/ui/coroutine/print/coroutine-print-verbose-1.stderr b/tests/ui/coroutine/print/coroutine-print-verbose-1.stderr
index daf88fc1f23..410189b9ab6 100644
--- a/tests/ui/coroutine/print/coroutine-print-verbose-1.stderr
+++ b/tests/ui/coroutine/print/coroutine-print-verbose-1.stderr
@@ -4,7 +4,7 @@ error: coroutine cannot be sent between threads safely
 LL |     require_send(send_gen);
    |     ^^^^^^^^^^^^^^^^^^^^^^ coroutine is not `Send`
    |
-   = help: the trait `Sync` is not implemented for `RefCell<i32>`, which is required by `{test1::{closure#0} upvar_tys=() witness={test1::{closure#0}}}: Send`
+   = help: the trait `Sync` is not implemented for `RefCell<i32>`
    = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
 note: coroutine is not `Send` as this value is used across a yield
   --> $DIR/coroutine-print-verbose-1.rs:35:9
@@ -25,7 +25,7 @@ error[E0277]: `RefCell<i32>` cannot be shared between threads safely
 LL |     require_send(send_gen);
    |     ^^^^^^^^^^^^^^^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely
    |
-   = help: the trait `Sync` is not implemented for `RefCell<i32>`, which is required by `{test2::{closure#0} upvar_tys=() witness={test2::{closure#0}}}: Send`
+   = help: the trait `Sync` is not implemented for `RefCell<i32>`
    = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
    = note: required for `Arc<RefCell<i32>>` to implement `Send`
 note: required because it's used within this coroutine
diff --git a/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr b/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr
index 0de53d9e1d7..2ab9d35f05a 100644
--- a/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr
+++ b/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr
@@ -9,7 +9,7 @@ LL | |         drop(a);
 LL | |     });
    | |______^ coroutine is not `Sync`
    |
-   = help: within `{main::{closure#0} upvar_tys=() witness={main::{closure#0}}}`, the trait `Sync` is not implemented for `NotSync`, which is required by `{main::{closure#0} upvar_tys=() witness={main::{closure#0}}}: Sync`
+   = help: within `{main::{closure#0} upvar_tys=() witness={main::{closure#0}}}`, the trait `Sync` is not implemented for `NotSync`
 note: coroutine is not `Sync` as this value is used across a yield
   --> $DIR/coroutine-print-verbose-2.rs:20:9
    |
@@ -34,7 +34,7 @@ LL | |         drop(a);
 LL | |     });
    | |______^ coroutine is not `Send`
    |
-   = help: within `{main::{closure#1} upvar_tys=() witness={main::{closure#1}}}`, the trait `Send` is not implemented for `NotSend`, which is required by `{main::{closure#1} upvar_tys=() witness={main::{closure#1}}}: Send`
+   = help: within `{main::{closure#1} upvar_tys=() witness={main::{closure#1}}}`, the trait `Send` is not implemented for `NotSend`
 note: coroutine is not `Send` as this value is used across a yield
   --> $DIR/coroutine-print-verbose-2.rs:27:9
    |
diff --git a/tests/ui/coroutine/ref-upvar-not-send.stderr b/tests/ui/coroutine/ref-upvar-not-send.stderr
index 4c7deab3f4c..892b5d261c2 100644
--- a/tests/ui/coroutine/ref-upvar-not-send.stderr
+++ b/tests/ui/coroutine/ref-upvar-not-send.stderr
@@ -10,7 +10,7 @@ LL | |         let _x = x;
 LL | |     });
    | |_____^ coroutine is not `Send`
    |
-   = help: the trait `Sync` is not implemented for `*mut ()`, which is required by `{coroutine@$DIR/ref-upvar-not-send.rs:15:30: 15:37}: Send`
+   = help: the trait `Sync` is not implemented for `*mut ()`
 note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
   --> $DIR/ref-upvar-not-send.rs:19:18
    |
@@ -34,7 +34,7 @@ LL | |         let _y = y;
 LL | |     });
    | |_____^ coroutine is not `Send`
    |
-   = help: within `{coroutine@$DIR/ref-upvar-not-send.rs:23:30: 23:37}`, the trait `Send` is not implemented for `*mut ()`, which is required by `{coroutine@$DIR/ref-upvar-not-send.rs:23:30: 23:37}: Send`
+   = help: within `{coroutine@$DIR/ref-upvar-not-send.rs:23:30: 23:37}`, the trait `Send` is not implemented for `*mut ()`
 note: captured value is not `Send` because `&mut` references cannot be sent unless their referent is `Send`
   --> $DIR/ref-upvar-not-send.rs:27:18
    |
diff --git a/tests/ui/coroutine/resume-arg-outlives-2.rs b/tests/ui/coroutine/resume-arg-outlives-2.rs
new file mode 100644
index 00000000000..387b143ea27
--- /dev/null
+++ b/tests/ui/coroutine/resume-arg-outlives-2.rs
@@ -0,0 +1,34 @@
+// Regression test for 132104
+
+#![feature(coroutine_trait, coroutines)]
+
+use std::ops::Coroutine;
+use std::{thread, time};
+
+fn demo<'not_static>(s: &'not_static str) -> thread::JoinHandle<()> {
+    let mut generator = Box::pin({
+        #[coroutine]
+        move |_ctx| {
+            let ctx: &'not_static str = yield;
+            yield;
+            dbg!(ctx);
+        }
+    });
+
+    // exploit:
+    generator.as_mut().resume("");
+    generator.as_mut().resume(s); // <- generator hoards it as `let ctx`.
+    //~^ ERROR borrowed data escapes outside of function
+    thread::spawn(move || {
+        thread::sleep(time::Duration::from_millis(200));
+        generator.as_mut().resume(""); // <- resumes from the last `yield`, running `dbg!(ctx)`.
+    })
+}
+
+fn main() {
+    let local = String::from("...");
+    let thread = demo(&local);
+    drop(local);
+    let _unrelated = String::from("UAF");
+    thread.join().unwrap();
+}
diff --git a/tests/ui/coroutine/resume-arg-outlives-2.stderr b/tests/ui/coroutine/resume-arg-outlives-2.stderr
new file mode 100644
index 00000000000..3d630d7e7e4
--- /dev/null
+++ b/tests/ui/coroutine/resume-arg-outlives-2.stderr
@@ -0,0 +1,17 @@
+error[E0521]: borrowed data escapes outside of function
+  --> $DIR/resume-arg-outlives-2.rs:20:5
+   |
+LL | fn demo<'not_static>(s: &'not_static str) -> thread::JoinHandle<()> {
+   |         -----------  - `s` is a reference that is only valid in the function body
+   |         |
+   |         lifetime `'not_static` defined here
+...
+LL |     generator.as_mut().resume(s); // <- generator hoards it as `let ctx`.
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     `s` escapes the function body here
+   |     argument requires that `'not_static` must outlive `'static`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0521`.
diff --git a/tests/ui/coroutine/resume-arg-outlives.rs b/tests/ui/coroutine/resume-arg-outlives.rs
new file mode 100644
index 00000000000..258be28e063
--- /dev/null
+++ b/tests/ui/coroutine/resume-arg-outlives.rs
@@ -0,0 +1,27 @@
+// Regression test for 132104
+
+#![feature(coroutine_trait, coroutines)]
+
+use std::ops::Coroutine;
+use std::pin::Pin;
+
+fn demo<'not_static>(s: &'not_static str) -> Pin<Box<impl Coroutine<&'not_static str> + 'static>> {
+    let mut generator = Box::pin({
+        #[coroutine]
+        move |ctx: &'not_static str| {
+            yield;
+            dbg!(ctx);
+        }
+    });
+    generator.as_mut().resume(s);
+    generator
+    //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {
+    let local = String::from("...");
+    let mut coro = demo(&local);
+    drop(local);
+    let _unrelated = String::from("UAF");
+    coro.as_mut().resume("");
+}
diff --git a/tests/ui/coroutine/resume-arg-outlives.stderr b/tests/ui/coroutine/resume-arg-outlives.stderr
new file mode 100644
index 00000000000..2a6337b4945
--- /dev/null
+++ b/tests/ui/coroutine/resume-arg-outlives.stderr
@@ -0,0 +1,20 @@
+error: lifetime may not live long enough
+  --> $DIR/resume-arg-outlives.rs:17:5
+   |
+LL | fn demo<'not_static>(s: &'not_static str) -> Pin<Box<impl Coroutine<&'not_static str> + 'static>> {
+   |         ----------- lifetime `'not_static` defined here
+...
+LL |     generator
+   |     ^^^^^^^^^ returning this value requires that `'not_static` must outlive `'static`
+   |
+help: consider changing `impl Coroutine<&'not_static str> + 'static`'s explicit `'static` bound to the lifetime of argument `s`
+   |
+LL | fn demo<'not_static>(s: &'not_static str) -> Pin<Box<impl Coroutine<&'not_static str> + 'not_static>> {
+   |                                                                                         ~~~~~~~~~~~
+help: alternatively, add an explicit `'static` bound to this reference
+   |
+LL | fn demo<'not_static>(s: &'static str) -> Pin<Box<impl Coroutine<&'not_static str> + 'static>> {
+   |                         ~~~~~~~~~~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/coroutine/unresolved-ct-var.stderr b/tests/ui/coroutine/unresolved-ct-var.stderr
index 8b87bac05ac..da2ec272f9f 100644
--- a/tests/ui/coroutine/unresolved-ct-var.stderr
+++ b/tests/ui/coroutine/unresolved-ct-var.stderr
@@ -8,7 +8,7 @@ LL |         let s = std::array::from_fn(|_| ()).await;
    |                 |                          help: remove the `.await`
    |                 this call returns `[(); _]`
    |
-   = help: the trait `Future` is not implemented for `[(); _]`, which is required by `[(); _]: IntoFuture`
+   = help: the trait `Future` is not implemented for `[(); _]`
    = note: [(); _] must be a future or must implement `IntoFuture` to be awaited
    = note: required for `[(); _]` to implement `IntoFuture`
 
diff --git a/tests/ui/coroutine/yield-outside-coroutine-issue-78653.stderr b/tests/ui/coroutine/yield-outside-coroutine-issue-78653.stderr
index 921e8d5d47a..b288e581d88 100644
--- a/tests/ui/coroutine/yield-outside-coroutine-issue-78653.stderr
+++ b/tests/ui/coroutine/yield-outside-coroutine-issue-78653.stderr
@@ -21,7 +21,7 @@ error[E0277]: `{integer}` is not an iterator
 LL |     yield || for i in 0 { }
    |                       ^ `{integer}` is not an iterator
    |
-   = help: the trait `Iterator` is not implemented for `{integer}`, which is required by `{integer}: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `{integer}`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
    = note: required for `{integer}` to implement `IntoIterator`
 
diff --git a/tests/ui/delegation/unsupported.stderr b/tests/ui/delegation/unsupported.stderr
index 1c79a603503..2f64d23b8d2 100644
--- a/tests/ui/delegation/unsupported.stderr
+++ b/tests/ui/delegation/unsupported.stderr
@@ -1,8 +1,3 @@
-error: using `#![feature(effects)]` without enabling next trait solver globally
-   |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
-
 error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:26:5: 26:24>::{synthetic#0}`
   --> $DIR/unsupported.rs:27:25
    |
@@ -89,7 +84,7 @@ LL |     reuse Trait::foo;
    |
    = note: cannot satisfy `_: effects::Trait`
 
-error: aborting due to 5 previous errors; 2 warnings emitted
+error: aborting due to 4 previous errors; 2 warnings emitted
 
 Some errors have detailed explanations: E0283, E0391.
 For more information about an error, try `rustc --explain E0283`.
diff --git a/tests/ui/derives/derives-span-Debug-enum-struct-variant.stderr b/tests/ui/derives/derives-span-Debug-enum-struct-variant.stderr
index b10805ac8f0..3f6c39bf939 100644
--- a/tests/ui/derives/derives-span-Debug-enum-struct-variant.stderr
+++ b/tests/ui/derives/derives-span-Debug-enum-struct-variant.stderr
@@ -7,7 +7,7 @@ LL | #[derive(Debug)]
 LL |      x: Error
    |      ^^^^^^^^ `Error` cannot be formatted using `{:?}`
    |
-   = help: the trait `Debug` is not implemented for `Error`, which is required by `&Error: Debug`
+   = help: the trait `Debug` is not implemented for `Error`
    = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error`
    = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `Error` with `#[derive(Debug)]`
diff --git a/tests/ui/derives/derives-span-Debug-enum.stderr b/tests/ui/derives/derives-span-Debug-enum.stderr
index 03297443901..eaeffaeb849 100644
--- a/tests/ui/derives/derives-span-Debug-enum.stderr
+++ b/tests/ui/derives/derives-span-Debug-enum.stderr
@@ -7,7 +7,7 @@ LL | #[derive(Debug)]
 LL |      Error
    |      ^^^^^ `Error` cannot be formatted using `{:?}`
    |
-   = help: the trait `Debug` is not implemented for `Error`, which is required by `&Error: Debug`
+   = help: the trait `Debug` is not implemented for `Error`
    = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error`
    = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `Error` with `#[derive(Debug)]`
diff --git a/tests/ui/derives/derives-span-Debug-struct.stderr b/tests/ui/derives/derives-span-Debug-struct.stderr
index 369c0b56ac4..4a725e260de 100644
--- a/tests/ui/derives/derives-span-Debug-struct.stderr
+++ b/tests/ui/derives/derives-span-Debug-struct.stderr
@@ -7,7 +7,7 @@ LL | struct Struct {
 LL |     x: Error
    |     ^^^^^^^^ `Error` cannot be formatted using `{:?}`
    |
-   = help: the trait `Debug` is not implemented for `Error`, which is required by `&Error: Debug`
+   = help: the trait `Debug` is not implemented for `Error`
    = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error`
    = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `Error` with `#[derive(Debug)]`
diff --git a/tests/ui/derives/derives-span-Debug-tuple-struct.stderr b/tests/ui/derives/derives-span-Debug-tuple-struct.stderr
index abfef9ef354..2f816e1c85b 100644
--- a/tests/ui/derives/derives-span-Debug-tuple-struct.stderr
+++ b/tests/ui/derives/derives-span-Debug-tuple-struct.stderr
@@ -7,7 +7,7 @@ LL | struct Struct(
 LL |     Error
    |     ^^^^^ `Error` cannot be formatted using `{:?}`
    |
-   = help: the trait `Debug` is not implemented for `Error`, which is required by `&Error: Debug`
+   = help: the trait `Debug` is not implemented for `Error`
    = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error`
    = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `Error` with `#[derive(Debug)]`
diff --git a/tests/ui/deriving/issue-103157.stderr b/tests/ui/deriving/issue-103157.stderr
index 612a7aff225..9754b0289c0 100644
--- a/tests/ui/deriving/issue-103157.stderr
+++ b/tests/ui/deriving/issue-103157.stderr
@@ -5,7 +5,7 @@ LL | #[derive(PartialEq, Eq)]
    |                     -- in this derive macro expansion
 ...
 LL |     Float(Option<f64>),
-   |           ^^^^^^^^^^^ the trait `Eq` is not implemented for `f64`, which is required by `Option<f64>: Eq`
+   |           ^^^^^^^^^^^ the trait `Eq` is not implemented for `f64`
    |
    = help: the following other types implement trait `Eq`:
              i128
diff --git a/tests/ui/drop/drop_order.rs b/tests/ui/drop/drop_order.rs
index 29b68d666fc..7a999c7c330 100644
--- a/tests/ui/drop/drop_order.rs
+++ b/tests/ui/drop/drop_order.rs
@@ -4,8 +4,8 @@
 //@ [edition2021] edition: 2021
 //@ [edition2024] compile-flags: -Z unstable-options
 //@ [edition2024] edition: 2024
+
 #![feature(let_chains)]
-#![cfg_attr(edition2024, feature(if_let_rescope))]
 
 use std::cell::RefCell;
 use std::convert::TryInto;
diff --git a/tests/ui/drop/drop_order_if_let_rescope.rs b/tests/ui/drop/drop_order_if_let_rescope.rs
index ae9f381820e..cea84bbaa2b 100644
--- a/tests/ui/drop/drop_order_if_let_rescope.rs
+++ b/tests/ui/drop/drop_order_if_let_rescope.rs
@@ -3,7 +3,6 @@
 //@ compile-flags: -Z validate-mir -Zunstable-options
 
 #![feature(let_chains)]
-#![feature(if_let_rescope)]
 
 use std::cell::RefCell;
 use std::convert::TryInto;
diff --git a/tests/ui/drop/if-let-rescope-borrowck-suggestions.rs b/tests/ui/drop/if-let-rescope-borrowck-suggestions.rs
index 2476f7cf258..e055c20d777 100644
--- a/tests/ui/drop/if-let-rescope-borrowck-suggestions.rs
+++ b/tests/ui/drop/if-let-rescope-borrowck-suggestions.rs
@@ -1,7 +1,6 @@
 //@ edition: 2024
 //@ compile-flags: -Z validate-mir -Zunstable-options
 
-#![feature(if_let_rescope)]
 #![deny(if_let_rescope)]
 
 struct Droppy;
diff --git a/tests/ui/drop/if-let-rescope-borrowck-suggestions.stderr b/tests/ui/drop/if-let-rescope-borrowck-suggestions.stderr
index 0c6f1ea28d2..3c87e196af6 100644
--- a/tests/ui/drop/if-let-rescope-borrowck-suggestions.stderr
+++ b/tests/ui/drop/if-let-rescope-borrowck-suggestions.stderr
@@ -1,5 +1,5 @@
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/if-let-rescope-borrowck-suggestions.rs:22:39
+  --> $DIR/if-let-rescope-borrowck-suggestions.rs:21:39
    |
 LL |     do_something(if let Some(value) = Droppy.get_ref() { value } else { &0 });
    |                                       ^^^^^^                   - temporary value is freed at the end of this statement
@@ -7,7 +7,7 @@ LL |     do_something(if let Some(value) = Droppy.get_ref() { value } else { &0
    |                                       creates a temporary value which is freed while still in use
    |
 note: lifetimes for temporaries generated in `if let`s have been shortened in Edition 2024 so that they are dropped here instead
-  --> $DIR/if-let-rescope-borrowck-suggestions.rs:22:64
+  --> $DIR/if-let-rescope-borrowck-suggestions.rs:21:64
    |
 LL |     do_something(if let Some(value) = Droppy.get_ref() { value } else { &0 });
    |                                                                ^
@@ -22,7 +22,7 @@ LL |     do_something({ match Droppy.get_ref()  { Some(value) => { value } _ =>
    |                  ~~~~~~~                   ++++++++++++++++           ~~~~       ++
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/if-let-rescope-borrowck-suggestions.rs:24:39
+  --> $DIR/if-let-rescope-borrowck-suggestions.rs:23:39
    |
 LL |     do_something(if let Some(value) = Droppy.get_ref() {
    |                                       ^^^^^^ creates a temporary value which is freed while still in use
@@ -31,7 +31,7 @@ LL |     } else if let Some(value) = Droppy.get_ref() {
    |     - temporary value is freed at the end of this statement
    |
 note: lifetimes for temporaries generated in `if let`s have been shortened in Edition 2024 so that they are dropped here instead
-  --> $DIR/if-let-rescope-borrowck-suggestions.rs:27:5
+  --> $DIR/if-let-rescope-borrowck-suggestions.rs:26:5
    |
 LL |     } else if let Some(value) = Droppy.get_ref() {
    |     ^
@@ -53,7 +53,7 @@ LL ~     }}});
    |
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/if-let-rescope-borrowck-suggestions.rs:27:33
+  --> $DIR/if-let-rescope-borrowck-suggestions.rs:26:33
    |
 LL |     } else if let Some(value) = Droppy.get_ref() {
    |                                 ^^^^^^ creates a temporary value which is freed while still in use
@@ -62,7 +62,7 @@ LL |     } else {
    |     - temporary value is freed at the end of this statement
    |
 note: lifetimes for temporaries generated in `if let`s have been shortened in Edition 2024 so that they are dropped here instead
-  --> $DIR/if-let-rescope-borrowck-suggestions.rs:30:5
+  --> $DIR/if-let-rescope-borrowck-suggestions.rs:29:5
    |
 LL |     } else {
    |     ^
diff --git a/tests/ui/drop/lint-if-let-rescope-gated.with_feature_gate.stderr b/tests/ui/drop/lint-if-let-rescope-gated.edition2021.stderr
index 48b7f3e11a6..48b7f3e11a6 100644
--- a/tests/ui/drop/lint-if-let-rescope-gated.with_feature_gate.stderr
+++ b/tests/ui/drop/lint-if-let-rescope-gated.edition2021.stderr
diff --git a/tests/ui/drop/lint-if-let-rescope-gated.rs b/tests/ui/drop/lint-if-let-rescope-gated.rs
index cef5de5a8fe..ba0246573b4 100644
--- a/tests/ui/drop/lint-if-let-rescope-gated.rs
+++ b/tests/ui/drop/lint-if-let-rescope-gated.rs
@@ -1,13 +1,13 @@
 // This test checks that the lint `if_let_rescope` only actions
-// when the feature gate is enabled.
-// Edition 2021 is used here because the lint should work especially
-// when edition migration towards 2024 is run.
+// when Edition 2021 or prior is targeted here because the lint should work especially
+// when edition migration towards 2024 is executed.
 
-//@ revisions: with_feature_gate without_feature_gate
-//@ [without_feature_gate] check-pass
-//@ edition: 2021
+//@ revisions: edition2021 edition2024
+//@ [edition2021] edition: 2021
+//@ [edition2024] edition: 2024
+//@ [edition2024] compile-flags: -Zunstable-options
+//@ [edition2024] check-pass
 
-#![cfg_attr(with_feature_gate, feature(if_let_rescope))]
 #![deny(if_let_rescope)]
 #![allow(irrefutable_let_patterns)]
 
@@ -25,10 +25,10 @@ impl Droppy {
 
 fn main() {
     if let Some(_value) = Droppy.get() {
-        //[with_feature_gate]~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024
-        //[with_feature_gate]~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021
-        //[with_feature_gate]~| WARN: this changes meaning in Rust 2024
+        //[edition2021]~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024
+        //[edition2021]~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021
+        //[edition2021]~| WARN: this changes meaning in Rust 2024
     } else {
-        //[with_feature_gate]~^ HELP: the value is now dropped here in Edition 2024
+        //[edition2021]~^ HELP: the value is now dropped here in Edition 2024
     }
 }
diff --git a/tests/ui/drop/lint-if-let-rescope-with-macro.rs b/tests/ui/drop/lint-if-let-rescope-with-macro.rs
index 282b3320d30..e7aeb81f4d1 100644
--- a/tests/ui/drop/lint-if-let-rescope-with-macro.rs
+++ b/tests/ui/drop/lint-if-let-rescope-with-macro.rs
@@ -4,7 +4,6 @@
 //@ edition:2021
 //@ compile-flags: -Z unstable-options
 
-#![feature(if_let_rescope)]
 #![deny(if_let_rescope)]
 #![allow(irrefutable_let_patterns)]
 
diff --git a/tests/ui/drop/lint-if-let-rescope-with-macro.stderr b/tests/ui/drop/lint-if-let-rescope-with-macro.stderr
index 5fd0c61d17a..de6cf6e8500 100644
--- a/tests/ui/drop/lint-if-let-rescope-with-macro.stderr
+++ b/tests/ui/drop/lint-if-let-rescope-with-macro.stderr
@@ -1,5 +1,5 @@
 error: `if let` assigns a shorter lifetime since Edition 2024
-  --> $DIR/lint-if-let-rescope-with-macro.rs:13:12
+  --> $DIR/lint-if-let-rescope-with-macro.rs:12:12
    |
 LL |           if let $p = $e { $($conseq)* } else { $($alt)* }
    |              ^^^
@@ -16,7 +16,7 @@ LL | |     };
    = warning: this changes meaning in Rust 2024
    = note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085>
 help: the value is now dropped here in Edition 2024
-  --> $DIR/lint-if-let-rescope-with-macro.rs:13:38
+  --> $DIR/lint-if-let-rescope-with-macro.rs:12:38
    |
 LL |           if let $p = $e { $($conseq)* } else { $($alt)* }
    |                                        ^
@@ -29,7 +29,7 @@ LL | |         {}
 LL | |     };
    | |_____- in this macro invocation
 note: the lint level is defined here
-  --> $DIR/lint-if-let-rescope-with-macro.rs:8:9
+  --> $DIR/lint-if-let-rescope-with-macro.rs:7:9
    |
 LL | #![deny(if_let_rescope)]
    |         ^^^^^^^^^^^^^^
diff --git a/tests/ui/drop/lint-if-let-rescope.fixed b/tests/ui/drop/lint-if-let-rescope.fixed
index 199068d0fd2..fec2e3b2ae7 100644
--- a/tests/ui/drop/lint-if-let-rescope.fixed
+++ b/tests/ui/drop/lint-if-let-rescope.fixed
@@ -1,7 +1,7 @@
 //@ run-rustfix
 
 #![deny(if_let_rescope)]
-#![feature(if_let_rescope, stmt_expr_attributes)]
+#![feature(stmt_expr_attributes)]
 #![allow(irrefutable_let_patterns, unused_parens)]
 
 fn droppy() -> Droppy {
diff --git a/tests/ui/drop/lint-if-let-rescope.rs b/tests/ui/drop/lint-if-let-rescope.rs
index 4c043c0266c..ee184695b97 100644
--- a/tests/ui/drop/lint-if-let-rescope.rs
+++ b/tests/ui/drop/lint-if-let-rescope.rs
@@ -1,7 +1,7 @@
 //@ run-rustfix
 
 #![deny(if_let_rescope)]
-#![feature(if_let_rescope, stmt_expr_attributes)]
+#![feature(stmt_expr_attributes)]
 #![allow(irrefutable_let_patterns, unused_parens)]
 
 fn droppy() -> Droppy {
diff --git a/tests/ui/dropck/const_drop_is_valid.stderr b/tests/ui/dropck/const_drop_is_valid.stderr
index f15b7ba946d..2383a6668a8 100644
--- a/tests/ui/dropck/const_drop_is_valid.stderr
+++ b/tests/ui/dropck/const_drop_is_valid.stderr
@@ -17,11 +17,6 @@ LL | #![feature(effects)]
    = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
    = note: `#[warn(incomplete_features)]` on by default
 
-error: using `#![feature(effects)]` without enabling next trait solver globally
-   |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
-
 error: const `impl` for trait `Drop` which is not marked with `#[const_trait]`
   --> $DIR/const_drop_is_valid.rs:6:12
    |
@@ -39,7 +34,7 @@ LL | impl const Drop for A {}
    |
    = help: implement the missing item: `fn drop(&mut self) { todo!() }`
 
-error: aborting due to 4 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors; 1 warning emitted
 
 Some errors have detailed explanations: E0046, E0658.
 For more information about an error, try `rustc --explain E0046`.
diff --git a/tests/ui/dst/dst-bad-deep-2.stderr b/tests/ui/dst/dst-bad-deep-2.stderr
index 554e81bee10..c7e9854340f 100644
--- a/tests/ui/dst/dst-bad-deep-2.stderr
+++ b/tests/ui/dst/dst-bad-deep-2.stderr
@@ -4,7 +4,7 @@ error[E0277]: the size for values of type `[isize]` cannot be known at compilati
 LL |     let h: &(([isize],),) = &(*g,);
    |                              ^^^^^ doesn't have a size known at compile-time
    |
-   = help: within `(([isize],),)`, the trait `Sized` is not implemented for `[isize]`, which is required by `(([isize],),): Sized`
+   = help: within `(([isize],),)`, the trait `Sized` is not implemented for `[isize]`
    = note: required because it appears within the type `([isize],)`
    = note: required because it appears within the type `(([isize],),)`
    = note: tuples must have a statically known size to be initialized
diff --git a/tests/ui/dst/dst-bad-deep.stderr b/tests/ui/dst/dst-bad-deep.stderr
index 4f180e593f8..1b0f9738ab0 100644
--- a/tests/ui/dst/dst-bad-deep.stderr
+++ b/tests/ui/dst/dst-bad-deep.stderr
@@ -4,7 +4,7 @@ error[E0277]: the size for values of type `[isize]` cannot be known at compilati
 LL |     let h: &Fat<Fat<[isize]>> = &Fat { ptr: *g };
    |                                  ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = help: within `Fat<Fat<[isize]>>`, the trait `Sized` is not implemented for `[isize]`, which is required by `Fat<Fat<[isize]>>: Sized`
+   = help: within `Fat<Fat<[isize]>>`, the trait `Sized` is not implemented for `[isize]`
 note: required because it appears within the type `Fat<[isize]>`
   --> $DIR/dst-bad-deep.rs:6:8
    |
diff --git a/tests/ui/editions/edition-keywords-2015-2015-parsing.rs b/tests/ui/editions/edition-keywords-2015-2015-parsing.rs
index 07104bdf217..4751d280467 100644
--- a/tests/ui/editions/edition-keywords-2015-2015-parsing.rs
+++ b/tests/ui/editions/edition-keywords-2015-2015-parsing.rs
@@ -13,8 +13,8 @@ pub fn check_async() {
     let mut r#async = 1; // OK
 
     r#async = consumes_async!(async); // OK
-    r#async = consumes_async!(r#async); //~ ERROR no rules expected the token `r#async`
-    r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async`
+    r#async = consumes_async!(r#async); //~ ERROR no rules expected `r#async`
+    r#async = consumes_async_raw!(async); //~ ERROR no rules expected `async`
     r#async = consumes_async_raw!(r#async); // OK
 
     if passes_ident!(async) == 1 {} // OK
diff --git a/tests/ui/editions/edition-keywords-2015-2015-parsing.stderr b/tests/ui/editions/edition-keywords-2015-2015-parsing.stderr
index 39944622d07..2519a9fded2 100644
--- a/tests/ui/editions/edition-keywords-2015-2015-parsing.stderr
+++ b/tests/ui/editions/edition-keywords-2015-2015-parsing.stderr
@@ -1,4 +1,4 @@
-error: no rules expected the token `r#async`
+error: no rules expected `r#async`
   --> $DIR/edition-keywords-2015-2015-parsing.rs:16:31
    |
 LL |     r#async = consumes_async!(r#async);
@@ -10,7 +10,7 @@ note: while trying to match `async`
 LL |     (async) => (1)
    |      ^^^^^
 
-error: no rules expected the token `async`
+error: no rules expected `async`
   --> $DIR/edition-keywords-2015-2015-parsing.rs:17:35
    |
 LL |     r#async = consumes_async_raw!(async);
diff --git a/tests/ui/editions/edition-keywords-2015-2018-parsing.rs b/tests/ui/editions/edition-keywords-2015-2018-parsing.rs
index 3c294f95cd2..4404ea26fb3 100644
--- a/tests/ui/editions/edition-keywords-2015-2018-parsing.rs
+++ b/tests/ui/editions/edition-keywords-2015-2018-parsing.rs
@@ -13,8 +13,8 @@ pub fn check_async() {
     let mut r#async = 1; // OK
 
     r#async = consumes_async!(async); // OK
-    r#async = consumes_async!(r#async); //~ ERROR no rules expected the token `r#async`
-    r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async`
+    r#async = consumes_async!(r#async); //~ ERROR no rules expected `r#async`
+    r#async = consumes_async_raw!(async); //~ ERROR no rules expected `async`
     r#async = consumes_async_raw!(r#async); // OK
 
     if passes_ident!(async) == 1 {} // OK
diff --git a/tests/ui/editions/edition-keywords-2015-2018-parsing.stderr b/tests/ui/editions/edition-keywords-2015-2018-parsing.stderr
index fa83908e666..0c0e5738415 100644
--- a/tests/ui/editions/edition-keywords-2015-2018-parsing.stderr
+++ b/tests/ui/editions/edition-keywords-2015-2018-parsing.stderr
@@ -1,4 +1,4 @@
-error: no rules expected the token `r#async`
+error: no rules expected `r#async`
   --> $DIR/edition-keywords-2015-2018-parsing.rs:16:31
    |
 LL |     r#async = consumes_async!(r#async);
@@ -10,7 +10,7 @@ note: while trying to match `async`
 LL |     (async) => (1)
    |      ^^^^^
 
-error: no rules expected the token `async`
+error: no rules expected `async`
   --> $DIR/edition-keywords-2015-2018-parsing.rs:17:35
    |
 LL |     r#async = consumes_async_raw!(async);
diff --git a/tests/ui/editions/edition-keywords-2018-2015-parsing.rs b/tests/ui/editions/edition-keywords-2018-2015-parsing.rs
index 59184543274..c346be50856 100644
--- a/tests/ui/editions/edition-keywords-2018-2015-parsing.rs
+++ b/tests/ui/editions/edition-keywords-2018-2015-parsing.rs
@@ -17,8 +17,8 @@ pub fn check_async() {
     let mut r#async = 1; // OK
 
     r#async = consumes_async!(async); // OK
-    r#async = consumes_async!(r#async); //~ ERROR no rules expected the token `r#async`
-    r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async`
+    r#async = consumes_async!(r#async); //~ ERROR no rules expected `r#async`
+    r#async = consumes_async_raw!(async); //~ ERROR no rules expected keyword `async`
     r#async = consumes_async_raw!(r#async); // OK
 
     if passes_ident!(async) == 1 {} // FIXME: Edition hygiene bug, async here is 2018 and reserved
diff --git a/tests/ui/editions/edition-keywords-2018-2015-parsing.stderr b/tests/ui/editions/edition-keywords-2018-2015-parsing.stderr
index 42db75f6659..aed5837abea 100644
--- a/tests/ui/editions/edition-keywords-2018-2015-parsing.stderr
+++ b/tests/ui/editions/edition-keywords-2018-2015-parsing.stderr
@@ -20,19 +20,19 @@ help: escape `async` to use it as an identifier
 LL |     module::r#async();
    |             ++
 
-error: no rules expected the token `r#async`
+error: no rules expected `r#async`
   --> $DIR/edition-keywords-2018-2015-parsing.rs:20:31
    |
 LL |     r#async = consumes_async!(r#async);
    |                               ^^^^^^^ no rules expected this token in macro call
    |
-note: while trying to match `async`
+note: while trying to match keyword `async`
   --> $DIR/auxiliary/edition-kw-macro-2015.rs:17:6
    |
 LL |     (async) => (1)
    |      ^^^^^
 
-error: no rules expected the token `async`
+error: no rules expected keyword `async`
   --> $DIR/edition-keywords-2018-2015-parsing.rs:21:35
    |
 LL |     r#async = consumes_async_raw!(async);
diff --git a/tests/ui/editions/edition-keywords-2018-2018-parsing.rs b/tests/ui/editions/edition-keywords-2018-2018-parsing.rs
index 4975246fa94..b75b68b3feb 100644
--- a/tests/ui/editions/edition-keywords-2018-2018-parsing.rs
+++ b/tests/ui/editions/edition-keywords-2018-2018-parsing.rs
@@ -24,8 +24,8 @@ pub fn check_async() {
     let mut r#async = 1; // OK
 
     r#async = consumes_async!(async); // OK
-    r#async = consumes_async!(r#async); //~ ERROR no rules expected the token `r#async`
-    r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async`
+    r#async = consumes_async!(r#async); //~ ERROR no rules expected `r#async`
+    r#async = consumes_async_raw!(async); //~ ERROR no rules expected keyword `async`
     r#async = consumes_async_raw!(r#async); // OK
 
     if passes_ident!(async) == 1 {} // FIXME: Edition hygiene bug, async here is 2018 and reserved
diff --git a/tests/ui/editions/edition-keywords-2018-2018-parsing.stderr b/tests/ui/editions/edition-keywords-2018-2018-parsing.stderr
index 4bbe1597233..6503e9cc73c 100644
--- a/tests/ui/editions/edition-keywords-2018-2018-parsing.stderr
+++ b/tests/ui/editions/edition-keywords-2018-2018-parsing.stderr
@@ -20,19 +20,19 @@ help: escape `async` to use it as an identifier
 LL |     module::r#async();
    |             ++
 
-error: no rules expected the token `r#async`
+error: no rules expected `r#async`
   --> $DIR/edition-keywords-2018-2018-parsing.rs:27:31
    |
 LL |     r#async = consumes_async!(r#async);
    |                               ^^^^^^^ no rules expected this token in macro call
    |
-note: while trying to match `async`
+note: while trying to match keyword `async`
   --> $DIR/auxiliary/edition-kw-macro-2018.rs:17:6
    |
 LL |     (async) => (1)
    |      ^^^^^
 
-error: no rules expected the token `async`
+error: no rules expected keyword `async`
   --> $DIR/edition-keywords-2018-2018-parsing.rs:28:35
    |
 LL |     r#async = consumes_async_raw!(async);
diff --git a/tests/ui/error-codes/E0277-2.stderr b/tests/ui/error-codes/E0277-2.stderr
index f4e18e3bb53..9a262f75590 100644
--- a/tests/ui/error-codes/E0277-2.stderr
+++ b/tests/ui/error-codes/E0277-2.stderr
@@ -4,7 +4,7 @@ error[E0277]: `*const u8` cannot be sent between threads safely
 LL |     is_send::<Foo>();
    |               ^^^ `*const u8` cannot be sent between threads safely
    |
-   = help: within `Foo`, the trait `Send` is not implemented for `*const u8`, which is required by `Foo: Send`
+   = help: within `Foo`, the trait `Send` is not implemented for `*const u8`
 note: required because it appears within the type `Baz`
   --> $DIR/E0277-2.rs:9:8
    |
diff --git a/tests/ui/error-codes/E0277.stderr b/tests/ui/error-codes/E0277.stderr
index 52ada36574e..a9ae8971df4 100644
--- a/tests/ui/error-codes/E0277.stderr
+++ b/tests/ui/error-codes/E0277.stderr
@@ -4,7 +4,7 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation
 LL | fn f(p: Path) { }
    |         ^^^^ doesn't have a size known at compile-time
    |
-   = help: within `Path`, the trait `Sized` is not implemented for `[u8]`, which is required by `Path: Sized`
+   = help: within `Path`, the trait `Sized` is not implemented for `[u8]`
 note: required because it appears within the type `Path`
   --> $SRC_DIR/std/src/path.rs:LL:COL
    = help: unsized fn params are gated as an unstable feature
diff --git a/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr
index bd4e9348227..9228a047e87 100644
--- a/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr
+++ b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied
   --> $DIR/blame-trait-error.rs:53:46
    |
 LL |     want(Wrapper { value: Burrito { filling: q } });
-   |     ----                                     ^ the trait `T3` is not implemented for `Q`, which is required by `Wrapper<Burrito<Q>>: T1`
+   |     ----                                     ^ the trait `T3` is not implemented for `Q`
    |     |
    |     required by a bound introduced by this call
    |
@@ -38,7 +38,7 @@ LL |     want(Some(()));
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `Iterator` is not implemented for `()`, which is required by `Option<()>: T1`
+   = help: the trait `Iterator` is not implemented for `()`
    = help: the trait `T1` is implemented for `Option<It>`
 note: required for `Option<()>` to implement `T1`
   --> $DIR/blame-trait-error.rs:21:20
@@ -109,7 +109,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied
   --> $DIR/blame-trait-error.rs:65:45
    |
 LL |     want(&ExampleTuple::ExampleTupleVariant(q));
-   |     ----                                    ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleTuple<Q>: T1`
+   |     ----                                    ^ the trait `T3` is not implemented for `Q`
    |     |
    |     required by a bound introduced by this call
    |
@@ -134,7 +134,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied
   --> $DIR/blame-trait-error.rs:68:31
    |
 LL |     want(&ExampleTupleVariant(q));
-   |     ----                      ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleTuple<Q>: T1`
+   |     ----                      ^ the trait `T3` is not implemented for `Q`
    |     |
    |     required by a bound introduced by this call
    |
@@ -159,7 +159,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied
   --> $DIR/blame-trait-error.rs:71:50
    |
 LL |     want(&ExampleOtherTuple::ExampleTupleVariant(q));
-   |     ----                                         ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleTuple<Q>: T1`
+   |     ----                                         ^ the trait `T3` is not implemented for `Q`
    |     |
    |     required by a bound introduced by this call
    |
@@ -184,7 +184,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied
   --> $DIR/blame-trait-error.rs:74:44
    |
 LL |     want(&ExampleDifferentTupleVariantName(q));
-   |     ----                                   ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleTuple<Q>: T1`
+   |     ----                                   ^ the trait `T3` is not implemented for `Q`
    |     |
    |     required by a bound introduced by this call
    |
@@ -209,7 +209,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied
   --> $DIR/blame-trait-error.rs:77:45
    |
 LL |     want(&ExampleYetAnotherTupleVariantName(q));
-   |     ----                                    ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleTuple<Q>: T1`
+   |     ----                                    ^ the trait `T3` is not implemented for `Q`
    |     |
    |     required by a bound introduced by this call
    |
@@ -234,7 +234,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied
   --> $DIR/blame-trait-error.rs:80:56
    |
 LL |     want(&ExampleStruct::ExampleStructVariant { field: q });
-   |     ---- required by a bound introduced by this call   ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleStruct<Q>: T1`
+   |     ---- required by a bound introduced by this call   ^ the trait `T3` is not implemented for `Q`
    |
 note: required for `ExampleStruct<Q>` to implement `T1`
   --> $DIR/blame-trait-error.rs:45:9
@@ -257,7 +257,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied
   --> $DIR/blame-trait-error.rs:83:41
    |
 LL |     want(&ExampleStructVariant { field: q });
-   |     ----                                ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleStruct<Q>: T1`
+   |     ----                                ^ the trait `T3` is not implemented for `Q`
    |     |
    |     required by a bound introduced by this call
    |
@@ -282,7 +282,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied
   --> $DIR/blame-trait-error.rs:86:61
    |
 LL |     want(&ExampleOtherStruct::ExampleStructVariant { field: q });
-   |     ---- required by a bound introduced by this call        ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleStruct<Q>: T1`
+   |     ---- required by a bound introduced by this call        ^ the trait `T3` is not implemented for `Q`
    |
 note: required for `ExampleStruct<Q>` to implement `T1`
   --> $DIR/blame-trait-error.rs:45:9
@@ -305,7 +305,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied
   --> $DIR/blame-trait-error.rs:89:54
    |
 LL |     want(&ExampleDifferentStructVariantName { field: q });
-   |     ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleStruct<Q>: T1`
+   |     ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`
    |
 note: required for `ExampleStruct<Q>` to implement `T1`
   --> $DIR/blame-trait-error.rs:45:9
@@ -328,7 +328,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied
   --> $DIR/blame-trait-error.rs:92:55
    |
 LL |     want(&ExampleYetAnotherStructVariantName { field: q });
-   |     ---- required by a bound introduced by this call  ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleStruct<Q>: T1`
+   |     ---- required by a bound introduced by this call  ^ the trait `T3` is not implemented for `Q`
    |
 note: required for `ExampleStruct<Q>` to implement `T1`
   --> $DIR/blame-trait-error.rs:45:9
@@ -351,7 +351,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied
   --> $DIR/blame-trait-error.rs:95:38
    |
 LL |     want(&ExampleActuallyTupleStruct(q, 0));
-   |     ----                             ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleActuallyTupleStruct<Q>: T1`
+   |     ----                             ^ the trait `T3` is not implemented for `Q`
    |     |
    |     required by a bound introduced by this call
    |
@@ -376,7 +376,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied
   --> $DIR/blame-trait-error.rs:98:43
    |
 LL |     want(&ExampleActuallyTupleStructOther(q, 0));
-   |     ----                                  ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleActuallyTupleStruct<Q>: T1`
+   |     ----                                  ^ the trait `T3` is not implemented for `Q`
    |     |
    |     required by a bound introduced by this call
    |
diff --git a/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr b/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr
index a2df6843f43..b6a24e12bcc 100644
--- a/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr
+++ b/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied
   --> $DIR/blame-trait-error-spans-on-exprs.rs:81:60
    |
 LL |     want(Wrapper { value: Burrito { spicy: false, filling: q } });
-   |     ---- required by a bound introduced by this call       ^ the trait `T3` is not implemented for `Q`, which is required by `Wrapper<Burrito<Q>>: T1`
+   |     ---- required by a bound introduced by this call       ^ the trait `T3` is not implemented for `Q`
    |
 note: required for `Burrito<Q>` to implement `T2`
   --> $DIR/blame-trait-error-spans-on-exprs.rs:22:13
@@ -32,7 +32,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied
   --> $DIR/blame-trait-error-spans-on-exprs.rs:85:84
    |
 LL |     want(Wrapper { value: BurritoKinds::SmallBurrito { spicy: true, small_filling: q } });
-   |     ---- required by a bound introduced by this call                               ^ the trait `T3` is not implemented for `Q`, which is required by `Wrapper<BurritoKinds<Q>>: T1`
+   |     ---- required by a bound introduced by this call                               ^ the trait `T3` is not implemented for `Q`
    |
 note: required for `BurritoKinds<Q>` to implement `T2`
   --> $DIR/blame-trait-error-spans-on-exprs.rs:32:13
@@ -62,7 +62,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied
   --> $DIR/blame-trait-error-spans-on-exprs.rs:89:39
    |
 LL |     want(Wrapper { value: Taco(false, q) });
-   |     ----                              ^ the trait `T3` is not implemented for `Q`, which is required by `Wrapper<Taco<Q>>: T1`
+   |     ----                              ^ the trait `T3` is not implemented for `Q`
    |     |
    |     required by a bound introduced by this call
    |
@@ -94,7 +94,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied
   --> $DIR/blame-trait-error-spans-on-exprs.rs:93:53
    |
 LL |     want(Wrapper { value: TacoKinds::OneTaco(false, q) });
-   |     ----                                            ^ the trait `T3` is not implemented for `Q`, which is required by `Wrapper<TacoKinds<Q>>: T1`
+   |     ----                                            ^ the trait `T3` is not implemented for `Q`
    |     |
    |     required by a bound introduced by this call
    |
@@ -126,7 +126,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied
   --> $DIR/blame-trait-error-spans-on-exprs.rs:97:74
    |
 LL |     want(Wrapper { value: GenericBurrito { spiciness: NotSpicy, filling: q } });
-   |     ---- required by a bound introduced by this call                     ^ the trait `T3` is not implemented for `Q`, which is required by `Wrapper<GenericBurrito<NotSpicy, Q>>: T1`
+   |     ---- required by a bound introduced by this call                     ^ the trait `T3` is not implemented for `Q`
    |
 note: required for `GenericBurrito<NotSpicy, Q>` to implement `T2`
   --> $DIR/blame-trait-error-spans-on-exprs.rs:47:16
@@ -156,7 +156,7 @@ error[E0277]: the trait bound `Q: T2` is not satisfied
   --> $DIR/blame-trait-error-spans-on-exprs.rs:101:14
    |
 LL |     want((3, q));
-   |     ----     ^ the trait `T2` is not implemented for `Q`, which is required by `({integer}, Q): T1`
+   |     ----     ^ the trait `T2` is not implemented for `Q`
    |     |
    |     required by a bound introduced by this call
    |
@@ -181,7 +181,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied
   --> $DIR/blame-trait-error-spans-on-exprs.rs:105:31
    |
 LL |     want(Wrapper { value: (3, q) });
-   |     ----                      ^ the trait `T3` is not implemented for `Q`, which is required by `Wrapper<({integer}, Q)>: T1`
+   |     ----                      ^ the trait `T3` is not implemented for `Q`
    |     |
    |     required by a bound introduced by this call
    |
@@ -213,7 +213,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied
   --> $DIR/blame-trait-error-spans-on-exprs.rs:109:15
    |
 LL |     want(((3, q), 5));
-   |     ----      ^ the trait `T3` is not implemented for `Q`, which is required by `(({integer}, Q), {integer}): T1`
+   |     ----      ^ the trait `T3` is not implemented for `Q`
    |     |
    |     required by a bound introduced by this call
    |
@@ -245,7 +245,7 @@ error[E0277]: the trait bound `Q: T1` is not satisfied
   --> $DIR/blame-trait-error-spans-on-exprs.rs:112:49
    |
 LL |     want(DoubleWrapper { item: Wrapper { value: q } });
-   |     ----                                        ^ the trait `T1` is not implemented for `Q`, which is required by `DoubleWrapper<Q>: T1`
+   |     ----                                        ^ the trait `T1` is not implemented for `Q`
    |     |
    |     required by a bound introduced by this call
    |
@@ -270,7 +270,7 @@ error[E0277]: the trait bound `Q: T1` is not satisfied
   --> $DIR/blame-trait-error-spans-on-exprs.rs:115:88
    |
 LL |     want(DoubleWrapper { item: Wrapper { value: DoubleWrapper { item: Wrapper { value: q } } } });
-   |     ---- required by a bound introduced by this call                                   ^ the trait `T1` is not implemented for `Q`, which is required by `DoubleWrapper<DoubleWrapper<Q>>: T1`
+   |     ---- required by a bound introduced by this call                                   ^ the trait `T1` is not implemented for `Q`
    |
 note: required for `DoubleWrapper<Q>` to implement `T1`
   --> $DIR/blame-trait-error-spans-on-exprs.rs:72:13
@@ -295,7 +295,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied
   --> $DIR/blame-trait-error-spans-on-exprs.rs:119:27
    |
 LL |     want(Wrapper { value: AliasBurrito { spiciness: q, filling: q } });
-   |     ----                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `T3` is not implemented for `Q`, which is required by `Wrapper<GenericBurrito<Q, Q>>: T1`
+   |     ----                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `T3` is not implemented for `Q`
    |     |
    |     required by a bound introduced by this call
    |
@@ -327,7 +327,7 @@ error[E0277]: the trait bound `Q: T1` is not satisfied
   --> $DIR/blame-trait-error-spans-on-exprs.rs:122:35
    |
 LL |     want(Two { a: Two { a: (), b: q }, b: () });
-   |     ----                          ^ the trait `T1` is not implemented for `Q`, which is required by `Two<Two<(), Q>, ()>: T1`
+   |     ----                          ^ the trait `T1` is not implemented for `Q`
    |     |
    |     required by a bound introduced by this call
    |
@@ -354,7 +354,7 @@ error[E0277]: the trait bound `Q: T1` is not satisfied
 LL |     want(
    |     ---- required by a bound introduced by this call
 LL |         Two { a: Two { a: (), b: Two { a: Two { a: (), b: q }, b: () } }, b: () },
-   |                                                           ^ the trait `T1` is not implemented for `Q`, which is required by `Two<Two<(), Two<Two<(), Q>, ()>>, ()>: T1`
+   |                                                           ^ the trait `T1` is not implemented for `Q`
    |
 note: required for `Two<Two<(), Q>, ()>` to implement `T1`
   --> $DIR/blame-trait-error-spans-on-exprs.rs:66:19
@@ -379,7 +379,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied
   --> $DIR/blame-trait-error-spans-on-exprs.rs:133:44
    |
 LL |     want(&Burrito { spicy: false, filling: q });
-   |     ----                                   ^ the trait `T3` is not implemented for `Q`, which is required by `&Burrito<Q>: T1`
+   |     ----                                   ^ the trait `T3` is not implemented for `Q`
    |     |
    |     required by a bound introduced by this call
    |
diff --git a/tests/ui/extern/extern-types-unsized.stderr b/tests/ui/extern/extern-types-unsized.stderr
index 7428e6a60b5..a587d4dda55 100644
--- a/tests/ui/extern/extern-types-unsized.stderr
+++ b/tests/ui/extern/extern-types-unsized.stderr
@@ -21,7 +21,7 @@ error[E0277]: the size for values of type `A` cannot be known at compilation tim
 LL |     assert_sized::<Foo>();
    |                    ^^^ doesn't have a size known at compile-time
    |
-   = help: within `Foo`, the trait `Sized` is not implemented for `A`, which is required by `Foo: Sized`
+   = help: within `Foo`, the trait `Sized` is not implemented for `A`
 note: required because it appears within the type `Foo`
   --> $DIR/extern-types-unsized.rs:9:8
    |
@@ -43,7 +43,7 @@ error[E0277]: the size for values of type `A` cannot be known at compilation tim
 LL |     assert_sized::<Bar<A>>();
    |                    ^^^^^^ doesn't have a size known at compile-time
    |
-   = help: within `Bar<A>`, the trait `Sized` is not implemented for `A`, which is required by `Bar<A>: Sized`
+   = help: within `Bar<A>`, the trait `Sized` is not implemented for `A`
 note: required because it appears within the type `Bar<A>`
   --> $DIR/extern-types-unsized.rs:14:8
    |
@@ -65,7 +65,7 @@ error[E0277]: the size for values of type `A` cannot be known at compilation tim
 LL |     assert_sized::<Bar<Bar<A>>>();
    |                    ^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = help: within `Bar<Bar<A>>`, the trait `Sized` is not implemented for `A`, which is required by `Bar<Bar<A>>: Sized`
+   = help: within `Bar<Bar<A>>`, the trait `Sized` is not implemented for `A`
 note: required because it appears within the type `Bar<A>`
   --> $DIR/extern-types-unsized.rs:14:8
    |
diff --git a/tests/ui/fail-simple.rs b/tests/ui/fail-simple.rs
index cd81a5d0a0f..55e547ee72b 100644
--- a/tests/ui/fail-simple.rs
+++ b/tests/ui/fail-simple.rs
@@ -1,3 +1,3 @@
 fn main() {
-    panic!(@); //~ ERROR no rules expected the token `@`
+    panic!(@); //~ ERROR no rules expected `@`
 }
diff --git a/tests/ui/fail-simple.stderr b/tests/ui/fail-simple.stderr
index 39fec3e2517..50c350b3ef5 100644
--- a/tests/ui/fail-simple.stderr
+++ b/tests/ui/fail-simple.stderr
@@ -1,4 +1,4 @@
-error: no rules expected the token `@`
+error: no rules expected `@`
   --> $DIR/fail-simple.rs:2:12
    |
 LL |     panic!(@);
diff --git a/tests/ui/feature-gates/feature-gate-if-let-rescope.rs b/tests/ui/feature-gates/feature-gate-if-let-rescope.rs
deleted file mode 100644
index bd1efd4fb7c..00000000000
--- a/tests/ui/feature-gates/feature-gate-if-let-rescope.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-// This test shows the code that could have been accepted by enabling #![feature(if_let_rescope)]
-
-struct A;
-struct B<'a, T>(&'a mut T);
-
-impl A {
-    fn f(&mut self) -> Option<B<'_, Self>> {
-        Some(B(self))
-    }
-}
-
-impl<'a, T> Drop for B<'a, T> {
-    fn drop(&mut self) {
-        // this is needed to keep NLL's hands off and to ensure
-        // the inner mutable borrow stays alive
-    }
-}
-
-fn main() {
-    let mut a = A;
-    if let None = a.f().as_ref() {
-        unreachable!()
-    } else {
-        a.f().unwrap();
-        //~^ ERROR cannot borrow `a` as mutable more than once at a time
-    };
-}
diff --git a/tests/ui/feature-gates/feature-gate-if-let-rescope.stderr b/tests/ui/feature-gates/feature-gate-if-let-rescope.stderr
deleted file mode 100644
index ff1846ae0b1..00000000000
--- a/tests/ui/feature-gates/feature-gate-if-let-rescope.stderr
+++ /dev/null
@@ -1,18 +0,0 @@
-error[E0499]: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/feature-gate-if-let-rescope.rs:24:9
-   |
-LL |     if let None = a.f().as_ref() {
-   |                   -----
-   |                   |
-   |                   first mutable borrow occurs here
-   |                   a temporary with access to the first borrow is created here ...
-...
-LL |         a.f().unwrap();
-   |         ^ second mutable borrow occurs here
-LL |
-LL |     };
-   |      - ... and the first borrow might be used here, when that temporary is dropped and runs the destructor for type `Option<B<'_, A>>`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0499`.
diff --git a/tests/ui/feature-gates/feature-gate-offset-of-slice.stderr b/tests/ui/feature-gates/feature-gate-offset-of-slice.stderr
index 5cf34a897f4..ae8d50344d5 100644
--- a/tests/ui/feature-gates/feature-gate-offset-of-slice.stderr
+++ b/tests/ui/feature-gates/feature-gate-offset-of-slice.stderr
@@ -13,7 +13,7 @@ error[E0277]: the size for values of type `[i32]` cannot be known at compilation
 LL |     offset_of!(T, y);
    |     ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = help: within `S`, the trait `Sized` is not implemented for `[i32]`, which is required by `S: Sized`
+   = help: within `S`, the trait `Sized` is not implemented for `[i32]`
 note: required because it appears within the type `S`
   --> $DIR/feature-gate-offset-of-slice.rs:3:8
    |
diff --git a/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr b/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr
index 0ee2d93fb26..7d9c5b81651 100644
--- a/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr
+++ b/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr
@@ -120,7 +120,7 @@ error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at
 LL | fn unsized_local() where Dst<dyn A>: Sized {
    |                          ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = help: within `Dst<(dyn A + 'static)>`, the trait `Sized` is not implemented for `(dyn A + 'static)`, which is required by `Dst<(dyn A + 'static)>: Sized`
+   = help: within `Dst<(dyn A + 'static)>`, the trait `Sized` is not implemented for `(dyn A + 'static)`
 note: required because it appears within the type `Dst<(dyn A + 'static)>`
   --> $DIR/feature-gate-trivial_bounds.rs:48:8
    |
diff --git a/tests/ui/fmt/ifmt-unimpl.stderr b/tests/ui/fmt/ifmt-unimpl.stderr
index f83e7c87728..b8d4425a4a7 100644
--- a/tests/ui/fmt/ifmt-unimpl.stderr
+++ b/tests/ui/fmt/ifmt-unimpl.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `str: UpperHex` is not satisfied
   --> $DIR/ifmt-unimpl.rs:2:21
    |
 LL |     format!("{:X}", "3");
-   |              ----   ^^^ the trait `UpperHex` is not implemented for `str`, which is required by `&str: UpperHex`
+   |              ----   ^^^ the trait `UpperHex` is not implemented for `str`
    |              |
    |              required by a bound introduced by this call
    |
diff --git a/tests/ui/for/for-c-in-str.stderr b/tests/ui/for/for-c-in-str.stderr
index 2544df64629..475cf8c8874 100644
--- a/tests/ui/for/for-c-in-str.stderr
+++ b/tests/ui/for/for-c-in-str.stderr
@@ -4,7 +4,7 @@ error[E0277]: `&str` is not an iterator
 LL |     for c in "asdf" {
    |              ^^^^^^ `&str` is not an iterator; try calling `.chars()` or `.bytes()`
    |
-   = help: the trait `Iterator` is not implemented for `&str`, which is required by `&str: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `&str`
    = note: required for `&str` to implement `IntoIterator`
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/for/for-loop-bogosity.stderr b/tests/ui/for/for-loop-bogosity.stderr
index 143e4a4efd1..194a2fa08ce 100644
--- a/tests/ui/for/for-loop-bogosity.stderr
+++ b/tests/ui/for/for-loop-bogosity.stderr
@@ -4,7 +4,7 @@ error[E0277]: `MyStruct` is not an iterator
 LL |     for x in bogus {
    |              ^^^^^ `MyStruct` is not an iterator
    |
-   = help: the trait `Iterator` is not implemented for `MyStruct`, which is required by `MyStruct: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `MyStruct`
    = note: required for `MyStruct` to implement `IntoIterator`
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/function-pointer/unsized-ret.stderr b/tests/ui/function-pointer/unsized-ret.stderr
index 81d603f4b20..66116273ff4 100644
--- a/tests/ui/function-pointer/unsized-ret.stderr
+++ b/tests/ui/function-pointer/unsized-ret.stderr
@@ -4,7 +4,7 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t
 LL |     foo::<fn() -> str, _>(None, ());
    |           ^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = help: within `fn() -> str`, the trait `Sized` is not implemented for `str`, which is required by `fn() -> str: Fn<_>`
+   = help: within `fn() -> str`, the trait `Sized` is not implemented for `str`
    = note: required because it appears within the type `fn() -> str`
 note: required by a bound in `foo`
   --> $DIR/unsized-ret.rs:5:11
@@ -18,7 +18,7 @@ error[E0277]: the size for values of type `(dyn std::fmt::Display + 'a)` cannot
 LL |     foo::<for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a), _>(None, (&(),));
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = help: within `for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a)`, the trait `for<'a> Sized` is not implemented for `(dyn std::fmt::Display + 'a)`, which is required by `for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a): Fn<_>`
+   = help: within `for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a)`, the trait `for<'a> Sized` is not implemented for `(dyn std::fmt::Display + 'a)`
    = note: required because it appears within the type `for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a)`
 note: required by a bound in `foo`
   --> $DIR/unsized-ret.rs:5:11
diff --git a/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.current.stderr b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.current.stderr
index c5c4f2c4d23..8779bab593a 100644
--- a/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.current.stderr
+++ b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.current.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `<Self as Foo>::Bar<()>: Eq<i32>` is not satisfied
   --> $DIR/assume-gat-normalization-for-nested-goals.rs:9:30
    |
 LL |     type Bar<T>: Baz<Self> = i32;
-   |                              ^^^ the trait `Eq<i32>` is not implemented for `<Self as Foo>::Bar<()>`, which is required by `i32: Baz<Self>`
+   |                              ^^^ the trait `Eq<i32>` is not implemented for `<Self as Foo>::Bar<()>`
    |
 note: required for `i32` to implement `Baz<Self>`
   --> $DIR/assume-gat-normalization-for-nested-goals.rs:16:23
diff --git a/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.next.stderr b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.next.stderr
index c5c4f2c4d23..8779bab593a 100644
--- a/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.next.stderr
+++ b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.next.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `<Self as Foo>::Bar<()>: Eq<i32>` is not satisfied
   --> $DIR/assume-gat-normalization-for-nested-goals.rs:9:30
    |
 LL |     type Bar<T>: Baz<Self> = i32;
-   |                              ^^^ the trait `Eq<i32>` is not implemented for `<Self as Foo>::Bar<()>`, which is required by `i32: Baz<Self>`
+   |                              ^^^ the trait `Eq<i32>` is not implemented for `<Self as Foo>::Bar<()>`
    |
 note: required for `i32` to implement `Baz<Self>`
   --> $DIR/assume-gat-normalization-for-nested-goals.rs:16:23
diff --git a/tests/ui/generic-associated-types/impl_bounds.stderr b/tests/ui/generic-associated-types/impl_bounds.stderr
index c3b119e2144..261070d1db4 100644
--- a/tests/ui/generic-associated-types/impl_bounds.stderr
+++ b/tests/ui/generic-associated-types/impl_bounds.stderr
@@ -25,7 +25,7 @@ error[E0277]: the trait bound `T: Copy` is not satisfied
   --> $DIR/impl_bounds.rs:18:33
    |
 LL |     type C = String where Self: Copy;
-   |                                 ^^^^ the trait `Copy` is not implemented for `T`, which is required by `Fooy<T>: Copy`
+   |                                 ^^^^ the trait `Copy` is not implemented for `T`
    |
 note: required for `Fooy<T>` to implement `Copy`
   --> $DIR/impl_bounds.rs:10:10
@@ -50,7 +50,7 @@ error[E0277]: the trait bound `T: Copy` is not satisfied
   --> $DIR/impl_bounds.rs:20:24
    |
 LL |     fn d() where Self: Copy {}
-   |                        ^^^^ the trait `Copy` is not implemented for `T`, which is required by `Fooy<T>: Copy`
+   |                        ^^^^ the trait `Copy` is not implemented for `T`
    |
 note: required for `Fooy<T>` to implement `Copy`
   --> $DIR/impl_bounds.rs:10:10
diff --git a/tests/ui/generic-associated-types/issue-101020.stderr b/tests/ui/generic-associated-types/issue-101020.stderr
index 7faab4e5274..9c3753c2d18 100644
--- a/tests/ui/generic-associated-types/issue-101020.stderr
+++ b/tests/ui/generic-associated-types/issue-101020.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `for<'a> &'a mut (): Foo<&'a mut ()>` is not satis
   --> $DIR/issue-101020.rs:31:22
    |
 LL |     (&mut EmptyIter).consume(());
-   |                      ^^^^^^^ the trait `for<'a> Foo<&'a mut ()>` is not implemented for `&'a mut ()`, which is required by `for<'a> &'a mut (): FuncInput<'a, &'a mut ()>`
+   |                      ^^^^^^^ the trait `for<'a> Foo<&'a mut ()>` is not implemented for `&'a mut ()`
    |
 help: this trait has no implementations, consider adding one
   --> $DIR/issue-101020.rs:28:1
diff --git a/tests/ui/generic-associated-types/issue-74824.current.stderr b/tests/ui/generic-associated-types/issue-74824.current.stderr
index b06c7f127ac..231136612a0 100644
--- a/tests/ui/generic-associated-types/issue-74824.current.stderr
+++ b/tests/ui/generic-associated-types/issue-74824.current.stderr
@@ -14,7 +14,7 @@ error[E0277]: the trait bound `T: Clone` is not satisfied
   --> $DIR/issue-74824.rs:10:26
    |
 LL |     type Copy<T>: Copy = Box<T>;
-   |                          ^^^^^^ the trait `Clone` is not implemented for `T`, which is required by `<Self as UnsafeCopy>::Copy<T>: Copy`
+   |                          ^^^^^^ the trait `Clone` is not implemented for `T`
    |
    = note: required for `Box<T>` to implement `Clone`
    = note: required for `<Self as UnsafeCopy>::Copy<T>` to implement `Copy`
diff --git a/tests/ui/generic-associated-types/issue-74824.next.stderr b/tests/ui/generic-associated-types/issue-74824.next.stderr
index b06c7f127ac..231136612a0 100644
--- a/tests/ui/generic-associated-types/issue-74824.next.stderr
+++ b/tests/ui/generic-associated-types/issue-74824.next.stderr
@@ -14,7 +14,7 @@ error[E0277]: the trait bound `T: Clone` is not satisfied
   --> $DIR/issue-74824.rs:10:26
    |
 LL |     type Copy<T>: Copy = Box<T>;
-   |                          ^^^^^^ the trait `Clone` is not implemented for `T`, which is required by `<Self as UnsafeCopy>::Copy<T>: Copy`
+   |                          ^^^^^^ the trait `Clone` is not implemented for `T`
    |
    = note: required for `Box<T>` to implement `Clone`
    = note: required for `<Self as UnsafeCopy>::Copy<T>` to implement `Copy`
diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89118.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89118.stderr
index 761fd9045a1..7fe803550bd 100644
--- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89118.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89118.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied
   --> $DIR/issue-89118.rs:19:8
    |
 LL |     C: StackContext,
-   |        ^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()`, which is required by `for<'a> Ctx<()>: BufferUdpStateContext<&'a ()>`
+   |        ^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()`
    |
 help: this trait has no implementations, consider adding one
   --> $DIR/issue-89118.rs:1:1
@@ -29,7 +29,7 @@ error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied
   --> $DIR/issue-89118.rs:29:9
    |
 LL | impl<C> EthernetWorker<C> {}
-   |         ^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()`, which is required by `for<'a> Ctx<()>: BufferUdpStateContext<&'a ()>`
+   |         ^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()`
    |
 help: this trait has no implementations, consider adding one
   --> $DIR/issue-89118.rs:1:1
@@ -56,7 +56,7 @@ error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied
   --> $DIR/issue-89118.rs:22:20
    |
 LL |     type Handler = Ctx<C::Dispatcher>;
-   |                    ^^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()`, which is required by `for<'a> Ctx<()>: BufferUdpStateContext<&'a ()>`
+   |                    ^^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()`
    |
 help: this trait has no implementations, consider adding one
   --> $DIR/issue-89118.rs:1:1
diff --git a/tests/ui/impl-trait/auto-trait-leak2.stderr b/tests/ui/impl-trait/auto-trait-leak2.stderr
index 1fcde0372fc..52fa28145d6 100644
--- a/tests/ui/impl-trait/auto-trait-leak2.stderr
+++ b/tests/ui/impl-trait/auto-trait-leak2.stderr
@@ -9,7 +9,7 @@ LL |     send(before());
    |     |
    |     required by a bound introduced by this call
    |
-   = help: within `impl Fn(i32)`, the trait `Send` is not implemented for `Rc<Cell<i32>>`, which is required by `impl Fn(i32): Send`
+   = help: within `impl Fn(i32)`, the trait `Send` is not implemented for `Rc<Cell<i32>>`
 note: required because it's used within this closure
   --> $DIR/auto-trait-leak2.rs:10:5
    |
@@ -37,7 +37,7 @@ LL |     send(after());
 LL | fn after() -> impl Fn(i32) {
    |               ------------ within this `impl Fn(i32)`
    |
-   = help: within `impl Fn(i32)`, the trait `Send` is not implemented for `Rc<Cell<i32>>`, which is required by `impl Fn(i32): Send`
+   = help: within `impl Fn(i32)`, the trait `Send` is not implemented for `Rc<Cell<i32>>`
 note: required because it's used within this closure
   --> $DIR/auto-trait-leak2.rs:38:5
    |
diff --git a/tests/crashes/126850.rs b/tests/ui/impl-trait/closure-in-type.rs
index 0ddc24c8bb1..1e06e6e21fd 100644
--- a/tests/crashes/126850.rs
+++ b/tests/ui/impl-trait/closure-in-type.rs
@@ -1,4 +1,5 @@
-//@ known-bug: rust-lang/rust#126850
+//@ check-pass
+
 fn bug<T>() -> impl Iterator<
     Item = [(); {
                |found: &String| Some(false);
diff --git a/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.svg b/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.svg
index e09b96e5ff2..a18fc11a1e3 100644
--- a/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.svg
+++ b/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.svg
@@ -29,7 +29,7 @@
 </tspan>
     <tspan x="10px" y="82px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> fn foo() -&gt; impl Foo&lt;i32&gt; {</tspan>
 </tspan>
-    <tspan x="10px" y="100px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>             </tspan><tspan class="fg-ansi256-009 bold">^^^^^^^^^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">the trait `Bar&lt;i32&gt;` is not implemented for `Struct`, which is required by `Struct: Foo&lt;i32&gt;`</tspan>
+    <tspan x="10px" y="100px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>             </tspan><tspan class="fg-ansi256-009 bold">^^^^^^^^^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">the trait `Bar&lt;i32&gt;` is not implemented for `Struct`</tspan>
 </tspan>
     <tspan x="10px" y="118px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
 </tspan>
diff --git a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr
index 9c546659564..8716088ccbd 100644
--- a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr
+++ b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr
@@ -16,7 +16,7 @@ LL | fn fuz() -> (usize, Trait) { (42, Struct) }
    |             |
    |             doesn't have a size known at compile-time
    |
-   = help: within `(usize, (dyn Trait + 'static))`, the trait `Sized` is not implemented for `(dyn Trait + 'static)`, which is required by `(usize, (dyn Trait + 'static)): Sized`
+   = help: within `(usize, (dyn Trait + 'static))`, the trait `Sized` is not implemented for `(dyn Trait + 'static)`
    = note: required because it appears within the type `(usize, (dyn Trait + 'static))`
    = note: the return type of a function must have a statically known size
 
@@ -38,7 +38,7 @@ LL | fn bar() -> (usize, dyn Trait) { (42, Struct) }
    |             |
    |             doesn't have a size known at compile-time
    |
-   = help: within `(usize, (dyn Trait + 'static))`, the trait `Sized` is not implemented for `(dyn Trait + 'static)`, which is required by `(usize, (dyn Trait + 'static)): Sized`
+   = help: within `(usize, (dyn Trait + 'static))`, the trait `Sized` is not implemented for `(dyn Trait + 'static)`
    = note: required because it appears within the type `(usize, (dyn Trait + 'static))`
    = note: the return type of a function must have a statically known size
 
diff --git a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr
index 058517f0014..38c7a9ea16e 100644
--- a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr
+++ b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr
@@ -8,7 +8,7 @@ LL | |
 ...  |
 LL | |     where
 LL | |         F: Callback<Self::CallbackArg>,
-   | |_______________________________________^ the trait `MyFn<i32>` is not implemented for `F`, which is required by `F: Callback<i32>`
+   | |_______________________________________^ the trait `MyFn<i32>` is not implemented for `F`
    |
 note: required for `F` to implement `Callback<i32>`
   --> $DIR/false-positive-predicate-entailment-error.rs:14:21
@@ -26,7 +26,7 @@ error[E0277]: the trait bound `F: MyFn<i32>` is not satisfied
   --> $DIR/false-positive-predicate-entailment-error.rs:36:30
    |
 LL |     fn autobatch<F>(self) -> impl Trait
-   |                              ^^^^^^^^^^ the trait `MyFn<i32>` is not implemented for `F`, which is required by `F: Callback<i32>`
+   |                              ^^^^^^^^^^ the trait `MyFn<i32>` is not implemented for `F`
    |
 note: required for `F` to implement `Callback<i32>`
   --> $DIR/false-positive-predicate-entailment-error.rs:14:21
@@ -58,7 +58,7 @@ LL | |
 ...  |
 LL | |     where
 LL | |         F: Callback<Self::CallbackArg>,
-   | |_______________________________________^ the trait `MyFn<i32>` is not implemented for `F`, which is required by `F: Callback<i32>`
+   | |_______________________________________^ the trait `MyFn<i32>` is not implemented for `F`
    |
 note: required for `F` to implement `Callback<i32>`
   --> $DIR/false-positive-predicate-entailment-error.rs:14:21
@@ -77,7 +77,7 @@ error[E0277]: the trait bound `F: MyFn<i32>` is not satisfied
   --> $DIR/false-positive-predicate-entailment-error.rs:36:30
    |
 LL |     fn autobatch<F>(self) -> impl Trait
-   |                              ^^^^^^^^^^ the trait `MyFn<i32>` is not implemented for `F`, which is required by `F: Callback<i32>`
+   |                              ^^^^^^^^^^ the trait `MyFn<i32>` is not implemented for `F`
    |
 note: required for `F` to implement `Callback<i32>`
   --> $DIR/false-positive-predicate-entailment-error.rs:14:21
@@ -91,7 +91,7 @@ error[E0277]: the trait bound `F: Callback<i32>` is not satisfied
   --> $DIR/false-positive-predicate-entailment-error.rs:27:12
    |
 LL |         F: Callback<Self::CallbackArg>;
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MyFn<i32>` is not implemented for `F`, which is required by `F: Callback<i32>`
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MyFn<i32>` is not implemented for `F`
    |
 note: required for `F` to implement `Callback<i32>`
   --> $DIR/false-positive-predicate-entailment-error.rs:14:21
@@ -111,7 +111,7 @@ LL | |
 ...  |
 LL | |     where
 LL | |         F: Callback<Self::CallbackArg>,
-   | |_______________________________________^ the trait `MyFn<i32>` is not implemented for `F`, which is required by `F: Callback<i32>`
+   | |_______________________________________^ the trait `MyFn<i32>` is not implemented for `F`
    |
 note: required for `F` to implement `Callback<i32>`
   --> $DIR/false-positive-predicate-entailment-error.rs:14:21
diff --git a/tests/ui/impl-trait/in-trait/return-type-notation.rs b/tests/ui/impl-trait/in-trait/return-type-notation.rs
new file mode 100644
index 00000000000..3945eb9bdee
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/return-type-notation.rs
@@ -0,0 +1,9 @@
+#![allow(incomplete_features)]
+#![feature(return_type_notation)]
+
+trait IntFactory {
+    fn stream(&self) -> impl IntFactory<stream(..): IntFactory<stream(..): Send> + Send>;
+    //~^ ERROR cycle detected when resolving lifetimes for `IntFactory::stream`
+}
+
+pub fn main() {}
diff --git a/tests/ui/impl-trait/in-trait/return-type-notation.stderr b/tests/ui/impl-trait/in-trait/return-type-notation.stderr
new file mode 100644
index 00000000000..d9fd780cdff
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/return-type-notation.stderr
@@ -0,0 +1,27 @@
+error[E0391]: cycle detected when resolving lifetimes for `IntFactory::stream`
+  --> $DIR/return-type-notation.rs:5:5
+   |
+LL |     fn stream(&self) -> impl IntFactory<stream(..): IntFactory<stream(..): Send> + Send>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...which requires computing function signature of `IntFactory::stream`...
+  --> $DIR/return-type-notation.rs:5:5
+   |
+LL |     fn stream(&self) -> impl IntFactory<stream(..): IntFactory<stream(..): Send> + Send>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires looking up late bound vars inside `IntFactory::stream`...
+  --> $DIR/return-type-notation.rs:5:5
+   |
+LL |     fn stream(&self) -> impl IntFactory<stream(..): IntFactory<stream(..): Send> + Send>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which again requires resolving lifetimes for `IntFactory::stream`, completing the cycle
+note: cycle used when listing captured lifetimes for opaque `IntFactory::stream::{opaque#0}`
+  --> $DIR/return-type-notation.rs:5:25
+   |
+LL |     fn stream(&self) -> impl IntFactory<stream(..): IntFactory<stream(..): Send> + Send>;
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/tests/ui/impl-trait/in-trait/shorthand-projection-in-rpitit-bound.rs b/tests/ui/impl-trait/in-trait/shorthand-projection-in-rpitit-bound.rs
new file mode 100644
index 00000000000..102b53f4957
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/shorthand-projection-in-rpitit-bound.rs
@@ -0,0 +1,13 @@
+//@ check-pass
+
+// Ensure that we can resolve a shorthand projection in an item bound in an RPITIT.
+
+pub trait Bar {
+    type Foo;
+}
+
+pub trait Baz {
+    fn boom<X: Bar>() -> impl Bar<Foo = X::Foo>;
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/in-trait/variance.rs b/tests/ui/impl-trait/in-trait/variance.rs
index 19905c608e3..cd2f43fca9a 100644
--- a/tests/ui/impl-trait/in-trait/variance.rs
+++ b/tests/ui/impl-trait/in-trait/variance.rs
@@ -4,7 +4,7 @@
 
 trait Foo<'i> {
     fn implicit_capture_early<'a: 'a>() -> impl Sized {}
-    //~^ [Self: o, 'i: o, 'a: *, 'a: o, 'i: o]
+    //~^ [Self: o, 'i: o, 'a: *, 'i: o, 'a: o]
 
     fn explicit_capture_early<'a: 'a>() -> impl Sized + use<'i, 'a, Self> {}
     //~^ [Self: o, 'i: o, 'a: *, 'i: o, 'a: o]
@@ -13,12 +13,12 @@ trait Foo<'i> {
     //~^ [Self: o, 'i: o, 'a: *, 'i: o]
 
     fn implicit_capture_late<'a>(_: &'a ()) -> impl Sized {}
-    //~^ [Self: o, 'i: o, 'a: o, 'i: o]
+    //~^ [Self: o, 'i: o, 'i: o, 'a: o]
 
     fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + use<'i, 'a, Self> {}
     //~^ [Self: o, 'i: o, 'i: o, 'a: o]
 
-    fn not_cpatured_late<'a>(_: &'a ()) -> impl Sized + use<'i, Self> {}
+    fn not_captured_late<'a>(_: &'a ()) -> impl Sized + use<'i, Self> {}
     //~^ [Self: o, 'i: o, 'i: o]
 }
 
diff --git a/tests/ui/impl-trait/in-trait/variance.stderr b/tests/ui/impl-trait/in-trait/variance.stderr
index f65174e1c35..d45cca982e9 100644
--- a/tests/ui/impl-trait/in-trait/variance.stderr
+++ b/tests/ui/impl-trait/in-trait/variance.stderr
@@ -1,4 +1,4 @@
-error: [Self: o, 'i: o, 'a: *, 'a: o, 'i: o]
+error: [Self: o, 'i: o, 'a: *, 'i: o, 'a: o]
   --> $DIR/variance.rs:6:44
    |
 LL |     fn implicit_capture_early<'a: 'a>() -> impl Sized {}
@@ -16,7 +16,7 @@ error: [Self: o, 'i: o, 'a: *, 'i: o]
 LL |     fn not_captured_early<'a: 'a>() -> impl Sized + use<'i, Self> {}
    |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: [Self: o, 'i: o, 'a: o, 'i: o]
+error: [Self: o, 'i: o, 'i: o, 'a: o]
   --> $DIR/variance.rs:15:48
    |
 LL |     fn implicit_capture_late<'a>(_: &'a ()) -> impl Sized {}
@@ -31,7 +31,7 @@ LL |     fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + use<'i, 'a, Sel
 error: [Self: o, 'i: o, 'i: o]
   --> $DIR/variance.rs:21:44
    |
-LL |     fn not_cpatured_late<'a>(_: &'a ()) -> impl Sized + use<'i, Self> {}
+LL |     fn not_captured_late<'a>(_: &'a ()) -> impl Sized + use<'i, Self> {}
    |                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 6 previous errors
diff --git a/tests/ui/impl-trait/issue-55872-1.stderr b/tests/ui/impl-trait/issue-55872-1.stderr
index 0c86824e622..8912cce1b4b 100644
--- a/tests/ui/impl-trait/issue-55872-1.stderr
+++ b/tests/ui/impl-trait/issue-55872-1.stderr
@@ -11,7 +11,7 @@ error[E0277]: the trait bound `S: Copy` is not satisfied in `(S, T)`
   --> $DIR/issue-55872-1.rs:12:29
    |
 LL |     fn foo<T: Default>() -> Self::E {
-   |                             ^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `S`, which is required by `(S, T): Copy`
+   |                             ^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `S`
    |
    = note: required because it appears within the type `(S, T)`
 help: consider further restricting this bound
@@ -23,7 +23,7 @@ error[E0277]: the trait bound `T: Copy` is not satisfied in `(S, T)`
   --> $DIR/issue-55872-1.rs:12:29
    |
 LL |     fn foo<T: Default>() -> Self::E {
-   |                             ^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `T`, which is required by `(S, T): Copy`
+   |                             ^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `T`
    |
    = note: required because it appears within the type `(S, T)`
 help: consider further restricting this bound
diff --git a/tests/ui/impl-trait/nested_impl_trait.stderr b/tests/ui/impl-trait/nested_impl_trait.stderr
index 83d1347aff4..31c3e0c9013 100644
--- a/tests/ui/impl-trait/nested_impl_trait.stderr
+++ b/tests/ui/impl-trait/nested_impl_trait.stderr
@@ -46,7 +46,7 @@ error[E0277]: the trait bound `impl Debug: From<impl Into<u32>>` is not satisfie
   --> $DIR/nested_impl_trait.rs:6:46
    |
 LL | fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
-   |                                              ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Debug`, which is required by `impl Into<u32>: Into<impl Debug>`
+   |                                              ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Debug`
    |
    = help: the trait `Into<U>` is implemented for `T`
    = note: required for `impl Into<u32>` to implement `Into<impl Debug>`
@@ -55,7 +55,7 @@ error[E0277]: the trait bound `impl Debug: From<impl Into<u32>>` is not satisfie
   --> $DIR/nested_impl_trait.rs:19:34
    |
 LL |     fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
-   |                                  ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Debug`, which is required by `impl Into<u32>: Into<impl Debug>`
+   |                                  ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Debug`
    |
    = help: the trait `Into<U>` is implemented for `T`
    = note: required for `impl Into<u32>` to implement `Into<impl Debug>`
diff --git a/tests/ui/impl-trait/precise-capturing/auxiliary/foreign.rs b/tests/ui/impl-trait/precise-capturing/auxiliary/foreign.rs
new file mode 100644
index 00000000000..49015bc48ba
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/auxiliary/foreign.rs
@@ -0,0 +1,6 @@
+//@ edition: 2024
+//@ compile-flags: -Zunstable-options
+
+use std::fmt::Display;
+
+pub fn hello(x: &Vec<i32>) -> impl Display { 0 }
diff --git a/tests/ui/impl-trait/precise-capturing/bound-modifiers.rs b/tests/ui/impl-trait/precise-capturing/bound-modifiers.rs
index 47695814668..46121308fa0 100644
--- a/tests/ui/impl-trait/precise-capturing/bound-modifiers.rs
+++ b/tests/ui/impl-trait/precise-capturing/bound-modifiers.rs
@@ -3,8 +3,6 @@
 fn polarity() -> impl Sized + ?use<> {}
 //~^ ERROR expected identifier, found keyword `use`
 //~| ERROR cannot find trait `r#use` in this scope
-//~| WARN relaxing a default bound only does something for `?Sized`
-//~| WARN relaxing a default bound only does something for `?Sized`
 
 fn asyncness() -> impl Sized + async use<> {}
 //~^ ERROR expected identifier, found keyword `use`
diff --git a/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr b/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr
index aaebfe2a86e..16e7470debf 100644
--- a/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr
+++ b/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr
@@ -5,19 +5,19 @@ LL | fn polarity() -> impl Sized + ?use<> {}
    |                                ^^^ expected identifier, found keyword
 
 error: expected identifier, found keyword `use`
-  --> $DIR/bound-modifiers.rs:9:38
+  --> $DIR/bound-modifiers.rs:7:38
    |
 LL | fn asyncness() -> impl Sized + async use<> {}
    |                                      ^^^ expected identifier, found keyword
 
 error: expected identifier, found keyword `use`
-  --> $DIR/bound-modifiers.rs:14:38
+  --> $DIR/bound-modifiers.rs:12:38
    |
 LL | fn constness() -> impl Sized + const use<> {}
    |                                      ^^^ expected identifier, found keyword
 
 error: expected identifier, found keyword `use`
-  --> $DIR/bound-modifiers.rs:19:37
+  --> $DIR/bound-modifiers.rs:17:37
    |
 LL | fn binder() -> impl Sized + for<'a> use<> {}
    |                                     ^^^ expected identifier, found keyword
@@ -29,25 +29,25 @@ LL | fn polarity() -> impl Sized + ?use<> {}
    |                                ^^^ not found in this scope
 
 error[E0405]: cannot find trait `r#use` in this scope
-  --> $DIR/bound-modifiers.rs:9:38
+  --> $DIR/bound-modifiers.rs:7:38
    |
 LL | fn asyncness() -> impl Sized + async use<> {}
    |                                      ^^^ not found in this scope
 
 error[E0405]: cannot find trait `r#use` in this scope
-  --> $DIR/bound-modifiers.rs:14:38
+  --> $DIR/bound-modifiers.rs:12:38
    |
 LL | fn constness() -> impl Sized + const use<> {}
    |                                      ^^^ not found in this scope
 
 error[E0405]: cannot find trait `r#use` in this scope
-  --> $DIR/bound-modifiers.rs:19:37
+  --> $DIR/bound-modifiers.rs:17:37
    |
 LL | fn binder() -> impl Sized + for<'a> use<> {}
    |                                     ^^^ not found in this scope
 
 error[E0658]: async closures are unstable
-  --> $DIR/bound-modifiers.rs:9:32
+  --> $DIR/bound-modifiers.rs:7:32
    |
 LL | fn asyncness() -> impl Sized + async use<> {}
    |                                ^^^^^
@@ -58,7 +58,7 @@ LL | fn asyncness() -> impl Sized + async use<> {}
    = help: to use an async block, remove the `||`: `async {`
 
 error[E0658]: const trait impls are experimental
-  --> $DIR/bound-modifiers.rs:14:32
+  --> $DIR/bound-modifiers.rs:12:32
    |
 LL | fn constness() -> impl Sized + const use<> {}
    |                                ^^^^^
@@ -67,21 +67,7 @@ LL | fn constness() -> impl Sized + const use<> {}
    = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
-  --> $DIR/bound-modifiers.rs:3:31
-   |
-LL | fn polarity() -> impl Sized + ?use<> {}
-   |                               ^^^^^^
-
-warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
-  --> $DIR/bound-modifiers.rs:3:31
-   |
-LL | fn polarity() -> impl Sized + ?use<> {}
-   |                               ^^^^^^
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: aborting due to 10 previous errors; 2 warnings emitted
+error: aborting due to 10 previous errors
 
 Some errors have detailed explanations: E0405, E0658.
 For more information about an error, try `rustc --explain E0405`.
diff --git a/tests/ui/impl-trait/precise-capturing/foreign-2021.rs b/tests/ui/impl-trait/precise-capturing/foreign-2021.rs
new file mode 100644
index 00000000000..aee412ff7f1
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/foreign-2021.rs
@@ -0,0 +1,15 @@
+//@ aux-build: foreign.rs
+
+extern crate foreign;
+
+fn main() {
+    let mut x = vec![];
+    let h = foreign::hello(&x);
+    //~^ NOTE this call may capture more lifetimes than intended
+    //~| NOTE immutable borrow occurs here
+    x.push(0);
+    //~^ ERROR cannot borrow `x` as mutable
+    //~| NOTE mutable borrow occurs here
+    println!("{h}");
+    //~^ NOTE immutable borrow later used here
+}
diff --git a/tests/ui/impl-trait/precise-capturing/foreign-2021.stderr b/tests/ui/impl-trait/precise-capturing/foreign-2021.stderr
new file mode 100644
index 00000000000..2a17ef72912
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/foreign-2021.stderr
@@ -0,0 +1,26 @@
+error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
+  --> $DIR/foreign-2021.rs:10:5
+   |
+LL |     let h = foreign::hello(&x);
+   |                            -- immutable borrow occurs here
+...
+LL |     x.push(0);
+   |     ^^^^^^^^^ mutable borrow occurs here
+...
+LL |     println!("{h}");
+   |               --- immutable borrow later used here
+   |
+note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules
+  --> $DIR/foreign-2021.rs:7:13
+   |
+LL |     let h = foreign::hello(&x);
+   |             ^^^^^^^^^^^^^^^^^^
+help: if you can modify this crate, add a precise capturing bound to avoid overcapturing: `+ use<>`
+  --> $DIR/auxiliary/foreign.rs:6:31
+   |
+LL | pub fn hello(x: &Vec<i32>) -> impl Display { 0 }
+   |                               ^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/tests/ui/impl-trait/precise-capturing/migration-note.rs b/tests/ui/impl-trait/precise-capturing/migration-note.rs
new file mode 100644
index 00000000000..a5bade4ddc5
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/migration-note.rs
@@ -0,0 +1,190 @@
+//@ edition: 2024
+//@ compile-flags: -Zunstable-options
+
+use std::fmt::Display;
+
+fn display_len<T>(x: &Vec<T>) -> impl Display {
+    //~^ NOTE in this expansion of desugaring of `impl Trait`
+    //~| NOTE in this expansion of desugaring of `impl Trait`
+    //~| NOTE in this expansion of desugaring of `impl Trait`
+    //~| NOTE in this expansion of desugaring of `impl Trait`
+    //~| NOTE in this expansion of desugaring of `impl Trait`
+    x.len()
+}
+
+fn conflicting_borrow() {
+    let mut x = vec![];
+    let a = display_len(&x);
+    //~^ NOTE this call may capture more lifetimes than intended
+    //~| NOTE immutable borrow occurs here
+    x.push(1);
+    //~^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable
+    //~| NOTE mutable borrow occurs here
+    println!("{a}");
+    //~^ NOTE immutable borrow later used here
+}
+
+fn needs_static() {
+    let x = vec![1];
+    //~^ NOTE binding `x` declared here
+    let a = display_len(&x);
+    //~^ ERROR `x` does not live long enough
+    //~| NOTE this call may capture more lifetimes than intended
+    //~| NOTE argument requires that `x` is borrowed for `'static`
+    //~| NOTE borrowed value does not live long enoug
+
+    fn needs_static(_: impl Sized + 'static) {}
+    needs_static(a);
+}
+//~^ NOTE `x` dropped here while still borrowed
+
+fn is_moved() {
+    let x = vec![1];
+    //~^ NOTE binding `x` declared here
+    let a = display_len(&x);
+    //~^ NOTE this call may capture more lifetimes than intended
+    //~| NOTE borrow of `x` occurs here
+
+    fn mv(_: impl Sized) {}
+    mv(x);
+    //~^ ERROR cannot move out of `x` because it is borrowed
+    //~| NOTE move out of `x` occurs here
+}
+//~^ NOTE borrow might be used here, when `a` is dropped
+
+fn display_len_mut<T>(x: &mut Vec<T>) -> impl Display {
+    //~^ NOTE in this expansion of desugaring of `impl Trait`
+    //~| NOTE in this expansion of desugaring of `impl Trait`
+    //~| NOTE in this expansion of desugaring of `impl Trait`
+    x.len()
+}
+
+fn conflicting_borrow_mut() {
+    let mut x = vec![];
+    let a = display_len_mut(&mut x);
+    //~^ NOTE this call may capture more lifetimes than intended
+    //~| NOTE first mutable borrow occurs here
+    x.push(1);
+    //~^ ERROR cannot borrow `x` as mutable more than once
+    //~| NOTE second mutable borrow occurs here
+    println!("{a}");
+    //~^ NOTE first borrow later used here
+}
+
+fn needs_static_mut() {
+    let mut x = vec![1];
+    //~^ NOTE binding `x` declared here
+    let a = display_len_mut(&mut x);
+    //~^ ERROR `x` does not live long enough
+    //~| NOTE this call may capture more lifetimes than intended
+    //~| NOTE argument requires that `x` is borrowed for `'static`
+    //~| NOTE borrowed value does not live long enough
+
+    fn needs_static(_: impl Sized + 'static) {}
+    needs_static(a);
+}
+//~^ NOTE `x` dropped here while still borrowed
+
+fn is_move_mut() {
+    let mut x = vec![1];
+    //~^ NOTE binding `x` declared here
+    let a = display_len_mut(&mut x);
+    //~^ NOTE this call may capture more lifetimes than intended
+    //~| NOTE borrow of `x` occurs here
+
+    fn mv(_: impl Sized) {}
+    mv(x);
+    //~^ ERROR cannot move out of `x` because it is borrowed
+    //~| NOTE move out of `x` occurs here
+}
+//~^ NOTE borrow might be used here, when `a` is dropped
+
+struct S { f: i32 }
+
+fn display_field<T: Copy + Display>(t: &T) -> impl Display {
+    //~^ NOTE in this expansion of desugaring of `impl Trait`
+    //~| NOTE in this expansion of desugaring of `impl Trait`
+    //~| NOTE in this expansion of desugaring of `impl Trait`
+    *t
+}
+
+fn conflicting_borrow_field() {
+    let mut s = S { f: 0 };
+    let a = display_field(&s.f);
+    //~^ NOTE this call may capture more lifetimes than intended
+    //~| NOTE `s.f` is borrowed here
+    s.f = 1;
+    //~^ ERROR cannot assign to `s.f` because it is borrowed
+    //~| NOTE `s.f` is assigned to here but it was already borrowed
+    println!("{a}");
+    //~^ NOTE borrow later used here
+}
+
+fn display_field_mut<T: Copy + Display>(t: &mut T) -> impl Display {
+    *t
+}
+
+fn conflicting_borrow_field_mut() {
+    let mut s = S { f: 0 };
+    let a = display_field(&mut s.f);
+    //~^ NOTE this call may capture more lifetimes than intended
+    //~| NOTE `s.f` is borrowed here
+    s.f = 1;
+    //~^ ERROR cannot assign to `s.f` because it is borrowed
+    //~| NOTE `s.f` is assigned to here but it was already borrowed
+    println!("{a}");
+    //~^ NOTE borrow later used here
+}
+
+fn field_move() {
+    let mut s = S { f: 0 };
+    let a = display_field(&mut s.f);
+    //~^ NOTE this call may capture more lifetimes than intended
+    //~| NOTE `s.f` is borrowed here
+    s.f;
+    //~^ ERROR cannot use `s.f` because it was mutably borrowed
+    //~| NOTE use of borrowed `s.f`
+    println!("{a}");
+    //~^ NOTE borrow later used here
+}
+
+struct Z {
+    f: Vec<i32>,
+}
+
+fn live_long() {
+    let x;
+    {
+        let z = Z { f: vec![1] };
+        //~^ NOTE binding `z` declared here
+        x = display_len(&z.f);
+        //~^ ERROR `z.f` does not live long enough
+        //~| NOTE this call may capture more lifetimes than intended
+        //~| NOTE values in a scope are dropped in the opposite order they are defined
+        //~| NOTE borrowed value does not live long enough
+    }
+    //~^ NOTE `z.f` dropped here while still borrowed
+}
+//~^ NOTE borrow might be used here, when `x` is dropped
+
+fn temp() {
+    let x = { let x = display_len(&mut vec![0]); x };
+    //~^ ERROR temporary value dropped while borrowed
+    //~| NOTE this call may capture more lifetimes than intended
+    //~| NOTE consider using a `let` binding to create a longer lived value
+    //~| NOTE borrow later used here
+    //~| NOTE temporary value is freed at the end of this statement
+}
+
+// FIXME: This doesn't display a useful Rust 2024 suggestion :(
+fn returned() -> impl Sized {
+    let x = vec![0];
+    //~^ NOTE binding `x` declared here
+    display_len(&x)
+    //~^ ERROR `x` does not live long enough
+    //~| NOTE borrowed value does not live long enough
+    //~| NOTE argument requires that `x` is borrowed for `'static`
+}
+//~^ NOTE `x` dropped here while still borrowed
+
+fn main() {}
diff --git a/tests/ui/impl-trait/precise-capturing/migration-note.stderr b/tests/ui/impl-trait/precise-capturing/migration-note.stderr
new file mode 100644
index 00000000000..3ac47ed1bcd
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/migration-note.stderr
@@ -0,0 +1,284 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/migration-note.rs:183:17
+   |
+LL |     let x = vec![0];
+   |         - binding `x` declared here
+LL |
+LL |     display_len(&x)
+   |     ------------^^-
+   |     |           |
+   |     |           borrowed value does not live long enough
+   |     argument requires that `x` is borrowed for `'static`
+...
+LL | }
+   | - `x` dropped here while still borrowed
+
+error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
+  --> $DIR/migration-note.rs:20:5
+   |
+LL |     let a = display_len(&x);
+   |                         -- immutable borrow occurs here
+...
+LL |     x.push(1);
+   |     ^^^^^^^^^ mutable borrow occurs here
+...
+LL |     println!("{a}");
+   |               --- immutable borrow later used here
+   |
+note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules
+  --> $DIR/migration-note.rs:17:13
+   |
+LL |     let a = display_len(&x);
+   |             ^^^^^^^^^^^^^^^
+help: add a precise capturing bound to avoid overcapturing
+   |
+LL | fn display_len<T>(x: &Vec<T>) -> impl Display + use<T> {
+   |                                               ++++++++
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/migration-note.rs:30:25
+   |
+LL |     let x = vec![1];
+   |         - binding `x` declared here
+LL |
+LL |     let a = display_len(&x);
+   |             ------------^^-
+   |             |           |
+   |             |           borrowed value does not live long enough
+   |             argument requires that `x` is borrowed for `'static`
+...
+LL | }
+   | - `x` dropped here while still borrowed
+   |
+note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules
+  --> $DIR/migration-note.rs:30:13
+   |
+LL |     let a = display_len(&x);
+   |             ^^^^^^^^^^^^^^^
+help: add a precise capturing bound to avoid overcapturing
+   |
+LL | fn display_len<T>(x: &Vec<T>) -> impl Display + use<T> {
+   |                                               ++++++++
+
+error[E0505]: cannot move out of `x` because it is borrowed
+  --> $DIR/migration-note.rs:49:8
+   |
+LL |     let x = vec![1];
+   |         - binding `x` declared here
+LL |
+LL |     let a = display_len(&x);
+   |                         -- borrow of `x` occurs here
+...
+LL |     mv(x);
+   |        ^ move out of `x` occurs here
+...
+LL | }
+   | - borrow might be used here, when `a` is dropped and runs the destructor for type `impl std::fmt::Display`
+   |
+note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules
+  --> $DIR/migration-note.rs:44:13
+   |
+LL |     let a = display_len(&x);
+   |             ^^^^^^^^^^^^^^^
+help: add a precise capturing bound to avoid overcapturing
+   |
+LL | fn display_len<T>(x: &Vec<T>) -> impl Display + use<T> {
+   |                                               ++++++++
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     let a = display_len(&x.clone());
+   |                           ++++++++
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/migration-note.rs:67:5
+   |
+LL |     let a = display_len_mut(&mut x);
+   |                             ------ first mutable borrow occurs here
+...
+LL |     x.push(1);
+   |     ^ second mutable borrow occurs here
+...
+LL |     println!("{a}");
+   |               --- first borrow later used here
+   |
+note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules
+  --> $DIR/migration-note.rs:64:13
+   |
+LL |     let a = display_len_mut(&mut x);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^
+help: add a precise capturing bound to avoid overcapturing
+   |
+LL | fn display_len_mut<T>(x: &mut Vec<T>) -> impl Display + use<T> {
+   |                                                       ++++++++
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/migration-note.rs:77:29
+   |
+LL |     let mut x = vec![1];
+   |         ----- binding `x` declared here
+LL |
+LL |     let a = display_len_mut(&mut x);
+   |             ----------------^^^^^^-
+   |             |               |
+   |             |               borrowed value does not live long enough
+   |             argument requires that `x` is borrowed for `'static`
+...
+LL | }
+   | - `x` dropped here while still borrowed
+   |
+note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules
+  --> $DIR/migration-note.rs:77:13
+   |
+LL |     let a = display_len_mut(&mut x);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^
+help: add a precise capturing bound to avoid overcapturing
+   |
+LL | fn display_len_mut<T>(x: &mut Vec<T>) -> impl Display + use<T> {
+   |                                                       ++++++++
+
+error[E0505]: cannot move out of `x` because it is borrowed
+  --> $DIR/migration-note.rs:96:8
+   |
+LL |     let mut x = vec![1];
+   |         ----- binding `x` declared here
+LL |
+LL |     let a = display_len_mut(&mut x);
+   |                             ------ borrow of `x` occurs here
+...
+LL |     mv(x);
+   |        ^ move out of `x` occurs here
+...
+LL | }
+   | - borrow might be used here, when `a` is dropped and runs the destructor for type `impl std::fmt::Display`
+   |
+note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules
+  --> $DIR/migration-note.rs:91:13
+   |
+LL |     let a = display_len_mut(&mut x);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^
+help: add a precise capturing bound to avoid overcapturing
+   |
+LL | fn display_len_mut<T>(x: &mut Vec<T>) -> impl Display + use<T> {
+   |                                                       ++++++++
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     let a = display_len_mut(&mut x.clone());
+   |                                   ++++++++
+
+error[E0506]: cannot assign to `s.f` because it is borrowed
+  --> $DIR/migration-note.rs:116:5
+   |
+LL |     let a = display_field(&s.f);
+   |                           ---- `s.f` is borrowed here
+...
+LL |     s.f = 1;
+   |     ^^^^^^^ `s.f` is assigned to here but it was already borrowed
+...
+LL |     println!("{a}");
+   |               --- borrow later used here
+   |
+note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules
+  --> $DIR/migration-note.rs:113:13
+   |
+LL |     let a = display_field(&s.f);
+   |             ^^^^^^^^^^^^^^^^^^^
+help: add a precise capturing bound to avoid overcapturing
+   |
+LL | fn display_field<T: Copy + Display>(t: &T) -> impl Display + use<T> {
+   |                                                            ++++++++
+
+error[E0506]: cannot assign to `s.f` because it is borrowed
+  --> $DIR/migration-note.rs:132:5
+   |
+LL |     let a = display_field(&mut s.f);
+   |                           -------- `s.f` is borrowed here
+...
+LL |     s.f = 1;
+   |     ^^^^^^^ `s.f` is assigned to here but it was already borrowed
+...
+LL |     println!("{a}");
+   |               --- borrow later used here
+   |
+note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules
+  --> $DIR/migration-note.rs:129:13
+   |
+LL |     let a = display_field(&mut s.f);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^
+help: add a precise capturing bound to avoid overcapturing
+   |
+LL | fn display_field<T: Copy + Display>(t: &T) -> impl Display + use<T> {
+   |                                                            ++++++++
+
+error[E0503]: cannot use `s.f` because it was mutably borrowed
+  --> $DIR/migration-note.rs:144:5
+   |
+LL |     let a = display_field(&mut s.f);
+   |                           -------- `s.f` is borrowed here
+...
+LL |     s.f;
+   |     ^^^ use of borrowed `s.f`
+...
+LL |     println!("{a}");
+   |               --- borrow later used here
+   |
+note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules
+  --> $DIR/migration-note.rs:141:13
+   |
+LL |     let a = display_field(&mut s.f);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^
+help: add a precise capturing bound to avoid overcapturing
+   |
+LL | fn display_field<T: Copy + Display>(t: &T) -> impl Display + use<T> {
+   |                                                            ++++++++
+
+error[E0597]: `z.f` does not live long enough
+  --> $DIR/migration-note.rs:160:25
+   |
+LL |         let z = Z { f: vec![1] };
+   |             - binding `z` declared here
+LL |
+LL |         x = display_len(&z.f);
+   |                         ^^^^ borrowed value does not live long enough
+...
+LL |     }
+   |     - `z.f` dropped here while still borrowed
+LL |
+LL | }
+   | - borrow might be used here, when `x` is dropped and runs the destructor for type `impl std::fmt::Display`
+   |
+   = note: values in a scope are dropped in the opposite order they are defined
+note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules
+  --> $DIR/migration-note.rs:160:13
+   |
+LL |         x = display_len(&z.f);
+   |             ^^^^^^^^^^^^^^^^^
+help: add a precise capturing bound to avoid overcapturing
+   |
+LL | fn display_len<T>(x: &Vec<T>) -> impl Display + use<T> {
+   |                                               ++++++++
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/migration-note.rs:171:40
+   |
+LL |     let x = { let x = display_len(&mut vec![0]); x };
+   |                                        ^^^^^^^ - - borrow later used here
+   |                                        |       |
+   |                                        |       temporary value is freed at the end of this statement
+   |                                        creates a temporary value which is freed while still in use
+   |
+   = note: consider using a `let` binding to create a longer lived value
+note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules
+  --> $DIR/migration-note.rs:171:23
+   |
+LL |     let x = { let x = display_len(&mut vec![0]); x };
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: add a precise capturing bound to avoid overcapturing
+   |
+LL | fn display_len<T>(x: &Vec<T>) -> impl Display + use<T> {
+   |                                               ++++++++
+
+error: aborting due to 12 previous errors
+
+Some errors have detailed explanations: E0499, E0502, E0503, E0505, E0506, E0597, E0716.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/tests/ui/indexing/index-help.stderr b/tests/ui/indexing/index-help.stderr
index 1291bf2a461..4ec28ddf871 100644
--- a/tests/ui/indexing/index-help.stderr
+++ b/tests/ui/indexing/index-help.stderr
@@ -4,7 +4,7 @@ error[E0277]: the type `[{integer}]` cannot be indexed by `i32`
 LL |     x[0i32];
    |       ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
-   = help: the trait `SliceIndex<[{integer}]>` is not implemented for `i32`, which is required by `Vec<{integer}>: Index<_>`
+   = help: the trait `SliceIndex<[{integer}]>` is not implemented for `i32`
    = help: the trait `SliceIndex<[{integer}]>` is implemented for `usize`
    = help: for that trait implementation, expected `usize`, found `i32`
    = note: required for `Vec<{integer}>` to implement `Index<i32>`
diff --git a/tests/ui/indexing/indexing-requires-a-uint.stderr b/tests/ui/indexing/indexing-requires-a-uint.stderr
index 38e7881dcc6..3041c2c99a1 100644
--- a/tests/ui/indexing/indexing-requires-a-uint.stderr
+++ b/tests/ui/indexing/indexing-requires-a-uint.stderr
@@ -4,7 +4,7 @@ error[E0277]: the type `[{integer}]` cannot be indexed by `u8`
 LL |     [0][0u8];
    |         ^^^ slice indices are of type `usize` or ranges of `usize`
    |
-   = help: the trait `SliceIndex<[{integer}]>` is not implemented for `u8`, which is required by `[{integer}; 1]: Index<_>`
+   = help: the trait `SliceIndex<[{integer}]>` is not implemented for `u8`
    = help: the trait `SliceIndex<[{integer}]>` is implemented for `usize`
    = help: for that trait implementation, expected `usize`, found `u8`
    = note: required for `[{integer}]` to implement `Index<u8>`
diff --git a/tests/ui/indexing/point-at-index-for-obligation-failure.stderr b/tests/ui/indexing/point-at-index-for-obligation-failure.stderr
index df4d7cc0683..4cced22789f 100644
--- a/tests/ui/indexing/point-at-index-for-obligation-failure.stderr
+++ b/tests/ui/indexing/point-at-index-for-obligation-failure.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `String: Borrow<&str>` is not satisfied
   --> $DIR/point-at-index-for-obligation-failure.rs:5:9
    |
 LL |         &s
-   |         ^^ the trait `Borrow<&str>` is not implemented for `String`, which is required by `HashMap<String, String>: Index<&_>`
+   |         ^^ the trait `Borrow<&str>` is not implemented for `String`
    |
    = help: the trait `Borrow<str>` is implemented for `String`
    = help: for that trait implementation, expected `str`, found `&str`
diff --git a/tests/ui/integral-indexing.stderr b/tests/ui/integral-indexing.stderr
index ad2c3af424b..97e658617cf 100644
--- a/tests/ui/integral-indexing.stderr
+++ b/tests/ui/integral-indexing.stderr
@@ -4,7 +4,7 @@ error[E0277]: the type `[isize]` cannot be indexed by `u8`
 LL |     v[3u8];
    |       ^^^ slice indices are of type `usize` or ranges of `usize`
    |
-   = help: the trait `SliceIndex<[isize]>` is not implemented for `u8`, which is required by `Vec<isize>: Index<_>`
+   = help: the trait `SliceIndex<[isize]>` is not implemented for `u8`
    = help: the trait `SliceIndex<[isize]>` is implemented for `usize`
    = help: for that trait implementation, expected `usize`, found `u8`
    = note: required for `Vec<isize>` to implement `Index<u8>`
@@ -15,7 +15,7 @@ error[E0277]: the type `[isize]` cannot be indexed by `i8`
 LL |     v[3i8];
    |       ^^^ slice indices are of type `usize` or ranges of `usize`
    |
-   = help: the trait `SliceIndex<[isize]>` is not implemented for `i8`, which is required by `Vec<isize>: Index<_>`
+   = help: the trait `SliceIndex<[isize]>` is not implemented for `i8`
    = help: the trait `SliceIndex<[isize]>` is implemented for `usize`
    = help: for that trait implementation, expected `usize`, found `i8`
    = note: required for `Vec<isize>` to implement `Index<i8>`
@@ -26,7 +26,7 @@ error[E0277]: the type `[isize]` cannot be indexed by `u32`
 LL |     v[3u32];
    |       ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
-   = help: the trait `SliceIndex<[isize]>` is not implemented for `u32`, which is required by `Vec<isize>: Index<_>`
+   = help: the trait `SliceIndex<[isize]>` is not implemented for `u32`
    = help: the trait `SliceIndex<[isize]>` is implemented for `usize`
    = help: for that trait implementation, expected `usize`, found `u32`
    = note: required for `Vec<isize>` to implement `Index<u32>`
@@ -37,7 +37,7 @@ error[E0277]: the type `[isize]` cannot be indexed by `i32`
 LL |     v[3i32];
    |       ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
-   = help: the trait `SliceIndex<[isize]>` is not implemented for `i32`, which is required by `Vec<isize>: Index<_>`
+   = help: the trait `SliceIndex<[isize]>` is not implemented for `i32`
    = help: the trait `SliceIndex<[isize]>` is implemented for `usize`
    = help: for that trait implementation, expected `usize`, found `i32`
    = note: required for `Vec<isize>` to implement `Index<i32>`
@@ -48,7 +48,7 @@ error[E0277]: the type `[u8]` cannot be indexed by `u8`
 LL |     s.as_bytes()[3u8];
    |                  ^^^ slice indices are of type `usize` or ranges of `usize`
    |
-   = help: the trait `SliceIndex<[u8]>` is not implemented for `u8`, which is required by `[u8]: Index<_>`
+   = help: the trait `SliceIndex<[u8]>` is not implemented for `u8`
    = help: the trait `SliceIndex<[u8]>` is implemented for `usize`
    = help: for that trait implementation, expected `usize`, found `u8`
    = note: required for `[u8]` to implement `Index<u8>`
@@ -59,7 +59,7 @@ error[E0277]: the type `[u8]` cannot be indexed by `i8`
 LL |     s.as_bytes()[3i8];
    |                  ^^^ slice indices are of type `usize` or ranges of `usize`
    |
-   = help: the trait `SliceIndex<[u8]>` is not implemented for `i8`, which is required by `[u8]: Index<_>`
+   = help: the trait `SliceIndex<[u8]>` is not implemented for `i8`
    = help: the trait `SliceIndex<[u8]>` is implemented for `usize`
    = help: for that trait implementation, expected `usize`, found `i8`
    = note: required for `[u8]` to implement `Index<i8>`
@@ -70,7 +70,7 @@ error[E0277]: the type `[u8]` cannot be indexed by `u32`
 LL |     s.as_bytes()[3u32];
    |                  ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
-   = help: the trait `SliceIndex<[u8]>` is not implemented for `u32`, which is required by `[u8]: Index<_>`
+   = help: the trait `SliceIndex<[u8]>` is not implemented for `u32`
    = help: the trait `SliceIndex<[u8]>` is implemented for `usize`
    = help: for that trait implementation, expected `usize`, found `u32`
    = note: required for `[u8]` to implement `Index<u32>`
@@ -81,7 +81,7 @@ error[E0277]: the type `[u8]` cannot be indexed by `i32`
 LL |     s.as_bytes()[3i32];
    |                  ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
-   = help: the trait `SliceIndex<[u8]>` is not implemented for `i32`, which is required by `[u8]: Index<_>`
+   = help: the trait `SliceIndex<[u8]>` is not implemented for `i32`
    = help: the trait `SliceIndex<[u8]>` is implemented for `usize`
    = help: for that trait implementation, expected `usize`, found `i32`
    = note: required for `[u8]` to implement `Index<i32>`
diff --git a/tests/ui/interior-mutability/interior-mutability.stderr b/tests/ui/interior-mutability/interior-mutability.stderr
index 29b250c1b07..cfc64445bf3 100644
--- a/tests/ui/interior-mutability/interior-mutability.stderr
+++ b/tests/ui/interior-mutability/interior-mutability.stderr
@@ -6,7 +6,7 @@ LL |     catch_unwind(|| { x.set(23); });
    |     |
    |     required by a bound introduced by this call
    |
-   = help: within `Cell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<i32>`, which is required by `{closure@$DIR/interior-mutability.rs:5:18: 5:20}: UnwindSafe`
+   = help: within `Cell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<i32>`
 note: required because it appears within the type `Cell<i32>`
   --> $SRC_DIR/core/src/cell.rs:LL:COL
    = note: required for `&Cell<i32>` to implement `UnwindSafe`
diff --git a/tests/ui/intrinsics/safe-intrinsic-mismatch.effects.stderr b/tests/ui/intrinsics/safe-intrinsic-mismatch.effects.stderr
index 55983a445a4..c59e357b275 100644
--- a/tests/ui/intrinsics/safe-intrinsic-mismatch.effects.stderr
+++ b/tests/ui/intrinsics/safe-intrinsic-mismatch.effects.stderr
@@ -1,8 +1,3 @@
-error: using `#![feature(effects)]` without enabling next trait solver globally
-   |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
-
 error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `size_of`
   --> $DIR/safe-intrinsic-mismatch.rs:11:5
    |
@@ -47,6 +42,6 @@ LL | const fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {}
    = note: expected signature `unsafe fn(_, _, _)`
               found signature `fn(_, _, _)`
 
-error: aborting due to 7 previous errors
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/issues/issue-21763.stderr b/tests/ui/issues/issue-21763.stderr
index aa4938a0c0b..135b705eeef 100644
--- a/tests/ui/issues/issue-21763.stderr
+++ b/tests/ui/issues/issue-21763.stderr
@@ -4,7 +4,7 @@ error[E0277]: `Rc<()>` cannot be sent between threads safely
 LL |     foo::<HashMap<Rc<()>, Rc<()>>>();
    |           ^^^^^^^^^^^^^^^^^^^^^^^ `Rc<()>` cannot be sent between threads safely
    |
-   = help: within `(Rc<()>, Rc<()>)`, the trait `Send` is not implemented for `Rc<()>`, which is required by `HashMap<Rc<()>, Rc<()>>: Send`
+   = help: within `(Rc<()>, Rc<()>)`, the trait `Send` is not implemented for `Rc<()>`
    = note: required because it appears within the type `(Rc<()>, Rc<()>)`
    = note: required for `hashbrown::raw::RawTable<(Rc<()>, Rc<()>)>` to implement `Send`
 note: required because it appears within the type `hashbrown::map::HashMap<Rc<()>, Rc<()>, RandomState>`
diff --git a/tests/ui/issues/issue-22872.stderr b/tests/ui/issues/issue-22872.stderr
index 03e5393da48..6ff710b1133 100644
--- a/tests/ui/issues/issue-22872.stderr
+++ b/tests/ui/issues/issue-22872.stderr
@@ -4,7 +4,7 @@ error[E0277]: `<P as Process<'_>>::Item` is not an iterator
 LL |     let _: Box<dyn for<'b> Wrap<'b>> = Box::new(Wrapper(process));
    |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^ `<P as Process<'_>>::Item` is not an iterator
    |
-   = help: the trait `Iterator` is not implemented for `<P as Process<'_>>::Item`, which is required by `for<'b> Wrapper<P>: Wrap<'b>`
+   = help: the trait `Iterator` is not implemented for `<P as Process<'_>>::Item`
 note: required for `Wrapper<P>` to implement `for<'b> Wrap<'b>`
   --> $DIR/issue-22872.rs:7:13
    |
diff --git a/tests/ui/issues/issue-22874.stderr b/tests/ui/issues/issue-22874.stderr
index 29ddf9756ff..7d5b601ed49 100644
--- a/tests/ui/issues/issue-22874.stderr
+++ b/tests/ui/issues/issue-22874.stderr
@@ -13,7 +13,7 @@ error[E0277]: the size for values of type `[String]` cannot be known at compilat
 LL |     &table.rows[0]
    |      ^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = help: the trait `Sized` is not implemented for `[String]`, which is required by `[_]: Index<_>`
+   = help: the trait `Sized` is not implemented for `[String]`
    = note: required for `[[String]]` to implement `Index<_>`
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/issues/issue-37534.rs b/tests/ui/issues/issue-37534.rs
index 40f7186db09..dff89d3888d 100644
--- a/tests/ui/issues/issue-37534.rs
+++ b/tests/ui/issues/issue-37534.rs
@@ -1,6 +1,5 @@
 struct Foo<T: ?Hash> {}
 //~^ ERROR expected trait, found derive macro `Hash`
-//~^^ ERROR parameter `T` is never used
-//~^^^ WARN relaxing a default bound only does something for `?Sized`
+//~| WARN relaxing a default bound only does something for `?Sized`
 
 fn main() {}
diff --git a/tests/ui/issues/issue-37534.stderr b/tests/ui/issues/issue-37534.stderr
index a687e733d3d..8747bd5ac6f 100644
--- a/tests/ui/issues/issue-37534.stderr
+++ b/tests/ui/issues/issue-37534.stderr
@@ -15,15 +15,6 @@ warning: relaxing a default bound only does something for `?Sized`; all other tr
 LL | struct Foo<T: ?Hash> {}
    |               ^^^^^
 
-error[E0392]: type parameter `T` is never used
-  --> $DIR/issue-37534.rs:1:12
-   |
-LL | struct Foo<T: ?Hash> {}
-   |            ^ unused type parameter
-   |
-   = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
-
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 1 previous error; 1 warning emitted
 
-Some errors have detailed explanations: E0392, E0404.
-For more information about an error, try `rustc --explain E0392`.
+For more information about this error, try `rustc --explain E0404`.
diff --git a/tests/ui/issues/issue-40827.stderr b/tests/ui/issues/issue-40827.stderr
index 44ae90cbc0f..7f5c578ae4f 100644
--- a/tests/ui/issues/issue-40827.stderr
+++ b/tests/ui/issues/issue-40827.stderr
@@ -6,7 +6,7 @@ LL |     f(Foo(Arc::new(Bar::B(None))));
    |     |
    |     required by a bound introduced by this call
    |
-   = help: within `Bar`, the trait `Sync` is not implemented for `Rc<Foo>`, which is required by `Foo: Send`
+   = help: within `Bar`, the trait `Sync` is not implemented for `Rc<Foo>`
 note: required because it appears within the type `Bar`
   --> $DIR/issue-40827.rs:6:6
    |
@@ -32,7 +32,7 @@ LL |     f(Foo(Arc::new(Bar::B(None))));
    |     |
    |     required by a bound introduced by this call
    |
-   = help: within `Bar`, the trait `Send` is not implemented for `Rc<Foo>`, which is required by `Foo: Send`
+   = help: within `Bar`, the trait `Send` is not implemented for `Rc<Foo>`
 note: required because it appears within the type `Bar`
   --> $DIR/issue-40827.rs:6:6
    |
diff --git a/tests/ui/issues/issue-7364.stderr b/tests/ui/issues/issue-7364.stderr
index d5b6dde1f10..65ec1d75053 100644
--- a/tests/ui/issues/issue-7364.stderr
+++ b/tests/ui/issues/issue-7364.stderr
@@ -4,7 +4,7 @@ error[E0277]: `RefCell<isize>` cannot be shared between threads safely
 LL | static boxed: Box<RefCell<isize>> = Box::new(RefCell::new(0));
    |               ^^^^^^^^^^^^^^^^^^^ `RefCell<isize>` cannot be shared between threads safely
    |
-   = help: the trait `Sync` is not implemented for `RefCell<isize>`, which is required by `Box<RefCell<isize>>: Sync`
+   = help: the trait `Sync` is not implemented for `RefCell<isize>`
    = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
    = note: required for `Unique<RefCell<isize>>` to implement `Sync`
 note: required because it appears within the type `Box<RefCell<isize>>`
diff --git a/tests/ui/iterators/float_iterator_hint.stderr b/tests/ui/iterators/float_iterator_hint.stderr
index 29319b9400f..c3cb00c3c68 100644
--- a/tests/ui/iterators/float_iterator_hint.stderr
+++ b/tests/ui/iterators/float_iterator_hint.stderr
@@ -4,7 +4,7 @@ error[E0277]: `{float}` is not an iterator
 LL |     for i in 0.2 {
    |              ^^^ `{float}` is not an iterator
    |
-   = help: the trait `Iterator` is not implemented for `{float}`, which is required by `{float}: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `{float}`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
    = note: required for `{float}` to implement `IntoIterator`
 
diff --git a/tests/ui/iterators/integral.stderr b/tests/ui/iterators/integral.stderr
index 74bbe28d6b7..c142fec8da0 100644
--- a/tests/ui/iterators/integral.stderr
+++ b/tests/ui/iterators/integral.stderr
@@ -4,7 +4,7 @@ error[E0277]: `{integer}` is not an iterator
 LL |     for _ in 42 {}
    |              ^^ `{integer}` is not an iterator
    |
-   = help: the trait `Iterator` is not implemented for `{integer}`, which is required by `{integer}: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `{integer}`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
    = note: required for `{integer}` to implement `IntoIterator`
 
@@ -14,7 +14,7 @@ error[E0277]: `u8` is not an iterator
 LL |     for _ in 42 as u8 {}
    |              ^^^^^^^^ `u8` is not an iterator
    |
-   = help: the trait `Iterator` is not implemented for `u8`, which is required by `u8: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `u8`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
    = note: required for `u8` to implement `IntoIterator`
 
@@ -24,7 +24,7 @@ error[E0277]: `i8` is not an iterator
 LL |     for _ in 42 as i8 {}
    |              ^^^^^^^^ `i8` is not an iterator
    |
-   = help: the trait `Iterator` is not implemented for `i8`, which is required by `i8: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `i8`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
    = note: required for `i8` to implement `IntoIterator`
 
@@ -34,7 +34,7 @@ error[E0277]: `u16` is not an iterator
 LL |     for _ in 42 as u16 {}
    |              ^^^^^^^^^ `u16` is not an iterator
    |
-   = help: the trait `Iterator` is not implemented for `u16`, which is required by `u16: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `u16`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
    = note: required for `u16` to implement `IntoIterator`
 
@@ -44,7 +44,7 @@ error[E0277]: `i16` is not an iterator
 LL |     for _ in 42 as i16 {}
    |              ^^^^^^^^^ `i16` is not an iterator
    |
-   = help: the trait `Iterator` is not implemented for `i16`, which is required by `i16: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `i16`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
    = note: required for `i16` to implement `IntoIterator`
 
@@ -54,7 +54,7 @@ error[E0277]: `u32` is not an iterator
 LL |     for _ in 42 as u32 {}
    |              ^^^^^^^^^ `u32` is not an iterator
    |
-   = help: the trait `Iterator` is not implemented for `u32`, which is required by `u32: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `u32`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
    = note: required for `u32` to implement `IntoIterator`
 
@@ -64,7 +64,7 @@ error[E0277]: `i32` is not an iterator
 LL |     for _ in 42 as i32 {}
    |              ^^^^^^^^^ `i32` is not an iterator
    |
-   = help: the trait `Iterator` is not implemented for `i32`, which is required by `i32: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `i32`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
    = note: required for `i32` to implement `IntoIterator`
 
@@ -74,7 +74,7 @@ error[E0277]: `u64` is not an iterator
 LL |     for _ in 42 as u64 {}
    |              ^^^^^^^^^ `u64` is not an iterator
    |
-   = help: the trait `Iterator` is not implemented for `u64`, which is required by `u64: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `u64`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
    = note: required for `u64` to implement `IntoIterator`
 
@@ -84,7 +84,7 @@ error[E0277]: `i64` is not an iterator
 LL |     for _ in 42 as i64 {}
    |              ^^^^^^^^^ `i64` is not an iterator
    |
-   = help: the trait `Iterator` is not implemented for `i64`, which is required by `i64: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `i64`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
    = note: required for `i64` to implement `IntoIterator`
 
@@ -94,7 +94,7 @@ error[E0277]: `usize` is not an iterator
 LL |     for _ in 42 as usize {}
    |              ^^^^^^^^^^^ `usize` is not an iterator
    |
-   = help: the trait `Iterator` is not implemented for `usize`, which is required by `usize: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `usize`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
    = note: required for `usize` to implement `IntoIterator`
 
@@ -104,7 +104,7 @@ error[E0277]: `isize` is not an iterator
 LL |     for _ in 42 as isize {}
    |              ^^^^^^^^^^^ `isize` is not an iterator
    |
-   = help: the trait `Iterator` is not implemented for `isize`, which is required by `isize: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `isize`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
    = note: required for `isize` to implement `IntoIterator`
 
@@ -114,7 +114,7 @@ error[E0277]: `{float}` is not an iterator
 LL |     for _ in 42.0 {}
    |              ^^^^ `{float}` is not an iterator
    |
-   = help: the trait `Iterator` is not implemented for `{float}`, which is required by `{float}: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `{float}`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
    = note: required for `{float}` to implement `IntoIterator`
 
diff --git a/tests/ui/iterators/issue-28098.stderr b/tests/ui/iterators/issue-28098.stderr
index 3cb1b2f7270..a724f03ad4a 100644
--- a/tests/ui/iterators/issue-28098.stderr
+++ b/tests/ui/iterators/issue-28098.stderr
@@ -14,7 +14,7 @@ error[E0277]: `bool` is not an iterator
 LL |     for _ in false {}
    |              ^^^^^ `bool` is not an iterator
    |
-   = help: the trait `Iterator` is not implemented for `bool`, which is required by `bool: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `bool`
    = note: required for `bool` to implement `IntoIterator`
 
 error[E0277]: `()` is not an iterator
@@ -61,7 +61,7 @@ error[E0277]: `bool` is not an iterator
 LL |     for _ in false {}
    |              ^^^^^ `bool` is not an iterator
    |
-   = help: the trait `Iterator` is not implemented for `bool`, which is required by `bool: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `bool`
    = note: required for `bool` to implement `IntoIterator`
 
 error[E0277]: `()` is not an iterator
diff --git a/tests/ui/iterators/ranges.stderr b/tests/ui/iterators/ranges.stderr
index a5d43ecbb63..b9fbcd5304b 100644
--- a/tests/ui/iterators/ranges.stderr
+++ b/tests/ui/iterators/ranges.stderr
@@ -4,7 +4,7 @@ error[E0277]: `RangeTo<{integer}>` is not an iterator
 LL |     for _ in ..10 {}
    |              ^^^^ if you meant to iterate until a value, add a starting value
    |
-   = help: the trait `Iterator` is not implemented for `RangeTo<{integer}>`, which is required by `RangeTo<{integer}>: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `RangeTo<{integer}>`
    = note: `..end` is a `RangeTo`, which cannot be iterated on; you might have meant to have a bounded `Range`: `0..end`
    = note: required for `RangeTo<{integer}>` to implement `IntoIterator`
 
@@ -14,7 +14,7 @@ error[E0277]: `RangeToInclusive<{integer}>` is not an iterator
 LL |     for _ in ..=10 {}
    |              ^^^^^ if you meant to iterate until a value (including it), add a starting value
    |
-   = help: the trait `Iterator` is not implemented for `RangeToInclusive<{integer}>`, which is required by `RangeToInclusive<{integer}>: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `RangeToInclusive<{integer}>`
    = note: `..=end` is a `RangeToInclusive`, which cannot be iterated on; you might have meant to have a bounded `RangeInclusive`: `0..=end`
    = note: required for `RangeToInclusive<{integer}>` to implement `IntoIterator`
 
diff --git a/tests/ui/iterators/string.stderr b/tests/ui/iterators/string.stderr
index 29f560677c0..ddfe0169b84 100644
--- a/tests/ui/iterators/string.stderr
+++ b/tests/ui/iterators/string.stderr
@@ -4,7 +4,7 @@ error[E0277]: `String` is not an iterator
 LL |     for _ in "".to_owned() {}
    |              ^^^^^^^^^^^^^ `String` is not an iterator; try calling `.chars()` or `.bytes()`
    |
-   = help: the trait `Iterator` is not implemented for `String`, which is required by `String: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `String`
    = note: required for `String` to implement `IntoIterator`
 
 error[E0277]: `&str` is not an iterator
@@ -13,7 +13,7 @@ error[E0277]: `&str` is not an iterator
 LL |     for _ in "" {}
    |              ^^ `&str` is not an iterator; try calling `.chars()` or `.bytes()`
    |
-   = help: the trait `Iterator` is not implemented for `&str`, which is required by `&str: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `&str`
    = note: required for `&str` to implement `IntoIterator`
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/json/json-bom-plus-crlf-multifile.rs b/tests/ui/json/json-bom-plus-crlf-multifile.rs
index ae608770aae..79c4b2430e1 100644
--- a/tests/ui/json/json-bom-plus-crlf-multifile.rs
+++ b/tests/ui/json/json-bom-plus-crlf-multifile.rs
@@ -1,6 +1,8 @@
 // (This line has BOM so it's ignored by compiletest for directives)

 //

 //@ compile-flags: --json=diagnostic-short --error-format=json

+//@ reference: input.byte-order-mark

+//@ reference: input.crlf

 // ignore-tidy-cr

 

 #[path = "json-bom-plus-crlf-multifile-aux.rs"]

diff --git a/tests/ui/json/json-bom-plus-crlf.rs b/tests/ui/json/json-bom-plus-crlf.rs
index 4a309128199..9e250c256eb 100644
--- a/tests/ui/json/json-bom-plus-crlf.rs
+++ b/tests/ui/json/json-bom-plus-crlf.rs
@@ -1,6 +1,8 @@
 // (This line has BOM so it's ignored by compiletest for directives)

 //

 //@ compile-flags: --json=diagnostic-short --error-format=json

+//@ reference: input.byte-order-mark

+//@ reference: input.crlf

 // ignore-tidy-cr

 

 // For easier verifying, the byte offsets in this file should match those

diff --git a/tests/ui/json/json-bom-plus-crlf.stderr b/tests/ui/json/json-bom-plus-crlf.stderr
index cd1e3665b3e..fee70431bdf 100644
--- a/tests/ui/json/json-bom-plus-crlf.stderr
+++ b/tests/ui/json/json-bom-plus-crlf.stderr
@@ -24,7 +24,7 @@ This error occurs when an expression was used in a place where the compiler
 expected an expression of a different type. It can occur in several cases, the
 most common being when calling a function and passing an argument which has a
 different type than the matching type in the function declaration.
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":607,"byte_end":608,"line_start":16,"line_end":16,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":"    let s : String = 1;  // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":598,"byte_end":604,"line_start":16,"line_end":16,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String = 1;  // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":608,"byte_end":608,"line_start":16,"line_end":16,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":"    let s : String = 1;  // Error in the middle of line.","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:16:22: error[E0308]: mismatched types: expected `String`, found integer
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":672,"byte_end":673,"line_start":18,"line_end":18,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":"    let s : String = 1;  // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":663,"byte_end":669,"line_start":18,"line_end":18,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String = 1;  // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":673,"byte_end":673,"line_start":18,"line_end":18,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":"    let s : String = 1;  // Error in the middle of line.","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:18:22: error[E0308]: mismatched types: expected `String`, found integer
 "}
 {"$message_type":"diagnostic","message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
 
@@ -52,7 +52,7 @@ This error occurs when an expression was used in a place where the compiler
 expected an expression of a different type. It can occur in several cases, the
 most common being when calling a function and passing an argument which has a
 different type than the matching type in the function declaration.
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":667,"byte_end":668,"line_start":18,"line_end":18,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":"    let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":658,"byte_end":664,"line_start":18,"line_end":18,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":668,"byte_end":668,"line_start":18,"line_end":18,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":"    let s : String = 1","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:18:22: error[E0308]: mismatched types: expected `String`, found integer
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":732,"byte_end":733,"line_start":20,"line_end":20,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":"    let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":723,"byte_end":729,"line_start":20,"line_end":20,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":733,"byte_end":733,"line_start":20,"line_end":20,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":"    let s : String = 1","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:20:22: error[E0308]: mismatched types: expected `String`, found integer
 "}
 {"$message_type":"diagnostic","message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
 
@@ -80,7 +80,7 @@ This error occurs when an expression was used in a place where the compiler
 expected an expression of a different type. It can occur in several cases, the
 most common being when calling a function and passing an argument which has a
 different type than the matching type in the function declaration.
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":731,"byte_end":732,"line_start":22,"line_end":22,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1;  // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":721,"byte_end":727,"line_start":21,"line_end":21,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":732,"byte_end":732,"line_start":22,"line_end":22,"column_start":2,"column_end":2,"is_primary":true,"text":[{"text":"1;  // Error after the newline.","highlight_start":2,"highlight_end":2}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:22:1: error[E0308]: mismatched types: expected `String`, found integer
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":796,"byte_end":797,"line_start":24,"line_end":24,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1;  // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":786,"byte_end":792,"line_start":23,"line_end":23,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":797,"byte_end":797,"line_start":24,"line_end":24,"column_start":2,"column_end":2,"is_primary":true,"text":[{"text":"1;  // Error after the newline.","highlight_start":2,"highlight_end":2}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:24:1: error[E0308]: mismatched types: expected `String`, found integer
 "}
 {"$message_type":"diagnostic","message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
 
@@ -108,7 +108,7 @@ This error occurs when an expression was used in a place where the compiler
 expected an expression of a different type. It can occur in several cases, the
 most common being when calling a function and passing an argument which has a
 different type than the matching type in the function declaration.
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":787,"byte_end":795,"line_start":24,"line_end":25,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":"    let s : String = (","highlight_start":22,"highlight_end":23},{"text":"    );  // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected `String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":778,"byte_end":784,"line_start":24,"line_end":24,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf.rs:24:22: error[E0308]: mismatched types: expected `String`, found `()`
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":852,"byte_end":860,"line_start":26,"line_end":27,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":"    let s : String = (","highlight_start":22,"highlight_end":23},{"text":"    );  // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected `String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":843,"byte_end":849,"line_start":26,"line_end":26,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf.rs:26:22: error[E0308]: mismatched types: expected `String`, found `()`
 "}
 {"$message_type":"diagnostic","message":"aborting due to 4 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 4 previous errors
 "}
diff --git a/tests/ui/kindck/kindck-impl-type-params-2.stderr b/tests/ui/kindck/kindck-impl-type-params-2.stderr
index a7d169d3ac4..38dc94f9104 100644
--- a/tests/ui/kindck/kindck-impl-type-params-2.stderr
+++ b/tests/ui/kindck/kindck-impl-type-params-2.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied
   --> $DIR/kindck-impl-type-params-2.rs:13:16
    |
 LL |     take_param(&x);
-   |     ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>`, which is required by `Box<{integer}>: Foo`
+   |     ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>`
    |     |
    |     required by a bound introduced by this call
    |
diff --git a/tests/ui/kindck/kindck-impl-type-params.stderr b/tests/ui/kindck/kindck-impl-type-params.stderr
index 5892596dc6a..da9a8e5532c 100644
--- a/tests/ui/kindck/kindck-impl-type-params.stderr
+++ b/tests/ui/kindck/kindck-impl-type-params.stderr
@@ -21,7 +21,7 @@ error[E0277]: the trait bound `T: Copy` is not satisfied
   --> $DIR/kindck-impl-type-params.rs:16:13
    |
 LL |     let a = &t as &dyn Gettable<T>;
-   |             ^^ the trait `Copy` is not implemented for `T`, which is required by `S<T>: Gettable<T>`
+   |             ^^ the trait `Copy` is not implemented for `T`
    |
 note: required for `S<T>` to implement `Gettable<T>`
   --> $DIR/kindck-impl-type-params.rs:12:32
@@ -59,7 +59,7 @@ error[E0277]: the trait bound `T: Copy` is not satisfied
   --> $DIR/kindck-impl-type-params.rs:23:31
    |
 LL |     let a: &dyn Gettable<T> = &t;
-   |                               ^^ the trait `Copy` is not implemented for `T`, which is required by `S<T>: Gettable<T>`
+   |                               ^^ the trait `Copy` is not implemented for `T`
    |
 note: required for `S<T>` to implement `Gettable<T>`
   --> $DIR/kindck-impl-type-params.rs:12:32
@@ -78,7 +78,7 @@ error[E0277]: the trait bound `String: Copy` is not satisfied
   --> $DIR/kindck-impl-type-params.rs:36:13
    |
 LL |     let a = t as Box<dyn Gettable<String>>;
-   |             ^ the trait `Copy` is not implemented for `String`, which is required by `S<String>: Gettable<String>`
+   |             ^ the trait `Copy` is not implemented for `String`
    |
    = help: the trait `Gettable<T>` is implemented for `S<T>`
 note: required for `S<String>` to implement `Gettable<String>`
@@ -94,7 +94,7 @@ error[E0277]: the trait bound `Foo: Copy` is not satisfied
   --> $DIR/kindck-impl-type-params.rs:44:37
    |
 LL |     let a: Box<dyn Gettable<Foo>> = t;
-   |                                     ^ the trait `Copy` is not implemented for `Foo`, which is required by `S<Foo>: Gettable<Foo>`
+   |                                     ^ the trait `Copy` is not implemented for `Foo`
    |
    = help: the trait `Gettable<T>` is implemented for `S<T>`
 note: required for `S<Foo>` to implement `Gettable<Foo>`
diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr b/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr
index e797ca01f4b..c392879db3e 100644
--- a/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr
+++ b/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied
   --> $DIR/kindck-inherited-copy-bound.rs:21:16
    |
 LL |     take_param(&x);
-   |     ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>`, which is required by `Box<{integer}>: Foo`
+   |     ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>`
    |     |
    |     required by a bound introduced by this call
    |
diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.dyn_compatible_for_dispatch.stderr b/tests/ui/kindck/kindck-inherited-copy-bound.dyn_compatible_for_dispatch.stderr
index b4424f4750e..34dcad13af3 100644
--- a/tests/ui/kindck/kindck-inherited-copy-bound.dyn_compatible_for_dispatch.stderr
+++ b/tests/ui/kindck/kindck-inherited-copy-bound.dyn_compatible_for_dispatch.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied
   --> $DIR/kindck-inherited-copy-bound.rs:21:16
    |
 LL |     take_param(&x);
-   |     ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>`, which is required by `Box<{integer}>: Foo`
+   |     ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>`
    |     |
    |     required by a bound introduced by this call
    |
diff --git a/tests/ui/kindck/kindck-nonsendable-1.stderr b/tests/ui/kindck/kindck-nonsendable-1.stderr
index 8cc931bc48e..8bb784d1d49 100644
--- a/tests/ui/kindck/kindck-nonsendable-1.stderr
+++ b/tests/ui/kindck/kindck-nonsendable-1.stderr
@@ -8,7 +8,7 @@ LL |     bar(move|| foo(x));
    |     |   within this `{closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:15}`
    |     required by a bound introduced by this call
    |
-   = help: within `{closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:15}`, the trait `Send` is not implemented for `Rc<usize>`, which is required by `{closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:15}: Send`
+   = help: within `{closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:15}`, the trait `Send` is not implemented for `Rc<usize>`
 note: required because it's used within this closure
   --> $DIR/kindck-nonsendable-1.rs:9:9
    |
diff --git a/tests/ui/kindck/kindck-send-object.stderr b/tests/ui/kindck/kindck-send-object.stderr
index 7d0c711abc4..0e2ff1730c8 100644
--- a/tests/ui/kindck/kindck-send-object.stderr
+++ b/tests/ui/kindck/kindck-send-object.stderr
@@ -4,7 +4,7 @@ error[E0277]: `&'static (dyn Dummy + 'static)` cannot be sent between threads sa
 LL |     assert_send::<&'static (dyn Dummy + 'static)>();
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&'static (dyn Dummy + 'static)` cannot be sent between threads safely
    |
-   = help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send`
+   = help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)`
    = note: required for `&'static (dyn Dummy + 'static)` to implement `Send`
 note: required by a bound in `assert_send`
   --> $DIR/kindck-send-object.rs:5:18
@@ -18,7 +18,7 @@ error[E0277]: `dyn Dummy` cannot be sent between threads safely
 LL |     assert_send::<Box<dyn Dummy>>();
    |                   ^^^^^^^^^^^^^^ `dyn Dummy` cannot be sent between threads safely
    |
-   = help: the trait `Send` is not implemented for `dyn Dummy`, which is required by `Box<dyn Dummy>: Send`
+   = help: the trait `Send` is not implemented for `dyn Dummy`
    = note: required for `Unique<dyn Dummy>` to implement `Send`
 note: required because it appears within the type `Box<dyn Dummy>`
   --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
diff --git a/tests/ui/kindck/kindck-send-object1.stderr b/tests/ui/kindck/kindck-send-object1.stderr
index 7f39dab2086..e3ff2eb9ff4 100644
--- a/tests/ui/kindck/kindck-send-object1.stderr
+++ b/tests/ui/kindck/kindck-send-object1.stderr
@@ -4,7 +4,7 @@ error[E0277]: `&'a (dyn Dummy + 'a)` cannot be sent between threads safely
 LL |     assert_send::<&'a dyn Dummy>();
    |                   ^^^^^^^^^^^^^ `&'a (dyn Dummy + 'a)` cannot be sent between threads safely
    |
-   = help: the trait `Sync` is not implemented for `(dyn Dummy + 'a)`, which is required by `&'a (dyn Dummy + 'a): Send`
+   = help: the trait `Sync` is not implemented for `(dyn Dummy + 'a)`
    = note: required for `&'a (dyn Dummy + 'a)` to implement `Send`
 note: required by a bound in `assert_send`
   --> $DIR/kindck-send-object1.rs:5:18
@@ -18,7 +18,7 @@ error[E0277]: `(dyn Dummy + 'a)` cannot be sent between threads safely
 LL |     assert_send::<Box<dyn Dummy + 'a>>();
    |                   ^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be sent between threads safely
    |
-   = help: the trait `Send` is not implemented for `(dyn Dummy + 'a)`, which is required by `Box<(dyn Dummy + 'a)>: Send`
+   = help: the trait `Send` is not implemented for `(dyn Dummy + 'a)`
    = note: required for `Unique<(dyn Dummy + 'a)>` to implement `Send`
 note: required because it appears within the type `Box<(dyn Dummy + 'a)>`
   --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
diff --git a/tests/ui/kindck/kindck-send-object2.stderr b/tests/ui/kindck/kindck-send-object2.stderr
index a481a132cce..8898bf5b3fa 100644
--- a/tests/ui/kindck/kindck-send-object2.stderr
+++ b/tests/ui/kindck/kindck-send-object2.stderr
@@ -4,7 +4,7 @@ error[E0277]: `&'static (dyn Dummy + 'static)` cannot be sent between threads sa
 LL |     assert_send::<&'static dyn Dummy>();
    |                   ^^^^^^^^^^^^^^^^^^ `&'static (dyn Dummy + 'static)` cannot be sent between threads safely
    |
-   = help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send`
+   = help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)`
    = note: required for `&'static (dyn Dummy + 'static)` to implement `Send`
 note: required by a bound in `assert_send`
   --> $DIR/kindck-send-object2.rs:3:18
@@ -18,7 +18,7 @@ error[E0277]: `dyn Dummy` cannot be sent between threads safely
 LL |     assert_send::<Box<dyn Dummy>>();
    |                   ^^^^^^^^^^^^^^ `dyn Dummy` cannot be sent between threads safely
    |
-   = help: the trait `Send` is not implemented for `dyn Dummy`, which is required by `Box<dyn Dummy>: Send`
+   = help: the trait `Send` is not implemented for `dyn Dummy`
    = note: required for `Unique<dyn Dummy>` to implement `Send`
 note: required because it appears within the type `Box<dyn Dummy>`
   --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
diff --git a/tests/ui/kindck/kindck-send-owned.stderr b/tests/ui/kindck/kindck-send-owned.stderr
index 4bc0212089b..860a9391bbb 100644
--- a/tests/ui/kindck/kindck-send-owned.stderr
+++ b/tests/ui/kindck/kindck-send-owned.stderr
@@ -4,7 +4,7 @@ error[E0277]: `*mut u8` cannot be sent between threads safely
 LL |     assert_send::<Box<*mut u8>>();
    |                   ^^^^^^^^^^^^ `*mut u8` cannot be sent between threads safely
    |
-   = help: the trait `Send` is not implemented for `*mut u8`, which is required by `Box<*mut u8>: Send`
+   = help: the trait `Send` is not implemented for `*mut u8`
    = note: required for `Unique<*mut u8>` to implement `Send`
 note: required because it appears within the type `Box<*mut u8>`
   --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
diff --git a/tests/ui/layout/debug.stderr b/tests/ui/layout/debug.stderr
index c9715a8e146..bd31665dac1 100644
--- a/tests/ui/layout/debug.stderr
+++ b/tests/ui/layout/debug.stderr
@@ -10,7 +10,7 @@ error: layout_of(E) = Layout {
                abi: Align(4 bytes),
                pref: $SOME_ALIGN,
            },
-           abi: Aggregate {
+           abi: Memory {
                sized: true,
            },
            fields: Arbitrary {
@@ -48,7 +48,7 @@ error: layout_of(E) = Layout {
                            abi: Align(1 bytes),
                            pref: $SOME_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -150,7 +150,7 @@ error: layout_of(U) = Layout {
                abi: Align(4 bytes),
                pref: $SOME_ALIGN,
            },
-           abi: Aggregate {
+           abi: Memory {
                sized: true,
            },
            fields: Union(
@@ -337,7 +337,7 @@ error: layout_of(V) = Layout {
                abi: Align(2 bytes),
                pref: $SOME_ALIGN,
            },
-           abi: Aggregate {
+           abi: Memory {
                sized: true,
            },
            fields: Union(
@@ -361,7 +361,7 @@ error: layout_of(W) = Layout {
                abi: Align(2 bytes),
                pref: $SOME_ALIGN,
            },
-           abi: Aggregate {
+           abi: Memory {
                sized: true,
            },
            fields: Union(
@@ -385,7 +385,7 @@ error: layout_of(Y) = Layout {
                abi: Align(2 bytes),
                pref: $SOME_ALIGN,
            },
-           abi: Aggregate {
+           abi: Memory {
                sized: true,
            },
            fields: Union(
@@ -409,7 +409,7 @@ error: layout_of(P1) = Layout {
                abi: Align(1 bytes),
                pref: $SOME_ALIGN,
            },
-           abi: Aggregate {
+           abi: Memory {
                sized: true,
            },
            fields: Union(
@@ -433,7 +433,7 @@ error: layout_of(P2) = Layout {
                abi: Align(1 bytes),
                pref: $SOME_ALIGN,
            },
-           abi: Aggregate {
+           abi: Memory {
                sized: true,
            },
            fields: Union(
@@ -457,7 +457,7 @@ error: layout_of(P3) = Layout {
                abi: Align(1 bytes),
                pref: $SOME_ALIGN,
            },
-           abi: Aggregate {
+           abi: Memory {
                sized: true,
            },
            fields: Union(
@@ -481,7 +481,7 @@ error: layout_of(P4) = Layout {
                abi: Align(1 bytes),
                pref: $SOME_ALIGN,
            },
-           abi: Aggregate {
+           abi: Memory {
                sized: true,
            },
            fields: Union(
diff --git a/tests/ui/layout/enum-scalar-pair-int-ptr.rs b/tests/ui/layout/enum-scalar-pair-int-ptr.rs
index 885cc3e37df..ebb3fdb1514 100644
--- a/tests/ui/layout/enum-scalar-pair-int-ptr.rs
+++ b/tests/ui/layout/enum-scalar-pair-int-ptr.rs
@@ -18,7 +18,7 @@ enum ScalarPairPointerWithInt { //~ERROR: abi: ScalarPair
 // of a different size. (Assumes that no target has 8 bit pointers, which
 // feels pretty safe.)
 #[rustc_layout(abi)]
-enum NotScalarPairPointerWithSmallerInt { //~ERROR: abi: Aggregate
+enum NotScalarPairPointerWithSmallerInt { //~ERROR: abi: Memory
     A(u8),
     B(Box<()>),
 }
diff --git a/tests/ui/layout/enum-scalar-pair-int-ptr.stderr b/tests/ui/layout/enum-scalar-pair-int-ptr.stderr
index b25eda628cd..357c8182ebd 100644
--- a/tests/ui/layout/enum-scalar-pair-int-ptr.stderr
+++ b/tests/ui/layout/enum-scalar-pair-int-ptr.stderr
@@ -4,7 +4,7 @@ error: abi: ScalarPair(Initialized { value: Int(I?, false), valid_range: $VALID_
 LL | enum ScalarPairPointerWithInt {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: abi: Aggregate { sized: true }
+error: abi: Memory { sized: true }
   --> $DIR/enum-scalar-pair-int-ptr.rs:21:1
    |
 LL | enum NotScalarPairPointerWithSmallerInt {
diff --git a/tests/ui/layout/hexagon-enum.stderr b/tests/ui/layout/hexagon-enum.stderr
index a2ad4a1ab58..59fe667923f 100644
--- a/tests/ui/layout/hexagon-enum.stderr
+++ b/tests/ui/layout/hexagon-enum.stderr
@@ -48,7 +48,7 @@ error: layout_of(A) = Layout {
                            abi: Align(1 bytes),
                            pref: Align(1 bytes),
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -122,7 +122,7 @@ error: layout_of(B) = Layout {
                            abi: Align(1 bytes),
                            pref: Align(1 bytes),
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -196,7 +196,7 @@ error: layout_of(C) = Layout {
                            abi: Align(2 bytes),
                            pref: Align(2 bytes),
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -270,7 +270,7 @@ error: layout_of(P) = Layout {
                            abi: Align(4 bytes),
                            pref: Align(4 bytes),
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -344,7 +344,7 @@ error: layout_of(T) = Layout {
                            abi: Align(4 bytes),
                            pref: Align(4 bytes),
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
diff --git a/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr b/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr
index d3ba1a295b1..ca041fb539b 100644
--- a/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr
+++ b/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr
@@ -90,7 +90,7 @@ error: layout_of(MissingPayloadField) = Layout {
                            abi: Align(1 bytes),
                            pref: $PREF_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -489,7 +489,7 @@ error: layout_of(NicheFirst) = Layout {
                            abi: Align(1 bytes),
                            pref: $PREF_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -509,7 +509,7 @@ error: layout_of(NicheFirst) = Layout {
                            abi: Align(1 bytes),
                            pref: $PREF_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -641,7 +641,7 @@ error: layout_of(NicheSecond) = Layout {
                            abi: Align(1 bytes),
                            pref: $PREF_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -661,7 +661,7 @@ error: layout_of(NicheSecond) = Layout {
                            abi: Align(1 bytes),
                            pref: $PREF_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
diff --git a/tests/ui/layout/issue-96185-overaligned-enum.stderr b/tests/ui/layout/issue-96185-overaligned-enum.stderr
index c539eb453d9..bc40a2aa482 100644
--- a/tests/ui/layout/issue-96185-overaligned-enum.stderr
+++ b/tests/ui/layout/issue-96185-overaligned-enum.stderr
@@ -4,7 +4,7 @@ error: layout_of(Aligned1) = Layout {
                abi: Align(8 bytes),
                pref: $PREF_ALIGN,
            },
-           abi: Aggregate {
+           abi: Memory {
                sized: true,
            },
            fields: Arbitrary {
@@ -42,7 +42,7 @@ error: layout_of(Aligned1) = Layout {
                            abi: Align(8 bytes),
                            pref: $PREF_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -64,7 +64,7 @@ error: layout_of(Aligned1) = Layout {
                            abi: Align(8 bytes),
                            pref: $PREF_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -142,7 +142,7 @@ error: layout_of(Aligned2) = Layout {
                            abi: Align(1 bytes),
                            pref: $PREF_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -164,7 +164,7 @@ error: layout_of(Aligned2) = Layout {
                            abi: Align(1 bytes),
                            pref: $PREF_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
diff --git a/tests/ui/layout/struct.rs b/tests/ui/layout/struct.rs
index d072d123b0d..309624e667c 100644
--- a/tests/ui/layout/struct.rs
+++ b/tests/ui/layout/struct.rs
@@ -6,7 +6,7 @@
 #![crate_type = "lib"]
 
 #[rustc_layout(abi)]
-struct AlignedZstPreventsScalar(i16, [i32; 0]); //~ERROR: abi: Aggregate
+struct AlignedZstPreventsScalar(i16, [i32; 0]); //~ERROR: abi: Memory
 
 #[rustc_layout(abi)]
 struct AlignedZstButStillScalar(i32, [i16; 0]); //~ERROR: abi: Scalar
diff --git a/tests/ui/layout/struct.stderr b/tests/ui/layout/struct.stderr
index b61c9a99cce..7bc9af61ed4 100644
--- a/tests/ui/layout/struct.stderr
+++ b/tests/ui/layout/struct.stderr
@@ -1,4 +1,4 @@
-error: abi: Aggregate { sized: true }
+error: abi: Memory { sized: true }
   --> $DIR/struct.rs:9:1
    |
 LL | struct AlignedZstPreventsScalar(i16, [i32; 0]);
diff --git a/tests/ui/layout/thumb-enum.stderr b/tests/ui/layout/thumb-enum.stderr
index 6f6ab498206..bf043af586b 100644
--- a/tests/ui/layout/thumb-enum.stderr
+++ b/tests/ui/layout/thumb-enum.stderr
@@ -48,7 +48,7 @@ error: layout_of(A) = Layout {
                            abi: Align(1 bytes),
                            pref: Align(4 bytes),
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -122,7 +122,7 @@ error: layout_of(B) = Layout {
                            abi: Align(1 bytes),
                            pref: Align(4 bytes),
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -196,7 +196,7 @@ error: layout_of(C) = Layout {
                            abi: Align(2 bytes),
                            pref: Align(4 bytes),
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -270,7 +270,7 @@ error: layout_of(P) = Layout {
                            abi: Align(4 bytes),
                            pref: Align(4 bytes),
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -344,7 +344,7 @@ error: layout_of(T) = Layout {
                            abi: Align(4 bytes),
                            pref: Align(4 bytes),
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
diff --git a/tests/ui/layout/zero-sized-array-enum-niche.stderr b/tests/ui/layout/zero-sized-array-enum-niche.stderr
index ee34cfdfb0d..d61408098df 100644
--- a/tests/ui/layout/zero-sized-array-enum-niche.stderr
+++ b/tests/ui/layout/zero-sized-array-enum-niche.stderr
@@ -4,7 +4,7 @@ error: layout_of(Result<[u32; 0], bool>) = Layout {
                abi: Align(4 bytes),
                pref: $PREF_ALIGN,
            },
-           abi: Aggregate {
+           abi: Memory {
                sized: true,
            },
            fields: Arbitrary {
@@ -42,7 +42,7 @@ error: layout_of(Result<[u32; 0], bool>) = Layout {
                            abi: Align(4 bytes),
                            pref: $PREF_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -66,7 +66,7 @@ error: layout_of(Result<[u32; 0], bool>) = Layout {
                            abi: Align(1 bytes),
                            pref: $PREF_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -109,7 +109,7 @@ error: layout_of(MultipleAlignments) = Layout {
                abi: Align(4 bytes),
                pref: $PREF_ALIGN,
            },
-           abi: Aggregate {
+           abi: Memory {
                sized: true,
            },
            fields: Arbitrary {
@@ -147,7 +147,7 @@ error: layout_of(MultipleAlignments) = Layout {
                            abi: Align(2 bytes),
                            pref: $PREF_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -171,7 +171,7 @@ error: layout_of(MultipleAlignments) = Layout {
                            abi: Align(4 bytes),
                            pref: $PREF_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -195,7 +195,7 @@ error: layout_of(MultipleAlignments) = Layout {
                            abi: Align(1 bytes),
                            pref: $PREF_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -238,7 +238,7 @@ error: layout_of(Result<[u32; 0], Packed<NonZero<u16>>>) = Layout {
                abi: Align(4 bytes),
                pref: $PREF_ALIGN,
            },
-           abi: Aggregate {
+           abi: Memory {
                sized: true,
            },
            fields: Arbitrary {
@@ -276,7 +276,7 @@ error: layout_of(Result<[u32; 0], Packed<NonZero<u16>>>) = Layout {
                            abi: Align(4 bytes),
                            pref: $PREF_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -300,7 +300,7 @@ error: layout_of(Result<[u32; 0], Packed<NonZero<u16>>>) = Layout {
                            abi: Align(1 bytes),
                            pref: $PREF_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -343,7 +343,7 @@ error: layout_of(Result<[u32; 0], Packed<U16IsZero>>) = Layout {
                abi: Align(4 bytes),
                pref: $PREF_ALIGN,
            },
-           abi: Aggregate {
+           abi: Memory {
                sized: true,
            },
            fields: Arbitrary {
@@ -385,7 +385,7 @@ error: layout_of(Result<[u32; 0], Packed<U16IsZero>>) = Layout {
                            abi: Align(4 bytes),
                            pref: $PREF_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -409,7 +409,7 @@ error: layout_of(Result<[u32; 0], Packed<U16IsZero>>) = Layout {
                            abi: Align(1 bytes),
                            pref: $PREF_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
diff --git a/tests/ui/lexer/lexer-crlf-line-endings-string-literal-doc-comment.rs b/tests/ui/lexer/lexer-crlf-line-endings-string-literal-doc-comment.rs
index b355997a4b3..ee193a58ce1 100644
--- a/tests/ui/lexer/lexer-crlf-line-endings-string-literal-doc-comment.rs
+++ b/tests/ui/lexer/lexer-crlf-line-endings-string-literal-doc-comment.rs
@@ -1,4 +1,5 @@
 //@ run-pass

+//@ reference: input.crlf

 // ignore-tidy-cr

 // ignore-tidy-cr (repeated again because of tidy bug)

 // license is ignored because tidy can't handle the CRLF here properly.

diff --git a/tests/ui/lint/cli-lint-override.forbid_warn.stderr b/tests/ui/lint/cli-lint-override.forbid_warn.stderr
index d8c75c33b0c..169be997b48 100644
--- a/tests/ui/lint/cli-lint-override.forbid_warn.stderr
+++ b/tests/ui/lint/cli-lint-override.forbid_warn.stderr
@@ -2,9 +2,8 @@ error: extern declarations without an explicit ABI are deprecated
   --> $DIR/cli-lint-override.rs:12:1
    |
 LL | extern fn foo() {}
-   | ^^^^^^^^^^^^^^^ ABI should be specified here
+   | ^^^^^^ help: explicitly specify the C ABI: `extern "C"`
    |
-   = help: the default ABI is C
    = note: requested on the command line with `-F missing-abi`
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/lint/cli-lint-override.force_warn_deny.stderr b/tests/ui/lint/cli-lint-override.force_warn_deny.stderr
index 779c24c93f2..574f2ca66a4 100644
--- a/tests/ui/lint/cli-lint-override.force_warn_deny.stderr
+++ b/tests/ui/lint/cli-lint-override.force_warn_deny.stderr
@@ -2,9 +2,8 @@ warning: extern declarations without an explicit ABI are deprecated
   --> $DIR/cli-lint-override.rs:12:1
    |
 LL | extern fn foo() {}
-   | ^^^^^^^^^^^^^^^ ABI should be specified here
+   | ^^^^^^ help: explicitly specify the C ABI: `extern "C"`
    |
-   = help: the default ABI is C
    = note: requested on the command line with `--force-warn missing-abi`
 
 warning: 1 warning emitted
diff --git a/tests/ui/lint/cli-lint-override.warn_deny.stderr b/tests/ui/lint/cli-lint-override.warn_deny.stderr
index 1ba42e9ce32..bfec37ada95 100644
--- a/tests/ui/lint/cli-lint-override.warn_deny.stderr
+++ b/tests/ui/lint/cli-lint-override.warn_deny.stderr
@@ -2,9 +2,8 @@ error: extern declarations without an explicit ABI are deprecated
   --> $DIR/cli-lint-override.rs:12:1
    |
 LL | extern fn foo() {}
-   | ^^^^^^^^^^^^^^^ ABI should be specified here
+   | ^^^^^^ help: explicitly specify the C ABI: `extern "C"`
    |
-   = help: the default ABI is C
    = note: requested on the command line with `-D missing-abi`
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.cdylib_.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.cdylib_.stderr
index 140d72b9742..1192b690e29 100644
--- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.cdylib_.stderr
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.cdylib_.stderr
@@ -1,11 +1,11 @@
 error: crate `NonSnakeCase` should have a snake case name
-  --> $DIR/lint-non-snake-case-crate.rs:29:18
+  --> $DIR/lint-non-snake-case-crate.rs:36:18
    |
 LL | #![crate_name = "NonSnakeCase"]
    |                  ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case`
    |
 note: the lint level is defined here
-  --> $DIR/lint-non-snake-case-crate.rs:31:9
+  --> $DIR/lint-non-snake-case-crate.rs:38:9
    |
 LL | #![deny(non_snake_case)]
    |         ^^^^^^^^^^^^^^
diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.dylib_.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.dylib_.stderr
index 140d72b9742..1192b690e29 100644
--- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.dylib_.stderr
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.dylib_.stderr
@@ -1,11 +1,11 @@
 error: crate `NonSnakeCase` should have a snake case name
-  --> $DIR/lint-non-snake-case-crate.rs:29:18
+  --> $DIR/lint-non-snake-case-crate.rs:36:18
    |
 LL | #![crate_name = "NonSnakeCase"]
    |                  ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case`
    |
 note: the lint level is defined here
-  --> $DIR/lint-non-snake-case-crate.rs:31:9
+  --> $DIR/lint-non-snake-case-crate.rs:38:9
    |
 LL | #![deny(non_snake_case)]
    |         ^^^^^^^^^^^^^^
diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.lib_.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.lib_.stderr
index 140d72b9742..1192b690e29 100644
--- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.lib_.stderr
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.lib_.stderr
@@ -1,11 +1,11 @@
 error: crate `NonSnakeCase` should have a snake case name
-  --> $DIR/lint-non-snake-case-crate.rs:29:18
+  --> $DIR/lint-non-snake-case-crate.rs:36:18
    |
 LL | #![crate_name = "NonSnakeCase"]
    |                  ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case`
    |
 note: the lint level is defined here
-  --> $DIR/lint-non-snake-case-crate.rs:31:9
+  --> $DIR/lint-non-snake-case-crate.rs:38:9
    |
 LL | #![deny(non_snake_case)]
    |         ^^^^^^^^^^^^^^
diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.proc_macro_.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.proc_macro_.stderr
index 140d72b9742..1192b690e29 100644
--- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.proc_macro_.stderr
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.proc_macro_.stderr
@@ -1,11 +1,11 @@
 error: crate `NonSnakeCase` should have a snake case name
-  --> $DIR/lint-non-snake-case-crate.rs:29:18
+  --> $DIR/lint-non-snake-case-crate.rs:36:18
    |
 LL | #![crate_name = "NonSnakeCase"]
    |                  ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case`
    |
 note: the lint level is defined here
-  --> $DIR/lint-non-snake-case-crate.rs:31:9
+  --> $DIR/lint-non-snake-case-crate.rs:38:9
    |
 LL | #![deny(non_snake_case)]
    |         ^^^^^^^^^^^^^^
diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rlib_.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rlib_.stderr
index 140d72b9742..1192b690e29 100644
--- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rlib_.stderr
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rlib_.stderr
@@ -1,11 +1,11 @@
 error: crate `NonSnakeCase` should have a snake case name
-  --> $DIR/lint-non-snake-case-crate.rs:29:18
+  --> $DIR/lint-non-snake-case-crate.rs:36:18
    |
 LL | #![crate_name = "NonSnakeCase"]
    |                  ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case`
    |
 note: the lint level is defined here
-  --> $DIR/lint-non-snake-case-crate.rs:31:9
+  --> $DIR/lint-non-snake-case-crate.rs:38:9
    |
 LL | #![deny(non_snake_case)]
    |         ^^^^^^^^^^^^^^
diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rs
index 097b246c165..6f701cd27c6 100644
--- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rs
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rs
@@ -10,10 +10,17 @@
 
 // But should fire on non-binary crates.
 
-//@[cdylib_] ignore-musl (dylibs are not supported)
-//@[dylib_] ignore-musl (dylibs are not supported)
-//@[dylib_] ignore-wasm (dylib is not supported)
-//@[proc_macro_] ignore-wasm (dylib is not supported)
+// FIXME(#132309): dylib crate type is not supported on wasm; we need a proper
+// supports-crate-type directive. Also, needs-dynamic-linking should rule out
+// musl since it supports neither dylibs nor cdylibs.
+//@[dylib_] ignore-wasm
+//@[dylib_] ignore-musl
+//@[cdylib_] ignore-musl
+
+//@[dylib_] needs-dynamic-linking
+//@[cdylib_] needs-dynamic-linking
+//@[proc_macro_] force-host
+//@[proc_macro_] no-prefer-dynamic
 
 //@[cdylib_] compile-flags: --crate-type=cdylib
 //@[dylib_] compile-flags: --crate-type=dylib
diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.staticlib_.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.staticlib_.stderr
index 140d72b9742..1192b690e29 100644
--- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.staticlib_.stderr
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.staticlib_.stderr
@@ -1,11 +1,11 @@
 error: crate `NonSnakeCase` should have a snake case name
-  --> $DIR/lint-non-snake-case-crate.rs:29:18
+  --> $DIR/lint-non-snake-case-crate.rs:36:18
    |
 LL | #![crate_name = "NonSnakeCase"]
    |                  ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case`
    |
 note: the lint level is defined here
-  --> $DIR/lint-non-snake-case-crate.rs:31:9
+  --> $DIR/lint-non-snake-case-crate.rs:38:9
    |
 LL | #![deny(non_snake_case)]
    |         ^^^^^^^^^^^^^^
diff --git a/tests/ui/macros/assert-trailing-junk.with-generic-asset.stderr b/tests/ui/macros/assert-trailing-junk.with-generic-asset.stderr
index 1e73320e439..7582c8e8659 100644
--- a/tests/ui/macros/assert-trailing-junk.with-generic-asset.stderr
+++ b/tests/ui/macros/assert-trailing-junk.with-generic-asset.stderr
@@ -10,7 +10,7 @@ error: expected one of `,`, `.`, `?`, or an operator, found `some`
 LL |     assert!(true some extra junk);
    |                  ^^^^ expected one of `,`, `.`, `?`, or an operator
 
-error: no rules expected the token `blah`
+error: no rules expected `blah`
   --> $DIR/assert-trailing-junk.rs:15:30
    |
 LL |     assert!(true, "whatever" blah);
@@ -28,7 +28,7 @@ LL |     assert!(true "whatever" blah);
    |                 |
    |                 help: try adding a comma
 
-error: no rules expected the token `blah`
+error: no rules expected `blah`
   --> $DIR/assert-trailing-junk.rs:18:29
    |
 LL |     assert!(true "whatever" blah);
diff --git a/tests/ui/macros/assert-trailing-junk.without-generic-asset.stderr b/tests/ui/macros/assert-trailing-junk.without-generic-asset.stderr
index 1e73320e439..7582c8e8659 100644
--- a/tests/ui/macros/assert-trailing-junk.without-generic-asset.stderr
+++ b/tests/ui/macros/assert-trailing-junk.without-generic-asset.stderr
@@ -10,7 +10,7 @@ error: expected one of `,`, `.`, `?`, or an operator, found `some`
 LL |     assert!(true some extra junk);
    |                  ^^^^ expected one of `,`, `.`, `?`, or an operator
 
-error: no rules expected the token `blah`
+error: no rules expected `blah`
   --> $DIR/assert-trailing-junk.rs:15:30
    |
 LL |     assert!(true, "whatever" blah);
@@ -28,7 +28,7 @@ LL |     assert!(true "whatever" blah);
    |                 |
    |                 help: try adding a comma
 
-error: no rules expected the token `blah`
+error: no rules expected `blah`
   --> $DIR/assert-trailing-junk.rs:18:29
    |
 LL |     assert!(true "whatever" blah);
diff --git a/tests/ui/macros/best-failure.rs b/tests/ui/macros/best-failure.rs
index bbdd465d5ec..1b73066c874 100644
--- a/tests/ui/macros/best-failure.rs
+++ b/tests/ui/macros/best-failure.rs
@@ -2,7 +2,7 @@ macro_rules! number {
     (neg false, $self:ident) => { $self };
     ($signed:tt => $ty:ty;) => {
         number!(neg $signed, $self);
-        //~^ ERROR no rules expected the token `$`
+        //~^ ERROR no rules expected `$`
     };
 }
 
diff --git a/tests/ui/macros/best-failure.stderr b/tests/ui/macros/best-failure.stderr
index c5f8b9abc19..914ff7fd820 100644
--- a/tests/ui/macros/best-failure.stderr
+++ b/tests/ui/macros/best-failure.stderr
@@ -1,4 +1,4 @@
-error: no rules expected the token `$`
+error: no rules expected `$`
   --> $DIR/best-failure.rs:4:30
    |
 LL | macro_rules! number {
diff --git a/tests/ui/macros/expr_2021_inline_const.edi2021.stderr b/tests/ui/macros/expr_2021_inline_const.edi2021.stderr
index 22d662aaaf2..bf7eb3888b3 100644
--- a/tests/ui/macros/expr_2021_inline_const.edi2021.stderr
+++ b/tests/ui/macros/expr_2021_inline_const.edi2021.stderr
@@ -1,4 +1,4 @@
-error: no rules expected the token `const`
+error: no rules expected keyword `const`
   --> $DIR/expr_2021_inline_const.rs:23:12
    |
 LL | macro_rules! m2021 {
@@ -13,7 +13,7 @@ note: while trying to match meta-variable `$e:expr_2021`
 LL |     ($e:expr_2021) => {
    |      ^^^^^^^^^^^^
 
-error: no rules expected the token `const`
+error: no rules expected keyword `const`
   --> $DIR/expr_2021_inline_const.rs:24:12
    |
 LL | macro_rules! m2024 {
diff --git a/tests/ui/macros/expr_2021_inline_const.edi2024.stderr b/tests/ui/macros/expr_2021_inline_const.edi2024.stderr
index 2555e4f757a..1028ddc4267 100644
--- a/tests/ui/macros/expr_2021_inline_const.edi2024.stderr
+++ b/tests/ui/macros/expr_2021_inline_const.edi2024.stderr
@@ -1,4 +1,4 @@
-error: no rules expected the token `const`
+error: no rules expected keyword `const`
   --> $DIR/expr_2021_inline_const.rs:23:12
    |
 LL | macro_rules! m2021 {
diff --git a/tests/ui/macros/expr_2021_inline_const.rs b/tests/ui/macros/expr_2021_inline_const.rs
index 39a542fe4d9..312256f1879 100644
--- a/tests/ui/macros/expr_2021_inline_const.rs
+++ b/tests/ui/macros/expr_2021_inline_const.rs
@@ -20,8 +20,8 @@ macro_rules! test {
 }
 
 fn main() {
-    m2021!(const { 1 }); //~ ERROR: no rules expected the token `const`
-    m2024!(const { 1 }); //[edi2021]~ ERROR: no rules expected the token `const`
+    m2021!(const { 1 }); //~ ERROR: no rules expected keyword `const`
+    m2024!(const { 1 }); //[edi2021]~ ERROR: no rules expected keyword `const`
 
     test!(expr);
 }
diff --git a/tests/ui/macros/expr_2024_underscore_expr.edi2021.stderr b/tests/ui/macros/expr_2024_underscore_expr.edi2021.stderr
index 34df20a69ef..7b3ca54bb71 100644
--- a/tests/ui/macros/expr_2024_underscore_expr.edi2021.stderr
+++ b/tests/ui/macros/expr_2024_underscore_expr.edi2021.stderr
@@ -1,4 +1,4 @@
-error: no rules expected the token `_`
+error: no rules expected reserved identifier `_`
   --> $DIR/expr_2024_underscore_expr.rs:19:12
    |
 LL | macro_rules! m2021 {
@@ -13,7 +13,7 @@ note: while trying to match meta-variable `$e:expr_2021`
 LL |     ($e:expr_2021) => {
    |      ^^^^^^^^^^^^
 
-error: no rules expected the token `_`
+error: no rules expected reserved identifier `_`
   --> $DIR/expr_2024_underscore_expr.rs:20:12
    |
 LL | macro_rules! m2024 {
diff --git a/tests/ui/macros/expr_2024_underscore_expr.edi2024.stderr b/tests/ui/macros/expr_2024_underscore_expr.edi2024.stderr
index 372c5d8637c..59104dafa18 100644
--- a/tests/ui/macros/expr_2024_underscore_expr.edi2024.stderr
+++ b/tests/ui/macros/expr_2024_underscore_expr.edi2024.stderr
@@ -1,4 +1,4 @@
-error: no rules expected the token `_`
+error: no rules expected reserved identifier `_`
   --> $DIR/expr_2024_underscore_expr.rs:19:12
    |
 LL | macro_rules! m2021 {
diff --git a/tests/ui/macros/expr_2024_underscore_expr.rs b/tests/ui/macros/expr_2024_underscore_expr.rs
index 86e31374506..6f8ec139109 100644
--- a/tests/ui/macros/expr_2024_underscore_expr.rs
+++ b/tests/ui/macros/expr_2024_underscore_expr.rs
@@ -16,6 +16,6 @@ macro_rules! m2024 {
 }
 
 fn main() {
-    m2021!(_); //~ ERROR: no rules expected the token `_`
-    m2024!(_); //[edi2021]~ ERROR: no rules expected the token `_`
+    m2021!(_); //~ ERROR: no rules expected reserved identifier `_`
+    m2024!(_); //[edi2021]~ ERROR: no rules expected reserved identifier `_`
 }
diff --git a/tests/ui/macros/issue-118786.rs b/tests/ui/macros/issue-118786.rs
index a41372e4ea8..a73b737fe07 100644
--- a/tests/ui/macros/issue-118786.rs
+++ b/tests/ui/macros/issue-118786.rs
@@ -5,7 +5,7 @@
 macro_rules! make_macro {
     ($macro_name:tt) => {
         macro_rules! $macro_name {
-        //~^ ERROR macro expansion ignores token `{` and any following
+        //~^ ERROR macro expansion ignores `{` and any tokens following
         //~| ERROR cannot find macro `macro_rules` in this scope
         //~| put a macro name here
             () => {}
diff --git a/tests/ui/macros/issue-118786.stderr b/tests/ui/macros/issue-118786.stderr
index 256b742ee16..7fa5c2b83dd 100644
--- a/tests/ui/macros/issue-118786.stderr
+++ b/tests/ui/macros/issue-118786.stderr
@@ -13,7 +13,7 @@ help: add a semicolon
 LL |         macro_rules! $macro_name; {
    |                                 +
 
-error: macro expansion ignores token `{` and any following
+error: macro expansion ignores `{` and any tokens following
   --> $DIR/issue-118786.rs:7:34
    |
 LL |         macro_rules! $macro_name {
diff --git a/tests/ui/macros/issue-30007.rs b/tests/ui/macros/issue-30007.rs
index 918a821bae9..e36e47a3e7c 100644
--- a/tests/ui/macros/issue-30007.rs
+++ b/tests/ui/macros/issue-30007.rs
@@ -1,5 +1,5 @@
 macro_rules! t {
-    () => ( String ; );     //~ ERROR macro expansion ignores token `;`
+    () => ( String ; );     //~ ERROR macro expansion ignores `;`
 }
 
 fn main() {
diff --git a/tests/ui/macros/issue-30007.stderr b/tests/ui/macros/issue-30007.stderr
index f303221cf8a..129733ed69a 100644
--- a/tests/ui/macros/issue-30007.stderr
+++ b/tests/ui/macros/issue-30007.stderr
@@ -1,4 +1,4 @@
-error: macro expansion ignores token `;` and any following
+error: macro expansion ignores `;` and any tokens following
   --> $DIR/issue-30007.rs:2:20
    |
 LL |     () => ( String ; );
diff --git a/tests/ui/macros/issue-54441.rs b/tests/ui/macros/issue-54441.rs
index b24d7e1f6be..37ab4e63647 100644
--- a/tests/ui/macros/issue-54441.rs
+++ b/tests/ui/macros/issue-54441.rs
@@ -1,6 +1,6 @@
 macro_rules! m {
     () => {
-        let //~ ERROR macro expansion ignores token `let` and any following
+        let //~ ERROR macro expansion ignores keyword `let` and any tokens following
     };
 }
 
diff --git a/tests/ui/macros/issue-54441.stderr b/tests/ui/macros/issue-54441.stderr
index fb2c103139b..f5f8b8ca2b2 100644
--- a/tests/ui/macros/issue-54441.stderr
+++ b/tests/ui/macros/issue-54441.stderr
@@ -1,4 +1,4 @@
-error: macro expansion ignores token `let` and any following
+error: macro expansion ignores keyword `let` and any tokens following
   --> $DIR/issue-54441.rs:3:9
    |
 LL |         let
diff --git a/tests/ui/macros/macro-at-most-once-rep-2015.rs b/tests/ui/macros/macro-at-most-once-rep-2015.rs
index 8f2531a25ae..08967b82531 100644
--- a/tests/ui/macros/macro-at-most-once-rep-2015.rs
+++ b/tests/ui/macros/macro-at-most-once-rep-2015.rs
@@ -22,21 +22,21 @@ macro_rules! barstar {
 pub fn main() {
     foo!();
     foo!(a);
-    foo!(a?); //~ ERROR no rules expected the token `?`
-    foo!(a?a); //~ ERROR no rules expected the token `?`
-    foo!(a?a?a); //~ ERROR no rules expected the token `?`
+    foo!(a?); //~ ERROR no rules expected `?`
+    foo!(a?a); //~ ERROR no rules expected `?`
+    foo!(a?a?a); //~ ERROR no rules expected `?`
 
     barplus!(); //~ERROR unexpected end of macro invocation
     barplus!(a); //~ERROR unexpected end of macro invocation
-    barplus!(a?); //~ ERROR no rules expected the token `?`
-    barplus!(a?a); //~ ERROR no rules expected the token `?`
+    barplus!(a?); //~ ERROR no rules expected `?`
+    barplus!(a?a); //~ ERROR no rules expected `?`
     barplus!(a+);
     barplus!(+);
 
     barstar!(); //~ERROR unexpected end of macro invocation
     barstar!(a); //~ERROR unexpected end of macro invocation
-    barstar!(a?); //~ ERROR no rules expected the token `?`
-    barstar!(a?a); //~ ERROR no rules expected the token `?`
+    barstar!(a?); //~ ERROR no rules expected `?`
+    barstar!(a?a); //~ ERROR no rules expected `?`
     barstar!(a*);
     barstar!(*);
 }
diff --git a/tests/ui/macros/macro-at-most-once-rep-2015.stderr b/tests/ui/macros/macro-at-most-once-rep-2015.stderr
index 7c45b85bc8d..7f161cdc8d0 100644
--- a/tests/ui/macros/macro-at-most-once-rep-2015.stderr
+++ b/tests/ui/macros/macro-at-most-once-rep-2015.stderr
@@ -4,7 +4,7 @@ error: the `?` macro repetition operator does not take a separator
 LL |     ($(a),?) => {};
    |          ^
 
-error: no rules expected the token `?`
+error: no rules expected `?`
   --> $DIR/macro-at-most-once-rep-2015.rs:25:11
    |
 LL | macro_rules! foo {
@@ -15,7 +15,7 @@ LL |     foo!(a?);
    |
    = note: while trying to match sequence end
 
-error: no rules expected the token `?`
+error: no rules expected `?`
   --> $DIR/macro-at-most-once-rep-2015.rs:26:11
    |
 LL | macro_rules! foo {
@@ -26,7 +26,7 @@ LL |     foo!(a?a);
    |
    = note: while trying to match sequence end
 
-error: no rules expected the token `?`
+error: no rules expected `?`
   --> $DIR/macro-at-most-once-rep-2015.rs:27:11
    |
 LL | macro_rules! foo {
@@ -67,7 +67,7 @@ note: while trying to match `+`
 LL |     ($(a)?+) => {}; // ok. matches "a+" and "+"
    |           ^
 
-error: no rules expected the token `?`
+error: no rules expected `?`
   --> $DIR/macro-at-most-once-rep-2015.rs:31:15
    |
 LL | macro_rules! barplus {
@@ -82,7 +82,7 @@ note: while trying to match `+`
 LL |     ($(a)?+) => {}; // ok. matches "a+" and "+"
    |           ^
 
-error: no rules expected the token `?`
+error: no rules expected `?`
   --> $DIR/macro-at-most-once-rep-2015.rs:32:15
    |
 LL | macro_rules! barplus {
@@ -127,7 +127,7 @@ note: while trying to match `*`
 LL |     ($(a)?*) => {}; // ok. matches "a*" and "*"
    |           ^
 
-error: no rules expected the token `?`
+error: no rules expected `?`
   --> $DIR/macro-at-most-once-rep-2015.rs:38:15
    |
 LL | macro_rules! barstar {
@@ -142,7 +142,7 @@ note: while trying to match `*`
 LL |     ($(a)?*) => {}; // ok. matches "a*" and "*"
    |           ^
 
-error: no rules expected the token `?`
+error: no rules expected `?`
   --> $DIR/macro-at-most-once-rep-2015.rs:39:15
    |
 LL | macro_rules! barstar {
diff --git a/tests/ui/macros/macro-at-most-once-rep-2018.rs b/tests/ui/macros/macro-at-most-once-rep-2018.rs
index 7f43055ded6..98fbb2ad207 100644
--- a/tests/ui/macros/macro-at-most-once-rep-2018.rs
+++ b/tests/ui/macros/macro-at-most-once-rep-2018.rs
@@ -22,21 +22,21 @@ macro_rules! barstar {
 pub fn main() {
     foo!();
     foo!(a);
-    foo!(a?); //~ ERROR no rules expected the token `?`
-    foo!(a?a); //~ ERROR no rules expected the token `?`
-    foo!(a?a?a); //~ ERROR no rules expected the token `?`
+    foo!(a?); //~ ERROR no rules expected `?`
+    foo!(a?a); //~ ERROR no rules expected `?`
+    foo!(a?a?a); //~ ERROR no rules expected `?`
 
     barplus!(); //~ERROR unexpected end of macro invocation
     barplus!(a); //~ERROR unexpected end of macro invocation
-    barplus!(a?); //~ ERROR no rules expected the token `?`
-    barplus!(a?a); //~ ERROR no rules expected the token `?`
+    barplus!(a?); //~ ERROR no rules expected `?`
+    barplus!(a?a); //~ ERROR no rules expected `?`
     barplus!(a+);
     barplus!(+);
 
     barstar!(); //~ERROR unexpected end of macro invocation
     barstar!(a); //~ERROR unexpected end of macro invocation
-    barstar!(a?); //~ ERROR no rules expected the token `?`
-    barstar!(a?a); //~ ERROR no rules expected the token `?`
+    barstar!(a?); //~ ERROR no rules expected `?`
+    barstar!(a?a); //~ ERROR no rules expected `?`
     barstar!(a*);
     barstar!(*);
 }
diff --git a/tests/ui/macros/macro-at-most-once-rep-2018.stderr b/tests/ui/macros/macro-at-most-once-rep-2018.stderr
index 696520b2826..f165a199b10 100644
--- a/tests/ui/macros/macro-at-most-once-rep-2018.stderr
+++ b/tests/ui/macros/macro-at-most-once-rep-2018.stderr
@@ -4,7 +4,7 @@ error: the `?` macro repetition operator does not take a separator
 LL |     ($(a),?) => {};
    |          ^
 
-error: no rules expected the token `?`
+error: no rules expected `?`
   --> $DIR/macro-at-most-once-rep-2018.rs:25:11
    |
 LL | macro_rules! foo {
@@ -15,7 +15,7 @@ LL |     foo!(a?);
    |
    = note: while trying to match sequence end
 
-error: no rules expected the token `?`
+error: no rules expected `?`
   --> $DIR/macro-at-most-once-rep-2018.rs:26:11
    |
 LL | macro_rules! foo {
@@ -26,7 +26,7 @@ LL |     foo!(a?a);
    |
    = note: while trying to match sequence end
 
-error: no rules expected the token `?`
+error: no rules expected `?`
   --> $DIR/macro-at-most-once-rep-2018.rs:27:11
    |
 LL | macro_rules! foo {
@@ -67,7 +67,7 @@ note: while trying to match `+`
 LL |     ($(a)?+) => {}; // ok. matches "a+" and "+"
    |           ^
 
-error: no rules expected the token `?`
+error: no rules expected `?`
   --> $DIR/macro-at-most-once-rep-2018.rs:31:15
    |
 LL | macro_rules! barplus {
@@ -82,7 +82,7 @@ note: while trying to match `+`
 LL |     ($(a)?+) => {}; // ok. matches "a+" and "+"
    |           ^
 
-error: no rules expected the token `?`
+error: no rules expected `?`
   --> $DIR/macro-at-most-once-rep-2018.rs:32:15
    |
 LL | macro_rules! barplus {
@@ -127,7 +127,7 @@ note: while trying to match `*`
 LL |     ($(a)?*) => {}; // ok. matches "a*" and "*"
    |           ^
 
-error: no rules expected the token `?`
+error: no rules expected `?`
   --> $DIR/macro-at-most-once-rep-2018.rs:38:15
    |
 LL | macro_rules! barstar {
@@ -142,7 +142,7 @@ note: while trying to match `*`
 LL |     ($(a)?*) => {}; // ok. matches "a*" and "*"
    |           ^
 
-error: no rules expected the token `?`
+error: no rules expected `?`
   --> $DIR/macro-at-most-once-rep-2018.rs:39:15
    |
 LL | macro_rules! barstar {
diff --git a/tests/ui/macros/macro-context.rs b/tests/ui/macros/macro-context.rs
index d09fdf118e6..a31470263a0 100644
--- a/tests/ui/macros/macro-context.rs
+++ b/tests/ui/macros/macro-context.rs
@@ -1,9 +1,9 @@
 // (typeof used because it's surprisingly hard to find an unparsed token after a stmt)
 macro_rules! m {
     () => ( i ; typeof );   //~ ERROR expected expression, found reserved keyword `typeof`
-                            //~| ERROR macro expansion ignores token `typeof`
-                            //~| ERROR macro expansion ignores token `;`
-                            //~| ERROR macro expansion ignores token `;`
+                            //~| ERROR macro expansion ignores reserved keyword `typeof`
+                            //~| ERROR macro expansion ignores `;`
+                            //~| ERROR macro expansion ignores `;`
                             //~| ERROR cannot find type `i` in this scope
                             //~| ERROR cannot find value `i` in this scope
                             //~| WARN trailing semicolon in macro
diff --git a/tests/ui/macros/macro-context.stderr b/tests/ui/macros/macro-context.stderr
index 7785f415946..4820a43f00c 100644
--- a/tests/ui/macros/macro-context.stderr
+++ b/tests/ui/macros/macro-context.stderr
@@ -1,4 +1,4 @@
-error: macro expansion ignores token `;` and any following
+error: macro expansion ignores `;` and any tokens following
   --> $DIR/macro-context.rs:3:15
    |
 LL |     () => ( i ; typeof );
@@ -9,7 +9,7 @@ LL |     let a: m!();
    |
    = note: the usage of `m!` is likely invalid in type context
 
-error: macro expansion ignores token `typeof` and any following
+error: macro expansion ignores reserved keyword `typeof` and any tokens following
   --> $DIR/macro-context.rs:3:17
    |
 LL |     () => ( i ; typeof );
@@ -20,7 +20,7 @@ LL |     let i = m!();
    |
    = note: the usage of `m!` is likely invalid in expression context
 
-error: macro expansion ignores token `;` and any following
+error: macro expansion ignores `;` and any tokens following
   --> $DIR/macro-context.rs:3:15
    |
 LL |     () => ( i ; typeof );
diff --git a/tests/ui/macros/macro-in-expression-context.fixed b/tests/ui/macros/macro-in-expression-context.fixed
index f4d04ca37bf..7c830707ffd 100644
--- a/tests/ui/macros/macro-in-expression-context.fixed
+++ b/tests/ui/macros/macro-in-expression-context.fixed
@@ -11,7 +11,7 @@ macro_rules! foo {
         //~| NOTE `#[warn(semicolon_in_expressions_from_macros)]` on by default
         assert_eq!("B", "B");
     }
-    //~^^ ERROR macro expansion ignores token `assert_eq` and any following
+    //~^^ ERROR macro expansion ignores `assert_eq` and any tokens following
     //~| NOTE the usage of `foo!` is likely invalid in expression context
 }
 
diff --git a/tests/ui/macros/macro-in-expression-context.rs b/tests/ui/macros/macro-in-expression-context.rs
index 8921a056377..da95017aa5f 100644
--- a/tests/ui/macros/macro-in-expression-context.rs
+++ b/tests/ui/macros/macro-in-expression-context.rs
@@ -11,7 +11,7 @@ macro_rules! foo {
         //~| NOTE `#[warn(semicolon_in_expressions_from_macros)]` on by default
         assert_eq!("B", "B");
     }
-    //~^^ ERROR macro expansion ignores token `assert_eq` and any following
+    //~^^ ERROR macro expansion ignores `assert_eq` and any tokens following
     //~| NOTE the usage of `foo!` is likely invalid in expression context
 }
 
diff --git a/tests/ui/macros/macro-in-expression-context.stderr b/tests/ui/macros/macro-in-expression-context.stderr
index 2eee63f307a..43419f2678c 100644
--- a/tests/ui/macros/macro-in-expression-context.stderr
+++ b/tests/ui/macros/macro-in-expression-context.stderr
@@ -1,4 +1,4 @@
-error: macro expansion ignores token `assert_eq` and any following
+error: macro expansion ignores `assert_eq` and any tokens following
   --> $DIR/macro-in-expression-context.rs:12:9
    |
 LL |         assert_eq!("B", "B");
diff --git a/tests/ui/macros/macro-non-lifetime.rs b/tests/ui/macros/macro-non-lifetime.rs
index 26e1f2afa91..3defffd2960 100644
--- a/tests/ui/macros/macro-non-lifetime.rs
+++ b/tests/ui/macros/macro-non-lifetime.rs
@@ -4,5 +4,5 @@ macro_rules! m { ($x:lifetime) => { } }
 
 fn main() {
     m!(a);
-    //~^ ERROR no rules expected the token `a`
+    //~^ ERROR no rules expected `a`
 }
diff --git a/tests/ui/macros/macro-non-lifetime.stderr b/tests/ui/macros/macro-non-lifetime.stderr
index 9ff3d741c01..35040a2229b 100644
--- a/tests/ui/macros/macro-non-lifetime.stderr
+++ b/tests/ui/macros/macro-non-lifetime.stderr
@@ -1,4 +1,4 @@
-error: no rules expected the token `a`
+error: no rules expected `a`
   --> $DIR/macro-non-lifetime.rs:6:8
    |
 LL | macro_rules! m { ($x:lifetime) => { } }
diff --git a/tests/ui/macros/missing-comma.rs b/tests/ui/macros/missing-comma.rs
index 92f8a779505..64cfb0db31a 100644
--- a/tests/ui/macros/missing-comma.rs
+++ b/tests/ui/macros/missing-comma.rs
@@ -19,16 +19,16 @@ fn main() {
     println!("{}" a);
     //~^ ERROR expected `,`, found `a`
     foo!(a b);
-    //~^ ERROR no rules expected the token `b`
+    //~^ ERROR no rules expected `b`
     foo!(a, b, c, d e);
-    //~^ ERROR no rules expected the token `e`
+    //~^ ERROR no rules expected `e`
     foo!(a, b, c d, e);
-    //~^ ERROR no rules expected the token `d`
+    //~^ ERROR no rules expected `d`
     foo!(a, b, c d e);
-    //~^ ERROR no rules expected the token `d`
+    //~^ ERROR no rules expected `d`
     bar!(Level::Error, );
     //~^ ERROR unexpected end of macro invocation
     check!(<str as Debug>::fmt, "fmt");
     check!(<str as Debug>::fmt, "fmt",);
-    //~^ ERROR no rules expected the token `,`
+    //~^ ERROR no rules expected `,`
 }
diff --git a/tests/ui/macros/missing-comma.stderr b/tests/ui/macros/missing-comma.stderr
index 81877a29ed8..9913ba34919 100644
--- a/tests/ui/macros/missing-comma.stderr
+++ b/tests/ui/macros/missing-comma.stderr
@@ -4,7 +4,7 @@ error: expected `,`, found `a`
 LL |     println!("{}" a);
    |                   ^ expected `,`
 
-error: no rules expected the token `b`
+error: no rules expected `b`
   --> $DIR/missing-comma.rs:21:12
    |
 LL | macro_rules! foo {
@@ -21,7 +21,7 @@ note: while trying to match meta-variable `$a:ident`
 LL |     ($a:ident) => ();
    |      ^^^^^^^^
 
-error: no rules expected the token `e`
+error: no rules expected `e`
   --> $DIR/missing-comma.rs:23:21
    |
 LL | macro_rules! foo {
@@ -38,7 +38,7 @@ note: while trying to match meta-variable `$d:ident`
 LL |     ($a:ident, $b:ident, $c:ident, $d:ident) => ();
    |                                    ^^^^^^^^
 
-error: no rules expected the token `d`
+error: no rules expected `d`
   --> $DIR/missing-comma.rs:25:18
    |
 LL | macro_rules! foo {
@@ -55,7 +55,7 @@ note: while trying to match meta-variable `$c:ident`
 LL |     ($a:ident, $b:ident, $c:ident) => ();
    |                          ^^^^^^^^
 
-error: no rules expected the token `d`
+error: no rules expected `d`
   --> $DIR/missing-comma.rs:27:18
    |
 LL | macro_rules! foo {
@@ -85,7 +85,7 @@ note: while trying to match meta-variable `$arg:tt`
 LL |     ($lvl:expr, $($arg:tt)+) => {}
    |                   ^^^^^^^
 
-error: no rules expected the token `,`
+error: no rules expected `,`
   --> $DIR/missing-comma.rs:32:38
    |
 LL | macro_rules! check {
diff --git a/tests/ui/macros/nonterminal-matching.rs b/tests/ui/macros/nonterminal-matching.rs
index 5f0d6b2f90e..a655b665103 100644
--- a/tests/ui/macros/nonterminal-matching.rs
+++ b/tests/ui/macros/nonterminal-matching.rs
@@ -16,7 +16,7 @@ macro complex_nonterminal($nt_item: item) {
         struct S;
     }
 
-    n!(a $nt_item b); //~ ERROR no rules expected the token `enum E {}`
+    n!(a $nt_item b); //~ ERROR no rules expected item `enum E {}`
 }
 
 simple_nonterminal!(a, 'a, (x, y, z)); // OK
@@ -29,10 +29,10 @@ macro_rules! foo {
     (ident $x:ident) => { bar!(ident $x); };
     (lifetime $x:lifetime) => { bar!(lifetime $x); };
     (tt $x:tt) => { bar!(tt $x); };
-    (expr $x:expr) => { bar!(expr $x); }; //~ ERROR: no rules expected the token `3`
-    (literal $x:literal) => { bar!(literal $x); }; //~ ERROR: no rules expected the token `4`
-    (path $x:path) => { bar!(path $x); }; //~ ERROR: no rules expected the token `a::b::c`
-    (stmt $x:stmt) => { bar!(stmt $x); }; //~ ERROR: no rules expected the token `let abc = 0`
+    (expr $x:expr) => { bar!(expr $x); }; //~ ERROR: no rules expected expression `3`
+    (literal $x:literal) => { bar!(literal $x); }; //~ ERROR: no rules expected literal `4`
+    (path $x:path) => { bar!(path $x); }; //~ ERROR: no rules expected path `a::b::c`
+    (stmt $x:stmt) => { bar!(stmt $x); }; //~ ERROR: no rules expected statement `let abc = 0`
 }
 
 macro_rules! bar {
diff --git a/tests/ui/macros/nonterminal-matching.stderr b/tests/ui/macros/nonterminal-matching.stderr
index 3ee88b5f52e..e283dfcb8fd 100644
--- a/tests/ui/macros/nonterminal-matching.stderr
+++ b/tests/ui/macros/nonterminal-matching.stderr
@@ -1,4 +1,4 @@
-error: no rules expected the token `enum E {}`
+error: no rules expected item `enum E {}`
   --> $DIR/nonterminal-matching.rs:19:10
    |
 LL |     macro n(a $nt_item b) {
@@ -10,7 +10,7 @@ LL |     n!(a $nt_item b);
 LL | complex_nonterminal!(enum E {});
    | ------------------------------- in this macro invocation
    |
-note: while trying to match `enum E {}`
+note: while trying to match item `enum E {}`
   --> $DIR/nonterminal-matching.rs:15:15
    |
 LL |     macro n(a $nt_item b) {
@@ -23,7 +23,7 @@ LL | complex_nonterminal!(enum E {});
    = help: try using `:tt` instead in the macro definition
    = note: this error originates in the macro `complex_nonterminal` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: no rules expected the token `3`
+error: no rules expected expression `3`
   --> $DIR/nonterminal-matching.rs:32:35
    |
 LL |     (expr $x:expr) => { bar!(expr $x); };
@@ -45,7 +45,7 @@ LL |     (expr 3) => {};
    = help: try using `:tt` instead in the macro definition
    = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: no rules expected the token `4`
+error: no rules expected literal `4`
   --> $DIR/nonterminal-matching.rs:33:44
    |
 LL |     (literal $x:literal) => { bar!(literal $x); };
@@ -67,7 +67,7 @@ LL |     (literal 4) => {};
    = help: try using `:tt` instead in the macro definition
    = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: no rules expected the token `a::b::c`
+error: no rules expected path `a::b::c`
   --> $DIR/nonterminal-matching.rs:34:35
    |
 LL |     (path $x:path) => { bar!(path $x); };
@@ -89,7 +89,7 @@ LL |     (path a::b::c) => {};
    = help: try using `:tt` instead in the macro definition
    = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: no rules expected the token `let abc = 0`
+error: no rules expected statement `let abc = 0`
   --> $DIR/nonterminal-matching.rs:35:35
    |
 LL |     (stmt $x:stmt) => { bar!(stmt $x); };
@@ -101,7 +101,7 @@ LL | macro_rules! bar {
 LL | foo!(stmt let abc = 0);
    | ---------------------- in this macro invocation
    |
-note: while trying to match `let`
+note: while trying to match keyword `let`
   --> $DIR/nonterminal-matching.rs:45:11
    |
 LL |     (stmt let abc = 0) => {};
diff --git a/tests/ui/macros/not-utf8.rs b/tests/ui/macros/not-utf8.rs
index 3c433a4e27c..8100d65a9f8 100644
--- a/tests/ui/macros/not-utf8.rs
+++ b/tests/ui/macros/not-utf8.rs
@@ -1,4 +1,6 @@
 //@ error-pattern: did not contain valid UTF-8
+//@ reference: input.encoding.utf8
+//@ reference: input.encoding.invalid
 
 fn foo() {
     include!("not-utf8.bin")
diff --git a/tests/ui/macros/not-utf8.stderr b/tests/ui/macros/not-utf8.stderr
index bf4704285c0..0d587cab5f3 100644
--- a/tests/ui/macros/not-utf8.stderr
+++ b/tests/ui/macros/not-utf8.stderr
@@ -1,5 +1,5 @@
 error: couldn't read $DIR/not-utf8.bin: stream did not contain valid UTF-8
-  --> $DIR/not-utf8.rs:4:5
+  --> $DIR/not-utf8.rs:6:5
    |
 LL |     include!("not-utf8.bin")
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/macros/syntax-error-recovery.rs b/tests/ui/macros/syntax-error-recovery.rs
index f6178c137db..016e4def284 100644
--- a/tests/ui/macros/syntax-error-recovery.rs
+++ b/tests/ui/macros/syntax-error-recovery.rs
@@ -10,7 +10,7 @@ macro_rules! values {
     };
 }
 //~^^^^^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found type `(String)`
-//~| ERROR macro expansion ignores token `(String)` and any following
+//~| ERROR macro expansion ignores type `(String)` and any tokens following
 
 values!(STRING(1) as (String) => cfg(test),);
 //~^ ERROR expected one of `!` or `::`, found `<eof>`
diff --git a/tests/ui/macros/syntax-error-recovery.stderr b/tests/ui/macros/syntax-error-recovery.stderr
index 6218bf43a1e..3cfbd8ce82b 100644
--- a/tests/ui/macros/syntax-error-recovery.stderr
+++ b/tests/ui/macros/syntax-error-recovery.stderr
@@ -10,7 +10,7 @@ LL | values!(STRING(1) as (String) => cfg(test),);
    = help: enum variants can be `Variant`, `Variant = <integer>`, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`
    = note: this error originates in the macro `values` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: macro expansion ignores token `(String)` and any following
+error: macro expansion ignores type `(String)` and any tokens following
   --> $DIR/syntax-error-recovery.rs:7:26
    |
 LL |                 $token $($inner)? = $value,
diff --git a/tests/ui/macros/trace_faulty_macros.stderr b/tests/ui/macros/trace_faulty_macros.stderr
index 66d7b76bb07..10ad3faab16 100644
--- a/tests/ui/macros/trace_faulty_macros.stderr
+++ b/tests/ui/macros/trace_faulty_macros.stderr
@@ -1,4 +1,4 @@
-error: no rules expected the token `bcd`
+error: no rules expected `bcd`
   --> $DIR/trace_faulty_macros.rs:7:26
    |
 LL | macro_rules! my_faulty_macro {
diff --git a/tests/ui/mir/clone-canonicalization-miscompile-132353.rs b/tests/ui/mir/clone-canonicalization-miscompile-132353.rs
new file mode 100644
index 00000000000..ba740c10f90
--- /dev/null
+++ b/tests/ui/mir/clone-canonicalization-miscompile-132353.rs
@@ -0,0 +1,25 @@
+//! The mir-opt added in <https://github.com/rust-lang/rust/pull/128299> unfortunately seems to lead
+//! to a miscompile (reported in <https://github.com/rust-lang/rust/issues/132353>, minimization
+//! reproduced in this test file).
+//@ revisions: release debug
+// Note: it's not strictly cargo's release profile, but any non-zero opt-level was sufficient to
+// reproduce the miscompile.
+//@[release] compile-flags: -C opt-level=1
+//@[debug] compile-flags: -C opt-level=0
+//@ run-pass
+
+fn pop_min(mut score2head: Vec<Option<usize>>) -> Option<usize> {
+    loop {
+        if let Some(col) = score2head[0] {
+            score2head[0] = None;
+            return Some(col);
+        }
+    }
+}
+
+fn main() {
+    let min = pop_min(vec![Some(1)]);
+    println!("min: {:?}", min);
+    // panic happened on 1.83.0 beta in release mode but not debug mode.
+    let _ = min.unwrap();
+}
diff --git a/tests/ui/mir/mir_let_chains_drop_order.rs b/tests/ui/mir/mir_let_chains_drop_order.rs
index daf0a62fc85..92199625207 100644
--- a/tests/ui/mir/mir_let_chains_drop_order.rs
+++ b/tests/ui/mir/mir_let_chains_drop_order.rs
@@ -8,7 +8,6 @@
 // See `mir_drop_order.rs` for more information
 
 #![feature(let_chains)]
-#![cfg_attr(edition2024, feature(if_let_rescope))]
 #![allow(irrefutable_let_patterns)]
 
 use std::cell::RefCell;
diff --git a/tests/ui/modules/issue-107649.stderr b/tests/ui/modules/issue-107649.stderr
index d5405c6576a..0d203c1aacb 100644
--- a/tests/ui/modules/issue-107649.stderr
+++ b/tests/ui/modules/issue-107649.stderr
@@ -4,7 +4,7 @@ error[E0277]: `Dummy` doesn't implement `Debug`
 105 |     dbg!(lib::Dummy);
     |     ^^^^^^^^^^^^^^^^ `Dummy` cannot be formatted using `{:?}`
     |
-    = help: the trait `Debug` is not implemented for `Dummy`, which is required by `&Dummy: Debug`
+    = help: the trait `Debug` is not implemented for `Dummy`
     = note: add `#[derive(Debug)]` to `Dummy` or manually `impl Debug for Dummy`
     = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `Dummy` with `#[derive(Debug)]`
diff --git a/tests/ui/mut/mutable-enum-indirect.stderr b/tests/ui/mut/mutable-enum-indirect.stderr
index d7af327df5a..0b7783b3318 100644
--- a/tests/ui/mut/mutable-enum-indirect.stderr
+++ b/tests/ui/mut/mutable-enum-indirect.stderr
@@ -6,7 +6,7 @@ LL |     bar(&x);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: within `&Foo`, the trait `Sync` is not implemented for `NoSync`, which is required by `&Foo: Sync`
+   = help: within `&Foo`, the trait `Sync` is not implemented for `NoSync`
 note: required because it appears within the type `Foo`
   --> $DIR/mutable-enum-indirect.rs:11:6
    |
diff --git a/tests/ui/nll/issue-54556-niconii.edition2021.stderr b/tests/ui/nll/issue-54556-niconii.edition2021.stderr
index 31a03abbc98..abee09ed950 100644
--- a/tests/ui/nll/issue-54556-niconii.edition2021.stderr
+++ b/tests/ui/nll/issue-54556-niconii.edition2021.stderr
@@ -1,5 +1,5 @@
 error[E0597]: `counter` does not live long enough
-  --> $DIR/issue-54556-niconii.rs:30:20
+  --> $DIR/issue-54556-niconii.rs:28:20
    |
 LL |     let counter = Mutex;
    |         ------- binding `counter` declared here
diff --git a/tests/ui/nll/issue-54556-niconii.rs b/tests/ui/nll/issue-54556-niconii.rs
index 1a7ad17cc84..f01e0523cbf 100644
--- a/tests/ui/nll/issue-54556-niconii.rs
+++ b/tests/ui/nll/issue-54556-niconii.rs
@@ -12,8 +12,6 @@
 //@ [edition2024] compile-flags: -Z unstable-options
 //@ [edition2024] check-pass
 
-#![cfg_attr(edition2024, feature(if_let_rescope))]
-
 struct Mutex;
 struct MutexGuard<'a>(&'a Mutex);
 
diff --git a/tests/ui/no-send-res-ports.stderr b/tests/ui/no-send-res-ports.stderr
index c71d8ecba37..9c30261e5cb 100644
--- a/tests/ui/no-send-res-ports.stderr
+++ b/tests/ui/no-send-res-ports.stderr
@@ -13,7 +13,7 @@ LL | |         println!("{:?}", y);
 LL | |     });
    | |_____^ `Rc<()>` cannot be sent between threads safely
    |
-   = help: within `{closure@$DIR/no-send-res-ports.rs:25:19: 25:25}`, the trait `Send` is not implemented for `Rc<()>`, which is required by `{closure@$DIR/no-send-res-ports.rs:25:19: 25:25}: Send`
+   = help: within `{closure@$DIR/no-send-res-ports.rs:25:19: 25:25}`, the trait `Send` is not implemented for `Rc<()>`
 note: required because it appears within the type `Port<()>`
   --> $DIR/no-send-res-ports.rs:5:8
    |
diff --git a/tests/ui/no_send-enum.stderr b/tests/ui/no_send-enum.stderr
index e24f79c7dd6..3b66c7db545 100644
--- a/tests/ui/no_send-enum.stderr
+++ b/tests/ui/no_send-enum.stderr
@@ -6,7 +6,7 @@ LL |     bar(x);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: within `Foo`, the trait `Send` is not implemented for `NoSend`, which is required by `Foo: Send`
+   = help: within `Foo`, the trait `Send` is not implemented for `NoSend`
 note: required because it appears within the type `Foo`
   --> $DIR/no_send-enum.rs:8:6
    |
diff --git a/tests/ui/no_share-enum.stderr b/tests/ui/no_share-enum.stderr
index 5b6c8bf0b4f..89939216d5b 100644
--- a/tests/ui/no_share-enum.stderr
+++ b/tests/ui/no_share-enum.stderr
@@ -6,7 +6,7 @@ LL |     bar(x);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: within `Foo`, the trait `Sync` is not implemented for `NoSync`, which is required by `Foo: Sync`
+   = help: within `Foo`, the trait `Sync` is not implemented for `NoSync`
 note: required because it appears within the type `Foo`
   --> $DIR/no_share-enum.rs:8:6
    |
diff --git a/tests/ui/not-clone-closure.stderr b/tests/ui/not-clone-closure.stderr
index 9b557b15582..783c165eeb2 100644
--- a/tests/ui/not-clone-closure.stderr
+++ b/tests/ui/not-clone-closure.stderr
@@ -5,7 +5,7 @@ LL |     let hello = move || {
    |                 ------- within this `{closure@$DIR/not-clone-closure.rs:7:17: 7:24}`
 ...
 LL |     let hello = hello.clone();
-   |                       ^^^^^ within `{closure@$DIR/not-clone-closure.rs:7:17: 7:24}`, the trait `Clone` is not implemented for `S`, which is required by `{closure@$DIR/not-clone-closure.rs:7:17: 7:24}: Clone`
+   |                       ^^^^^ within `{closure@$DIR/not-clone-closure.rs:7:17: 7:24}`, the trait `Clone` is not implemented for `S`
    |
 note: required because it's used within this closure
   --> $DIR/not-clone-closure.rs:7:17
diff --git a/tests/ui/not-panic/not-panic-safe-2.stderr b/tests/ui/not-panic/not-panic-safe-2.stderr
index 8c4cf9c98ed..0c399f15a25 100644
--- a/tests/ui/not-panic/not-panic-safe-2.stderr
+++ b/tests/ui/not-panic/not-panic-safe-2.stderr
@@ -4,7 +4,7 @@ error[E0277]: the type `UnsafeCell<i32>` may contain interior mutability and a r
 LL |     assert::<Rc<RefCell<i32>>>();
    |              ^^^^^^^^^^^^^^^^ `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
-   = help: within `RefCell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<i32>`, which is required by `Rc<RefCell<i32>>: UnwindSafe`
+   = help: within `RefCell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<i32>`
 note: required because it appears within the type `RefCell<i32>`
   --> $SRC_DIR/core/src/cell.rs:LL:COL
    = note: required for `Rc<RefCell<i32>>` to implement `UnwindSafe`
@@ -20,7 +20,7 @@ error[E0277]: the type `UnsafeCell<isize>` may contain interior mutability and a
 LL |     assert::<Rc<RefCell<i32>>>();
    |              ^^^^^^^^^^^^^^^^ `UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
-   = help: within `RefCell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<isize>`, which is required by `Rc<RefCell<i32>>: UnwindSafe`
+   = help: within `RefCell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<isize>`
 note: required because it appears within the type `Cell<isize>`
   --> $SRC_DIR/core/src/cell.rs:LL:COL
 note: required because it appears within the type `RefCell<i32>`
diff --git a/tests/ui/not-panic/not-panic-safe-3.stderr b/tests/ui/not-panic/not-panic-safe-3.stderr
index 2373ada63f6..53028d6a337 100644
--- a/tests/ui/not-panic/not-panic-safe-3.stderr
+++ b/tests/ui/not-panic/not-panic-safe-3.stderr
@@ -4,7 +4,7 @@ error[E0277]: the type `UnsafeCell<i32>` may contain interior mutability and a r
 LL |     assert::<Arc<RefCell<i32>>>();
    |              ^^^^^^^^^^^^^^^^^ `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
-   = help: within `RefCell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<i32>`, which is required by `Arc<RefCell<i32>>: UnwindSafe`
+   = help: within `RefCell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<i32>`
 note: required because it appears within the type `RefCell<i32>`
   --> $SRC_DIR/core/src/cell.rs:LL:COL
    = note: required for `Arc<RefCell<i32>>` to implement `UnwindSafe`
@@ -20,7 +20,7 @@ error[E0277]: the type `UnsafeCell<isize>` may contain interior mutability and a
 LL |     assert::<Arc<RefCell<i32>>>();
    |              ^^^^^^^^^^^^^^^^^ `UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
-   = help: within `RefCell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<isize>`, which is required by `Arc<RefCell<i32>>: UnwindSafe`
+   = help: within `RefCell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<isize>`
 note: required because it appears within the type `Cell<isize>`
   --> $SRC_DIR/core/src/cell.rs:LL:COL
 note: required because it appears within the type `RefCell<i32>`
diff --git a/tests/ui/not-panic/not-panic-safe-4.stderr b/tests/ui/not-panic/not-panic-safe-4.stderr
index d77cac8f272..b1361cfd87e 100644
--- a/tests/ui/not-panic/not-panic-safe-4.stderr
+++ b/tests/ui/not-panic/not-panic-safe-4.stderr
@@ -4,7 +4,7 @@ error[E0277]: the type `UnsafeCell<i32>` may contain interior mutability and a r
 LL |     assert::<&RefCell<i32>>();
    |              ^^^^^^^^^^^^^ `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
-   = help: within `RefCell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<i32>`, which is required by `&RefCell<i32>: UnwindSafe`
+   = help: within `RefCell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<i32>`
 note: required because it appears within the type `RefCell<i32>`
   --> $SRC_DIR/core/src/cell.rs:LL:COL
    = note: required for `&RefCell<i32>` to implement `UnwindSafe`
@@ -25,7 +25,7 @@ error[E0277]: the type `UnsafeCell<isize>` may contain interior mutability and a
 LL |     assert::<&RefCell<i32>>();
    |              ^^^^^^^^^^^^^ `UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
-   = help: within `RefCell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<isize>`, which is required by `&RefCell<i32>: UnwindSafe`
+   = help: within `RefCell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<isize>`
 note: required because it appears within the type `Cell<isize>`
   --> $SRC_DIR/core/src/cell.rs:LL:COL
 note: required because it appears within the type `RefCell<i32>`
diff --git a/tests/ui/not-panic/not-panic-safe-5.stderr b/tests/ui/not-panic/not-panic-safe-5.stderr
index 0de9a2cc0cd..fbbd81d6d4c 100644
--- a/tests/ui/not-panic/not-panic-safe-5.stderr
+++ b/tests/ui/not-panic/not-panic-safe-5.stderr
@@ -4,7 +4,7 @@ error[E0277]: the type `UnsafeCell<i32>` may contain interior mutability and a r
 LL |     assert::<*const UnsafeCell<i32>>();
    |              ^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
-   = help: the trait `RefUnwindSafe` is not implemented for `UnsafeCell<i32>`, which is required by `*const UnsafeCell<i32>: UnwindSafe`
+   = help: the trait `RefUnwindSafe` is not implemented for `UnsafeCell<i32>`
    = note: required for `*const UnsafeCell<i32>` to implement `UnwindSafe`
 note: required by a bound in `assert`
   --> $DIR/not-panic-safe-5.rs:6:14
diff --git a/tests/ui/not-panic/not-panic-safe-6.stderr b/tests/ui/not-panic/not-panic-safe-6.stderr
index 7714a577f8a..47f28257409 100644
--- a/tests/ui/not-panic/not-panic-safe-6.stderr
+++ b/tests/ui/not-panic/not-panic-safe-6.stderr
@@ -4,7 +4,7 @@ error[E0277]: the type `UnsafeCell<i32>` may contain interior mutability and a r
 LL |     assert::<*mut RefCell<i32>>();
    |              ^^^^^^^^^^^^^^^^^ `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
-   = help: within `RefCell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<i32>`, which is required by `*mut RefCell<i32>: UnwindSafe`
+   = help: within `RefCell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<i32>`
 note: required because it appears within the type `RefCell<i32>`
   --> $SRC_DIR/core/src/cell.rs:LL:COL
    = note: required for `*mut RefCell<i32>` to implement `UnwindSafe`
@@ -20,7 +20,7 @@ error[E0277]: the type `UnsafeCell<isize>` may contain interior mutability and a
 LL |     assert::<*mut RefCell<i32>>();
    |              ^^^^^^^^^^^^^^^^^ `UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
-   = help: within `RefCell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<isize>`, which is required by `*mut RefCell<i32>: UnwindSafe`
+   = help: within `RefCell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<isize>`
 note: required because it appears within the type `Cell<isize>`
   --> $SRC_DIR/core/src/cell.rs:LL:COL
 note: required because it appears within the type `RefCell<i32>`
diff --git a/tests/ui/offset-of/offset-of-arg-count.rs b/tests/ui/offset-of/offset-of-arg-count.rs
index c86e61a61a7..f4c8b91d7da 100644
--- a/tests/ui/offset-of/offset-of-arg-count.rs
+++ b/tests/ui/offset-of/offset-of-arg-count.rs
@@ -3,7 +3,7 @@ use std::mem::offset_of;
 fn main() {
     offset_of!(NotEnoughArguments); //~ ERROR unexpected end of macro invocation
     offset_of!(NotEnoughArgumentsWithAComma, ); //~ ERROR unexpected end of macro invocation
-    offset_of!(Container, field, too many arguments); //~ ERROR no rules expected the token `too`
+    offset_of!(Container, field, too many arguments); //~ ERROR no rules expected `too`
     offset_of!(S, f); // compiles fine
     offset_of!(S, f,); // also compiles fine
     offset_of!(S, f.); //~ ERROR unexpected token: `)`
diff --git a/tests/ui/offset-of/offset-of-arg-count.stderr b/tests/ui/offset-of/offset-of-arg-count.stderr
index 4cb24b3d034..0772bb18e0c 100644
--- a/tests/ui/offset-of/offset-of-arg-count.stderr
+++ b/tests/ui/offset-of/offset-of-arg-count.stderr
@@ -16,7 +16,7 @@ LL |     offset_of!(NotEnoughArgumentsWithAComma, );
 note: while trying to match meta-variable `$fields:expr`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
 
-error: no rules expected the token `too`
+error: no rules expected `too`
   --> $DIR/offset-of-arg-count.rs:6:34
    |
 LL |     offset_of!(Container, field, too many arguments);
diff --git a/tests/ui/offset-of/offset-of-dst-field.stderr b/tests/ui/offset-of/offset-of-dst-field.stderr
index bcfe796897e..714bf7a0266 100644
--- a/tests/ui/offset-of/offset-of-dst-field.stderr
+++ b/tests/ui/offset-of/offset-of-dst-field.stderr
@@ -58,7 +58,7 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation
 LL |     offset_of!(Delta<Alpha>, z);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = help: within `Alpha`, the trait `Sized` is not implemented for `[u8]`, which is required by `Alpha: Sized`
+   = help: within `Alpha`, the trait `Sized` is not implemented for `[u8]`
 note: required because it appears within the type `Alpha`
   --> $DIR/offset-of-dst-field.rs:5:8
    |
diff --git a/tests/ui/offset-of/offset-of-tuple.stderr b/tests/ui/offset-of/offset-of-tuple.stderr
index dd20859e04e..38ce49c9179 100644
--- a/tests/ui/offset-of/offset-of-tuple.stderr
+++ b/tests/ui/offset-of/offset-of-tuple.stderr
@@ -76,7 +76,7 @@ error: suffixes on a tuple index are invalid
 LL |     offset_of!((u8, u8), 1_u8);
    |                          ^^^^ invalid suffix `u8`
 
-error: no rules expected the token `+`
+error: no rules expected `+`
   --> $DIR/offset-of-tuple.rs:11:26
    |
 LL |     offset_of!((u8, u8), +1);
diff --git a/tests/ui/on-unimplemented/slice-index.stderr b/tests/ui/on-unimplemented/slice-index.stderr
index 0f8d105abef..d53ecb9db0c 100644
--- a/tests/ui/on-unimplemented/slice-index.stderr
+++ b/tests/ui/on-unimplemented/slice-index.stderr
@@ -4,7 +4,7 @@ error[E0277]: the type `[i32]` cannot be indexed by `i32`
 LL |     x[1i32];
    |       ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
-   = help: the trait `SliceIndex<[i32]>` is not implemented for `i32`, which is required by `[i32]: Index<_>`
+   = help: the trait `SliceIndex<[i32]>` is not implemented for `i32`
    = help: the trait `SliceIndex<[i32]>` is implemented for `usize`
    = help: for that trait implementation, expected `usize`, found `i32`
    = note: required for `[i32]` to implement `Index<i32>`
@@ -15,7 +15,7 @@ error[E0277]: the type `[i32]` cannot be indexed by `RangeTo<i32>`
 LL |     x[..1i32];
    |       ^^^^^^ slice indices are of type `usize` or ranges of `usize`
    |
-   = help: the trait `SliceIndex<[i32]>` is not implemented for `RangeTo<i32>`, which is required by `[i32]: Index<_>`
+   = help: the trait `SliceIndex<[i32]>` is not implemented for `RangeTo<i32>`
    = help: the following other types implement trait `SliceIndex<T>`:
              `RangeTo<usize>` implements `SliceIndex<[T]>`
              `RangeTo<usize>` implements `SliceIndex<str>`
diff --git a/tests/ui/or-patterns/or-patterns-syntactic-fail-2018.rs b/tests/ui/or-patterns/or-patterns-syntactic-fail-2018.rs
index 7a94c96b79d..fb227bf0e91 100644
--- a/tests/ui/or-patterns/or-patterns-syntactic-fail-2018.rs
+++ b/tests/ui/or-patterns/or-patterns-syntactic-fail-2018.rs
@@ -9,5 +9,5 @@ macro_rules! accept_pat {
     ($p:pat) => {};
 }
 
-accept_pat!(p | q); //~ ERROR no rules expected the token `|`
-accept_pat!(|p| q); //~ ERROR no rules expected the token `|`
+accept_pat!(p | q); //~ ERROR no rules expected `|`
+accept_pat!(|p| q); //~ ERROR no rules expected `|`
diff --git a/tests/ui/or-patterns/or-patterns-syntactic-fail-2018.stderr b/tests/ui/or-patterns/or-patterns-syntactic-fail-2018.stderr
index acc2099bbc6..47dac84ee49 100644
--- a/tests/ui/or-patterns/or-patterns-syntactic-fail-2018.stderr
+++ b/tests/ui/or-patterns/or-patterns-syntactic-fail-2018.stderr
@@ -1,4 +1,4 @@
-error: no rules expected the token `|`
+error: no rules expected `|`
   --> $DIR/or-patterns-syntactic-fail-2018.rs:12:15
    |
 LL | macro_rules! accept_pat {
@@ -13,7 +13,7 @@ note: while trying to match meta-variable `$p:pat`
 LL |     ($p:pat) => {};
    |      ^^^^^^
 
-error: no rules expected the token `|`
+error: no rules expected `|`
   --> $DIR/or-patterns-syntactic-fail-2018.rs:13:13
    |
 LL | macro_rules! accept_pat {
diff --git a/tests/ui/parser/macro/macro-doc-comments-1.rs b/tests/ui/parser/macro/macro-doc-comments-1.rs
index 8d8103bb1e0..1aaa993e072 100644
--- a/tests/ui/parser/macro/macro-doc-comments-1.rs
+++ b/tests/ui/parser/macro/macro-doc-comments-1.rs
@@ -4,6 +4,6 @@ macro_rules! outer {
 
 outer! {
     //! Inner
-} //~^ ERROR no rules expected the token `!`
+} //~^ ERROR no rules expected `!`
 
 fn main() { }
diff --git a/tests/ui/parser/macro/macro-doc-comments-1.stderr b/tests/ui/parser/macro/macro-doc-comments-1.stderr
index 9d2d1bc0072..6b7e758980c 100644
--- a/tests/ui/parser/macro/macro-doc-comments-1.stderr
+++ b/tests/ui/parser/macro/macro-doc-comments-1.stderr
@@ -1,4 +1,4 @@
-error: no rules expected the token `!`
+error: no rules expected `!`
   --> $DIR/macro-doc-comments-1.rs:6:5
    |
 LL | macro_rules! outer {
diff --git a/tests/ui/parser/macro/macro-doc-comments-2.rs b/tests/ui/parser/macro/macro-doc-comments-2.rs
index 8f33720ae80..2bee2435ef8 100644
--- a/tests/ui/parser/macro/macro-doc-comments-2.rs
+++ b/tests/ui/parser/macro/macro-doc-comments-2.rs
@@ -4,6 +4,6 @@ macro_rules! inner {
 
 inner! {
     /// Outer
-} //~^ ERROR no rules expected the token `[`
+} //~^ ERROR no rules expected `[`
 
 fn main() { }
diff --git a/tests/ui/parser/macro/macro-doc-comments-2.stderr b/tests/ui/parser/macro/macro-doc-comments-2.stderr
index 22efd995b46..02c12bf9591 100644
--- a/tests/ui/parser/macro/macro-doc-comments-2.stderr
+++ b/tests/ui/parser/macro/macro-doc-comments-2.stderr
@@ -1,4 +1,4 @@
-error: no rules expected the token `[`
+error: no rules expected `[`
   --> $DIR/macro-doc-comments-2.rs:6:5
    |
 LL | macro_rules! inner {
diff --git a/tests/ui/parser/macro/macro-expand-to-match-arm.rs b/tests/ui/parser/macro/macro-expand-to-match-arm.rs
index db38fa0d7bc..0e27836b718 100644
--- a/tests/ui/parser/macro/macro-expand-to-match-arm.rs
+++ b/tests/ui/parser/macro/macro-expand-to-match-arm.rs
@@ -1,7 +1,7 @@
 macro_rules! arm {
     ($pattern:pat => $block:block) => {
         $pattern => $block
-        //~^ ERROR macro expansion ignores token `=>` and any following
+        //~^ ERROR macro expansion ignores `=>` and any tokens following
         //~| NOTE the usage of `arm!` is likely invalid in pattern context
         //~| NOTE macros cannot expand to match arms
     };
diff --git a/tests/ui/parser/macro/macro-expand-to-match-arm.stderr b/tests/ui/parser/macro/macro-expand-to-match-arm.stderr
index e3e7ff89c81..1927d80fd72 100644
--- a/tests/ui/parser/macro/macro-expand-to-match-arm.stderr
+++ b/tests/ui/parser/macro/macro-expand-to-match-arm.stderr
@@ -1,4 +1,4 @@
-error: macro expansion ignores token `=>` and any following
+error: macro expansion ignores `=>` and any tokens following
   --> $DIR/macro-expand-to-match-arm.rs:3:18
    |
 LL |         $pattern => $block
diff --git a/tests/ui/parser/macro/macro-incomplete-parse.rs b/tests/ui/parser/macro/macro-incomplete-parse.rs
index 544e4aa7b1b..612196aa4b2 100644
--- a/tests/ui/parser/macro/macro-incomplete-parse.rs
+++ b/tests/ui/parser/macro/macro-incomplete-parse.rs
@@ -2,7 +2,7 @@ macro_rules! ignored_item {
     () => {
         fn foo() {}
         fn bar() {}
-        , //~ ERROR macro expansion ignores token `,`
+        , //~ ERROR macro expansion ignores `,`
     }
 }
 
@@ -13,7 +13,7 @@ macro_rules! ignored_expr {
 }
 
 macro_rules! ignored_pat {
-    () => ( 1, 2 ) //~ ERROR macro expansion ignores token `,`
+    () => ( 1, 2 ) //~ ERROR macro expansion ignores `,`
 }
 
 ignored_item!();
diff --git a/tests/ui/parser/macro/macro-incomplete-parse.stderr b/tests/ui/parser/macro/macro-incomplete-parse.stderr
index 707417b725e..096b5f718ae 100644
--- a/tests/ui/parser/macro/macro-incomplete-parse.stderr
+++ b/tests/ui/parser/macro/macro-incomplete-parse.stderr
@@ -1,4 +1,4 @@
-error: macro expansion ignores token `,` and any following
+error: macro expansion ignores `,` and any tokens following
   --> $DIR/macro-incomplete-parse.rs:5:9
    |
 LL |         ,
@@ -20,7 +20,7 @@ LL |     ignored_expr!();
    |
    = note: this error originates in the macro `ignored_expr` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: macro expansion ignores token `,` and any following
+error: macro expansion ignores `,` and any tokens following
   --> $DIR/macro-incomplete-parse.rs:16:14
    |
 LL |     () => ( 1, 2 )
diff --git a/tests/ui/parser/macro/trait-non-item-macros.rs b/tests/ui/parser/macro/trait-non-item-macros.rs
index 97fb564bf64..e93000193b6 100644
--- a/tests/ui/parser/macro/trait-non-item-macros.rs
+++ b/tests/ui/parser/macro/trait-non-item-macros.rs
@@ -1,7 +1,7 @@
 macro_rules! bah {
     ($a:expr) => {
         $a
-    }; //~^ ERROR macro expansion ignores token `2` and any following
+    }; //~^ ERROR macro expansion ignores expression `2` and any tokens following
 }
 
 trait Bar {
diff --git a/tests/ui/parser/macro/trait-non-item-macros.stderr b/tests/ui/parser/macro/trait-non-item-macros.stderr
index db20e6b24aa..1a828483778 100644
--- a/tests/ui/parser/macro/trait-non-item-macros.stderr
+++ b/tests/ui/parser/macro/trait-non-item-macros.stderr
@@ -1,4 +1,4 @@
-error: macro expansion ignores token `2` and any following
+error: macro expansion ignores expression `2` and any tokens following
   --> $DIR/trait-non-item-macros.rs:3:9
    |
 LL |         $a
diff --git a/tests/ui/parser/shebang/issue-71471-ignore-tidy.rs b/tests/ui/parser/shebang/issue-71471-ignore-tidy.rs
index a2505180884..e9bff91f1e8 100644
--- a/tests/ui/parser/shebang/issue-71471-ignore-tidy.rs
+++ b/tests/ui/parser/shebang/issue-71471-ignore-tidy.rs
@@ -1,2 +1,4 @@
 
 #!B //~ expected `[`, found `B`
+
+//@ reference: input.shebang
diff --git a/tests/ui/parser/shebang/multiline-attrib.rs b/tests/ui/parser/shebang/multiline-attrib.rs
index bb083610e55..2d2e0298638 100644
--- a/tests/ui/parser/shebang/multiline-attrib.rs
+++ b/tests/ui/parser/shebang/multiline-attrib.rs
@@ -1,6 +1,7 @@
 #!
 [allow(unused_variables)]
 //@ check-pass
+//@ reference: input.shebang.inner-attribute
 
 fn main() {
     let x = 5;
diff --git a/tests/ui/parser/shebang/regular-attrib.rs b/tests/ui/parser/shebang/regular-attrib.rs
index aed633d3ef1..c2ac25661ef 100644
--- a/tests/ui/parser/shebang/regular-attrib.rs
+++ b/tests/ui/parser/shebang/regular-attrib.rs
@@ -1,5 +1,6 @@
 #![allow(unused_variables)]
 //@ check-pass
+//@ reference: input.shebang.inner-attribute
 fn main() {
     let x = 5;
 }
diff --git a/tests/ui/parser/shebang/shebang-and-attrib.rs b/tests/ui/parser/shebang/shebang-and-attrib.rs
index a66c10db532..d73db6b22f0 100644
--- a/tests/ui/parser/shebang/shebang-and-attrib.rs
+++ b/tests/ui/parser/shebang/shebang-and-attrib.rs
@@ -1,6 +1,7 @@
 #!/usr/bin/env run-cargo-script
 
 //@ check-pass
+//@ reference: input.shebang.inner-attribute
 #![allow(unused_variables)]
 
 
diff --git a/tests/ui/parser/shebang/shebang-comment.rs b/tests/ui/parser/shebang/shebang-comment.rs
index 37bcac8b29e..6f89e8954c3 100644
--- a/tests/ui/parser/shebang/shebang-comment.rs
+++ b/tests/ui/parser/shebang/shebang-comment.rs
@@ -1,6 +1,7 @@
 #!//bin/bash
 
 //@ check-pass
+//@ reference: input.shebang
 fn main() {
     println!("a valid shebang (that is also a rust comment)")
 }
diff --git a/tests/ui/parser/shebang/shebang-doc-comment.rs b/tests/ui/parser/shebang/shebang-doc-comment.rs
index 72866753e0e..4992c758325 100644
--- a/tests/ui/parser/shebang/shebang-doc-comment.rs
+++ b/tests/ui/parser/shebang/shebang-doc-comment.rs
@@ -1,3 +1,5 @@
 #!///bin/bash
 [allow(unused_variables)]
 //~^ ERROR expected item, found `[`
+
+//@ reference: input.shebang.inner-attribute
diff --git a/tests/ui/parser/shebang/shebang-empty.rs b/tests/ui/parser/shebang/shebang-empty.rs
index bb0df599783..51bf8a07c90 100644
--- a/tests/ui/parser/shebang/shebang-empty.rs
+++ b/tests/ui/parser/shebang/shebang-empty.rs
@@ -1,4 +1,5 @@
 #!
 
 //@ check-pass
+//@ reference: input.shebang
 fn main() {}
diff --git a/tests/ui/parser/shebang/shebang-must-start-file.rs b/tests/ui/parser/shebang/shebang-must-start-file.rs
index e0392572dc8..f91e32f744e 100644
--- a/tests/ui/parser/shebang/shebang-must-start-file.rs
+++ b/tests/ui/parser/shebang/shebang-must-start-file.rs
@@ -1,6 +1,8 @@
 // something on the first line for tidy
 #!/bin/bash  //~ expected `[`, found `/`
 
+//@ reference: input.shebang
+
 fn main() {
     println!("ok!");
 }
diff --git a/tests/ui/parser/shebang/shebang-space.rs b/tests/ui/parser/shebang/shebang-space.rs
index cc58eed8b8a..803d4e04057 100644
--- a/tests/ui/parser/shebang/shebang-space.rs
+++ b/tests/ui/parser/shebang/shebang-space.rs
@@ -1,5 +1,6 @@
 #!    
 
 //@ check-pass
+//@ reference: input.shebang
 // ignore-tidy-end-whitespace
 fn main() {}
diff --git a/tests/ui/parser/shebang/sneaky-attrib.rs b/tests/ui/parser/shebang/sneaky-attrib.rs
index eb814c6af24..e22c45cc39f 100644
--- a/tests/ui/parser/shebang/sneaky-attrib.rs
+++ b/tests/ui/parser/shebang/sneaky-attrib.rs
@@ -11,6 +11,7 @@
 [allow(unused_variables)]
 
 //@ check-pass
+//@ reference: input.shebang.inner-attribute
 fn main() {
     let x = 5;
 }
diff --git a/tests/ui/parser/shebang/valid-shebang.rs b/tests/ui/parser/shebang/valid-shebang.rs
index e59d4074ddf..f93b0e15d77 100644
--- a/tests/ui/parser/shebang/valid-shebang.rs
+++ b/tests/ui/parser/shebang/valid-shebang.rs
@@ -1,6 +1,7 @@
 #!/usr/bin/env run-cargo-script
 
 //@ check-pass
+//@ reference: input.shebang
 fn main() {
     println!("Hello World!");
 }
diff --git a/tests/ui/parser/struct-literal-in-for.stderr b/tests/ui/parser/struct-literal-in-for.stderr
index d2ef2ad7b5a..1c91eba68e3 100644
--- a/tests/ui/parser/struct-literal-in-for.stderr
+++ b/tests/ui/parser/struct-literal-in-for.stderr
@@ -23,7 +23,7 @@ LL | |         x: 3
 LL | |     }.hi() {
    | |__________^ `bool` is not an iterator
    |
-   = help: the trait `Iterator` is not implemented for `bool`, which is required by `bool: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `bool`
    = note: required for `bool` to implement `IntoIterator`
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/parser/utf16-be-without-bom.rs b/tests/ui/parser/utf16-be-without-bom.rs
index 68e89bc7c22..f5fe8dc5a8c 100644
--- a/tests/ui/parser/utf16-be-without-bom.rs
+++ b/tests/ui/parser/utf16-be-without-bom.rs
Binary files differdiff --git a/tests/ui/parser/utf16-be-without-bom.stderr b/tests/ui/parser/utf16-be-without-bom.stderr
index 55ebf7aacd2..b915c7941b3 100644
--- a/tests/ui/parser/utf16-be-without-bom.stderr
+++ b/tests/ui/parser/utf16-be-without-bom.stderr
@@ -1,5 +1,5 @@
 error: unknown start of token: \u{0}
-  --> $DIR/utf16-be-without-bom.rs:4:1
+  --> $DIR/utf16-be-without-bom.rs:5:1
    |
 LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    | ^
@@ -7,7 +7,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used
 
 error: unknown start of token: \u{0}
-  --> $DIR/utf16-be-without-bom.rs:4:3
+  --> $DIR/utf16-be-without-bom.rs:5:3
    |
 LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    |   ^
@@ -15,7 +15,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used
 
 error: unknown start of token: \u{0}
-  --> $DIR/utf16-be-without-bom.rs:4:5
+  --> $DIR/utf16-be-without-bom.rs:5:5
    |
 LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    |     ^
@@ -23,7 +23,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used
 
 error: unknown start of token: \u{0}
-  --> $DIR/utf16-be-without-bom.rs:4:7
+  --> $DIR/utf16-be-without-bom.rs:5:7
    |
 LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    |       ^
@@ -31,7 +31,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used
 
 error: unknown start of token: \u{0}
-  --> $DIR/utf16-be-without-bom.rs:4:9
+  --> $DIR/utf16-be-without-bom.rs:5:9
    |
 LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    |         ^
@@ -39,7 +39,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used
 
 error: unknown start of token: \u{0}
-  --> $DIR/utf16-be-without-bom.rs:4:11
+  --> $DIR/utf16-be-without-bom.rs:5:11
    |
 LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    |           ^
@@ -47,7 +47,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used
 
 error: unknown start of token: \u{0}
-  --> $DIR/utf16-be-without-bom.rs:4:13
+  --> $DIR/utf16-be-without-bom.rs:5:13
    |
 LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    |             ^
@@ -55,7 +55,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used
 
 error: unknown start of token: \u{0}
-  --> $DIR/utf16-be-without-bom.rs:4:15
+  --> $DIR/utf16-be-without-bom.rs:5:15
    |
 LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    |               ^
@@ -63,7 +63,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used
 
 error: unknown start of token: \u{0}
-  --> $DIR/utf16-be-without-bom.rs:4:17
+  --> $DIR/utf16-be-without-bom.rs:5:17
    |
 LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    |                 ^
@@ -71,7 +71,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used
 
 error: unknown start of token: \u{0}
-  --> $DIR/utf16-be-without-bom.rs:4:19
+  --> $DIR/utf16-be-without-bom.rs:5:19
    |
 LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    |                   ^
@@ -79,7 +79,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used
 
 error: unknown start of token: \u{0}
-  --> $DIR/utf16-be-without-bom.rs:4:21
+  --> $DIR/utf16-be-without-bom.rs:5:21
    |
 LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    |                     ^
@@ -87,7 +87,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used
 
 error: unknown start of token: \u{0}
-  --> $DIR/utf16-be-without-bom.rs:4:23
+  --> $DIR/utf16-be-without-bom.rs:5:23
    |
 LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    |                       ^
@@ -95,7 +95,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used
 
 error: unknown start of token: \u{0}
-  --> $DIR/utf16-be-without-bom.rs:4:25
+  --> $DIR/utf16-be-without-bom.rs:5:25
    |
 LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    |                         ^
@@ -103,7 +103,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used
 
 error: expected one of `!` or `::`, found `n`
-  --> $DIR/utf16-be-without-bom.rs:4:4
+  --> $DIR/utf16-be-without-bom.rs:5:4
    |
 LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    |    ^ expected one of `!` or `::`
diff --git a/tests/ui/parser/utf16-le-without-bom.rs b/tests/ui/parser/utf16-le-without-bom.rs
index bdf4860d016..8c781b27dc0 100644
--- a/tests/ui/parser/utf16-le-without-bom.rs
+++ b/tests/ui/parser/utf16-le-without-bom.rs
Binary files differdiff --git a/tests/ui/parser/utf16-le-without-bom.stderr b/tests/ui/parser/utf16-le-without-bom.stderr
index ad272a70f06..d937a07bc66 100644
--- a/tests/ui/parser/utf16-le-without-bom.stderr
+++ b/tests/ui/parser/utf16-le-without-bom.stderr
@@ -1,5 +1,5 @@
 error: unknown start of token: \u{0}
-  --> $DIR/utf16-le-without-bom.rs:4:2
+  --> $DIR/utf16-le-without-bom.rs:5:2
    |
 LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    |  ^
@@ -7,7 +7,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used
 
 error: unknown start of token: \u{0}
-  --> $DIR/utf16-le-without-bom.rs:4:4
+  --> $DIR/utf16-le-without-bom.rs:5:4
    |
 LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    |    ^
@@ -15,7 +15,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used
 
 error: unknown start of token: \u{0}
-  --> $DIR/utf16-le-without-bom.rs:4:6
+  --> $DIR/utf16-le-without-bom.rs:5:6
    |
 LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    |      ^
@@ -23,7 +23,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used
 
 error: unknown start of token: \u{0}
-  --> $DIR/utf16-le-without-bom.rs:4:8
+  --> $DIR/utf16-le-without-bom.rs:5:8
    |
 LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    |        ^
@@ -31,7 +31,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used
 
 error: unknown start of token: \u{0}
-  --> $DIR/utf16-le-without-bom.rs:4:10
+  --> $DIR/utf16-le-without-bom.rs:5:10
    |
 LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    |          ^
@@ -39,7 +39,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used
 
 error: unknown start of token: \u{0}
-  --> $DIR/utf16-le-without-bom.rs:4:12
+  --> $DIR/utf16-le-without-bom.rs:5:12
    |
 LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    |            ^
@@ -47,7 +47,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used
 
 error: unknown start of token: \u{0}
-  --> $DIR/utf16-le-without-bom.rs:4:14
+  --> $DIR/utf16-le-without-bom.rs:5:14
    |
 LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    |              ^
@@ -55,7 +55,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used
 
 error: unknown start of token: \u{0}
-  --> $DIR/utf16-le-without-bom.rs:4:16
+  --> $DIR/utf16-le-without-bom.rs:5:16
    |
 LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    |                ^
@@ -63,7 +63,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used
 
 error: unknown start of token: \u{0}
-  --> $DIR/utf16-le-without-bom.rs:4:18
+  --> $DIR/utf16-le-without-bom.rs:5:18
    |
 LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    |                  ^
@@ -71,7 +71,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used
 
 error: unknown start of token: \u{0}
-  --> $DIR/utf16-le-without-bom.rs:4:20
+  --> $DIR/utf16-le-without-bom.rs:5:20
    |
 LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    |                    ^
@@ -79,7 +79,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used
 
 error: unknown start of token: \u{0}
-  --> $DIR/utf16-le-without-bom.rs:4:22
+  --> $DIR/utf16-le-without-bom.rs:5:22
    |
 LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    |                      ^
@@ -87,7 +87,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used
 
 error: unknown start of token: \u{0}
-  --> $DIR/utf16-le-without-bom.rs:4:24
+  --> $DIR/utf16-le-without-bom.rs:5:24
    |
 LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    |                        ^
@@ -95,7 +95,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used
 
 error: unknown start of token: \u{0}
-  --> $DIR/utf16-le-without-bom.rs:5:1
+  --> $DIR/utf16-le-without-bom.rs:6:1
    |
 LL | ␀
    | ^
@@ -103,7 +103,7 @@ LL | ␀
    = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used
 
 error: expected one of `!` or `::`, found `n`
-  --> $DIR/utf16-le-without-bom.rs:4:3
+  --> $DIR/utf16-le-without-bom.rs:5:3
    |
 LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀
    |   ^ expected one of `!` or `::`
diff --git a/tests/ui/proc-macro/attr-invalid-exprs.rs b/tests/ui/proc-macro/attr-invalid-exprs.rs
index 3d8806ee800..ec0b79469a4 100644
--- a/tests/ui/proc-macro/attr-invalid-exprs.rs
+++ b/tests/ui/proc-macro/attr-invalid-exprs.rs
@@ -13,7 +13,7 @@ fn main() {
     //~^ ERROR expected expression, found end of macro arguments
 
     let _ = #[duplicate] "Hello, world!";
-    //~^ ERROR macro expansion ignores token `,` and any following
+    //~^ ERROR macro expansion ignores `,` and any tokens following
 
     let _ = {
         #[no_output]
@@ -22,7 +22,7 @@ fn main() {
 
     let _ = {
         #[duplicate]
-        //~^ ERROR macro expansion ignores token `,` and any following
+        //~^ ERROR macro expansion ignores `,` and any tokens following
         "Hello, world!"
     };
 }
diff --git a/tests/ui/proc-macro/attr-invalid-exprs.stderr b/tests/ui/proc-macro/attr-invalid-exprs.stderr
index f96939bb6ef..0d500c87145 100644
--- a/tests/ui/proc-macro/attr-invalid-exprs.stderr
+++ b/tests/ui/proc-macro/attr-invalid-exprs.stderr
@@ -4,7 +4,7 @@ error: expected expression, found end of macro arguments
 LL |     let _ = #[no_output] "Hello, world!";
    |             ^^^^^^^^^^^^
 
-error: macro expansion ignores token `,` and any following
+error: macro expansion ignores `,` and any tokens following
   --> $DIR/attr-invalid-exprs.rs:15:13
    |
 LL |     let _ = #[duplicate] "Hello, world!";
@@ -16,7 +16,7 @@ help: you might be missing a semicolon here
 LL |     let _ = #[duplicate]; "Hello, world!";
    |                         +
 
-error: macro expansion ignores token `,` and any following
+error: macro expansion ignores `,` and any tokens following
   --> $DIR/attr-invalid-exprs.rs:24:9
    |
 LL |         #[duplicate]
diff --git a/tests/ui/proc-macro/expand-expr.rs b/tests/ui/proc-macro/expand-expr.rs
index 5f7375d7450..e06ddc51a29 100644
--- a/tests/ui/proc-macro/expand-expr.rs
+++ b/tests/ui/proc-macro/expand-expr.rs
@@ -114,8 +114,8 @@ expand_expr_fail!(echo_pm!($)); //~ ERROR: expected expression, found `$`
 
 // We get errors reported and recover during macro expansion if the macro
 // doesn't produce a valid expression.
-expand_expr_is!("string", echo_tts!("string"; hello)); //~ ERROR: macro expansion ignores token `hello` and any following
-expand_expr_is!("string", echo_pm!("string"; hello)); //~ ERROR: macro expansion ignores token `;` and any following
+expand_expr_is!("string", echo_tts!("string"; hello)); //~ ERROR: macro expansion ignores `hello` and any tokens following
+expand_expr_is!("string", echo_pm!("string"; hello)); //~ ERROR: macro expansion ignores `;` and any tokens following
 
 // For now, fail if a non-literal expression is expanded.
 expand_expr_fail!(arbitrary_expression() + "etc");
diff --git a/tests/ui/proc-macro/expand-expr.stderr b/tests/ui/proc-macro/expand-expr.stderr
index 2b92472e5ab..8b1df177cfa 100644
--- a/tests/ui/proc-macro/expand-expr.stderr
+++ b/tests/ui/proc-macro/expand-expr.stderr
@@ -22,7 +22,7 @@ error: expected expression, found `$`
 LL | expand_expr_fail!(echo_pm!($));
    |                            ^ expected expression
 
-error: macro expansion ignores token `hello` and any following
+error: macro expansion ignores `hello` and any tokens following
   --> $DIR/expand-expr.rs:117:47
    |
 LL | expand_expr_is!("string", echo_tts!("string"; hello));
@@ -34,7 +34,7 @@ help: you might be missing a semicolon here
 LL | expand_expr_is!("string", echo_tts!("string"; hello););
    |                                                     +
 
-error: macro expansion ignores token `;` and any following
+error: macro expansion ignores `;` and any tokens following
   --> $DIR/expand-expr.rs:118:44
    |
 LL | expand_expr_is!("string", echo_pm!("string"; hello));
diff --git a/tests/ui/range/range-1.stderr b/tests/ui/range/range-1.stderr
index f98420557c6..f77601bc43c 100644
--- a/tests/ui/range/range-1.stderr
+++ b/tests/ui/range/range-1.stderr
@@ -8,7 +8,7 @@ error[E0277]: the trait bound `bool: Step` is not satisfied
   --> $DIR/range-1.rs:9:14
    |
 LL |     for i in false..true {}
-   |              ^^^^^^^^^^^ the trait `Step` is not implemented for `bool`, which is required by `std::ops::Range<bool>: IntoIterator`
+   |              ^^^^^^^^^^^ the trait `Step` is not implemented for `bool`
    |
    = help: the following other types implement trait `Step`:
              Char
diff --git a/tests/ui/recursion/recursive-requirements.stderr b/tests/ui/recursion/recursive-requirements.stderr
index f5cbed0ce34..bb63f7cd0dc 100644
--- a/tests/ui/recursion/recursive-requirements.stderr
+++ b/tests/ui/recursion/recursive-requirements.stderr
@@ -4,7 +4,7 @@ error[E0277]: `*const Bar` cannot be shared between threads safely
 LL |     let _: AssertSync<Foo> = unimplemented!();
    |            ^^^^^^^^^^^^^^^ `*const Bar` cannot be shared between threads safely
    |
-   = help: within `Foo`, the trait `Sync` is not implemented for `*const Bar`, which is required by `Foo: Sync`
+   = help: within `Foo`, the trait `Sync` is not implemented for `*const Bar`
 note: required because it appears within the type `Foo`
   --> $DIR/recursive-requirements.rs:5:12
    |
@@ -22,7 +22,7 @@ error[E0277]: `*const Foo` cannot be shared between threads safely
 LL |     let _: AssertSync<Foo> = unimplemented!();
    |            ^^^^^^^^^^^^^^^ `*const Foo` cannot be shared between threads safely
    |
-   = help: within `Foo`, the trait `Sync` is not implemented for `*const Foo`, which is required by `Foo: Sync`
+   = help: within `Foo`, the trait `Sync` is not implemented for `*const Foo`
 note: required because it appears within the type `Bar`
   --> $DIR/recursive-requirements.rs:10:12
    |
diff --git a/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr b/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr
index e2e57fe0e73..64a0cb7f31a 100644
--- a/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr
+++ b/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr
@@ -190,7 +190,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                abi: Align(8 bytes),
                pref: $SOME_ALIGN,
            },
-           abi: Aggregate {
+           abi: Memory {
                sized: true,
            },
            fields: Arbitrary {
@@ -254,7 +254,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                            abi: Align(8 bytes),
                            pref: $SOME_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
diff --git a/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr b/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr
index 6ecdab1cc14..5c4daa6d519 100644
--- a/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr
+++ b/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr
@@ -190,7 +190,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                abi: Align(8 bytes),
                pref: $SOME_ALIGN,
            },
-           abi: Aggregate {
+           abi: Memory {
                sized: true,
            },
            fields: Arbitrary {
@@ -254,7 +254,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                            abi: Align(8 bytes),
                            pref: $SOME_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
diff --git a/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr b/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr
index e2e57fe0e73..64a0cb7f31a 100644
--- a/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr
+++ b/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr
@@ -190,7 +190,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                abi: Align(8 bytes),
                pref: $SOME_ALIGN,
            },
-           abi: Aggregate {
+           abi: Memory {
                sized: true,
            },
            fields: Arbitrary {
@@ -254,7 +254,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                            abi: Align(8 bytes),
                            pref: $SOME_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
diff --git a/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr b/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr
index e2e57fe0e73..64a0cb7f31a 100644
--- a/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr
+++ b/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr
@@ -190,7 +190,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                abi: Align(8 bytes),
                pref: $SOME_ALIGN,
            },
-           abi: Aggregate {
+           abi: Memory {
                sized: true,
            },
            fields: Arbitrary {
@@ -254,7 +254,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                            abi: Align(8 bytes),
                            pref: $SOME_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
diff --git a/tests/ui/repr/repr-c-int-dead-variants.stderr b/tests/ui/repr/repr-c-int-dead-variants.stderr
index f7df576df24..75005a64523 100644
--- a/tests/ui/repr/repr-c-int-dead-variants.stderr
+++ b/tests/ui/repr/repr-c-int-dead-variants.stderr
@@ -190,7 +190,7 @@ error: layout_of(DeadBranchHasOtherFieldU8) = Layout {
                abi: Align(8 bytes),
                pref: $SOME_ALIGN,
            },
-           abi: Aggregate {
+           abi: Memory {
                sized: true,
            },
            fields: Arbitrary {
@@ -254,7 +254,7 @@ error: layout_of(DeadBranchHasOtherFieldU8) = Layout {
                            abi: Align(8 bytes),
                            pref: $SOME_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr
index 4d23922892e..0a703367d96 100644
--- a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr
@@ -4,7 +4,7 @@ error[E0277]: the trait bound `f32: Termination` is not satisfied
 LL | #[test]
    | ------- in this procedural macro expansion
 LL | fn can_parse_zero_as_f32() -> Result<f32, ParseFloatError> {
-   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Termination` is not implemented for `f32`, which is required by `Result<f32, ParseFloatError>: Termination`
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Termination` is not implemented for `f32`
    |
    = note: required for `Result<f32, ParseFloatError>` to implement `Termination`
 note: required by a bound in `assert_test_result`
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs
index b8c0eb3e6d6..4b2fc4a03b6 100644
--- a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs
@@ -68,7 +68,7 @@ fn _macros() {
         _ => {}
     }
     use_expr!(let 0 = 1);
-    //~^ ERROR no rules expected the token `let`
+    //~^ ERROR no rules expected keyword `let`
 }
 
 fn main() {}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr
index 2341dbbbdbd..1c710b04897 100644
--- a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr
@@ -131,7 +131,7 @@ LL |     use_expr!((let 0 = 1));
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 
-error: no rules expected the token `let`
+error: no rules expected keyword `let`
   --> $DIR/feature-gate.rs:70:15
    |
 LL |     macro_rules! use_expr {
diff --git a/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr
index eb6abbf8045..7ec018a95cc 100644
--- a/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr
+++ b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr
@@ -4,7 +4,7 @@ error[E0277]: `NotDebug` doesn't implement `Debug`
 LL |     let _: NotDebug = dbg!(NotDebug);
    |                       ^^^^^^^^^^^^^^ `NotDebug` cannot be formatted using `{:?}`
    |
-   = help: the trait `Debug` is not implemented for `NotDebug`, which is required by `&NotDebug: Debug`
+   = help: the trait `Debug` is not implemented for `NotDebug`
    = note: add `#[derive(Debug)]` to `NotDebug` or manually `impl Debug for NotDebug`
    = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `NotDebug` with `#[derive(Debug)]`
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.rs
index bca7564efd8..2087fc42cf1 100644
--- a/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.rs
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.rs
@@ -54,7 +54,7 @@ fn _macros() {
     #[cfg(FALSE)] (let 0 = 1);
     //~^ ERROR expected expression, found `let` statement
     use_expr!(let 0 = 1);
-    //~^ ERROR no rules expected the token `let`
+    //~^ ERROR no rules expected keyword `let`
 }
 
 fn main() {}
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.stderr
index 2b1a49be3da..7c874ae78a8 100644
--- a/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.stderr
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.stderr
@@ -14,7 +14,7 @@ LL |     noop_expr!((let 0 = 1));
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 
-error: no rules expected the token `let`
+error: no rules expected keyword `let`
   --> $DIR/feature-gate.rs:56:15
    |
 LL |     macro_rules! use_expr {
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/irrefutable-lets.disallowed.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/irrefutable-lets.disallowed.stderr
index be4a5231558..130d0296c5e 100644
--- a/tests/ui/rfcs/rfc-2497-if-let-chains/irrefutable-lets.disallowed.stderr
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/irrefutable-lets.disallowed.stderr
@@ -111,5 +111,23 @@ LL |     while let Some(ref first) = opt && let second = first && let _third = s
    = note: these patterns will always match
    = help: consider moving them into the body
 
-error: aborting due to 12 previous errors
+error: trailing irrefutable pattern in let chain
+  --> $DIR/irrefutable-lets.rs:87:12
+   |
+LL |         && let x = &opt
+   |            ^^^^^^^^^^^^
+   |
+   = note: this pattern will always match
+   = help: consider moving it into the body
+
+error: leading irrefutable pattern in let chain
+  --> $DIR/irrefutable-lets.rs:93:12
+   |
+LL |         if let x = opt.clone().map(|_| 1)
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this pattern will always match
+   = help: consider moving it outside of the construct
+
+error: aborting due to 14 previous errors
 
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/irrefutable-lets.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/irrefutable-lets.rs
index bd4df337614..e7d69f89773 100644
--- a/tests/ui/rfcs/rfc-2497-if-let-chains/irrefutable-lets.rs
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/irrefutable-lets.rs
@@ -75,4 +75,24 @@ fn main() {
         && let Range { start: local_start, end: _ } = first
         && let None = local_start {
     }
+
+    // No error. An extra nesting level would be required for the `else if`.
+    if opt == Some(None..None) {
+    } else if let x = opt.clone().map(|_| 1)
+        && x == Some(1)
+    {}
+
+    if opt == Some(None..None) {
+    } else if opt.is_some()
+        && let x = &opt
+        //[disallowed]~^ ERROR trailing irrefutable pattern in let chain
+    {}
+
+    if opt == Some(None..None) {
+    } else {
+        if let x = opt.clone().map(|_| 1)
+        //[disallowed]~^ ERROR leading irrefutable pattern in let chain
+            && x == Some(1)
+        {}
+    }
 }
diff --git a/tests/ui/self/arbitrary-self-from-method-substs-ice.rs b/tests/ui/self/arbitrary-self-from-method-substs-ice.rs
index a544c8ea0d1..d121a194be6 100644
--- a/tests/ui/self/arbitrary-self-from-method-substs-ice.rs
+++ b/tests/ui/self/arbitrary-self-from-method-substs-ice.rs
@@ -8,7 +8,7 @@ use std::ops::Deref;
 struct Foo(u32);
 impl Foo {
     const fn get<R: Deref<Target = Self>>(self: R) -> u32 {
-        //~^ ERROR: `R` cannot be used as the type of `self`
+        //~^ ERROR invalid generic `self` parameter type
         //~| ERROR destructor of `R` cannot be evaluated at compile-time
         self.0
         //~^ ERROR cannot call non-const fn `<R as Deref>::deref` in constant function
diff --git a/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr b/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr
index 6ae60e7af47..7252b5890fd 100644
--- a/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr
+++ b/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr
@@ -15,18 +15,16 @@ LL |     const fn get<R: Deref<Target = Self>>(self: R) -> u32 {
 LL |     }
    |     - value is dropped here
 
-error[E0658]: `R` cannot be used as the type of `self` without the `arbitrary_self_types` feature
+error[E0801]: invalid generic `self` parameter type: `R`
   --> $DIR/arbitrary-self-from-method-substs-ice.rs:10:49
    |
 LL |     const fn get<R: Deref<Target = Self>>(self: R) -> u32 {
    |                                                 ^
    |
-   = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
-   = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+   = note: type of `self` must not be a method generic parameter type
+   = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
 error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0015, E0493, E0658.
+Some errors have detailed explanations: E0015, E0493, E0801.
 For more information about an error, try `rustc --explain E0015`.
diff --git a/tests/ui/self/arbitrary-self-from-method-substs.default.stderr b/tests/ui/self/arbitrary-self-from-method-substs.default.stderr
index 4cc69666b88..5dc3a0b0234 100644
--- a/tests/ui/self/arbitrary-self-from-method-substs.default.stderr
+++ b/tests/ui/self/arbitrary-self-from-method-substs.default.stderr
@@ -1,14 +1,168 @@
-error[E0658]: `R` cannot be used as the type of `self` without the `arbitrary_self_types` feature
-  --> $DIR/arbitrary-self-from-method-substs.rs:8:43
+error[E0801]: invalid generic `self` parameter type: `R`
+  --> $DIR/arbitrary-self-from-method-substs.rs:9:43
    |
 LL |     fn get<R: Deref<Target = Self>>(self: R) -> u32 {
    |                                           ^
    |
+   = note: type of `self` must not be a method generic parameter type
+   = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0801]: invalid generic `self` parameter type: `&R`
+  --> $DIR/arbitrary-self-from-method-substs.rs:13:44
+   |
+LL |     fn get1<R: Deref<Target = Self>>(self: &R) -> u32 {
+   |                                            ^^
+   |
+   = note: type of `self` must not be a method generic parameter type
+   = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0801]: invalid generic `self` parameter type: `&mut R`
+  --> $DIR/arbitrary-self-from-method-substs.rs:17:44
+   |
+LL |     fn get2<R: Deref<Target = Self>>(self: &mut R) -> u32 {
+   |                                            ^^^^^^
+   |
+   = note: type of `self` must not be a method generic parameter type
+   = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0801]: invalid generic `self` parameter type: `Rc<R>`
+  --> $DIR/arbitrary-self-from-method-substs.rs:21:44
+   |
+LL |     fn get3<R: Deref<Target = Self>>(self: std::rc::Rc<R>) -> u32 {
+   |                                            ^^^^^^^^^^^^^^
+   |
+   = note: type of `self` must not be a method generic parameter type
+   = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0801]: invalid generic `self` parameter type: `&Rc<R>`
+  --> $DIR/arbitrary-self-from-method-substs.rs:25:44
+   |
+LL |     fn get4<R: Deref<Target = Self>>(self: &std::rc::Rc<R>) -> u32 {
+   |                                            ^^^^^^^^^^^^^^^
+   |
+   = note: type of `self` must not be a method generic parameter type
+   = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0801]: invalid generic `self` parameter type: `Rc<&R>`
+  --> $DIR/arbitrary-self-from-method-substs.rs:29:44
+   |
+LL |     fn get5<R: Deref<Target = Self>>(self: std::rc::Rc<&R>) -> u32 {
+   |                                            ^^^^^^^^^^^^^^^
+   |
+   = note: type of `self` must not be a method generic parameter type
+   = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0658]: `<FR as FindReceiver>::Receiver` cannot be used as the type of `self` without the `arbitrary_self_types` feature
+  --> $DIR/arbitrary-self-from-method-substs.rs:33:37
+   |
+LL |     fn get6<FR: FindReceiver>(self: FR::Receiver, other: FR) -> u32 {
+   |                                     ^^^^^^^^^^^^
+   |
    = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
    = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
    = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
-error: aborting due to 1 previous error
+error[E0658]: `R` cannot be used as the type of `self` without the `arbitrary_self_types` feature
+  --> $DIR/arbitrary-self-from-method-substs.rs:61:18
+   |
+LL |     fn get(self: R) {}
+   |                  ^
+   |
+   = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
+   = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0271]: type mismatch resolving `<Silly as FindReceiver>::Receiver == Foo`
+  --> $DIR/arbitrary-self-from-method-substs.rs:92:9
+   |
+LL |     foo.get6(Silly);
+   |         ^^^^ type mismatch resolving `<Silly as FindReceiver>::Receiver == Foo`
+   |
+note: expected this to be `Foo`
+  --> $DIR/arbitrary-self-from-method-substs.rs:71:21
+   |
+LL |     type Receiver = std::rc::Rc<Foo>;
+   |                     ^^^^^^^^^^^^^^^^
+   = note: expected struct `Foo`
+              found struct `Rc<Foo>`
+
+error[E0271]: type mismatch resolving `<Silly as FindReceiver>::Receiver == &Foo`
+  --> $DIR/arbitrary-self-from-method-substs.rs:96:9
+   |
+LL |     foo.get6(Silly);
+   |         ^^^^ type mismatch resolving `<Silly as FindReceiver>::Receiver == &Foo`
+   |
+note: expected this to be `&Foo`
+  --> $DIR/arbitrary-self-from-method-substs.rs:71:21
+   |
+LL |     type Receiver = std::rc::Rc<Foo>;
+   |                     ^^^^^^^^^^^^^^^^
+   = note: expected reference `&Foo`
+                 found struct `Rc<Foo>`
+
+error[E0599]: the method `get` exists for struct `Rc<Bar<_>>`, but its trait bounds were not satisfied
+  --> $DIR/arbitrary-self-from-method-substs.rs:100:7
+   |
+LL | struct Bar<R>(std::marker::PhantomData<R>);
+   | ------------- doesn't satisfy `Bar<_>: Deref`
+...
+LL |     t.get();
+   |       ^^^ method cannot be called on `Rc<Bar<_>>` due to unsatisfied trait bounds
+   |
+note: the following trait bounds were not satisfied:
+      `<&Bar<_> as Deref>::Target = Bar<&Bar<_>>`
+      `<&Rc<Bar<_>> as Deref>::Target = Bar<&Rc<Bar<_>>>`
+      `<&mut Bar<_> as Deref>::Target = Bar<&mut Bar<_>>`
+      `<&mut Rc<Bar<_>> as Deref>::Target = Bar<&mut Rc<Bar<_>>>`
+      `<Rc<Bar<_>> as Deref>::Target = Bar<Rc<Bar<_>>>`
+      `Bar<_>: Deref`
+  --> $DIR/arbitrary-self-from-method-substs.rs:60:9
+   |
+LL | impl<R: std::ops::Deref<Target = Self>> Bar<R> {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  ------
+   |         |               |
+   |         |               unsatisfied trait bound introduced here
+   |         unsatisfied trait bound introduced here
+note: the trait `Deref` must be implemented
+  --> $SRC_DIR/core/src/ops/deref.rs:LL:COL
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `get`, perhaps you need to implement it:
+           candidate #1: `SliceIndex`
+
+error[E0599]: the method `get` exists for reference `&Rc<Bar<_>>`, but its trait bounds were not satisfied
+  --> $DIR/arbitrary-self-from-method-substs.rs:108:7
+   |
+LL | struct Bar<R>(std::marker::PhantomData<R>);
+   | ------------- doesn't satisfy `Bar<_>: Deref`
+...
+LL |     t.get();
+   |       ^^^ method cannot be called on `&Rc<Bar<_>>` due to unsatisfied trait bounds
+   |
+note: the following trait bounds were not satisfied:
+      `<&&Rc<Bar<_>> as Deref>::Target = Bar<&&Rc<Bar<_>>>`
+      `<&Bar<_> as Deref>::Target = Bar<&Bar<_>>`
+      `<&Rc<Bar<_>> as Deref>::Target = Bar<&Rc<Bar<_>>>`
+      `<&mut &Rc<Bar<_>> as Deref>::Target = Bar<&mut &Rc<Bar<_>>>`
+      `<&mut Bar<_> as Deref>::Target = Bar<&mut Bar<_>>`
+      `<&mut Rc<Bar<_>> as Deref>::Target = Bar<&mut Rc<Bar<_>>>`
+      `<Rc<Bar<_>> as Deref>::Target = Bar<Rc<Bar<_>>>`
+      `Bar<_>: Deref`
+  --> $DIR/arbitrary-self-from-method-substs.rs:60:9
+   |
+LL | impl<R: std::ops::Deref<Target = Self>> Bar<R> {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  ------
+   |         |               |
+   |         |               unsatisfied trait bound introduced here
+   |         unsatisfied trait bound introduced here
+note: the trait `Deref` must be implemented
+  --> $SRC_DIR/core/src/ops/deref.rs:LL:COL
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `get`, perhaps you need to implement it:
+           candidate #1: `SliceIndex`
+
+error: aborting due to 12 previous errors
 
-For more information about this error, try `rustc --explain E0658`.
+Some errors have detailed explanations: E0271, E0599, E0658, E0801.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/tests/ui/self/arbitrary-self-from-method-substs.feature.stderr b/tests/ui/self/arbitrary-self-from-method-substs.feature.stderr
index 44e553f1a06..6e864f44aa3 100644
--- a/tests/ui/self/arbitrary-self-from-method-substs.feature.stderr
+++ b/tests/ui/self/arbitrary-self-from-method-substs.feature.stderr
@@ -1,9 +1,179 @@
+error[E0801]: invalid generic `self` parameter type: `R`
+  --> $DIR/arbitrary-self-from-method-substs.rs:9:43
+   |
+LL |     fn get<R: Deref<Target = Self>>(self: R) -> u32 {
+   |                                           ^
+   |
+   = note: type of `self` must not be a method generic parameter type
+   = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0801]: invalid generic `self` parameter type: `&R`
+  --> $DIR/arbitrary-self-from-method-substs.rs:13:44
+   |
+LL |     fn get1<R: Deref<Target = Self>>(self: &R) -> u32 {
+   |                                            ^^
+   |
+   = note: type of `self` must not be a method generic parameter type
+   = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0801]: invalid generic `self` parameter type: `&mut R`
+  --> $DIR/arbitrary-self-from-method-substs.rs:17:44
+   |
+LL |     fn get2<R: Deref<Target = Self>>(self: &mut R) -> u32 {
+   |                                            ^^^^^^
+   |
+   = note: type of `self` must not be a method generic parameter type
+   = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0801]: invalid generic `self` parameter type: `Rc<R>`
+  --> $DIR/arbitrary-self-from-method-substs.rs:21:44
+   |
+LL |     fn get3<R: Deref<Target = Self>>(self: std::rc::Rc<R>) -> u32 {
+   |                                            ^^^^^^^^^^^^^^
+   |
+   = note: type of `self` must not be a method generic parameter type
+   = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0801]: invalid generic `self` parameter type: `&Rc<R>`
+  --> $DIR/arbitrary-self-from-method-substs.rs:25:44
+   |
+LL |     fn get4<R: Deref<Target = Self>>(self: &std::rc::Rc<R>) -> u32 {
+   |                                            ^^^^^^^^^^^^^^^
+   |
+   = note: type of `self` must not be a method generic parameter type
+   = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0801]: invalid generic `self` parameter type: `Rc<&R>`
+  --> $DIR/arbitrary-self-from-method-substs.rs:29:44
+   |
+LL |     fn get5<R: Deref<Target = Self>>(self: std::rc::Rc<&R>) -> u32 {
+   |                                            ^^^^^^^^^^^^^^^
+   |
+   = note: type of `self` must not be a method generic parameter type
+   = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
 error[E0308]: mismatched types
-  --> $DIR/arbitrary-self-from-method-substs.rs:16:5
+  --> $DIR/arbitrary-self-from-method-substs.rs:76:5
    |
 LL |     foo.get::<&Foo>();
    |     ^^^ expected `&Foo`, found `Foo`
 
-error: aborting due to 1 previous error
+error[E0308]: mismatched types
+  --> $DIR/arbitrary-self-from-method-substs.rs:78:5
+   |
+LL |     foo.get::<std::rc::Rc<Foo>>();
+   |     ^^^ expected `Rc<Foo>`, found `Foo`
+   |
+   = note: expected struct `Rc<Foo>`
+              found struct `Foo`
+
+error[E0308]: mismatched types
+  --> $DIR/arbitrary-self-from-method-substs.rs:84:5
+   |
+LL |     smart_ptr.get::<SmartPtr2<Foo>>();
+   |     ^^^^^^^^^ expected `SmartPtr2<'_, Foo>`, found `SmartPtr<'_, Foo>`
+   |
+   = note: expected struct `SmartPtr2<'_, Foo>`
+              found struct `SmartPtr<'_, Foo>`
+
+error[E0308]: mismatched types
+  --> $DIR/arbitrary-self-from-method-substs.rs:86:5
+   |
+LL |     smart_ptr.get::<&Foo>();
+   |     ^^^^^^^^^ expected `&Foo`, found `SmartPtr<'_, Foo>`
+   |
+   = note: expected reference `&Foo`
+                 found struct `SmartPtr<'_, Foo, >`
+
+error[E0271]: type mismatch resolving `<Silly as FindReceiver>::Receiver == Foo`
+  --> $DIR/arbitrary-self-from-method-substs.rs:92:9
+   |
+LL |     foo.get6(Silly);
+   |         ^^^^ type mismatch resolving `<Silly as FindReceiver>::Receiver == Foo`
+   |
+note: expected this to be `Foo`
+  --> $DIR/arbitrary-self-from-method-substs.rs:71:21
+   |
+LL |     type Receiver = std::rc::Rc<Foo>;
+   |                     ^^^^^^^^^^^^^^^^
+   = note: expected struct `Foo`
+              found struct `Rc<Foo>`
+
+error[E0271]: type mismatch resolving `<Silly as FindReceiver>::Receiver == &Foo`
+  --> $DIR/arbitrary-self-from-method-substs.rs:96:9
+   |
+LL |     foo.get6(Silly);
+   |         ^^^^ type mismatch resolving `<Silly as FindReceiver>::Receiver == &Foo`
+   |
+note: expected this to be `&Foo`
+  --> $DIR/arbitrary-self-from-method-substs.rs:71:21
+   |
+LL |     type Receiver = std::rc::Rc<Foo>;
+   |                     ^^^^^^^^^^^^^^^^
+   = note: expected reference `&Foo`
+                 found struct `Rc<Foo>`
+
+error[E0599]: the method `get` exists for struct `Rc<Bar<_>>`, but its trait bounds were not satisfied
+  --> $DIR/arbitrary-self-from-method-substs.rs:100:7
+   |
+LL | struct Bar<R>(std::marker::PhantomData<R>);
+   | ------------- doesn't satisfy `Bar<_>: Deref`
+...
+LL |     t.get();
+   |       ^^^ method cannot be called on `Rc<Bar<_>>` due to unsatisfied trait bounds
+   |
+note: the following trait bounds were not satisfied:
+      `<&Bar<_> as Deref>::Target = Bar<&Bar<_>>`
+      `<&Rc<Bar<_>> as Deref>::Target = Bar<&Rc<Bar<_>>>`
+      `<&mut Bar<_> as Deref>::Target = Bar<&mut Bar<_>>`
+      `<&mut Rc<Bar<_>> as Deref>::Target = Bar<&mut Rc<Bar<_>>>`
+      `<Rc<Bar<_>> as Deref>::Target = Bar<Rc<Bar<_>>>`
+      `Bar<_>: Deref`
+  --> $DIR/arbitrary-self-from-method-substs.rs:60:9
+   |
+LL | impl<R: std::ops::Deref<Target = Self>> Bar<R> {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  ------
+   |         |               |
+   |         |               unsatisfied trait bound introduced here
+   |         unsatisfied trait bound introduced here
+note: the trait `Deref` must be implemented
+  --> $SRC_DIR/core/src/ops/deref.rs:LL:COL
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `get`, perhaps you need to implement it:
+           candidate #1: `SliceIndex`
+
+error[E0599]: the method `get` exists for reference `&Rc<Bar<_>>`, but its trait bounds were not satisfied
+  --> $DIR/arbitrary-self-from-method-substs.rs:108:7
+   |
+LL | struct Bar<R>(std::marker::PhantomData<R>);
+   | ------------- doesn't satisfy `Bar<_>: Deref`
+...
+LL |     t.get();
+   |       ^^^ method cannot be called on `&Rc<Bar<_>>` due to unsatisfied trait bounds
+   |
+note: the following trait bounds were not satisfied:
+      `<&&Rc<Bar<_>> as Deref>::Target = Bar<&&Rc<Bar<_>>>`
+      `<&Bar<_> as Deref>::Target = Bar<&Bar<_>>`
+      `<&Rc<Bar<_>> as Deref>::Target = Bar<&Rc<Bar<_>>>`
+      `<&mut &Rc<Bar<_>> as Deref>::Target = Bar<&mut &Rc<Bar<_>>>`
+      `<&mut Bar<_> as Deref>::Target = Bar<&mut Bar<_>>`
+      `<&mut Rc<Bar<_>> as Deref>::Target = Bar<&mut Rc<Bar<_>>>`
+      `<Rc<Bar<_>> as Deref>::Target = Bar<Rc<Bar<_>>>`
+      `Bar<_>: Deref`
+  --> $DIR/arbitrary-self-from-method-substs.rs:60:9
+   |
+LL | impl<R: std::ops::Deref<Target = Self>> Bar<R> {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  ------
+   |         |               |
+   |         |               unsatisfied trait bound introduced here
+   |         unsatisfied trait bound introduced here
+note: the trait `Deref` must be implemented
+  --> $SRC_DIR/core/src/ops/deref.rs:LL:COL
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `get`, perhaps you need to implement it:
+           candidate #1: `SliceIndex`
+
+error: aborting due to 14 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
+Some errors have detailed explanations: E0271, E0308, E0599, E0801.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/tests/ui/self/arbitrary-self-from-method-substs.rs b/tests/ui/self/arbitrary-self-from-method-substs.rs
index 99977ed9b8c..f2d65859615 100644
--- a/tests/ui/self/arbitrary-self-from-method-substs.rs
+++ b/tests/ui/self/arbitrary-self-from-method-substs.rs
@@ -2,17 +2,109 @@
 #![cfg_attr(feature, feature(arbitrary_self_types))]
 
 use std::ops::Deref;
+use std::marker::PhantomData;
 
 struct Foo(u32);
 impl Foo {
     fn get<R: Deref<Target = Self>>(self: R) -> u32 {
-        //[default]~^ ERROR: `R` cannot be used as the type of `self`
+        //~^ ERROR: invalid generic `self` parameter type
         self.0
     }
+    fn get1<R: Deref<Target = Self>>(self: &R) -> u32 {
+        //~^ ERROR: invalid generic `self` parameter type
+        self.0
+    }
+    fn get2<R: Deref<Target = Self>>(self: &mut R) -> u32 {
+        //~^ ERROR: invalid generic `self` parameter type
+        self.0
+    }
+    fn get3<R: Deref<Target = Self>>(self: std::rc::Rc<R>) -> u32 {
+        //~^ ERROR: invalid generic `self` parameter type
+        self.0
+    }
+    fn get4<R: Deref<Target = Self>>(self: &std::rc::Rc<R>) -> u32 {
+        //~^ ERROR: invalid generic `self` parameter type
+        self.0
+    }
+    fn get5<R: Deref<Target = Self>>(self: std::rc::Rc<&R>) -> u32 {
+        //~^ ERROR: invalid generic `self` parameter type
+        self.0
+    }
+    fn get6<FR: FindReceiver>(self: FR::Receiver, other: FR) -> u32 {
+        //[default]~^ ERROR: `<FR as FindReceiver>::Receiver` cannot be used as the type of `self`
+        42
+    }
+}
+
+
+struct SmartPtr<'a, T: ?Sized>(&'a T);
+
+impl<'a, T: ?Sized> Deref for SmartPtr<'a, T> {
+    type Target = T;
+    fn deref(&self) -> &Self::Target {
+        unimplemented!()
+    }
+}
+
+struct SmartPtr2<'a, T: ?Sized>(&'a T);
+
+impl<'a, T: ?Sized> Deref for SmartPtr2<'a, T> {
+    type Target = T;
+    fn deref(&self) -> &Self::Target {
+        unimplemented!()
+    }
+}
+
+struct Bar<R>(std::marker::PhantomData<R>);
+
+impl<R: std::ops::Deref<Target = Self>> Bar<R> {
+    fn get(self: R) {}
+    //[default]~^ ERROR: `R` cannot be used as the type of `self`
+}
+
+trait FindReceiver {
+    type Receiver: Deref<Target = Foo>;
+}
+
+struct Silly;
+impl FindReceiver for Silly {
+    type Receiver = std::rc::Rc<Foo>;
 }
 
 fn main() {
     let mut foo = Foo(1);
     foo.get::<&Foo>();
     //[feature]~^ ERROR mismatched types
+    foo.get::<std::rc::Rc<Foo>>();
+    //[feature]~^ ERROR mismatched types
+
+    let smart_ptr = SmartPtr(&foo);
+    let smart_ptr2 = SmartPtr2(&foo);
+    smart_ptr.get(); // this compiles
+    smart_ptr.get::<SmartPtr2<Foo>>();
+    //[feature]~^ ERROR mismatched types
+    smart_ptr.get::<&Foo>();
+    //[feature]~^ ERROR mismatched types
+
+    let mut foo = Foo(1);
+    // This test is slightly contrived in an attempt to generate a mismatched types
+    // error for the self type below, without using the turbofish.
+    foo.get6(Silly);
+    //~^ ERROR type mismatch
+    let mut foo = Foo(1);
+    let foo = &foo;
+    foo.get6(Silly);
+    //~^ ERROR type mismatch
+
+    let t = std::rc::Rc::new(Bar(std::marker::PhantomData));
+    t.get();
+    //~^ ERROR its trait bounds were not satisfied
+    let t = &t;
+    // This is a further attempt at triggering 'type mismatch' errors
+    // from arbitrary self types without resorting to the turbofish.
+    // Ideally, here, t is Thing<Rc<Target=Self>> while we're going to call
+    // it with a &t method receiver. However, this doesn't work since that
+    // type of t becomes recursive and trait bounds can't be satisfied.
+    t.get();
+    //~^ ERROR its trait bounds were not satisfied
 }
diff --git a/tests/ui/specialization/min_specialization/issue-79224.stderr b/tests/ui/specialization/min_specialization/issue-79224.stderr
index db88be88a81..268fc3a9591 100644
--- a/tests/ui/specialization/min_specialization/issue-79224.stderr
+++ b/tests/ui/specialization/min_specialization/issue-79224.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `B: Clone` is not satisfied
   --> $DIR/issue-79224.rs:18:29
    |
 LL | impl<B: ?Sized> Display for Cow<'_, B> {
-   |                             ^^^^^^^^^^ the trait `Clone` is not implemented for `B`, which is required by `B: ToOwned`
+   |                             ^^^^^^^^^^ the trait `Clone` is not implemented for `B`
    |
    = note: required for `B` to implement `ToOwned`
 help: consider further restricting this bound
@@ -14,7 +14,7 @@ error[E0277]: the trait bound `B: Clone` is not satisfied
   --> $DIR/issue-79224.rs:20:5
    |
 LL |     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `B`, which is required by `B: ToOwned`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `B`
    |
    = note: required for `B` to implement `ToOwned`
 help: consider further restricting this bound
@@ -26,7 +26,7 @@ error[E0277]: the trait bound `B: Clone` is not satisfied
   --> $DIR/issue-79224.rs:20:13
    |
 LL |     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-   |             ^^^^ the trait `Clone` is not implemented for `B`, which is required by `B: ToOwned`
+   |             ^^^^ the trait `Clone` is not implemented for `B`
    |
    = note: required for `B` to implement `ToOwned`
 help: consider further restricting this bound
@@ -44,7 +44,7 @@ LL | |
 LL | |
 LL | |         write!(f, "foo")
 LL | |     }
-   | |_____^ the trait `Clone` is not implemented for `B`, which is required by `B: ToOwned`
+   | |_____^ the trait `Clone` is not implemented for `B`
    |
    = note: required for `B` to implement `ToOwned`
 help: consider further restricting this bound
diff --git a/tests/ui/statics/unsized_type2.stderr b/tests/ui/statics/unsized_type2.stderr
index 4e47b37afdc..b18a99fab72 100644
--- a/tests/ui/statics/unsized_type2.stderr
+++ b/tests/ui/statics/unsized_type2.stderr
@@ -4,7 +4,7 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t
 LL | pub static WITH_ERROR: Foo = Foo { version: 0 };
    |                        ^^^ doesn't have a size known at compile-time
    |
-   = help: within `Foo`, the trait `Sized` is not implemented for `str`, which is required by `Foo: Sized`
+   = help: within `Foo`, the trait `Sized` is not implemented for `str`
 note: required because it appears within the type `Foo`
   --> $DIR/unsized_type2.rs:5:12
    |
@@ -17,7 +17,7 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t
 LL | pub static WITH_ERROR: Foo = Foo { version: 0 };
    |                              ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = help: within `Foo`, the trait `Sized` is not implemented for `str`, which is required by `Foo: Sized`
+   = help: within `Foo`, the trait `Sized` is not implemented for `str`
 note: required because it appears within the type `Foo`
   --> $DIR/unsized_type2.rs:5:12
    |
diff --git a/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr b/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr
index 59e09e48523..35dd570e91f 100644
--- a/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr
+++ b/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr
@@ -26,7 +26,7 @@ error[E0277]: `(dyn Qux + 'static)` cannot be shared between threads safely
 LL | static FOO: &Lint = &Lint { desc: "desc" };
    |             ^^^^^ `(dyn Qux + 'static)` cannot be shared between threads safely
    |
-   = help: within `&'static Lint`, the trait `Sync` is not implemented for `(dyn Qux + 'static)`, which is required by `&'static Lint: Sync`
+   = help: within `&'static Lint`, the trait `Sync` is not implemented for `(dyn Qux + 'static)`
    = note: required because it appears within the type `&'static (dyn Qux + 'static)`
 note: required because it appears within the type `Lint`
   --> $DIR/unsizing-wfcheck-issue-127299.rs:7:12
diff --git a/tests/ui/str/str-idx.stderr b/tests/ui/str/str-idx.stderr
index 84806cbea0d..e8bbb8058fa 100644
--- a/tests/ui/str/str-idx.stderr
+++ b/tests/ui/str/str-idx.stderr
@@ -4,7 +4,7 @@ error[E0277]: the type `str` cannot be indexed by `{integer}`
 LL |     let _: u8 = s[4];
    |                   ^ string indices are ranges of `usize`
    |
-   = help: the trait `SliceIndex<str>` is not implemented for `{integer}`, which is required by `str: Index<_>`
+   = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
    = help: the trait `SliceIndex<[_]>` is implemented for `usize`
@@ -49,7 +49,7 @@ error[E0277]: the type `str` cannot be indexed by `char`
 LL |     let _: u8 = s['c'];
    |                   ^^^ string indices are ranges of `usize`
    |
-   = help: the trait `SliceIndex<str>` is not implemented for `char`, which is required by `str: Index<_>`
+   = help: the trait `SliceIndex<str>` is not implemented for `char`
    = note: required for `str` to implement `Index<char>`
 
 error: aborting due to 4 previous errors
diff --git a/tests/ui/str/str-mut-idx.stderr b/tests/ui/str/str-mut-idx.stderr
index 679f783126f..9390d689252 100644
--- a/tests/ui/str/str-mut-idx.stderr
+++ b/tests/ui/str/str-mut-idx.stderr
@@ -30,7 +30,7 @@ error[E0277]: the type `str` cannot be indexed by `usize`
 LL |     s[1usize] = bot();
    |       ^^^^^^ string indices are ranges of `usize`
    |
-   = help: the trait `SliceIndex<str>` is not implemented for `usize`, which is required by `str: Index<_>`
+   = help: the trait `SliceIndex<str>` is not implemented for `usize`
    = help: the trait `SliceIndex<[_]>` is implemented for `usize`
    = help: for that trait implementation, expected `[_]`, found `str`
    = note: required for `str` to implement `Index<usize>`
@@ -73,7 +73,7 @@ error[E0277]: the type `str` cannot be indexed by `char`
 LL |     s['c'];
    |       ^^^ string indices are ranges of `usize`
    |
-   = help: the trait `SliceIndex<str>` is not implemented for `char`, which is required by `str: Index<_>`
+   = help: the trait `SliceIndex<str>` is not implemented for `char`
    = note: required for `str` to implement `Index<char>`
 
 error: aborting due to 6 previous errors
diff --git a/tests/ui/suggestions/derive-clone-for-eq.stderr b/tests/ui/suggestions/derive-clone-for-eq.stderr
index 6fae6e1316d..680890e880c 100644
--- a/tests/ui/suggestions/derive-clone-for-eq.stderr
+++ b/tests/ui/suggestions/derive-clone-for-eq.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `T: Clone` is not satisfied
   --> $DIR/derive-clone-for-eq.rs:4:17
    |
 LL | #[derive(Clone, Eq)]
-   |                 ^^ the trait `Clone` is not implemented for `T`, which is required by `Struct<T>: PartialEq`
+   |                 ^^ the trait `Clone` is not implemented for `T`
    |
 note: required for `Struct<T>` to implement `PartialEq`
   --> $DIR/derive-clone-for-eq.rs:7:19
diff --git a/tests/ui/suggestions/derive-macro-missing-bounds.stderr b/tests/ui/suggestions/derive-macro-missing-bounds.stderr
index 5da85a9d061..bffcb1af487 100644
--- a/tests/ui/suggestions/derive-macro-missing-bounds.stderr
+++ b/tests/ui/suggestions/derive-macro-missing-bounds.stderr
@@ -6,7 +6,7 @@ LL |     #[derive(Debug)]
 LL |     struct Outer<T>(Inner<T>);
    |                     ^^^^^^^^ `a::Inner<T>` cannot be formatted using `{:?}`
    |
-   = help: the trait `Debug` is not implemented for `a::Inner<T>`, which is required by `&a::Inner<T>: Debug`
+   = help: the trait `Debug` is not implemented for `a::Inner<T>`
    = note: add `#[derive(Debug)]` to `a::Inner<T>` or manually `impl Debug for a::Inner<T>`
    = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `a::Inner<T>` with `#[derive(Debug)]`
@@ -25,7 +25,7 @@ error[E0277]: the trait bound `T: c::Trait` is not satisfied
 LL |     #[derive(Debug)]
    |              ----- in this derive macro expansion
 LL |     struct Outer<T>(Inner<T>);
-   |                     ^^^^^^^^ the trait `c::Trait` is not implemented for `T`, which is required by `&c::Inner<T>: Debug`
+   |                     ^^^^^^^^ the trait `c::Trait` is not implemented for `T`
    |
 note: required for `c::Inner<T>` to implement `Debug`
   --> $DIR/derive-macro-missing-bounds.rs:34:28
@@ -49,7 +49,7 @@ error[E0277]: the trait bound `T: d::Trait` is not satisfied
 LL |     #[derive(Debug)]
    |              ----- in this derive macro expansion
 LL |     struct Outer<T>(Inner<T>);
-   |                     ^^^^^^^^ the trait `d::Trait` is not implemented for `T`, which is required by `&d::Inner<T>: Debug`
+   |                     ^^^^^^^^ the trait `d::Trait` is not implemented for `T`
    |
 note: required for `d::Inner<T>` to implement `Debug`
   --> $DIR/derive-macro-missing-bounds.rs:49:13
@@ -71,7 +71,7 @@ error[E0277]: the trait bound `T: e::Trait` is not satisfied
 LL |     #[derive(Debug)]
    |              ----- in this derive macro expansion
 LL |     struct Outer<T>(Inner<T>);
-   |                     ^^^^^^^^ the trait `e::Trait` is not implemented for `T`, which is required by `&e::Inner<T>: Debug`
+   |                     ^^^^^^^^ the trait `e::Trait` is not implemented for `T`
    |
 note: required for `e::Inner<T>` to implement `Debug`
   --> $DIR/derive-macro-missing-bounds.rs:64:13
@@ -93,7 +93,7 @@ error[E0277]: the trait bound `T: f::Trait` is not satisfied
 LL |     #[derive(Debug)]
    |              ----- in this derive macro expansion
 LL |     struct Outer<T>(Inner<T>);
-   |                     ^^^^^^^^ the trait `f::Trait` is not implemented for `T`, which is required by `&f::Inner<T>: Debug`
+   |                     ^^^^^^^^ the trait `f::Trait` is not implemented for `T`
    |
 note: required for `f::Inner<T>` to implement `Debug`
   --> $DIR/derive-macro-missing-bounds.rs:79:20
diff --git a/tests/ui/suggestions/into-str.stderr b/tests/ui/suggestions/into-str.stderr
index ac6e531fee2..d02d3186082 100644
--- a/tests/ui/suggestions/into-str.stderr
+++ b/tests/ui/suggestions/into-str.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `&str: From<String>` is not satisfied
   --> $DIR/into-str.rs:4:9
    |
 LL |     foo(String::new());
-   |     --- ^^^^^^^^^^^^^ the trait `From<String>` is not implemented for `&str`, which is required by `String: Into<&str>`
+   |     --- ^^^^^^^^^^^^^ the trait `From<String>` is not implemented for `&str`
    |     |
    |     required by a bound introduced by this call
    |
diff --git a/tests/ui/suggestions/issue-71394-no-from-impl.stderr b/tests/ui/suggestions/issue-71394-no-from-impl.stderr
index 79f5dcf4b73..31f8f1d455a 100644
--- a/tests/ui/suggestions/issue-71394-no-from-impl.stderr
+++ b/tests/ui/suggestions/issue-71394-no-from-impl.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `&[i8]: From<&[u8]>` is not satisfied
   --> $DIR/issue-71394-no-from-impl.rs:8:25
    |
 LL |     let _: &[i8] = data.into();
-   |                         ^^^^ the trait `From<&[u8]>` is not implemented for `&[i8]`, which is required by `&[u8]: Into<_>`
+   |                         ^^^^ the trait `From<&[u8]>` is not implemented for `&[i8]`
    |
    = help: the following other types implement trait `From<T>`:
              `[T; 10]` implements `From<(T, T, T, T, T, T, T, T, T, T)>`
diff --git a/tests/ui/suggestions/issue-88696.stderr b/tests/ui/suggestions/issue-88696.stderr
index a8bc970e055..b4f0793c225 100644
--- a/tests/ui/suggestions/issue-88696.stderr
+++ b/tests/ui/suggestions/issue-88696.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `Result<u32, i32>: From<Result<u64, i32>>` is not
   --> $DIR/issue-88696.rs:9:9
    |
 LL |     a().into()
-   |         ^^^^ the trait `From<Result<u64, i32>>` is not implemented for `Result<u32, i32>`, which is required by `Result<u64, i32>: Into<_>`
+   |         ^^^^ the trait `From<Result<u64, i32>>` is not implemented for `Result<u32, i32>`
    |
    = note: required for `Result<u64, i32>` to implement `Into<Result<u32, i32>>`
 
diff --git a/tests/ui/suggestions/issue-96223.stderr b/tests/ui/suggestions/issue-96223.stderr
index 4a77b240f3e..a54a4e7b3be 100644
--- a/tests/ui/suggestions/issue-96223.stderr
+++ b/tests/ui/suggestions/issue-96223.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `for<'de> EmptyBis<'de>: Foo<'_>` is not satisfied
   --> $DIR/issue-96223.rs:49:17
    |
 LL |     icey_bounds(&p);
-   |     ----------- ^^ the trait `for<'de> Foo<'_>` is not implemented for `EmptyBis<'de>`, which is required by `Empty: Dummy<EmptyMarker>`
+   |     ----------- ^^ the trait `for<'de> Foo<'_>` is not implemented for `EmptyBis<'de>`
    |     |
    |     required by a bound introduced by this call
    |
diff --git a/tests/ui/suggestions/issue-96555.stderr b/tests/ui/suggestions/issue-96555.stderr
index f77681ae80f..1a1e069f09e 100644
--- a/tests/ui/suggestions/issue-96555.stderr
+++ b/tests/ui/suggestions/issue-96555.stderr
@@ -6,7 +6,7 @@ LL |     m::f1().await;
    |     |
    |     this call returns `()`
    |
-   = help: the trait `Future` is not implemented for `()`, which is required by `(): IntoFuture`
+   = help: the trait `Future` is not implemented for `()`
    = note: () must be a future or must implement `IntoFuture` to be awaited
    = note: required for `()` to implement `IntoFuture`
 help: remove the `.await`
@@ -27,7 +27,7 @@ LL |     m::f2().await;
    |     |
    |     this call returns `()`
    |
-   = help: the trait `Future` is not implemented for `()`, which is required by `(): IntoFuture`
+   = help: the trait `Future` is not implemented for `()`
    = note: () must be a future or must implement `IntoFuture` to be awaited
    = note: required for `()` to implement `IntoFuture`
 help: remove the `.await`
@@ -48,7 +48,7 @@ LL |     m::f3().await;
    |     |
    |     this call returns `()`
    |
-   = help: the trait `Future` is not implemented for `()`, which is required by `(): IntoFuture`
+   = help: the trait `Future` is not implemented for `()`
    = note: () must be a future or must implement `IntoFuture` to be awaited
    = note: required for `()` to implement `IntoFuture`
 help: remove the `.await`
diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr
index db16fff826f..d65ad109241 100644
--- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr
+++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr
@@ -21,7 +21,7 @@ LL | #[derive(Debug, Copy, Clone)]
    |          ----- in this derive macro expansion
 LL | pub struct AABB<K: Debug> {
 LL |     pub loc: Vector2<K>,
-   |     ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `K`, which is required by `Vector2<K>: Debug`
+   |     ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `K`
    |
 note: required for `Vector2<K>` to implement `Debug`
   --> $DIR/missing-bound-in-derive-copy-impl-2.rs:4:10
@@ -64,7 +64,7 @@ LL | #[derive(Debug, Copy, Clone)]
    |                       ----- in this derive macro expansion
 ...
 LL |     pub size: Vector2<K>,
-   |     ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `K`, which is required by `Vector2<K>: Clone`
+   |     ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `K`
    |
 note: required for `Vector2<K>` to implement `Clone`
   --> $DIR/missing-bound-in-derive-copy-impl-2.rs:4:23
diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr
index cf383b5c8ff..316c2fa0fc9 100644
--- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr
+++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr
@@ -57,7 +57,7 @@ LL | #[derive(Debug, Copy, Clone)]
    |          ----- in this derive macro expansion
 LL | pub struct AABB<K> {
 LL |     pub loc: Vector2<K>,
-   |     ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `K`, which is required by `Vector2<K>: Debug`
+   |     ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `K`
    |
 note: required for `Vector2<K>` to implement `Debug`
   --> $DIR/missing-bound-in-derive-copy-impl.rs:3:10
@@ -130,7 +130,7 @@ LL | #[derive(Debug, Copy, Clone)]
    |                       ----- in this derive macro expansion
 ...
 LL |     pub size: Vector2<K>,
-   |     ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `K`, which is required by `Vector2<K>: Clone`
+   |     ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `K`
    |
 note: required for `Vector2<K>` to implement `Clone`
   --> $DIR/missing-bound-in-derive-copy-impl.rs:3:23
diff --git a/tests/ui/suggestions/path-by-value.stderr b/tests/ui/suggestions/path-by-value.stderr
index 62feafe534d..d870e21043c 100644
--- a/tests/ui/suggestions/path-by-value.stderr
+++ b/tests/ui/suggestions/path-by-value.stderr
@@ -4,7 +4,7 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation
 LL | fn f(p: Path) { }
    |         ^^^^ doesn't have a size known at compile-time
    |
-   = help: within `Path`, the trait `Sized` is not implemented for `[u8]`, which is required by `Path: Sized`
+   = help: within `Path`, the trait `Sized` is not implemented for `[u8]`
 note: required because it appears within the type `Path`
   --> $SRC_DIR/std/src/path.rs:LL:COL
    = help: unsized fn params are gated as an unstable feature
diff --git a/tests/ui/suggestions/path-display.stderr b/tests/ui/suggestions/path-display.stderr
index f9159c45030..46d0b35825b 100644
--- a/tests/ui/suggestions/path-display.stderr
+++ b/tests/ui/suggestions/path-display.stderr
@@ -4,7 +4,7 @@ error[E0277]: `Path` doesn't implement `std::fmt::Display`
 LL |     println!("{}", path);
    |                    ^^^^ `Path` cannot be formatted with the default formatter; call `.display()` on it
    |
-   = help: the trait `std::fmt::Display` is not implemented for `Path`, which is required by `&Path: std::fmt::Display`
+   = help: the trait `std::fmt::Display` is not implemented for `Path`
    = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
    = note: call `.display()` or `.to_string_lossy()` to safely print paths, as they may contain non-Unicode data
    = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/suggestions/suggest-dereferencing-index.stderr b/tests/ui/suggestions/suggest-dereferencing-index.stderr
index 86487cdcc44..2316acbe9da 100644
--- a/tests/ui/suggestions/suggest-dereferencing-index.stderr
+++ b/tests/ui/suggestions/suggest-dereferencing-index.stderr
@@ -4,7 +4,7 @@ error[E0277]: the type `[{integer}]` cannot be indexed by `&usize`
 LL |     let one_item_please: i32 = [1, 2, 3][i];
    |                                          ^ slice indices are of type `usize` or ranges of `usize`
    |
-   = help: the trait `SliceIndex<[{integer}]>` is not implemented for `&usize`, which is required by `[{integer}; 3]: Index<_>`
+   = help: the trait `SliceIndex<[{integer}]>` is not implemented for `&usize`
    = help: the trait `SliceIndex<[{integer}]>` is implemented for `usize`
    = help: for that trait implementation, expected `usize`, found `&usize`
    = note: required for `[{integer}]` to implement `Index<&usize>`
diff --git a/tests/ui/suggestions/suggest-pin-macro.stderr b/tests/ui/suggestions/suggest-pin-macro.stderr
index 68f4099a976..a761a454ad5 100644
--- a/tests/ui/suggestions/suggest-pin-macro.stderr
+++ b/tests/ui/suggestions/suggest-pin-macro.stderr
@@ -2,7 +2,7 @@ error[E0277]: `PhantomPinned` cannot be unpinned
   --> $DIR/suggest-pin-macro.rs:22:17
    |
 LL |     dummy(test1.get_mut());
-   |                 ^^^^^^^ within `Test`, the trait `Unpin` is not implemented for `PhantomPinned`, which is required by `Test: Unpin`
+   |                 ^^^^^^^ within `Test`, the trait `Unpin` is not implemented for `PhantomPinned`
    |
    = note: consider using the `pin!` macro
            consider using `Box::pin` if you need to access the pinned value outside of the current scope
diff --git a/tests/ui/suggestions/suggest-remove-refs-1.stderr b/tests/ui/suggestions/suggest-remove-refs-1.stderr
index 171184bf77d..523f78dffcc 100644
--- a/tests/ui/suggestions/suggest-remove-refs-1.stderr
+++ b/tests/ui/suggestions/suggest-remove-refs-1.stderr
@@ -4,7 +4,7 @@ error[E0277]: `&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
 LL |     for (i, _) in &v.iter().enumerate() {
    |                   ^^^^^^^^^^^^^^^^^^^^^ `&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
    |
-   = help: the trait `Iterator` is not implemented for `&Enumerate<std::slice::Iter<'_, {integer}>>`, which is required by `&Enumerate<std::slice::Iter<'_, {integer}>>: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `&Enumerate<std::slice::Iter<'_, {integer}>>`
    = note: required for `&Enumerate<std::slice::Iter<'_, {integer}>>` to implement `IntoIterator`
 help: consider removing the leading `&`-reference
    |
diff --git a/tests/ui/suggestions/suggest-remove-refs-2.stderr b/tests/ui/suggestions/suggest-remove-refs-2.stderr
index 4e1994523dc..bbe3261e148 100644
--- a/tests/ui/suggestions/suggest-remove-refs-2.stderr
+++ b/tests/ui/suggestions/suggest-remove-refs-2.stderr
@@ -4,7 +4,7 @@ error[E0277]: `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterat
 LL |     for (i, _) in & & & & &v.iter().enumerate() {
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
    |
-   = help: the trait `Iterator` is not implemented for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>`, which is required by `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>`
    = note: required for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` to implement `IntoIterator`
 help: consider removing 5 leading `&`-references
    |
diff --git a/tests/ui/suggestions/suggest-remove-refs-3.stderr b/tests/ui/suggestions/suggest-remove-refs-3.stderr
index 1d180f9d8be..a3e142563ff 100644
--- a/tests/ui/suggestions/suggest-remove-refs-3.stderr
+++ b/tests/ui/suggestions/suggest-remove-refs-3.stderr
@@ -8,7 +8,7 @@ LL | |         .iter()
 LL | |         .enumerate() {
    | |____________________^ `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
    |
-   = help: the trait `Iterator` is not implemented for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>`, which is required by `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>`
    = note: required for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` to implement `IntoIterator`
 help: consider removing 5 leading `&`-references
    |
diff --git a/tests/ui/suggestions/suggest-remove-refs-4.stderr b/tests/ui/suggestions/suggest-remove-refs-4.stderr
index 7ab34c4af51..ed9fc2dd256 100644
--- a/tests/ui/suggestions/suggest-remove-refs-4.stderr
+++ b/tests/ui/suggestions/suggest-remove-refs-4.stderr
@@ -4,7 +4,7 @@ error[E0277]: `&&std::slice::Iter<'_, {integer}>` is not an iterator
 LL |     for _i in &foo {}
    |               ^^^^ `&&std::slice::Iter<'_, {integer}>` is not an iterator
    |
-   = help: the trait `Iterator` is not implemented for `&&std::slice::Iter<'_, {integer}>`, which is required by `&&std::slice::Iter<'_, {integer}>: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `&&std::slice::Iter<'_, {integer}>`
    = note: required for `&&std::slice::Iter<'_, {integer}>` to implement `IntoIterator`
 help: consider removing 2 leading `&`-references
    |
diff --git a/tests/ui/suggestions/suggest-remove-refs-5.stderr b/tests/ui/suggestions/suggest-remove-refs-5.stderr
index b132c56473e..ae83012c70e 100644
--- a/tests/ui/suggestions/suggest-remove-refs-5.stderr
+++ b/tests/ui/suggestions/suggest-remove-refs-5.stderr
@@ -4,7 +4,7 @@ error[E0277]: `&mut &mut &mut &mut Vec<i32>` is not an iterator
 LL |     for _ in &mut &mut v {}
    |              ^^^^^^^^^^^ `&mut &mut &mut &mut Vec<i32>` is not an iterator
    |
-   = help: the trait `Iterator` is not implemented for `Vec<i32>`, which is required by `&mut &mut &mut &mut Vec<i32>: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `Vec<i32>`
    = note: required for `&mut Vec<i32>` to implement `Iterator`
    = note: 3 redundant requirements hidden
    = note: required for `&mut &mut &mut &mut Vec<i32>` to implement `Iterator`
@@ -21,7 +21,7 @@ error[E0277]: `&mut &mut &mut [u8; 1]` is not an iterator
 LL |     for _ in &mut v {}
    |              ^^^^^^ `&mut &mut &mut [u8; 1]` is not an iterator
    |
-   = help: the trait `Iterator` is not implemented for `[u8; 1]`, which is required by `&mut &mut &mut [u8; 1]: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `[u8; 1]`
    = note: required for `&mut [u8; 1]` to implement `Iterator`
    = note: 2 redundant requirements hidden
    = note: required for `&mut &mut &mut [u8; 1]` to implement `Iterator`
diff --git a/tests/ui/sync/mutexguard-sync.stderr b/tests/ui/sync/mutexguard-sync.stderr
index 6b686741d1f..1501a793d5e 100644
--- a/tests/ui/sync/mutexguard-sync.stderr
+++ b/tests/ui/sync/mutexguard-sync.stderr
@@ -6,7 +6,7 @@ LL |     test_sync(guard);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `Sync` is not implemented for `Cell<i32>`, which is required by `MutexGuard<'_, Cell<i32>>: Sync`
+   = help: the trait `Sync` is not implemented for `Cell<i32>`
    = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI32` instead
    = note: required for `MutexGuard<'_, Cell<i32>>` to implement `Sync`
 note: required by a bound in `test_sync`
diff --git a/tests/ui/sync/reentrantlockguard-sync.stderr b/tests/ui/sync/reentrantlockguard-sync.stderr
index ed2e3e2f112..6bedf8f9f2e 100644
--- a/tests/ui/sync/reentrantlockguard-sync.stderr
+++ b/tests/ui/sync/reentrantlockguard-sync.stderr
@@ -6,7 +6,7 @@ LL |     test_sync(guard);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `Sync` is not implemented for `Cell<i32>`, which is required by `ReentrantLockGuard<'_, Cell<i32>>: Sync`
+   = help: the trait `Sync` is not implemented for `Cell<i32>`
    = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI32` instead
    = note: required for `ReentrantLockGuard<'_, Cell<i32>>` to implement `Sync`
 note: required by a bound in `test_sync`
diff --git a/tests/ui/thir-print/thir-tree-match.stdout b/tests/ui/thir-print/thir-tree-match.stdout
index b2431698cc6..8cff7887661 100644
--- a/tests/ui/thir-print/thir-tree-match.stdout
+++ b/tests/ui/thir-print/thir-tree-match.stdout
@@ -41,7 +41,7 @@ body:
                             Block {
                                 targeted_by_break: false
                                 span: $DIR/thir-tree-match.rs:15:32: 21:2 (#0)
-                                region_scope: Node(25)
+                                region_scope: Node(3)
                                 safety_mode: Safe
                                 stmts: []
                                 expr:
@@ -51,8 +51,8 @@ body:
                                         span: $DIR/thir-tree-match.rs:16:5: 20:6 (#0)
                                         kind: 
                                             Scope {
-                                                region_scope: Node(3)
-                                                lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).3))
+                                                region_scope: Node(4)
+                                                lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).4))
                                                 value:
                                                     Expr {
                                                         ty: bool
@@ -67,8 +67,8 @@ body:
                                                                         span: $DIR/thir-tree-match.rs:16:11: 16:14 (#0)
                                                                         kind: 
                                                                             Scope {
-                                                                                region_scope: Node(4)
-                                                                                lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).4))
+                                                                                region_scope: Node(5)
+                                                                                lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).5))
                                                                                 value:
                                                                                     Expr {
                                                                                         ty: Foo
@@ -123,16 +123,16 @@ body:
                                                                         body: 
                                                                             Expr {
                                                                                 ty: bool
-                                                                                temp_lifetime: Some(Node(12))
+                                                                                temp_lifetime: Some(Node(13))
                                                                                 span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0)
                                                                                 kind: 
                                                                                     Scope {
-                                                                                        region_scope: Node(13)
-                                                                                        lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).13))
+                                                                                        region_scope: Node(14)
+                                                                                        lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).14))
                                                                                         value:
                                                                                             Expr {
                                                                                                 ty: bool
-                                                                                                temp_lifetime: Some(Node(12))
+                                                                                                temp_lifetime: Some(Node(13))
                                                                                                 span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0)
                                                                                                 kind: 
                                                                                                     Literal( lit: Spanned { node: Bool(true), span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0) }, neg: false)
@@ -140,8 +140,8 @@ body:
                                                                                             }
                                                                                     }
                                                                             }
-                                                                        lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).12))
-                                                                        scope: Node(12)
+                                                                        lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).13))
+                                                                        scope: Node(13)
                                                                         span: $DIR/thir-tree-match.rs:17:9: 17:40 (#0)
                                                                     }
                                                                     Arm {
@@ -175,16 +175,16 @@ body:
                                                                         body: 
                                                                             Expr {
                                                                                 ty: bool
-                                                                                temp_lifetime: Some(Node(18))
+                                                                                temp_lifetime: Some(Node(19))
                                                                                 span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0)
                                                                                 kind: 
                                                                                     Scope {
-                                                                                        region_scope: Node(19)
-                                                                                        lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).19))
+                                                                                        region_scope: Node(20)
+                                                                                        lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).20))
                                                                                         value:
                                                                                             Expr {
                                                                                                 ty: bool
-                                                                                                temp_lifetime: Some(Node(18))
+                                                                                                temp_lifetime: Some(Node(19))
                                                                                                 span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0)
                                                                                                 kind: 
                                                                                                     Literal( lit: Spanned { node: Bool(false), span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0) }, neg: false)
@@ -192,8 +192,8 @@ body:
                                                                                             }
                                                                                     }
                                                                             }
-                                                                        lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).18))
-                                                                        scope: Node(18)
+                                                                        lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).19))
+                                                                        scope: Node(19)
                                                                         span: $DIR/thir-tree-match.rs:18:9: 18:32 (#0)
                                                                     }
                                                                     Arm {
@@ -219,16 +219,16 @@ body:
                                                                         body: 
                                                                             Expr {
                                                                                 ty: bool
-                                                                                temp_lifetime: Some(Node(23))
+                                                                                temp_lifetime: Some(Node(24))
                                                                                 span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0)
                                                                                 kind: 
                                                                                     Scope {
-                                                                                        region_scope: Node(24)
-                                                                                        lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).24))
+                                                                                        region_scope: Node(25)
+                                                                                        lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).25))
                                                                                         value:
                                                                                             Expr {
                                                                                                 ty: bool
-                                                                                                temp_lifetime: Some(Node(23))
+                                                                                                temp_lifetime: Some(Node(24))
                                                                                                 span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0)
                                                                                                 kind: 
                                                                                                     Literal( lit: Spanned { node: Bool(true), span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0) }, neg: false)
@@ -236,8 +236,8 @@ body:
                                                                                             }
                                                                                     }
                                                                             }
-                                                                        lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).23))
-                                                                        scope: Node(23)
+                                                                        lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).24))
+                                                                        scope: Node(24)
                                                                         span: $DIR/thir-tree-match.rs:19:9: 19:28 (#0)
                                                                     }
                                                                 ]
diff --git a/tests/ui/trait-bounds/maybe-bound-generics-deny.rs b/tests/ui/trait-bounds/maybe-bound-generics-deny.rs
new file mode 100644
index 00000000000..dfa8e9886b6
--- /dev/null
+++ b/tests/ui/trait-bounds/maybe-bound-generics-deny.rs
@@ -0,0 +1,4 @@
+fn uwu<T: ?Sized<i32>>() {}
+//~^ ERROR trait takes 0 generic arguments but 1 generic argument was supplied
+
+fn main() {}
diff --git a/tests/ui/trait-bounds/maybe-bound-generics-deny.stderr b/tests/ui/trait-bounds/maybe-bound-generics-deny.stderr
new file mode 100644
index 00000000000..3297eb6279f
--- /dev/null
+++ b/tests/ui/trait-bounds/maybe-bound-generics-deny.stderr
@@ -0,0 +1,11 @@
+error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
+  --> $DIR/maybe-bound-generics-deny.rs:1:12
+   |
+LL | fn uwu<T: ?Sized<i32>>() {}
+   |            ^^^^^----- help: remove the unnecessary generics
+   |            |
+   |            expected 0 generic arguments
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/tests/ui/trait-bounds/maybe-bound-has-path-args.rs b/tests/ui/trait-bounds/maybe-bound-has-path-args.rs
new file mode 100644
index 00000000000..2cb63f25d06
--- /dev/null
+++ b/tests/ui/trait-bounds/maybe-bound-has-path-args.rs
@@ -0,0 +1,7 @@
+trait Trait {}
+
+fn test<T: ?self::<i32>::Trait>() {}
+//~^ ERROR type arguments are not allowed on this type
+//~| WARN relaxing a default bound only does something for `?Sized`
+
+fn main() {}
diff --git a/tests/ui/trait-bounds/maybe-bound-has-path-args.stderr b/tests/ui/trait-bounds/maybe-bound-has-path-args.stderr
new file mode 100644
index 00000000000..701e493f5a5
--- /dev/null
+++ b/tests/ui/trait-bounds/maybe-bound-has-path-args.stderr
@@ -0,0 +1,17 @@
+warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+  --> $DIR/maybe-bound-has-path-args.rs:3:12
+   |
+LL | fn test<T: ?self::<i32>::Trait>() {}
+   |            ^^^^^^^^^^^^^^^^^^^
+
+error[E0109]: type arguments are not allowed on this type
+  --> $DIR/maybe-bound-has-path-args.rs:3:20
+   |
+LL | fn test<T: ?self::<i32>::Trait>() {}
+   |             ----   ^^^ type argument not allowed
+   |             |
+   |             not allowed on this type
+
+error: aborting due to 1 previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0109`.
diff --git a/tests/ui/trait-bounds/maybe-bound-with-assoc.rs b/tests/ui/trait-bounds/maybe-bound-with-assoc.rs
new file mode 100644
index 00000000000..b6b2551e463
--- /dev/null
+++ b/tests/ui/trait-bounds/maybe-bound-with-assoc.rs
@@ -0,0 +1,12 @@
+trait HasAssoc {
+    type Assoc;
+}
+fn hasassoc<T: ?HasAssoc<Assoc = ()>>() {}
+//~^ WARN relaxing a default bound
+
+trait NoAssoc {}
+fn noassoc<T: ?NoAssoc<Missing = ()>>() {}
+//~^ WARN relaxing a default bound
+//~| ERROR associated type `Missing` not found for `NoAssoc`
+
+fn main() {}
diff --git a/tests/ui/trait-bounds/maybe-bound-with-assoc.stderr b/tests/ui/trait-bounds/maybe-bound-with-assoc.stderr
new file mode 100644
index 00000000000..91d78e59cd5
--- /dev/null
+++ b/tests/ui/trait-bounds/maybe-bound-with-assoc.stderr
@@ -0,0 +1,21 @@
+warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+  --> $DIR/maybe-bound-with-assoc.rs:4:16
+   |
+LL | fn hasassoc<T: ?HasAssoc<Assoc = ()>>() {}
+   |                ^^^^^^^^^^^^^^^^^^^^^
+
+warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+  --> $DIR/maybe-bound-with-assoc.rs:8:15
+   |
+LL | fn noassoc<T: ?NoAssoc<Missing = ()>>() {}
+   |               ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0220]: associated type `Missing` not found for `NoAssoc`
+  --> $DIR/maybe-bound-with-assoc.rs:8:24
+   |
+LL | fn noassoc<T: ?NoAssoc<Missing = ()>>() {}
+   |                        ^^^^^^^ associated type `Missing` not found
+
+error: aborting due to 1 previous error; 2 warnings emitted
+
+For more information about this error, try `rustc --explain E0220`.
diff --git a/tests/ui/trait-bounds/super-assoc-mismatch.stderr b/tests/ui/trait-bounds/super-assoc-mismatch.stderr
index f2c5eb47e59..780535283a3 100644
--- a/tests/ui/trait-bounds/super-assoc-mismatch.stderr
+++ b/tests/ui/trait-bounds/super-assoc-mismatch.stderr
@@ -53,7 +53,7 @@ error[E0277]: the trait bound `(): Sub` is not satisfied
   --> $DIR/super-assoc-mismatch.rs:29:21
    |
 LL |     type Assoc<T> = ();
-   |                     ^^ the trait `Sub` is not implemented for `()`, which is required by `<u8 as BoundOnGat>::Assoc<u8>: Sub`
+   |                     ^^ the trait `Sub` is not implemented for `()`
    |
 help: this trait has no implementations, consider adding one
   --> $DIR/super-assoc-mismatch.rs:7:1
@@ -87,7 +87,7 @@ error[E0277]: the trait bound `(): SubGeneric<u16>` is not satisfied
   --> $DIR/super-assoc-mismatch.rs:55:22
    |
 LL |     type Assoc1<T> = ();
-   |                      ^^ the trait `SubGeneric<u16>` is not implemented for `()`, which is required by `<u8 as MultiAssoc>::Assoc1<()>: SubGeneric<<u8 as MultiAssoc>::Assoc2>`
+   |                      ^^ the trait `SubGeneric<u16>` is not implemented for `()`
    |
 help: this trait has no implementations, consider adding one
   --> $DIR/super-assoc-mismatch.rs:43:1
diff --git a/tests/ui/traits/alias/cross-crate.stderr b/tests/ui/traits/alias/cross-crate.stderr
index 52eb7e44f44..8ed05b4758d 100644
--- a/tests/ui/traits/alias/cross-crate.stderr
+++ b/tests/ui/traits/alias/cross-crate.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `Rc<u32>: SendSync` is not satisfied
   --> $DIR/cross-crate.rs:14:17
    |
 LL |     use_alias::<Rc<u32>>();
-   |                 ^^^^^^^ the trait `Send` is not implemented for `Rc<u32>`, which is required by `Rc<u32>: SendSync`
+   |                 ^^^^^^^ the trait `Send` is not implemented for `Rc<u32>`
    |
    = note: required for `Rc<u32>` to implement `SendSync`
 note: required by a bound in `use_alias`
@@ -15,7 +15,7 @@ error[E0277]: the trait bound `Rc<u32>: SendSync` is not satisfied
   --> $DIR/cross-crate.rs:14:17
    |
 LL |     use_alias::<Rc<u32>>();
-   |                 ^^^^^^^ the trait `Sync` is not implemented for `Rc<u32>`, which is required by `Rc<u32>: SendSync`
+   |                 ^^^^^^^ the trait `Sync` is not implemented for `Rc<u32>`
    |
    = note: required for `Rc<u32>` to implement `SendSync`
 note: required by a bound in `use_alias`
diff --git a/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr
index c73c2f68032..27e23adb92a 100644
--- a/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr
+++ b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `(): IteratorAlias` is not satisfied
   --> $DIR/issue-108072-unmet-trait-alias-bound.rs:10:7
    |
 LL |     f(())
-   |     - ^^ the trait `Iterator` is not implemented for `()`, which is required by `(): IteratorAlias`
+   |     - ^^ the trait `Iterator` is not implemented for `()`
    |     |
    |     required by a bound introduced by this call
    |
diff --git a/tests/ui/traits/bound/assoc-fn-bound-root-obligation.rs b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.rs
index dc2de5bb715..667d283bea3 100644
--- a/tests/ui/traits/bound/assoc-fn-bound-root-obligation.rs
+++ b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.rs
@@ -2,7 +2,7 @@ fn strip_lf(s: &str) -> &str {
     s.strip_suffix(b'\n').unwrap_or(s)
     //~^ ERROR the trait bound `u8: Pattern` is not satisfied
     //~| NOTE required by a bound introduced by this call
-    //~| NOTE the trait `FnMut(char)` is not implemented for `u8`, which is required by `u8: Pattern`
+    //~| NOTE the trait `FnMut(char)` is not implemented for `u8`
     //~| HELP the following other types implement trait `Pattern`:
     //~| NOTE required for `u8` to implement `Pattern`
     //~| NOTE required by a bound in `core::str::<impl str>::strip_suffix`
diff --git a/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr
index 8351d15fdf3..1cd62d2cbdb 100644
--- a/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr
+++ b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `u8: Pattern` is not satisfied
   --> $DIR/assoc-fn-bound-root-obligation.rs:2:20
    |
 LL |     s.strip_suffix(b'\n').unwrap_or(s)
-   |       ------------ ^^^^^ the trait `FnMut(char)` is not implemented for `u8`, which is required by `u8: Pattern`
+   |       ------------ ^^^^^ the trait `FnMut(char)` is not implemented for `u8`
    |       |
    |       required by a bound introduced by this call
    |
diff --git a/tests/ui/traits/const-traits/const-bounds-non-const-trait.stderr b/tests/ui/traits/const-traits/const-bounds-non-const-trait.stderr
index d27be2a324b..8e836685eb0 100644
--- a/tests/ui/traits/const-traits/const-bounds-non-const-trait.stderr
+++ b/tests/ui/traits/const-traits/const-bounds-non-const-trait.stderr
@@ -7,11 +7,6 @@ LL | #![feature(const_trait_impl, effects)]
    = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
    = note: `#[warn(incomplete_features)]` on by default
 
-error: using `#![feature(effects)]` without enabling next trait solver globally
-   |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
-
 error: `~const` can only be applied to `#[const_trait]` traits
   --> $DIR/const-bounds-non-const-trait.rs:6:21
    |
@@ -32,5 +27,5 @@ error: `const` can only be applied to `#[const_trait]` traits
 LL | fn operate<T: const NonConst>() {}
    |               ^^^^^
 
-error: aborting due to 4 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors; 1 warning emitted
 
diff --git a/tests/ui/traits/const-traits/const-drop.precise.stderr b/tests/ui/traits/const-traits/const-drop.precise.stderr
index 2b8066e5ee7..381e4d78c28 100644
--- a/tests/ui/traits/const-traits/const-drop.precise.stderr
+++ b/tests/ui/traits/const-traits/const-drop.precise.stderr
@@ -48,6 +48,30 @@ LL | const fn a<T: ~const Destruct>(_: T) {}
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
+error[E0277]: the trait bound `T: const SomeTrait` is not satisfied
+  --> $DIR/const-drop.rs:67:46
+   |
+LL |     impl<T: ~const SomeTrait> const Drop for ConstDropWithBound<T> {
+   |                                              ^^^^^^^^^^^^^^^^^^^^^
+   |
+note: required by a bound in `t::ConstDropWithBound`
+  --> $DIR/const-drop.rs:65:38
+   |
+LL |     pub struct ConstDropWithBound<T: const SomeTrait>(pub core::marker::PhantomData<T>);
+   |                                      ^^^^^ required by this bound in `ConstDropWithBound`
+
+error[E0277]: the trait bound `T: const SomeTrait` is not satisfied
+  --> $DIR/const-drop.rs:68:22
+   |
+LL |         fn drop(&mut self) {
+   |                      ^^^^
+   |
+note: required by a bound in `t::ConstDropWithBound`
+  --> $DIR/const-drop.rs:65:38
+   |
+LL |     pub struct ConstDropWithBound<T: const SomeTrait>(pub core::marker::PhantomData<T>);
+   |                                      ^^^^^ required by this bound in `ConstDropWithBound`
+
 error[E0493]: destructor of `T` cannot be evaluated at compile-time
   --> $DIR/const-drop.rs:18:32
    |
@@ -66,7 +90,7 @@ help: add `#![feature(effects)]` to the crate attributes to enable
 LL + #![feature(effects)]
    |
 
-error: aborting due to 8 previous errors
+error: aborting due to 10 previous errors
 
-Some errors have detailed explanations: E0015, E0493.
+Some errors have detailed explanations: E0015, E0277, E0493.
 For more information about an error, try `rustc --explain E0015`.
diff --git a/tests/ui/traits/const-traits/const-drop.stock.stderr b/tests/ui/traits/const-traits/const-drop.stock.stderr
index 54ed2930b90..399e7849673 100644
--- a/tests/ui/traits/const-traits/const-drop.stock.stderr
+++ b/tests/ui/traits/const-traits/const-drop.stock.stderr
@@ -48,6 +48,30 @@ LL | const fn a<T: ~const Destruct>(_: T) {}
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
+error[E0277]: the trait bound `T: const SomeTrait` is not satisfied
+  --> $DIR/const-drop.rs:67:46
+   |
+LL |     impl<T: ~const SomeTrait> const Drop for ConstDropWithBound<T> {
+   |                                              ^^^^^^^^^^^^^^^^^^^^^
+   |
+note: required by a bound in `t::ConstDropWithBound`
+  --> $DIR/const-drop.rs:65:38
+   |
+LL |     pub struct ConstDropWithBound<T: const SomeTrait>(pub core::marker::PhantomData<T>);
+   |                                      ^^^^^ required by this bound in `ConstDropWithBound`
+
+error[E0277]: the trait bound `T: const SomeTrait` is not satisfied
+  --> $DIR/const-drop.rs:68:22
+   |
+LL |         fn drop(&mut self) {
+   |                      ^^^^
+   |
+note: required by a bound in `t::ConstDropWithBound`
+  --> $DIR/const-drop.rs:65:38
+   |
+LL |     pub struct ConstDropWithBound<T: const SomeTrait>(pub core::marker::PhantomData<T>);
+   |                                      ^^^^^ required by this bound in `ConstDropWithBound`
+
 error[E0493]: destructor of `T` cannot be evaluated at compile-time
   --> $DIR/const-drop.rs:18:32
    |
@@ -68,7 +92,7 @@ help: add `#![feature(effects)]` to the crate attributes to enable
 LL + #![feature(effects)]
    |
 
-error: aborting due to 8 previous errors
+error: aborting due to 10 previous errors
 
-Some errors have detailed explanations: E0015, E0493.
+Some errors have detailed explanations: E0015, E0277, E0493.
 For more information about an error, try `rustc --explain E0015`.
diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.stderr b/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.stderr
index 4bcc17952e6..8f4235dabad 100644
--- a/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.stderr
+++ b/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.stderr
@@ -7,11 +7,6 @@ LL | #![feature(derive_const, effects)]
    = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
    = note: `#[warn(incomplete_features)]` on by default
 
-error: using `#![feature(effects)]` without enabling next trait solver globally
-   |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
-
 error: const `impl` for trait `Default` which is not marked with `#[const_trait]`
   --> $DIR/derive-const-non-const-type.rs:10:16
    |
@@ -33,6 +28,6 @@ LL | pub struct S(A);
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
    = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-use.stderr b/tests/ui/traits/const-traits/const_derives/derive-const-use.stderr
index d471a8253ba..7fc44229e2a 100644
--- a/tests/ui/traits/const-traits/const_derives/derive-const-use.stderr
+++ b/tests/ui/traits/const-traits/const_derives/derive-const-use.stderr
@@ -19,11 +19,6 @@ error[E0635]: unknown feature `const_default_impls`
 LL | #![feature(const_trait_impl, const_cmp, const_default_impls, derive_const, effects)]
    |                                         ^^^^^^^^^^^^^^^^^^^
 
-error: using `#![feature(effects)]` without enabling next trait solver globally
-   |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
-
 error: const `impl` for trait `Default` which is not marked with `#[const_trait]`
   --> $DIR/derive-const-use.rs:7:12
    |
@@ -122,7 +117,7 @@ LL | pub struct S((), A);
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
    = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 13 previous errors; 1 warning emitted
+error: aborting due to 12 previous errors; 1 warning emitted
 
 Some errors have detailed explanations: E0015, E0635.
 For more information about an error, try `rustc --explain E0015`.
diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-with-params.stderr b/tests/ui/traits/const-traits/const_derives/derive-const-with-params.stderr
index 64285cff0a6..1395947bb15 100644
--- a/tests/ui/traits/const-traits/const_derives/derive-const-with-params.stderr
+++ b/tests/ui/traits/const-traits/const_derives/derive-const-with-params.stderr
@@ -7,11 +7,6 @@ LL | #![feature(const_trait_impl, effects)]
    = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
    = note: `#[warn(incomplete_features)]` on by default
 
-error: using `#![feature(effects)]` without enabling next trait solver globally
-   |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
-
 error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]`
   --> $DIR/derive-const-with-params.rs:7:16
    |
@@ -43,6 +38,6 @@ LL |     a == b
    |
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 
-error: aborting due to 5 previous errors; 1 warning emitted
+error: aborting due to 4 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/traits/const-traits/do-not-const-check.rs b/tests/ui/traits/const-traits/do-not-const-check.rs
index 443b6385735..d227a9a9c09 100644
--- a/tests/ui/traits/const-traits/do-not-const-check.rs
+++ b/tests/ui/traits/const-traits/do-not-const-check.rs
@@ -1,5 +1,6 @@
 //@ check-pass
-#![feature(const_trait_impl, rustc_attrs)]
+#![feature(const_trait_impl, rustc_attrs, effects)]
+//~^ WARN the feature `effects` is incomplete
 
 #[const_trait]
 trait IntoIter {
diff --git a/tests/ui/traits/const-traits/do-not-const-check.stderr b/tests/ui/traits/const-traits/do-not-const-check.stderr
new file mode 100644
index 00000000000..0d81ef74e8d
--- /dev/null
+++ b/tests/ui/traits/const-traits/do-not-const-check.stderr
@@ -0,0 +1,11 @@
+warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/do-not-const-check.rs:2:43
+   |
+LL | #![feature(const_trait_impl, rustc_attrs, effects)]
+   |                                           ^^^^^^^
+   |
+   = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/traits/const-traits/effects/ice-112822-expected-type-for-param.stderr b/tests/ui/traits/const-traits/effects/ice-112822-expected-type-for-param.stderr
index 5b0d5a8bb1d..36184856035 100644
--- a/tests/ui/traits/const-traits/effects/ice-112822-expected-type-for-param.stderr
+++ b/tests/ui/traits/const-traits/effects/ice-112822-expected-type-for-param.stderr
@@ -17,11 +17,6 @@ LL | #![feature(const_trait_impl, effects)]
    = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
    = note: `#[warn(incomplete_features)]` on by default
 
-error: using `#![feature(effects)]` without enabling next trait solver globally
-   |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
-
 error: `~const` can only be applied to `#[const_trait]` traits
   --> $DIR/ice-112822-expected-type-for-param.rs:3:25
    |
@@ -54,7 +49,7 @@ LL |                 assert_eq!(first, &b'f');
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
    = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 6 previous errors; 1 warning emitted
+error: aborting due to 5 previous errors; 1 warning emitted
 
 Some errors have detailed explanations: E0015, E0658.
 For more information about an error, try `rustc --explain E0015`.
diff --git a/tests/ui/traits/const-traits/effects/no-explicit-const-params.rs b/tests/ui/traits/const-traits/effects/no-explicit-const-params.rs
index b08aba9acbc..c6b94fa2230 100644
--- a/tests/ui/traits/const-traits/effects/no-explicit-const-params.rs
+++ b/tests/ui/traits/const-traits/effects/no-explicit-const-params.rs
@@ -23,4 +23,5 @@ const FOO: () = {
     //~^ ERROR: function takes 0 generic arguments but 1 generic argument was supplied
     <() as Bar<false>>::bar();
     //~^ ERROR: trait takes 0 generic arguments but 1 generic argument was supplied
+    //~| ERROR the trait bound `(): const Bar` is not satisfied
 };
diff --git a/tests/ui/traits/const-traits/effects/no-explicit-const-params.stderr b/tests/ui/traits/const-traits/effects/no-explicit-const-params.stderr
index a3aa970e94d..bd9acc7a6d2 100644
--- a/tests/ui/traits/const-traits/effects/no-explicit-const-params.stderr
+++ b/tests/ui/traits/const-traits/effects/no-explicit-const-params.stderr
@@ -7,11 +7,6 @@ LL | #![feature(const_trait_impl, effects)]
    = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
    = note: `#[warn(incomplete_features)]` on by default
 
-error: using `#![feature(effects)]` without enabling next trait solver globally
-   |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
-
 error[E0107]: function takes 0 generic arguments but 1 generic argument was supplied
   --> $DIR/no-explicit-const-params.rs:22:5
    |
@@ -40,6 +35,12 @@ note: trait defined here, with 0 generic parameters
 LL | trait Bar {
    |       ^^^
 
+error[E0277]: the trait bound `(): const Bar` is not satisfied
+  --> $DIR/no-explicit-const-params.rs:24:5
+   |
+LL |     <() as Bar<false>>::bar();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error[E0107]: function takes 0 generic arguments but 1 generic argument was supplied
   --> $DIR/no-explicit-const-params.rs:15:5
    |
@@ -70,4 +71,5 @@ LL | trait Bar {
 
 error: aborting due to 5 previous errors; 1 warning emitted
 
-For more information about this error, try `rustc --explain E0107`.
+Some errors have detailed explanations: E0107, E0277.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/tests/ui/traits/const-traits/effects/span-bug-issue-121418.stderr b/tests/ui/traits/const-traits/effects/span-bug-issue-121418.stderr
index 5ff1c6c5b9f..97663232fcf 100644
--- a/tests/ui/traits/const-traits/effects/span-bug-issue-121418.stderr
+++ b/tests/ui/traits/const-traits/effects/span-bug-issue-121418.stderr
@@ -17,11 +17,6 @@ LL | #![feature(effects)]
    = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
    = note: `#[warn(incomplete_features)]` on by default
 
-error: using `#![feature(effects)]` without enabling next trait solver globally
-   |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
-
 error[E0308]: mismatched types
   --> $DIR/span-bug-issue-121418.rs:9:27
    |
@@ -39,12 +34,12 @@ error[E0277]: the size for values of type `(dyn T + 'static)` cannot be known at
 LL |     pub const fn new() -> std::sync::Mutex<dyn T> {}
    |                           ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = help: within `Mutex<(dyn T + 'static)>`, the trait `Sized` is not implemented for `(dyn T + 'static)`, which is required by `Mutex<(dyn T + 'static)>: Sized`
+   = help: within `Mutex<(dyn T + 'static)>`, the trait `Sized` is not implemented for `(dyn T + 'static)`
 note: required because it appears within the type `Mutex<(dyn T + 'static)>`
   --> $SRC_DIR/std/src/sync/mutex.rs:LL:COL
    = note: the return type of a function must have a statically known size
 
-error: aborting due to 4 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors; 1 warning emitted
 
 Some errors have detailed explanations: E0277, E0308.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/const-traits/effects/spec-effectvar-ice.stderr b/tests/ui/traits/const-traits/effects/spec-effectvar-ice.stderr
index 0cb172a2d14..273f9943212 100644
--- a/tests/ui/traits/const-traits/effects/spec-effectvar-ice.stderr
+++ b/tests/ui/traits/const-traits/effects/spec-effectvar-ice.stderr
@@ -7,11 +7,6 @@ LL | #![feature(effects)]
    = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
    = note: `#[warn(incomplete_features)]` on by default
 
-error: using `#![feature(effects)]` without enabling next trait solver globally
-   |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
-
 error: const `impl` for trait `Foo` which is not marked with `#[const_trait]`
   --> $DIR/spec-effectvar-ice.rs:11:15
    |
@@ -60,5 +55,5 @@ error: cannot specialize on trait `Specialize`
 LL | impl<T> const Foo for T where T: const Specialize {}
    |                                  ^^^^^^^^^^^^^^^^
 
-error: aborting due to 6 previous errors; 1 warning emitted
+error: aborting due to 5 previous errors; 1 warning emitted
 
diff --git a/tests/ui/traits/const-traits/effects/trait-fn-const.stderr b/tests/ui/traits/const-traits/effects/trait-fn-const.stderr
index 15cb84026e4..33914cb306d 100644
--- a/tests/ui/traits/const-traits/effects/trait-fn-const.stderr
+++ b/tests/ui/traits/const-traits/effects/trait-fn-const.stderr
@@ -63,11 +63,6 @@ LL | #![feature(const_trait_impl, effects)]
    = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
    = note: `#[warn(incomplete_features)]` on by default
 
-error: using `#![feature(effects)]` without enabling next trait solver globally
-   |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
-
-error: aborting due to 5 previous errors; 1 warning emitted
+error: aborting due to 4 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0379`.
diff --git a/tests/ui/traits/const-traits/effects/with-without-next-solver.coherence.stderr b/tests/ui/traits/const-traits/effects/with-without-next-solver.coherence.stderr
deleted file mode 100644
index 20448f51de2..00000000000
--- a/tests/ui/traits/const-traits/effects/with-without-next-solver.coherence.stderr
+++ /dev/null
@@ -1,7 +0,0 @@
-error: using `#![feature(effects)]` without enabling next trait solver globally
-   |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/traits/const-traits/effects/with-without-next-solver.rs b/tests/ui/traits/const-traits/effects/with-without-next-solver.rs
deleted file mode 100644
index f022af05c50..00000000000
--- a/tests/ui/traits/const-traits/effects/with-without-next-solver.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-// test that we error correctly when effects is used without the next-solver flag.
-//@ revisions: stock coherence full
-//@[coherence] compile-flags: -Znext-solver=coherence
-//@[full] compile-flags: -Znext-solver
-//@[full] check-pass
-
-#![feature(effects)]
-#![allow(incomplete_features)]
-
-fn main() {}
diff --git a/tests/ui/traits/const-traits/effects/with-without-next-solver.stock.stderr b/tests/ui/traits/const-traits/effects/with-without-next-solver.stock.stderr
deleted file mode 100644
index 20448f51de2..00000000000
--- a/tests/ui/traits/const-traits/effects/with-without-next-solver.stock.stderr
+++ /dev/null
@@ -1,7 +0,0 @@
-error: using `#![feature(effects)]` without enabling next trait solver globally
-   |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/traits/const-traits/ice-119717-constant-lifetime.stderr b/tests/ui/traits/const-traits/ice-119717-constant-lifetime.stderr
index 50cdded8d51..9e22422ad3b 100644
--- a/tests/ui/traits/const-traits/ice-119717-constant-lifetime.stderr
+++ b/tests/ui/traits/const-traits/ice-119717-constant-lifetime.stderr
@@ -1,8 +1,3 @@
-error: using `#![feature(effects)]` without enabling next trait solver globally
-   |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
-
 error: const `impl` for trait `FromResidual` which is not marked with `#[const_trait]`
   --> $DIR/ice-119717-constant-lifetime.rs:6:15
    |
@@ -32,7 +27,7 @@ help: try replacing `_` with the type in the corresponding trait method signatur
 LL |     fn from_residual(t: T) -> T {
    |                               ~
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0121, E0210.
 For more information about an error, try `rustc --explain E0121`.
diff --git a/tests/ui/traits/const-traits/ice-120503-async-const-method.stderr b/tests/ui/traits/const-traits/ice-120503-async-const-method.stderr
index 90771c344b5..1a11aec4b26 100644
--- a/tests/ui/traits/const-traits/ice-120503-async-const-method.stderr
+++ b/tests/ui/traits/const-traits/ice-120503-async-const-method.stderr
@@ -55,11 +55,6 @@ LL | #![feature(effects)]
    = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
    = note: `#[warn(incomplete_features)]` on by default
 
-error: using `#![feature(effects)]` without enabling next trait solver globally
-   |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
-
 error[E0425]: cannot find function `main8` in this scope
   --> $DIR/ice-120503-async-const-method.rs:12:9
    |
@@ -69,7 +64,7 @@ LL |         main8().await;
 LL | fn main() {}
    | --------- similarly named function `main` defined here
 
-error: aborting due to 6 previous errors; 1 warning emitted
+error: aborting due to 5 previous errors; 1 warning emitted
 
 Some errors have detailed explanations: E0379, E0407, E0425.
 For more information about an error, try `rustc --explain E0379`.
diff --git a/tests/ui/traits/const-traits/ice-121536-const-method.stderr b/tests/ui/traits/const-traits/ice-121536-const-method.stderr
index 29187654c3c..4fe88f263c8 100644
--- a/tests/ui/traits/const-traits/ice-121536-const-method.stderr
+++ b/tests/ui/traits/const-traits/ice-121536-const-method.stderr
@@ -23,11 +23,6 @@ LL | #![feature(const_trait_impl, effects)]
    = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
    = note: `#[warn(incomplete_features)]` on by default
 
-error: using `#![feature(effects)]` without enabling next trait solver globally
-   |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
-
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 1 previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0379`.
diff --git a/tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.stderr b/tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.stderr
index dcb7dd7a142..1178c90fce5 100644
--- a/tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.stderr
+++ b/tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.stderr
@@ -1,8 +1,3 @@
-error: using `#![feature(effects)]` without enabling next trait solver globally
-   |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
-
 error: `~const` can only be applied to `#[const_trait]` traits
   --> $DIR/ice-123664-unexpected-bound-var.rs:4:27
    |
@@ -17,5 +12,5 @@ LL | const fn with_positive<F: ~const Fn()>() {}
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.stderr b/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.stderr
index 284757c1a89..0b1f8b40898 100644
--- a/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.stderr
+++ b/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.stderr
@@ -1,8 +1,3 @@
-error: using `#![feature(effects)]` without enabling next trait solver globally
-   |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
-
 error[E0119]: conflicting implementations of trait `Foo` for type `i32`
   --> $DIR/ice-124857-combine-effect-const-infer-vars.rs:11:1
    |
@@ -12,6 +7,6 @@ LL |
 LL | impl<T> const Foo for T where T: ~const Foo {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32`
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.stderr b/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.stderr
index 0ca16a1be40..db047bfd94d 100644
--- a/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.stderr
+++ b/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.stderr
@@ -1,8 +1,3 @@
-error: using `#![feature(effects)]` without enabling next trait solver globally
-   |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
-
 error: const `impl` for trait `FromResidual` which is not marked with `#[const_trait]`
   --> $DIR/ice-126148-failed-to-normalize.rs:8:12
    |
@@ -54,7 +49,7 @@ LL |     TryMe?;
    |
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 
-error: aborting due to 7 previous errors
+error: aborting due to 6 previous errors
 
 Some errors have detailed explanations: E0015, E0046.
 For more information about an error, try `rustc --explain E0015`.
diff --git a/tests/ui/traits/const-traits/impl-with-default-fn-fail.stderr b/tests/ui/traits/const-traits/impl-with-default-fn-fail.stderr
index 2ea203627f4..0135296526f 100644
--- a/tests/ui/traits/const-traits/impl-with-default-fn-fail.stderr
+++ b/tests/ui/traits/const-traits/impl-with-default-fn-fail.stderr
@@ -1,8 +1,3 @@
-error: using `#![feature(effects)]` without enabling next trait solver globally
-   |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
-
 error[E0046]: not all trait items implemented, missing: `req`
   --> $DIR/impl-with-default-fn-fail.rs:13:1
    |
@@ -12,6 +7,6 @@ LL |     fn req(&self);
 LL | impl const Tr for u16 {
    | ^^^^^^^^^^^^^^^^^^^^^ missing `req` in implementation
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0046`.
diff --git a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.stderr b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.stderr
index c51d169dd33..363fbee1f8b 100644
--- a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.stderr
+++ b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.stderr
@@ -7,16 +7,11 @@ LL | #![feature(const_trait_impl, effects)]
    = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
    = note: `#[warn(incomplete_features)]` on by default
 
-error: using `#![feature(effects)]` without enabling next trait solver globally
-   |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
-
 error: cannot specialize on const impl with non-const impl
   --> $DIR/const-default-impl-non-const-specialized-impl.rs:19:1
    |
 LL | impl Value for FortyTwo {
    | ^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 1 previous error; 1 warning emitted
 
diff --git a/tests/ui/traits/const-traits/specializing-constness.stderr b/tests/ui/traits/const-traits/specializing-constness.stderr
index e8c4fb0f0c7..226295bf949 100644
--- a/tests/ui/traits/const-traits/specializing-constness.stderr
+++ b/tests/ui/traits/const-traits/specializing-constness.stderr
@@ -7,16 +7,11 @@ LL | #![feature(const_trait_impl, effects, min_specialization, rustc_attrs)]
    = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
    = note: `#[warn(incomplete_features)]` on by default
 
-error: using `#![feature(effects)]` without enabling next trait solver globally
-   |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
-
 error: cannot specialize on const impl with non-const impl
   --> $DIR/specializing-constness.rs:23:1
    |
 LL | impl<T: Spec + Sup> A for T {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 1 previous error; 1 warning emitted
 
diff --git a/tests/ui/traits/const-traits/tilde-const-and-const-params.rs b/tests/ui/traits/const-traits/tilde-const-and-const-params.rs
index f6a7c7c1746..b316ac75a8a 100644
--- a/tests/ui/traits/const-traits/tilde-const-and-const-params.rs
+++ b/tests/ui/traits/const-traits/tilde-const-and-const-params.rs
@@ -8,6 +8,7 @@ struct Foo<const N: usize>;
 impl<const N: usize> Foo<N> {
     fn add<A: ~const Add42>(self) -> Foo<{ A::add(N) }> {
         //~^ ERROR `~const` is not allowed here
+        //~| ERROR the trait bound `A: const Add42` is not satisfied
         Foo
     }
 }
@@ -25,6 +26,7 @@ impl const Add42 for () {
 
 fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
     //~^ ERROR `~const` is not allowed here
+    //~| ERROR the trait bound `A: const Add42` is not satisfied
     Foo
 }
 
diff --git a/tests/ui/traits/const-traits/tilde-const-and-const-params.stderr b/tests/ui/traits/const-traits/tilde-const-and-const-params.stderr
index 84a425f6791..78bf85e9c6d 100644
--- a/tests/ui/traits/const-traits/tilde-const-and-const-params.stderr
+++ b/tests/ui/traits/const-traits/tilde-const-and-const-params.stderr
@@ -11,21 +11,29 @@ LL |     fn add<A: ~const Add42>(self) -> Foo<{ A::add(N) }> {
    |        ^^^
 
 error: `~const` is not allowed here
-  --> $DIR/tilde-const-and-const-params.rs:26:11
+  --> $DIR/tilde-const-and-const-params.rs:27:11
    |
 LL | fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
    |           ^^^^^^
    |
 note: this function is not `const`, so it cannot have `~const` trait bounds
-  --> $DIR/tilde-const-and-const-params.rs:26:4
+  --> $DIR/tilde-const-and-const-params.rs:27:4
    |
 LL | fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
    |    ^^^
 
-error: using `#![feature(effects)]` without enabling next trait solver globally
+error[E0277]: the trait bound `A: const Add42` is not satisfied
+  --> $DIR/tilde-const-and-const-params.rs:27:61
    |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
+LL | fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
+   |                                                             ^^^^^^^^^
+
+error[E0277]: the trait bound `A: const Add42` is not satisfied
+  --> $DIR/tilde-const-and-const-params.rs:9:44
+   |
+LL |     fn add<A: ~const Add42>(self) -> Foo<{ A::add(N) }> {
+   |                                            ^^^^^^^^^
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/copy-impl-cannot-normalize.stderr b/tests/ui/traits/copy-impl-cannot-normalize.stderr
index a98bb47f54f..3bdb8b70172 100644
--- a/tests/ui/traits/copy-impl-cannot-normalize.stderr
+++ b/tests/ui/traits/copy-impl-cannot-normalize.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `T: TraitFoo` is not satisfied
   --> $DIR/copy-impl-cannot-normalize.rs:22:18
    |
 LL | impl<T> Copy for Foo<T> {}
-   |                  ^^^^^^ the trait `TraitFoo` is not implemented for `T`, which is required by `Foo<T>: Clone`
+   |                  ^^^^^^ the trait `TraitFoo` is not implemented for `T`
    |
 note: required for `Foo<T>` to implement `Clone`
   --> $DIR/copy-impl-cannot-normalize.rs:12:9
diff --git a/tests/ui/traits/dont-autoderef-ty-with-escaping-var.stderr b/tests/ui/traits/dont-autoderef-ty-with-escaping-var.stderr
index fecb05cade7..a5d0e6ab095 100644
--- a/tests/ui/traits/dont-autoderef-ty-with-escaping-var.stderr
+++ b/tests/ui/traits/dont-autoderef-ty-with-escaping-var.stderr
@@ -8,7 +8,7 @@ error[E0277]: the trait bound `for<'a> &'a mut Vec<&'a u32>: Foo<'static, i32>`
   --> $DIR/dont-autoderef-ty-with-escaping-var.rs:17:6
    |
 LL |     <i32 as RefFoo<i32>>::ref_foo(unknown);
-   |      ^^^ the trait `for<'a> Foo<'static, i32>` is not implemented for `&'a mut Vec<&'a u32>`, which is required by `i32: RefFoo<i32>`
+   |      ^^^ the trait `for<'a> Foo<'static, i32>` is not implemented for `&'a mut Vec<&'a u32>`
    |
 help: this trait has no implementations, consider adding one
   --> $DIR/dont-autoderef-ty-with-escaping-var.rs:3:1
diff --git a/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr b/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr
index 17fced307ed..07edc4ede76 100644
--- a/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr
+++ b/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr
@@ -10,7 +10,7 @@ error[E0277]: the trait bound `NoClone: Magic` is not satisfied
   --> $DIR/supertrait-auto-trait.rs:16:23
    |
 LL |     let (a, b) = copy(NoClone);
-   |                  ---- ^^^^^^^ the trait `Copy` is not implemented for `NoClone`, which is required by `NoClone: Magic`
+   |                  ---- ^^^^^^^ the trait `Copy` is not implemented for `NoClone`
    |                  |
    |                  required by a bound introduced by this call
    |
diff --git a/tests/ui/traits/issue-43784-supertrait.stderr b/tests/ui/traits/issue-43784-supertrait.stderr
index 4c565c3fa1d..2bf365745a6 100644
--- a/tests/ui/traits/issue-43784-supertrait.stderr
+++ b/tests/ui/traits/issue-43784-supertrait.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `T: Copy` is not satisfied
   --> $DIR/issue-43784-supertrait.rs:8:22
    |
 LL | impl<T> Complete for T {}
-   |                      ^ the trait `Copy` is not implemented for `T`, which is required by `T: Partial`
+   |                      ^ the trait `Copy` is not implemented for `T`
    |
 note: required for `T` to implement `Partial`
   --> $DIR/issue-43784-supertrait.rs:1:11
diff --git a/tests/ui/traits/issue-7013.stderr b/tests/ui/traits/issue-7013.stderr
index 5067c7d7dd7..17493663172 100644
--- a/tests/ui/traits/issue-7013.stderr
+++ b/tests/ui/traits/issue-7013.stderr
@@ -4,7 +4,7 @@ error[E0277]: `Rc<RefCell<A>>` cannot be sent between threads safely
 LL |     let a = A {v: Box::new(B{v: None}) as Box<dyn Foo + Send>};
    |                   ^^^^^^^^^^^^^^^^^^^^ `Rc<RefCell<A>>` cannot be sent between threads safely
    |
-   = help: within `B`, the trait `Send` is not implemented for `Rc<RefCell<A>>`, which is required by `B: Send`
+   = help: within `B`, the trait `Send` is not implemented for `Rc<RefCell<A>>`
 note: required because it appears within the type `Option<Rc<RefCell<A>>>`
   --> $SRC_DIR/core/src/option.rs:LL:COL
 note: required because it appears within the type `B`
diff --git a/tests/ui/traits/issue-71036.stderr b/tests/ui/traits/issue-71036.stderr
index 35d543eb017..2452731f19f 100644
--- a/tests/ui/traits/issue-71036.stderr
+++ b/tests/ui/traits/issue-71036.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `&'a T: Unsize<&'a U>` is not satisfied
   --> $DIR/issue-71036.rs:11:1
    |
 LL | impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Foo<'a, U>> for Foo<'a, T> {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Unsize<&'a U>` is not implemented for `&'a T`, which is required by `&'a &'a T: DispatchFromDyn<&'a &'a U>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Unsize<&'a U>` is not implemented for `&'a T`
    |
    = note: all implementations of `Unsize` are provided automatically by the compiler, see <https://doc.rust-lang.org/stable/std/marker/trait.Unsize.html> for more information
    = note: required for `&'a &'a T` to implement `DispatchFromDyn<&'a &'a U>`
diff --git a/tests/ui/traits/issue-71136.stderr b/tests/ui/traits/issue-71136.stderr
index d37ad8ae34d..2c03c6bf08e 100644
--- a/tests/ui/traits/issue-71136.stderr
+++ b/tests/ui/traits/issue-71136.stderr
@@ -5,7 +5,7 @@ LL | #[derive(Clone)]
    |          ----- in this derive macro expansion
 LL | struct FooHolster {
 LL |     the_foos: Vec<Foo>,
-   |     ^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `Foo`, which is required by `Vec<Foo>: Clone`
+   |     ^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `Foo`
    |
    = note: required for `Vec<Foo>` to implement `Clone`
    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/traits/issue-91594.stderr b/tests/ui/traits/issue-91594.stderr
index 726ee5b6146..13568179e81 100644
--- a/tests/ui/traits/issue-91594.stderr
+++ b/tests/ui/traits/issue-91594.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `Foo: HasComponent<()>` is not satisfied
   --> $DIR/issue-91594.rs:10:19
    |
 LL | impl HasComponent<<Foo as Component<Foo>>::Interface> for Foo {}
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasComponent<()>` is not implemented for `Foo`, which is required by `Foo: Component<Foo>`
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasComponent<()>` is not implemented for `Foo`
    |
    = help: the trait `HasComponent<<Foo as Component<Foo>>::Interface>` is implemented for `Foo`
 note: required for `Foo` to implement `Component<Foo>`
diff --git a/tests/ui/traits/issue-97576.stderr b/tests/ui/traits/issue-97576.stderr
index bee254461f1..2c6cfd83b95 100644
--- a/tests/ui/traits/issue-97576.stderr
+++ b/tests/ui/traits/issue-97576.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `String: From<impl ToString>` is not satisfied
   --> $DIR/issue-97576.rs:8:22
    |
 LL |             bar: bar.into(),
-   |                      ^^^^ the trait `From<impl ToString>` is not implemented for `String`, which is required by `impl ToString: Into<_>`
+   |                      ^^^^ the trait `From<impl ToString>` is not implemented for `String`
    |
    = note: required for `impl ToString` to implement `Into<String>`
 
diff --git a/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr b/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr
index 2a3833beb26..8f5b937e586 100644
--- a/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr
+++ b/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr
@@ -49,7 +49,7 @@ LL |     is_send((8, TestType));
    |     |
    |     required by a bound introduced by this call
    |
-   = help: within `({integer}, dummy1c::TestType)`, the trait `Send` is not implemented for `dummy1c::TestType`, which is required by `({integer}, dummy1c::TestType): Send`
+   = help: within `({integer}, dummy1c::TestType)`, the trait `Send` is not implemented for `dummy1c::TestType`
    = note: required because it appears within the type `({integer}, dummy1c::TestType)`
 note: required by a bound in `is_send`
   --> $DIR/negated-auto-traits-error.rs:16:15
@@ -87,7 +87,7 @@ LL |     is_send(Box::new(Outer2(TestType)));
    |     |
    |     required by a bound introduced by this call
    |
-   = help: within `Outer2<dummy3::TestType>`, the trait `Send` is not implemented for `dummy3::TestType`, which is required by `Box<Outer2<dummy3::TestType>>: Send`
+   = help: within `Outer2<dummy3::TestType>`, the trait `Send` is not implemented for `dummy3::TestType`
 note: required because it appears within the type `Outer2<dummy3::TestType>`
   --> $DIR/negated-auto-traits-error.rs:12:8
    |
@@ -110,7 +110,7 @@ LL |     is_sync(Outer2(TestType));
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `Send` is not implemented for `main::TestType`, which is required by `Outer2<main::TestType>: Sync`
+   = help: the trait `Send` is not implemented for `main::TestType`
 note: required for `Outer2<main::TestType>` to implement `Sync`
   --> $DIR/negated-auto-traits-error.rs:14:22
    |
diff --git a/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr b/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr
index c2029a5a1c8..55f52181ec9 100644
--- a/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr
+++ b/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr
@@ -4,7 +4,7 @@ error: future cannot be sent between threads safely
 LL |     is_send(foo());
    |             ^^^^^ future returned by `foo` is not `Send`
    |
-   = help: the trait `Sync` is not implemented for `NotSync`, which is required by `impl Future<Output = ()>: Send`
+   = help: the trait `Sync` is not implemented for `NotSync`
 note: future is not `Send` as this value is used across an await
   --> $DIR/auto-with-drop_tracking_mir.rs:16:11
    |
diff --git a/tests/ui/traits/next-solver/builtin-fn-must-return-sized.stderr b/tests/ui/traits/next-solver/builtin-fn-must-return-sized.stderr
index b487ceef1d4..bb39d110777 100644
--- a/tests/ui/traits/next-solver/builtin-fn-must-return-sized.stderr
+++ b/tests/ui/traits/next-solver/builtin-fn-must-return-sized.stderr
@@ -4,7 +4,7 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t
 LL |     foo::<fn() -> str, _>(None, ());
    |           ^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = help: within `fn() -> str`, the trait `Sized` is not implemented for `str`, which is required by `fn() -> str: Fn<_>`
+   = help: within `fn() -> str`, the trait `Sized` is not implemented for `str`
    = note: required because it appears within the type `fn() -> str`
 note: required by a bound in `foo`
   --> $DIR/builtin-fn-must-return-sized.rs:10:11
diff --git a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.with.stderr b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.with.stderr
index a81229e5e35..9114bcadac0 100644
--- a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.with.stderr
+++ b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.with.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `A<X>: Trait<_, _, _>` is not satisfied
   --> $DIR/incompleteness-unstable-result.rs:65:19
    |
 LL |     impls_trait::<A<X>, _, _, _>();
-   |                   ^^^^ the trait `Trait<_, _, _>` is not implemented for `A<X>`, which is required by `A<X>: Trait<_, _, _>`
+   |                   ^^^^ the trait `Trait<_, _, _>` is not implemented for `A<X>`
    |
    = help: the trait `Trait<U, V, D>` is implemented for `A<T>`
 note: required for `A<X>` to implement `Trait<_, _, _>`
diff --git a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.without.stderr b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.without.stderr
index a81229e5e35..9114bcadac0 100644
--- a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.without.stderr
+++ b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.without.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `A<X>: Trait<_, _, _>` is not satisfied
   --> $DIR/incompleteness-unstable-result.rs:65:19
    |
 LL |     impls_trait::<A<X>, _, _, _>();
-   |                   ^^^^ the trait `Trait<_, _, _>` is not implemented for `A<X>`, which is required by `A<X>: Trait<_, _, _>`
+   |                   ^^^^ the trait `Trait<_, _, _>` is not implemented for `A<X>`
    |
    = help: the trait `Trait<U, V, D>` is implemented for `A<T>`
 note: required for `A<X>` to implement `Trait<_, _, _>`
diff --git a/tests/ui/traits/next-solver/diagnostics/point-at-failing-nested.stderr b/tests/ui/traits/next-solver/diagnostics/point-at-failing-nested.stderr
index 9a18a58debd..a841618ec6f 100644
--- a/tests/ui/traits/next-solver/diagnostics/point-at-failing-nested.stderr
+++ b/tests/ui/traits/next-solver/diagnostics/point-at-failing-nested.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `(): Foo` is not satisfied
   --> $DIR/point-at-failing-nested.rs:22:17
    |
 LL |     needs_foo::<()>();
-   |                 ^^ the trait `Bar` is not implemented for `()`, which is required by `(): Foo`
+   |                 ^^ the trait `Bar` is not implemented for `()`
    |
 help: this trait has no implementations, consider adding one
   --> $DIR/point-at-failing-nested.rs:4:1
diff --git a/tests/ui/traits/next-solver/diagnostics/where-clause-doesnt-apply.stderr b/tests/ui/traits/next-solver/diagnostics/where-clause-doesnt-apply.stderr
index ab1d4a56c02..29703679a86 100644
--- a/tests/ui/traits/next-solver/diagnostics/where-clause-doesnt-apply.stderr
+++ b/tests/ui/traits/next-solver/diagnostics/where-clause-doesnt-apply.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `(): Foo` is not satisfied
   --> $DIR/where-clause-doesnt-apply.rs:18:15
    |
 LL |     needs_foo(());
-   |     --------- ^^ the trait `Bar` is not implemented for `()`, which is required by `(): Foo`
+   |     --------- ^^ the trait `Bar` is not implemented for `()`
    |     |
    |     required by a bound introduced by this call
    |
diff --git a/tests/ui/traits/next-solver/dyn-incompatibility.stderr b/tests/ui/traits/next-solver/dyn-incompatibility.stderr
index 7f2c0646ef5..a720797efc4 100644
--- a/tests/ui/traits/next-solver/dyn-incompatibility.stderr
+++ b/tests/ui/traits/next-solver/dyn-incompatibility.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `T: Copy` is not satisfied in `dyn Setup<From = T>
   --> $DIR/dyn-incompatibility.rs:12:12
    |
 LL |     copy::<dyn Setup<From=T>>(t)
-   |            ^^^^^^^^^^^^^^^^^ within `dyn Setup<From = T>`, the trait `Copy` is not implemented for `T`, which is required by `dyn Setup<From = T>: Setup`
+   |            ^^^^^^^^^^^^^^^^^ within `dyn Setup<From = T>`, the trait `Copy` is not implemented for `T`
    |
    = note: required because it appears within the type `dyn Setup<From = T>`
 note: required by a bound in `copy`
@@ -35,7 +35,7 @@ error[E0277]: the trait bound `T: Copy` is not satisfied in `dyn Setup<From = T>
   --> $DIR/dyn-incompatibility.rs:12:5
    |
 LL |     copy::<dyn Setup<From=T>>(t)
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `dyn Setup<From = T>`, the trait `Copy` is not implemented for `T`, which is required by `dyn Setup<From = T>: Setup`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `dyn Setup<From = T>`, the trait `Copy` is not implemented for `T`
    |
    = note: required because it appears within the type `dyn Setup<From = T>`
 help: consider restricting type parameter `T`
diff --git a/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr
index 65e7dd2ab34..1f319cc6743 100644
--- a/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr
+++ b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `T: Clone` is not satisfied
   --> $DIR/global-cache-and-parallel-frontend.rs:15:17
    |
 LL | #[derive(Clone, Eq)]
-   |                 ^^ the trait `Clone` is not implemented for `T`, which is required by `Struct<T>: PartialEq`
+   |                 ^^ the trait `Clone` is not implemented for `T`
    |
 note: required for `Struct<T>` to implement `PartialEq`
   --> $DIR/global-cache-and-parallel-frontend.rs:18:19
diff --git a/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr b/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr
index f7d5d6fcee4..f4deb169516 100644
--- a/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr
+++ b/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr
@@ -29,7 +29,7 @@ error[E0277]: `V` is not an iterator
 LL |     bar();
    |     ^^^^^ `V` is not an iterator
    |
-   = help: the trait `Iterator` is not implemented for `V`, which is required by `V: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `V`
    = note: required for `V` to implement `IntoIterator`
 note: required by a bound in `bar`
   --> $DIR/bad-sized-cond.rs:12:15
@@ -46,7 +46,7 @@ error[E0277]: the size for values of type `V` cannot be known at compilation tim
 LL |     bar();
    |     ^^^^^ doesn't have a size known at compile-time
    |
-   = help: the trait `Sized` is not implemented for `V`, which is required by `V: IntoIterator`
+   = help: the trait `Sized` is not implemented for `V`
    = note: required for `V` to implement `IntoIterator`
 note: required by a bound in `bar`
   --> $DIR/bad-sized-cond.rs:12:15
diff --git a/tests/ui/traits/question-mark-result-err-mismatch.stderr b/tests/ui/traits/question-mark-result-err-mismatch.stderr
index 0e0ae6d5990..bad325a6720 100644
--- a/tests/ui/traits/question-mark-result-err-mismatch.stderr
+++ b/tests/ui/traits/question-mark-result-err-mismatch.stderr
@@ -11,7 +11,7 @@ LL | |             e;
 LL | |         })
    | |__________- this can't be annotated with `?` because it has type `Result<_, ()>`
 LL |           .map(|()| "")?;
-   |                        ^ the trait `From<()>` is not implemented for `String`, which is required by `Result<String, String>: FromResidual<Result<Infallible, ()>>`
+   |                        ^ the trait `From<()>` is not implemented for `String`
    |
    = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
    = note: required for `Result<String, String>` to implement `FromResidual<Result<Infallible, ()>>`
@@ -25,7 +25,7 @@ LL |     let x = foo();
    |             ----- this has type `Result<_, String>`
 ...
 LL |         .map_err(|_| ())?;
-   |          ---------------^ the trait `From<()>` is not implemented for `String`, which is required by `Result<(), String>: FromResidual<Result<Infallible, ()>>`
+   |          ---------------^ the trait `From<()>` is not implemented for `String`
    |          |
    |          this can't be annotated with `?` because it has type `Result<_, ()>`
    |
@@ -50,7 +50,7 @@ LL |           .ok_or_else(|| {
 LL | |             "Couldn't split the test string";
    | |                                             - help: remove this semicolon
 LL | |         })?;
-   | |          -^ the trait `From<()>` is not implemented for `String`, which is required by `Result<String, String>: FromResidual<Result<Infallible, ()>>`
+   | |          -^ the trait `From<()>` is not implemented for `String`
    | |__________|
    |            this can't be annotated with `?` because it has type `Result<_, ()>`
    |
diff --git a/tests/ui/traits/suggest-dereferences/dont-suggest-unsize-deref.stderr b/tests/ui/traits/suggest-dereferences/dont-suggest-unsize-deref.stderr
index 28a0646a86b..8024ad28d5a 100644
--- a/tests/ui/traits/suggest-dereferences/dont-suggest-unsize-deref.stderr
+++ b/tests/ui/traits/suggest-dereferences/dont-suggest-unsize-deref.stderr
@@ -6,7 +6,7 @@ LL |     use_iterator(i);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `Iterator` is not implemented for `&dyn IntoIterator<IntoIter = I, Item = i32>`, which is required by `&dyn IntoIterator<IntoIter = I, Item = i32>: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `&dyn IntoIterator<IntoIter = I, Item = i32>`
    = note: required for `&dyn IntoIterator<IntoIter = I, Item = i32>` to implement `IntoIterator`
 note: required by a bound in `use_iterator`
   --> $DIR/dont-suggest-unsize-deref.rs:3:8
diff --git a/tests/ui/traits/suggest-dereferences/invalid-suggest-deref-issue-127590.stderr b/tests/ui/traits/suggest-dereferences/invalid-suggest-deref-issue-127590.stderr
index 85d6cdf779b..f0957e5cd9f 100644
--- a/tests/ui/traits/suggest-dereferences/invalid-suggest-deref-issue-127590.stderr
+++ b/tests/ui/traits/suggest-dereferences/invalid-suggest-deref-issue-127590.stderr
@@ -6,7 +6,7 @@ LL |     for (src, dest) in std::iter::zip(fields.iter(), &variant.iter()) {
    |                        |
    |                        required by a bound introduced by this call
    |
-   = help: the trait `Iterator` is not implemented for `&std::slice::Iter<'_, {integer}>`, which is required by `&std::slice::Iter<'_, {integer}>: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `&std::slice::Iter<'_, {integer}>`
    = note: required for `&std::slice::Iter<'_, {integer}>` to implement `IntoIterator`
 note: required by a bound in `std::iter::zip`
   --> $SRC_DIR/core/src/iter/adapters/zip.rs:LL:COL
@@ -22,7 +22,7 @@ error[E0277]: `&std::slice::Iter<'_, {integer}>` is not an iterator
 LL |     for (src, dest) in std::iter::zip(fields.iter(), &variant.iter()) {
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&std::slice::Iter<'_, {integer}>` is not an iterator
    |
-   = help: the trait `Iterator` is not implemented for `&std::slice::Iter<'_, {integer}>`, which is required by `Zip<std::slice::Iter<'_, {integer}>, &std::slice::Iter<'_, {integer}>>: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `&std::slice::Iter<'_, {integer}>`
    = help: the trait `Iterator` is implemented for `std::slice::Iter<'_, T>`
    = note: required for `Zip<std::slice::Iter<'_, {integer}>, &std::slice::Iter<'_, {integer}>>` to implement `Iterator`
    = note: required for `Zip<std::slice::Iter<'_, {integer}>, &std::slice::Iter<'_, {integer}>>` to implement `IntoIterator`
@@ -35,7 +35,7 @@ LL |     for (src, dest) in std::iter::zip(fields.iter(), &variant.iter().clone(
    |                        |
    |                        required by a bound introduced by this call
    |
-   = help: the trait `Iterator` is not implemented for `&std::slice::Iter<'_, {integer}>`, which is required by `&std::slice::Iter<'_, {integer}>: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `&std::slice::Iter<'_, {integer}>`
    = note: required for `&std::slice::Iter<'_, {integer}>` to implement `IntoIterator`
 note: required by a bound in `std::iter::zip`
   --> $SRC_DIR/core/src/iter/adapters/zip.rs:LL:COL
@@ -51,7 +51,7 @@ error[E0277]: `&std::slice::Iter<'_, {integer}>` is not an iterator
 LL |     for (src, dest) in std::iter::zip(fields.iter(), &variant.iter().clone()) {
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&std::slice::Iter<'_, {integer}>` is not an iterator
    |
-   = help: the trait `Iterator` is not implemented for `&std::slice::Iter<'_, {integer}>`, which is required by `Zip<std::slice::Iter<'_, {integer}>, &std::slice::Iter<'_, {integer}>>: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `&std::slice::Iter<'_, {integer}>`
    = help: the trait `Iterator` is implemented for `std::slice::Iter<'_, T>`
    = note: required for `Zip<std::slice::Iter<'_, {integer}>, &std::slice::Iter<'_, {integer}>>` to implement `Iterator`
    = note: required for `Zip<std::slice::Iter<'_, {integer}>, &std::slice::Iter<'_, {integer}>>` to implement `IntoIterator`
diff --git a/tests/ui/traits/suggest-dereferences/issue-39029.stderr b/tests/ui/traits/suggest-dereferences/issue-39029.stderr
index 0eea6cbcc5a..fd45fa3cf74 100644
--- a/tests/ui/traits/suggest-dereferences/issue-39029.stderr
+++ b/tests/ui/traits/suggest-dereferences/issue-39029.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `NoToSocketAddrs: ToSocketAddrs` is not satisfied
   --> $DIR/issue-39029.rs:16:38
    |
 LL |     let _errors = TcpListener::bind(&bad);
-   |                   -----------------  ^^^ the trait `ToSocketAddrs` is not implemented for `NoToSocketAddrs`, which is required by `&NoToSocketAddrs: ToSocketAddrs`
+   |                   -----------------  ^^^ the trait `ToSocketAddrs` is not implemented for `NoToSocketAddrs`
    |                   |
    |                   required by a bound introduced by this call
    |
diff --git a/tests/ui/traits/suggest-dereferences/root-obligation.stderr b/tests/ui/traits/suggest-dereferences/root-obligation.stderr
index 2f5e1c5b537..dafd3469b6f 100644
--- a/tests/ui/traits/suggest-dereferences/root-obligation.stderr
+++ b/tests/ui/traits/suggest-dereferences/root-obligation.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `&char: Pattern` is not satisfied
   --> $DIR/root-obligation.rs:6:38
    |
 LL |         .filter(|c| "aeiou".contains(c))
-   |                             -------- ^ the trait `Fn(char)` is not implemented for `char`, which is required by `&char: Pattern`
+   |                             -------- ^ the trait `Fn(char)` is not implemented for `char`
    |                             |
    |                             required by a bound introduced by this call
    |
diff --git a/tests/ui/traits/suggest-dereferences/suggest-dereferencing-receiver-argument.stderr b/tests/ui/traits/suggest-dereferences/suggest-dereferencing-receiver-argument.stderr
index d1d75625aba..d6033bc6baa 100644
--- a/tests/ui/traits/suggest-dereferences/suggest-dereferencing-receiver-argument.stderr
+++ b/tests/ui/traits/suggest-dereferences/suggest-dereferencing-receiver-argument.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `TargetStruct: From<&{integer}>` is not satisfied
   --> $DIR/suggest-dereferencing-receiver-argument.rs:13:30
    |
 LL |     let _b: TargetStruct = a.into();
-   |                              ^^^^ the trait `From<&{integer}>` is not implemented for `TargetStruct`, which is required by `&{integer}: Into<_>`
+   |                              ^^^^ the trait `From<&{integer}>` is not implemented for `TargetStruct`
    |
    = note: required for `&{integer}` to implement `Into<TargetStruct>`
 help: consider dereferencing here
diff --git a/tests/ui/traits/unsend-future.stderr b/tests/ui/traits/unsend-future.stderr
index 4462208cb49..25df3419794 100644
--- a/tests/ui/traits/unsend-future.stderr
+++ b/tests/ui/traits/unsend-future.stderr
@@ -4,7 +4,7 @@ error: future cannot be sent between threads safely
 LL |     require_handler(handler)
    |                     ^^^^^^^ future returned by `handler` is not `Send`
    |
-   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `*const i32`, which is required by `fn() -> impl Future<Output = ()> {handler}: Handler`
+   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `*const i32`
 note: future is not `Send` as this value is used across an await
   --> $DIR/unsend-future.rs:15:14
    |
diff --git a/tests/ui/try-block/try-block-bad-type.stderr b/tests/ui/try-block/try-block-bad-type.stderr
index e9e6255cd2a..d94962e4031 100644
--- a/tests/ui/try-block/try-block-bad-type.stderr
+++ b/tests/ui/try-block/try-block-bad-type.stderr
@@ -2,7 +2,7 @@ error[E0277]: `?` couldn't convert the error to `TryFromSliceError`
   --> $DIR/try-block-bad-type.rs:7:16
    |
 LL |         Err("")?;
-   |         -------^ the trait `From<&str>` is not implemented for `TryFromSliceError`, which is required by `Result<u32, TryFromSliceError>: FromResidual<Result<Infallible, &str>>`
+   |         -------^ the trait `From<&str>` is not implemented for `TryFromSliceError`
    |         |
    |         this can't be annotated with `?` because it has type `Result<_, &str>`
    |
diff --git a/tests/ui/try-trait/bad-interconversion.stderr b/tests/ui/try-trait/bad-interconversion.stderr
index 82877baef3e..fe28912ba00 100644
--- a/tests/ui/try-trait/bad-interconversion.stderr
+++ b/tests/ui/try-trait/bad-interconversion.stderr
@@ -4,7 +4,7 @@ error[E0277]: `?` couldn't convert the error to `u8`
 LL | fn result_to_result() -> Result<u64, u8> {
    |                          --------------- expected `u8` because of this
 LL |     Ok(Err(123_i32)?)
-   |        ------------^ the trait `From<i32>` is not implemented for `u8`, which is required by `Result<u64, u8>: FromResidual<Result<Infallible, i32>>`
+   |        ------------^ the trait `From<i32>` is not implemented for `u8`
    |        |
    |        this can't be annotated with `?` because it has type `Result<_, i32>`
    |
diff --git a/tests/ui/try-trait/issue-32709.stderr b/tests/ui/try-trait/issue-32709.stderr
index 9b77f578437..475bd1ff3ac 100644
--- a/tests/ui/try-trait/issue-32709.stderr
+++ b/tests/ui/try-trait/issue-32709.stderr
@@ -4,7 +4,7 @@ error[E0277]: `?` couldn't convert the error to `()`
 LL | fn a() -> Result<i32, ()> {
    |           --------------- expected `()` because of this
 LL |     Err(5)?;
-   |     ------^ the trait `From<{integer}>` is not implemented for `()`, which is required by `Result<i32, ()>: FromResidual<Result<Infallible, {integer}>>`
+   |     ------^ the trait `From<{integer}>` is not implemented for `()`
    |     |
    |     this can't be annotated with `?` because it has type `Result<_, {integer}>`
    |
diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage2.stderr b/tests/ui/type-alias-impl-trait/auto-trait-leakage2.stderr
index 5c5506fb853..2ed918eca17 100644
--- a/tests/ui/type-alias-impl-trait/auto-trait-leakage2.stderr
+++ b/tests/ui/type-alias-impl-trait/auto-trait-leakage2.stderr
@@ -9,7 +9,7 @@ LL |     is_send(m::foo());
    |     |
    |     required by a bound introduced by this call
    |
-   = help: within `Foo`, the trait `Send` is not implemented for `Rc<u32>`, which is required by `Foo: Send`
+   = help: within `Foo`, the trait `Send` is not implemented for `Rc<u32>`
 note: required because it appears within the type `Foo`
   --> $DIR/auto-trait-leakage2.rs:7:16
    |
diff --git a/tests/ui/type-alias-impl-trait/escaping-bound-var.rs b/tests/ui/type-alias-impl-trait/escaping-bound-var.rs
index 1ff200680be..07206dd2491 100644
--- a/tests/ui/type-alias-impl-trait/escaping-bound-var.rs
+++ b/tests/ui/type-alias-impl-trait/escaping-bound-var.rs
@@ -8,6 +8,7 @@ trait Test<'a> {}
 
 pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>;
 //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
+//~| ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
 
 impl Trait<'_> for () {
     type Assoc = ();
diff --git a/tests/ui/type-alias-impl-trait/escaping-bound-var.stderr b/tests/ui/type-alias-impl-trait/escaping-bound-var.stderr
index 09f6fba79cf..c9f0618639a 100644
--- a/tests/ui/type-alias-impl-trait/escaping-bound-var.stderr
+++ b/tests/ui/type-alias-impl-trait/escaping-bound-var.stderr
@@ -10,6 +10,18 @@ note: lifetime declared here
 LL | pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>;
    |                         ^^
 
-error: aborting due to 1 previous error
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
+  --> $DIR/escaping-bound-var.rs:9:57
+   |
+LL | pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>;
+   |                                                         ^^
+   |
+note: lifetime declared here
+  --> $DIR/escaping-bound-var.rs:9:25
+   |
+LL | pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>;
+   |                         ^^
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0657`.
diff --git a/tests/ui/type-alias-impl-trait/issue-57700.rs b/tests/ui/type-alias-impl-trait/issue-57700.rs
deleted file mode 100644
index 8746545ecc9..00000000000
--- a/tests/ui/type-alias-impl-trait/issue-57700.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-#![feature(arbitrary_self_types)]
-#![feature(impl_trait_in_assoc_type)]
-
-use std::ops::Deref;
-
-trait Foo {
-    type Bar: Foo;
-
-    fn foo(self: impl Deref<Target = Self>) -> Self::Bar;
-}
-
-impl<C> Foo for C {
-    type Bar = impl Foo;
-
-    fn foo(self: impl Deref<Target = Self>) -> Self::Bar {
-        self
-        //~^ Error type parameter `impl Deref<Target = Self>` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-    }
-}
-
-fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/issue-57700.stderr b/tests/ui/type-alias-impl-trait/issue-57700.stderr
deleted file mode 100644
index 7efb05f40b0..00000000000
--- a/tests/ui/type-alias-impl-trait/issue-57700.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: type parameter `impl Deref<Target = Self>` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-  --> $DIR/issue-57700.rs:16:9
-   |
-LL |         self
-   |         ^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr
index a7840e0a5bf..b5f38074632 100644
--- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr
+++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `&'static B: From<&A>` is not satisfied
   --> $DIR/multiple-def-uses-in-one-fn.rs:9:45
    |
 LL | fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) {
-   |                                             ^^^^^^^^^^^^^^^^^^ the trait `From<&A>` is not implemented for `&'static B`, which is required by `&A: Into<&'static B>`
+   |                                             ^^^^^^^^^^^^^^^^^^ the trait `From<&A>` is not implemented for `&'static B`
    |
    = note: required for `&A` to implement `Into<&'static B>`
 help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
diff --git a/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr b/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr
index 913a35eb9fb..e4de9245951 100644
--- a/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr
+++ b/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `T: Trait` is not satisfied
   --> $DIR/underconstrained_generic.rs:22:5
    |
 LL |     ()
-   |     ^^ the trait `Trait` is not implemented for `T`, which is required by `(): ProofForConversion<T>`
+   |     ^^ the trait `Trait` is not implemented for `T`
    |
 note: required for `()` to implement `ProofForConversion<T>`
   --> $DIR/underconstrained_generic.rs:13:16
diff --git a/tests/ui/type-alias-impl-trait/variance.rs b/tests/ui/type-alias-impl-trait/variance.rs
index 113f6a4cc44..40e8ec0129a 100644
--- a/tests/ui/type-alias-impl-trait/variance.rs
+++ b/tests/ui/type-alias-impl-trait/variance.rs
@@ -11,11 +11,11 @@ type NotCapturedEarly<'a> = impl Sized; //~ ['a: *, 'a: o]
 type CapturedEarly<'a> = impl Sized + Captures<'a>; //~ ['a: *, 'a: o]
 //~^ ERROR: unconstrained opaque type
 
-type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>; //~ ['a: *, 'b: o, 'a: o]
+type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>; //~ ['a: *, 'a: o, 'b: o]
 //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
 //~| ERROR: unconstrained opaque type
 
-type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>; //~ ['a: *, 'b: o, 'a: o]
+type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>; //~ ['a: *, 'a: o, 'b: o]
 //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
 //~| ERROR: unconstrained opaque type
 
@@ -31,24 +31,24 @@ trait Foo<'i> {
 }
 
 impl<'i> Foo<'i> for &'i () {
-    type ImplicitCapture<'a> = impl Sized; //~ ['i: *, 'a: *, 'a: o, 'i: o]
+    type ImplicitCapture<'a> = impl Sized; //~ ['i: *, 'a: *, 'i: o, 'a: o]
     //~^ ERROR: unconstrained opaque type
 
-    type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ ['i: *, 'a: *, 'a: o, 'i: o]
+    type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ ['i: *, 'a: *, 'i: o, 'a: o]
     //~^ ERROR: unconstrained opaque type
 
-    type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ ['i: *, 'a: *, 'a: o, 'i: o]
+    type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ ['i: *, 'a: *, 'i: o, 'a: o]
     //~^ ERROR: unconstrained opaque type
 }
 
 impl<'i> Foo<'i> for () {
-    type ImplicitCapture<'a> = impl Sized; //~ ['i: *, 'a: *, 'a: o, 'i: o]
+    type ImplicitCapture<'a> = impl Sized; //~ ['i: *, 'a: *, 'i: o, 'a: o]
     //~^ ERROR: unconstrained opaque type
 
-    type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ ['i: *, 'a: *, 'a: o, 'i: o]
+    type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ ['i: *, 'a: *, 'i: o, 'a: o]
     //~^ ERROR: unconstrained opaque type
 
-    type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ ['i: *, 'a: *, 'a: o, 'i: o]
+    type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ ['i: *, 'a: *, 'i: o, 'a: o]
     //~^ ERROR: unconstrained opaque type
 }
 
diff --git a/tests/ui/type-alias-impl-trait/variance.stderr b/tests/ui/type-alias-impl-trait/variance.stderr
index 489dfe03d44..79ce8148f19 100644
--- a/tests/ui/type-alias-impl-trait/variance.stderr
+++ b/tests/ui/type-alias-impl-trait/variance.stderr
@@ -122,13 +122,13 @@ error: ['a: *, 'a: o]
 LL | type CapturedEarly<'a> = impl Sized + Captures<'a>;
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: ['a: *, 'b: o, 'a: o]
+error: ['a: *, 'a: o, 'b: o]
   --> $DIR/variance.rs:14:56
    |
 LL | type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>;
    |                                                        ^^^^^^^^^^
 
-error: ['a: *, 'b: o, 'a: o]
+error: ['a: *, 'a: o, 'b: o]
   --> $DIR/variance.rs:18:49
    |
 LL | type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>;
@@ -140,37 +140,37 @@ error: ['a: *, 'b: *, T: o, 'a: o, 'b: o]
 LL | type Bar<'a, 'b: 'b, T> = impl Sized;
    |                           ^^^^^^^^^^
 
-error: ['i: *, 'a: *, 'a: o, 'i: o]
+error: ['i: *, 'a: *, 'i: o, 'a: o]
   --> $DIR/variance.rs:34:32
    |
 LL |     type ImplicitCapture<'a> = impl Sized;
    |                                ^^^^^^^^^^
 
-error: ['i: *, 'a: *, 'a: o, 'i: o]
+error: ['i: *, 'a: *, 'i: o, 'a: o]
   --> $DIR/variance.rs:37:42
    |
 LL |     type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>;
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: ['i: *, 'a: *, 'a: o, 'i: o]
+error: ['i: *, 'a: *, 'i: o, 'a: o]
   --> $DIR/variance.rs:40:39
    |
 LL |     type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>;
    |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: ['i: *, 'a: *, 'a: o, 'i: o]
+error: ['i: *, 'a: *, 'i: o, 'a: o]
   --> $DIR/variance.rs:45:32
    |
 LL |     type ImplicitCapture<'a> = impl Sized;
    |                                ^^^^^^^^^^
 
-error: ['i: *, 'a: *, 'a: o, 'i: o]
+error: ['i: *, 'a: *, 'i: o, 'a: o]
   --> $DIR/variance.rs:48:42
    |
 LL |     type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>;
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: ['i: *, 'a: *, 'a: o, 'i: o]
+error: ['i: *, 'a: *, 'i: o, 'a: o]
   --> $DIR/variance.rs:51:39
    |
 LL |     type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>;
diff --git a/tests/ui/type/issue-58355.stderr b/tests/ui/type/issue-58355.stderr
index cd8e3538802..b6056f0fd65 100644
--- a/tests/ui/type/issue-58355.stderr
+++ b/tests/ui/type/issue-58355.stderr
@@ -4,7 +4,7 @@ error[E0277]: the size for values of type `dyn ToString` cannot be known at comp
 LL |     x = Some(Box::new(callback));
    |              ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = help: within `fn() -> dyn ToString`, the trait `Sized` is not implemented for `dyn ToString`, which is required by `fn() -> dyn ToString: Fn()`
+   = help: within `fn() -> dyn ToString`, the trait `Sized` is not implemented for `dyn ToString`
    = note: required because it appears within the type `fn() -> dyn ToString`
    = note: required for the cast from `Box<fn() -> dyn ToString>` to `Box<dyn Fn() -> (dyn ToString + 'static)>`
 
diff --git a/tests/ui/type/pattern_types/range_patterns.stderr b/tests/ui/type/pattern_types/range_patterns.stderr
index 8465e1b7ff2..7bd0d826cab 100644
--- a/tests/ui/type/pattern_types/range_patterns.stderr
+++ b/tests/ui/type/pattern_types/range_patterns.stderr
@@ -124,7 +124,7 @@ error: layout_of(Option<(u32) is 1..=>) = Layout {
                            abi: Align(1 bytes),
                            pref: $SOME_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
@@ -232,7 +232,7 @@ error: layout_of(Option<NonZero<u32>>) = Layout {
                            abi: Align(1 bytes),
                            pref: $SOME_ALIGN,
                        },
-                       abi: Aggregate {
+                       abi: Memory {
                            sized: true,
                        },
                        fields: Arbitrary {
diff --git a/tests/ui/typeck/bad-index-due-to-nested.stderr b/tests/ui/typeck/bad-index-due-to-nested.stderr
index 137c7b06396..bd7fd0392c3 100644
--- a/tests/ui/typeck/bad-index-due-to-nested.stderr
+++ b/tests/ui/typeck/bad-index-due-to-nested.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `K: Hash` is not satisfied
   --> $DIR/bad-index-due-to-nested.rs:20:5
    |
 LL |     map[k]
-   |     ^^^ the trait `Hash` is not implemented for `K`, which is required by `HashMap<_, _>: Index<&_>`
+   |     ^^^ the trait `Hash` is not implemented for `K`
    |
 note: required for `HashMap<K, V>` to implement `Index<&K>`
   --> $DIR/bad-index-due-to-nested.rs:7:12
@@ -21,7 +21,7 @@ error[E0277]: the trait bound `V: Copy` is not satisfied
   --> $DIR/bad-index-due-to-nested.rs:20:5
    |
 LL |     map[k]
-   |     ^^^ the trait `Copy` is not implemented for `V`, which is required by `HashMap<_, _>: Index<&_>`
+   |     ^^^ the trait `Copy` is not implemented for `V`
    |
 note: required for `HashMap<K, V>` to implement `Index<&K>`
   --> $DIR/bad-index-due-to-nested.rs:7:12
diff --git a/tests/ui/typeck/issue-90101.stderr b/tests/ui/typeck/issue-90101.stderr
index 796e904a438..2e140461c1d 100644
--- a/tests/ui/typeck/issue-90101.stderr
+++ b/tests/ui/typeck/issue-90101.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `PathBuf: From<Cow<'_, str>>` is not satisfied
   --> $DIR/issue-90101.rs:6:10
    |
 LL |     func(Path::new("hello").to_path_buf().to_string_lossy(), "world")
-   |     ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<Cow<'_, str>>` is not implemented for `PathBuf`, which is required by `Cow<'_, str>: Into<PathBuf>`
+   |     ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<Cow<'_, str>>` is not implemented for `PathBuf`
    |     |
    |     required by a bound introduced by this call
    |
diff --git a/tests/ui/typeck/suggest-similar-impls-for-root-obligation.stderr b/tests/ui/typeck/suggest-similar-impls-for-root-obligation.stderr
index 8410574e311..ab307aadec9 100644
--- a/tests/ui/typeck/suggest-similar-impls-for-root-obligation.stderr
+++ b/tests/ui/typeck/suggest-similar-impls-for-root-obligation.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `((),): Into<Bar>` is not satisfied
   --> $DIR/suggest-similar-impls-for-root-obligation.rs:14:24
    |
 LL |     let _: Bar = ((),).into();
-   |                        ^^^^ the trait `Foo<'_>` is not implemented for `((),)`, which is required by `((),): Into<_>`
+   |                        ^^^^ the trait `Foo<'_>` is not implemented for `((),)`
    |
    = help: the trait `Foo<'_>` is implemented for `()`
    = help: for that trait implementation, expected `()`, found `((),)`
diff --git a/tests/ui/typeck/typeck-default-trait-impl-negation-sync.stderr b/tests/ui/typeck/typeck-default-trait-impl-negation-sync.stderr
index f5311b6e8ed..b9fca1a1b54 100644
--- a/tests/ui/typeck/typeck-default-trait-impl-negation-sync.stderr
+++ b/tests/ui/typeck/typeck-default-trait-impl-negation-sync.stderr
@@ -17,7 +17,7 @@ error[E0277]: `UnsafeCell<u8>` cannot be shared between threads safely
 LL |     is_sync::<MyTypeWUnsafe>();
    |               ^^^^^^^^^^^^^ `UnsafeCell<u8>` cannot be shared between threads safely
    |
-   = help: within `MyTypeWUnsafe`, the trait `Sync` is not implemented for `UnsafeCell<u8>`, which is required by `MyTypeWUnsafe: Sync`
+   = help: within `MyTypeWUnsafe`, the trait `Sync` is not implemented for `UnsafeCell<u8>`
 note: required because it appears within the type `MyTypeWUnsafe`
   --> $DIR/typeck-default-trait-impl-negation-sync.rs:21:8
    |
@@ -35,7 +35,7 @@ error[E0277]: `Managed` cannot be shared between threads safely
 LL |     is_sync::<MyTypeManaged>();
    |               ^^^^^^^^^^^^^ `Managed` cannot be shared between threads safely
    |
-   = help: within `MyTypeManaged`, the trait `Sync` is not implemented for `Managed`, which is required by `MyTypeManaged: Sync`
+   = help: within `MyTypeManaged`, the trait `Sync` is not implemented for `Managed`
 note: required because it appears within the type `MyTypeManaged`
   --> $DIR/typeck-default-trait-impl-negation-sync.rs:25:8
    |
diff --git a/tests/ui/typeck/typeck-unsafe-always-share.stderr b/tests/ui/typeck/typeck-unsafe-always-share.stderr
index 3eb792b82e0..154e504996b 100644
--- a/tests/ui/typeck/typeck-unsafe-always-share.stderr
+++ b/tests/ui/typeck/typeck-unsafe-always-share.stderr
@@ -36,7 +36,7 @@ LL |     test(ms);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: within `MySync<NoSync>`, the trait `Sync` is not implemented for `UnsafeCell<NoSync>`, which is required by `MySync<NoSync>: Sync`
+   = help: within `MySync<NoSync>`, the trait `Sync` is not implemented for `UnsafeCell<NoSync>`
 note: required because it appears within the type `MySync<NoSync>`
   --> $DIR/typeck-unsafe-always-share.rs:8:8
    |
diff --git a/tests/ui/underscore-ident-matcher.rs b/tests/ui/underscore-ident-matcher.rs
index bddc8c80a7b..77ec70d43d5 100644
--- a/tests/ui/underscore-ident-matcher.rs
+++ b/tests/ui/underscore-ident-matcher.rs
@@ -5,5 +5,5 @@ macro_rules! identity {
 }
 
 fn main() {
-    let identity!(_) = 10; //~ ERROR no rules expected the token `_`
+    let identity!(_) = 10; //~ ERROR no rules expected reserved identifier `_`
 }
diff --git a/tests/ui/underscore-ident-matcher.stderr b/tests/ui/underscore-ident-matcher.stderr
index a663f34cde1..0c3f980cf6c 100644
--- a/tests/ui/underscore-ident-matcher.stderr
+++ b/tests/ui/underscore-ident-matcher.stderr
@@ -1,4 +1,4 @@
-error: no rules expected the token `_`
+error: no rules expected reserved identifier `_`
   --> $DIR/underscore-ident-matcher.rs:8:19
    |
 LL | macro_rules! identity {
diff --git a/tests/ui/union/projection-as-union-type-error-2.stderr b/tests/ui/union/projection-as-union-type-error-2.stderr
index 39cdf30d860..3b073ca1fb4 100644
--- a/tests/ui/union/projection-as-union-type-error-2.stderr
+++ b/tests/ui/union/projection-as-union-type-error-2.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `u8: NotImplemented` is not satisfied
   --> $DIR/projection-as-union-type-error-2.rs:18:8
    |
 LL |     a: <Foo as Identity>::Identity,
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NotImplemented` is not implemented for `u8`, which is required by `u8: Identity`
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NotImplemented` is not implemented for `u8`
    |
 help: this trait has no implementations, consider adding one
   --> $DIR/projection-as-union-type-error-2.rs:9:1
diff --git a/tests/ui/unsized-locals/issue-50940-with-feature.stderr b/tests/ui/unsized-locals/issue-50940-with-feature.stderr
index 4c06566709e..b39eb2e70bb 100644
--- a/tests/ui/unsized-locals/issue-50940-with-feature.stderr
+++ b/tests/ui/unsized-locals/issue-50940-with-feature.stderr
@@ -13,7 +13,7 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t
 LL |     A as fn(str) -> A<str>;
    |     ^ doesn't have a size known at compile-time
    |
-   = help: within `A<str>`, the trait `Sized` is not implemented for `str`, which is required by `A<str>: Sized`
+   = help: within `A<str>`, the trait `Sized` is not implemented for `str`
 note: required because it appears within the type `A<str>`
   --> $DIR/issue-50940-with-feature.rs:5:12
    |
diff --git a/tests/ui/unsized-locals/rust-call.stderr b/tests/ui/unsized-locals/rust-call.stderr
index b2e13b553e9..9eb0f3dabcc 100644
--- a/tests/ui/unsized-locals/rust-call.stderr
+++ b/tests/ui/unsized-locals/rust-call.stderr
@@ -4,7 +4,7 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation
 LL |     f(*slice);
    |       ^^^^^^ doesn't have a size known at compile-time
    |
-   = help: within `([u8],)`, the trait `Sized` is not implemented for `[u8]`, which is required by `([u8],): Sized`
+   = help: within `([u8],)`, the trait `Sized` is not implemented for `[u8]`
    = note: required because it appears within the type `([u8],)`
    = note: argument required to be sized due to `extern "rust-call"` ABI
 
diff --git a/tests/ui/unsized-locals/unsized-exprs.stderr b/tests/ui/unsized-locals/unsized-exprs.stderr
index 6da37749fac..8a2ecf0f6c3 100644
--- a/tests/ui/unsized-locals/unsized-exprs.stderr
+++ b/tests/ui/unsized-locals/unsized-exprs.stderr
@@ -4,7 +4,7 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation
 LL |     udrop::<(i32, [u8])>((42, *foo()));
    |                          ^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = help: within `({integer}, [u8])`, the trait `Sized` is not implemented for `[u8]`, which is required by `({integer}, [u8]): Sized`
+   = help: within `({integer}, [u8])`, the trait `Sized` is not implemented for `[u8]`
    = note: required because it appears within the type `({integer}, [u8])`
    = note: tuples must have a statically known size to be initialized
 
@@ -14,7 +14,7 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation
 LL |     udrop::<A<[u8]>>(A { 0: *foo() });
    |                      ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = help: within `A<[u8]>`, the trait `Sized` is not implemented for `[u8]`, which is required by `A<[u8]>: Sized`
+   = help: within `A<[u8]>`, the trait `Sized` is not implemented for `[u8]`
 note: required because it appears within the type `A<[u8]>`
   --> $DIR/unsized-exprs.rs:3:8
    |
@@ -28,7 +28,7 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation
 LL |     udrop::<A<[u8]>>(A(*foo()));
    |                      ^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = help: within `A<[u8]>`, the trait `Sized` is not implemented for `[u8]`, which is required by `A<[u8]>: Sized`
+   = help: within `A<[u8]>`, the trait `Sized` is not implemented for `[u8]`
 note: required because it appears within the type `A<[u8]>`
   --> $DIR/unsized-exprs.rs:3:8
    |
diff --git a/tests/ui/unsized/unsized-enum2.stderr b/tests/ui/unsized/unsized-enum2.stderr
index 48cca6eb4bd..71cf782120e 100644
--- a/tests/ui/unsized/unsized-enum2.stderr
+++ b/tests/ui/unsized/unsized-enum2.stderr
@@ -320,7 +320,7 @@ error[E0277]: the size for values of type `(dyn PathHelper1 + 'static)` cannot b
 LL |     VI(Path1),
    |        ^^^^^ doesn't have a size known at compile-time
    |
-   = help: within `Path1`, the trait `Sized` is not implemented for `(dyn PathHelper1 + 'static)`, which is required by `Path1: Sized`
+   = help: within `Path1`, the trait `Sized` is not implemented for `(dyn PathHelper1 + 'static)`
 note: required because it appears within the type `Path1`
   --> $DIR/unsized-enum2.rs:16:8
    |
@@ -343,7 +343,7 @@ error[E0277]: the size for values of type `(dyn PathHelper2 + 'static)` cannot b
 LL |     VJ{x: Path2},
    |           ^^^^^ doesn't have a size known at compile-time
    |
-   = help: within `Path2`, the trait `Sized` is not implemented for `(dyn PathHelper2 + 'static)`, which is required by `Path2: Sized`
+   = help: within `Path2`, the trait `Sized` is not implemented for `(dyn PathHelper2 + 'static)`
 note: required because it appears within the type `Path2`
   --> $DIR/unsized-enum2.rs:17:8
    |
@@ -366,7 +366,7 @@ error[E0277]: the size for values of type `(dyn PathHelper3 + 'static)` cannot b
 LL |     VK(isize, Path3),
    |               ^^^^^ doesn't have a size known at compile-time
    |
-   = help: within `Path3`, the trait `Sized` is not implemented for `(dyn PathHelper3 + 'static)`, which is required by `Path3: Sized`
+   = help: within `Path3`, the trait `Sized` is not implemented for `(dyn PathHelper3 + 'static)`
 note: required because it appears within the type `Path3`
   --> $DIR/unsized-enum2.rs:18:8
    |
@@ -389,7 +389,7 @@ error[E0277]: the size for values of type `(dyn PathHelper4 + 'static)` cannot b
 LL |     VL{u: isize, x: Path4},
    |                     ^^^^^ doesn't have a size known at compile-time
    |
-   = help: within `Path4`, the trait `Sized` is not implemented for `(dyn PathHelper4 + 'static)`, which is required by `Path4: Sized`
+   = help: within `Path4`, the trait `Sized` is not implemented for `(dyn PathHelper4 + 'static)`
 note: required because it appears within the type `Path4`
   --> $DIR/unsized-enum2.rs:19:8
    |
diff --git a/tests/ui/utf8-bom.rs b/tests/ui/utf8-bom.rs
index 5b9e27fb7b9..eb82f6652cb 100644
--- a/tests/ui/utf8-bom.rs
+++ b/tests/ui/utf8-bom.rs
@@ -1,4 +1,5 @@
 // This file has utf-8 BOM, it should be compiled normally without error.
 //@ run-pass
+//@ reference: input.byte-order-mark
 
 pub fn main() {}
diff --git a/tests/ui/wf/hir-wf-check-erase-regions.stderr b/tests/ui/wf/hir-wf-check-erase-regions.stderr
index 93449d60e9d..4b696dc1d1d 100644
--- a/tests/ui/wf/hir-wf-check-erase-regions.stderr
+++ b/tests/ui/wf/hir-wf-check-erase-regions.stderr
@@ -4,7 +4,7 @@ error[E0277]: `&'a T` is not an iterator
 LL |     type IntoIter = std::iter::Flatten<std::slice::Iter<'a, T>>;
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&'a T` is not an iterator
    |
-   = help: the trait `Iterator` is not implemented for `&'a T`, which is required by `Flatten<std::slice::Iter<'a, T>>: Iterator`
+   = help: the trait `Iterator` is not implemented for `&'a T`
    = help: the trait `Iterator` is implemented for `&mut I`
    = note: required for `Flatten<std::slice::Iter<'a, T>>` to implement `Iterator`
 note: required by a bound in `std::iter::IntoIterator::IntoIter`
@@ -16,7 +16,7 @@ error[E0277]: `&'a T` is not an iterator
 LL |     type IntoIter = std::iter::Flatten<std::slice::Iter<'a, T>>;
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&'a T` is not an iterator
    |
-   = help: the trait `Iterator` is not implemented for `&'a T`, which is required by `&'a T: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `&'a T`
    = help: the trait `Iterator` is implemented for `&mut I`
    = note: required for `&'a T` to implement `IntoIterator`
 note: required by a bound in `Flatten`
@@ -28,7 +28,7 @@ error[E0277]: `&'a T` is not an iterator
 LL |     fn into_iter(self) -> Self::IntoIter {
    |                           ^^^^^^^^^^^^^^ `&'a T` is not an iterator
    |
-   = help: the trait `Iterator` is not implemented for `&'a T`, which is required by `&'a T: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `&'a T`
    = help: the trait `Iterator` is implemented for `&mut I`
    = note: required for `&'a T` to implement `IntoIterator`
 note: required by a bound in `Flatten`
diff --git a/tests/ui/wf/wf-const-type.stderr b/tests/ui/wf/wf-const-type.stderr
index d73642729ea..dd6e97755bd 100644
--- a/tests/ui/wf/wf-const-type.stderr
+++ b/tests/ui/wf/wf-const-type.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `NotCopy: Copy` is not satisfied
   --> $DIR/wf-const-type.rs:10:12
    |
 LL | const FOO: IsCopy<Option<NotCopy>> = IsCopy { t: None };
-   |            ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopy`, which is required by `Option<NotCopy>: Copy`
+   |            ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopy`
    |
    = note: required for `Option<NotCopy>` to implement `Copy`
 note: required by a bound in `IsCopy`
@@ -20,7 +20,7 @@ error[E0277]: the trait bound `NotCopy: Copy` is not satisfied
   --> $DIR/wf-const-type.rs:10:12
    |
 LL | const FOO: IsCopy<Option<NotCopy>> = IsCopy { t: None };
-   |            ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopy`, which is required by `Option<NotCopy>: Copy`
+   |            ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopy`
    |
    = note: required for `Option<NotCopy>` to implement `Copy`
 note: required by a bound in `IsCopy`
@@ -39,7 +39,7 @@ error[E0277]: the trait bound `NotCopy: Copy` is not satisfied
   --> $DIR/wf-const-type.rs:10:50
    |
 LL | const FOO: IsCopy<Option<NotCopy>> = IsCopy { t: None };
-   |                                                  ^^^^ the trait `Copy` is not implemented for `NotCopy`, which is required by `Option<NotCopy>: Copy`
+   |                                                  ^^^^ the trait `Copy` is not implemented for `NotCopy`
    |
    = note: required for `Option<NotCopy>` to implement `Copy`
 note: required by a bound in `IsCopy`
diff --git a/tests/ui/wf/wf-static-type.stderr b/tests/ui/wf/wf-static-type.stderr
index 36234f3fd17..53b90c69960 100644
--- a/tests/ui/wf/wf-static-type.stderr
+++ b/tests/ui/wf/wf-static-type.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `NotCopy: Copy` is not satisfied
   --> $DIR/wf-static-type.rs:10:13
    |
 LL | static FOO: IsCopy<Option<NotCopy>> = IsCopy { t: None };
-   |             ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopy`, which is required by `Option<NotCopy>: Copy`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopy`
    |
    = note: required for `Option<NotCopy>` to implement `Copy`
 note: required by a bound in `IsCopy`
@@ -20,7 +20,7 @@ error[E0277]: the trait bound `NotCopy: Copy` is not satisfied
   --> $DIR/wf-static-type.rs:10:13
    |
 LL | static FOO: IsCopy<Option<NotCopy>> = IsCopy { t: None };
-   |             ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopy`, which is required by `Option<NotCopy>: Copy`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopy`
    |
    = note: required for `Option<NotCopy>` to implement `Copy`
 note: required by a bound in `IsCopy`
@@ -39,7 +39,7 @@ error[E0277]: the trait bound `NotCopy: Copy` is not satisfied
   --> $DIR/wf-static-type.rs:10:51
    |
 LL | static FOO: IsCopy<Option<NotCopy>> = IsCopy { t: None };
-   |                                                   ^^^^ the trait `Copy` is not implemented for `NotCopy`, which is required by `Option<NotCopy>: Copy`
+   |                                                   ^^^^ the trait `Copy` is not implemented for `NotCopy`
    |
    = note: required for `Option<NotCopy>` to implement `Copy`
 note: required by a bound in `IsCopy`
diff --git a/triagebot.toml b/triagebot.toml
index 2e8851e7ec2..7f4def6a11b 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -725,9 +725,6 @@ please modify the tool then regenerate the library source file with the tool
 instead of editing the library source file manually.
 """
 
-[mentions."src/librustdoc/clean/types.rs"]
-cc = ["@camelid"]
-
 [mentions."src/librustdoc/html/static"]
 message = "Some changes occurred in HTML/CSS/JS."
 cc = [
@@ -938,9 +935,6 @@ cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"]
 [mentions."tests/ui/stack-protector"]
 cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"]
 
-[mentions."tests/ui/check-cfg"]
-cc = ["@Urgau"]
-
 [mentions."compiler/rustc_middle/src/mir/coverage.rs"]
 message = "Some changes occurred in coverage instrumentation."
 cc = ["@Zalathar"]
@@ -972,7 +966,6 @@ cc = ["@kobzol"]
 warn_non_default_branch = true
 contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
 users_on_vacation = [
-    "BoxyUwU",
     "fmease",
     "jyn514",
     "oli-obk",