about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-05-11 07:00:13 +0000
committerbors <bors@rust-lang.org>2024-05-11 07:00:13 +0000
commit2427bf911371d9e945d5658b9fc03e65b89ecf63 (patch)
tree5969d2bffb75a23fa9e0f495de79cb0643af5979
parent6f4c7d997e55d9b7786c59823653d03464f8148d (diff)
parentce3daac283849eb600a294b9e5b4c384600c5b54 (diff)
downloadrust-2427bf911371d9e945d5658b9fc03e65b89ecf63.tar.gz
rust-2427bf911371d9e945d5658b9fc03e65b89ecf63.zip
Auto merge of #3597 - rust-lang:rustup-2024-05-11, r=RalfJung
Automatic Rustup
-rw-r--r--.github/workflows/ci.yml10
-rw-r--r--Cargo.lock30
-rw-r--r--compiler/rustc_abi/src/layout.rs7
-rw-r--r--compiler/rustc_abi/src/lib.rs54
-rw-r--r--compiler/rustc_ast/src/ast.rs19
-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/tokenstream.rs2
-rw-r--r--compiler/rustc_ast/src/visit.rs4
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs8
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs6
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs3
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs15
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/item.rs4
-rw-r--r--compiler/rustc_borrowck/src/consumers.rs4
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs3
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs55
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs7
-rw-r--r--compiler/rustc_borrowck/src/lib.rs62
-rw-r--r--compiler/rustc_borrowck/src/nll.rs8
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs32
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs2
-rw-r--r--compiler/rustc_borrowck/src/renumber.rs8
-rw-r--r--compiler/rustc_borrowck/src/type_check/input_output.rs5
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs42
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs123
-rw-r--r--compiler/rustc_borrowck/src/type_check/relate_tys.rs6
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs6
-rw-r--r--compiler/rustc_builtin_macros/src/assert/context.rs11
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs5
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/mod.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/format.rs11
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs7
-rw-r--r--compiler/rustc_codegen_cranelift/src/common.rs12
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs6
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/lib.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/num.rs10
-rw-r--r--compiler/rustc_codegen_cranelift/src/unsize.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/value_and_place.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/vtable.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/builder.rs13
-rw-r--r--compiler/rustc_codegen_gcc/src/debuginfo.rs3
-rw-r--r--compiler/rustc_codegen_gcc/src/type_of.rs13
-rw-r--r--compiler/rustc_codegen_llvm/src/abi.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/asm.rs22
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs9
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs5
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/mod.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs16
-rw-r--r--compiler/rustc_codegen_llvm/src/type_of.rs7
-rw-r--r--compiler/rustc_codegen_ssa/Cargo.toml2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs8
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs10
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/debuginfo.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/operand.rs36
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs97
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/type_.rs12
-rw-r--r--compiler/rustc_const_eval/messages.ftl15
-rw-r--r--compiler/rustc_const_eval/src/const_eval/error.rs12
-rw-r--r--compiler/rustc_const_eval/src/const_eval/eval_queries.rs10
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs35
-rw-r--r--compiler/rustc_const_eval/src/interpret/operator.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/place.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/terminator.rs15
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/ops.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs4
-rw-r--r--compiler/rustc_const_eval/src/util/check_validity_requirement.rs2
-rw-r--r--compiler/rustc_data_structures/src/fingerprint.rs1
-rw-r--r--compiler/rustc_data_structures/src/flock/windows.rs1
-rw-r--r--compiler/rustc_data_structures/src/graph/implementation/mod.rs1
-rw-r--r--compiler/rustc_data_structures/src/graph/implementation/tests.rs1
-rw-r--r--compiler/rustc_data_structures/src/graph/scc/mod.rs1
-rw-r--r--compiler/rustc_data_structures/src/lib.rs63
-rw-r--r--compiler/rustc_data_structures/src/macros.rs37
-rw-r--r--compiler/rustc_data_structures/src/obligation_forest/mod.rs2
-rw-r--r--compiler/rustc_data_structures/src/packed.rs4
-rw-r--r--compiler/rustc_data_structures/src/profiling.rs1
-rw-r--r--compiler/rustc_data_structures/src/stable_hasher.rs2
-rw-r--r--compiler/rustc_data_structures/src/tiny_list.rs80
-rw-r--r--compiler/rustc_data_structures/src/tiny_list/tests.rs155
-rw-r--r--compiler/rustc_data_structures/src/vec_linked_list.rs70
-rw-r--r--compiler/rustc_driver_impl/Cargo.toml2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0579.md1
-rw-r--r--compiler/rustc_errors/src/diagnostic_impls.rs6
-rw-r--r--compiler/rustc_expand/Cargo.toml1
-rw-r--r--compiler/rustc_expand/src/expand.rs4
-rw-r--r--compiler/rustc_expand/src/lib.rs20
-rw-r--r--compiler/rustc_expand/src/parse/tests.rs382
-rw-r--r--compiler/rustc_expand/src/placeholders.rs5
-rw-r--r--compiler/rustc_feature/src/accepted.rs2
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs2
-rw-r--r--compiler/rustc_feature/src/unstable.rs5
-rw-r--r--compiler/rustc_hir/src/hir.rs10
-rw-r--r--compiler/rustc_hir/src/intravisit.rs2
-rw-r--r--compiler/rustc_hir/src/lang_items.rs32
-rw-r--r--compiler/rustc_hir_analysis/src/autoderef.rs41
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs49
-rw-r--r--compiler/rustc_hir_analysis/src/check/dropck.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs30
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/orphan.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/unsafety.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs43
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs7
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/hir_wf_check.rs14
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/variance/mod.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/variance/solve.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/_match.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs27
-rw-r--r--compiler/rustc_hir_typeck/src/check.rs20
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs88
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs170
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs13
-rw-r--r--compiler/rustc_hir_typeck/src/expectation.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs55
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs27
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs35
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs23
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs123
-rw-r--r--compiler/rustc_hir_typeck/src/gather_locals.rs15
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/mem_categorization.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/method/confirm.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/method/mod.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/method/prelude2021.rs40
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs11
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs45
-rw-r--r--compiler/rustc_hir_typeck/src/op.rs11
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs30
-rw-r--r--compiler/rustc_hir_typeck/src/place_op.rs15
-rw-r--r--compiler/rustc_infer/src/errors/note_and_explain.rs10
-rw-r--r--compiler/rustc_infer/src/infer/canonical/mod.rs20
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs131
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs29
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs6
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs6
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs4
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs5
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note.rs10
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs3
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/suggest.rs2
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs84
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types/mod.rs16
-rw-r--r--compiler/rustc_infer/src/infer/outlives/obligations.rs4
-rw-r--r--compiler/rustc_infer/src/infer/projection.rs6
-rw-r--r--compiler/rustc_infer/src/infer/relate/generalize.rs56
-rw-r--r--compiler/rustc_infer/src/infer/relate/lattice.rs7
-rw-r--r--compiler/rustc_infer/src/infer/snapshot/fudge.rs4
-rw-r--r--compiler/rustc_infer/src/traits/mod.rs18
-rw-r--r--compiler/rustc_infer/src/traits/structural_impls.rs8
-rw-r--r--compiler/rustc_infer/src/traits/util.rs4
-rw-r--r--compiler/rustc_interface/Cargo.toml1
-rw-r--r--compiler/rustc_interface/src/interface.rs51
-rw-r--r--compiler/rustc_lint/src/builtin.rs11
-rw-r--r--compiler/rustc_lint/src/context.rs2
-rw-r--r--compiler/rustc_lint/src/context/diagnostics/check_cfg.rs8
-rw-r--r--compiler/rustc_lint/src/for_loops_over_fallibles.rs11
-rw-r--r--compiler/rustc_lint/src/non_local_def.rs3
-rw-r--r--compiler/rustc_lint/src/reference_casting.rs8
-rw-r--r--compiler/rustc_lint/src/types.rs69
-rw-r--r--compiler/rustc_lint/src/unused.rs4
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs1
-rw-r--r--compiler/rustc_llvm/Cargo.toml2
-rw-r--r--compiler/rustc_macros/src/lift.rs2
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs2
-rw-r--r--compiler/rustc_middle/src/macros.rs2
-rw-r--r--compiler/rustc_middle/src/mir/interpret/mod.rs17
-rw-r--r--compiler/rustc_middle/src/mir/tcx.rs10
-rw-r--r--compiler/rustc_middle/src/thir.rs17
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs71
-rw-r--r--compiler/rustc_middle/src/traits/solve/inspect.rs2
-rw-r--r--compiler/rustc_middle/src/traits/solve/inspect/format.rs3
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs16
-rw-r--r--compiler/rustc_middle/src/ty/context.rs53
-rw-r--r--compiler/rustc_middle/src/ty/generic_args.rs16
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs30
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs45
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs8
-rw-r--r--compiler/rustc_middle/src/ty/normalize_erasing_regions.rs23
-rw-r--r--compiler/rustc_middle/src/ty/predicate.rs88
-rw-r--r--compiler/rustc_middle/src/ty/print/mod.rs23
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs19
-rw-r--r--compiler/rustc_middle/src/ty/region.rs4
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs10
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs16
-rw-r--r--compiler/rustc_middle/src/ty/util.rs7
-rw-r--r--compiler/rustc_middle/src/values.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/coverageinfo.rs26
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs47
-rw-r--r--compiler/rustc_mir_build/src/build/matches/test.rs21
-rw-r--r--compiler/rustc_mir_build/src/build/matches/util.rs10
-rw-r--r--compiler/rustc_mir_transform/src/check_alignment.rs2
-rw-r--r--compiler/rustc_mir_transform/src/coverage/mappings.rs281
-rw-r--r--compiler/rustc_mir_transform/src/coverage/mod.rs159
-rw-r--r--compiler/rustc_mir_transform/src/coverage/spans.rs8
-rw-r--r--compiler/rustc_mir_transform/src/dataflow_const_prop.rs2
-rw-r--r--compiler/rustc_mir_transform/src/gvn.rs6
-rw-r--r--compiler/rustc_mir_transform/src/large_enums.rs2
-rw-r--r--compiler/rustc_mir_transform/src/mentioned_items.rs4
-rw-r--r--compiler/rustc_mir_transform/src/normalize_array_len.rs4
-rw-r--r--compiler/rustc_monomorphize/src/lib.rs5
-rw-r--r--compiler/rustc_monomorphize/src/polymorphize.rs6
-rw-r--r--compiler/rustc_next_trait_solver/src/canonicalizer.rs8
-rw-r--r--compiler/rustc_parse/Cargo.toml4
-rw-r--r--compiler/rustc_parse/messages.ftl6
-rw-r--r--compiler/rustc_parse/src/errors.rs14
-rw-r--r--compiler/rustc_parse/src/lexer/diagnostics.rs8
-rw-r--r--compiler/rustc_parse/src/lexer/mod.rs2
-rw-r--r--compiler/rustc_parse/src/lexer/unicode_chars.rs2
-rw-r--r--compiler/rustc_parse/src/lib.rs1
-rw-r--r--compiler/rustc_parse/src/parser/attr.rs56
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs49
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs40
-rw-r--r--compiler/rustc_parse/src/parser/item.rs32
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs98
-rw-r--r--compiler/rustc_parse/src/parser/mut_visit/tests.rs (renamed from compiler/rustc_expand/src/mut_visit/tests.rs)3
-rw-r--r--compiler/rustc_parse/src/parser/path.rs19
-rw-r--r--compiler/rustc_parse/src/parser/stmt.rs8
-rw-r--r--compiler/rustc_parse/src/parser/tests.rs (renamed from compiler/rustc_expand/src/tests.rs)401
-rw-r--r--compiler/rustc_parse/src/parser/tokenstream/tests.rs (renamed from compiler/rustc_expand/src/tokenstream/tests.rs)3
-rw-r--r--compiler/rustc_passes/messages.ftl10
-rw-r--r--compiler/rustc_passes/src/errors.rs10
-rw-r--r--compiler/rustc_passes/src/loops.rs32
-rw-r--r--compiler/rustc_passes/src/reachable.rs32
-rw-r--r--compiler/rustc_pattern_analysis/src/usefulness.rs1
-rw-r--r--compiler/rustc_privacy/src/lib.rs5
-rw-r--r--compiler/rustc_query_impl/src/plumbing.rs6
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs2
-rw-r--r--compiler/rustc_resolve/src/check_unused.rs70
-rw-r--r--compiler/rustc_resolve/src/late.rs6
-rw-r--r--compiler/rustc_session/src/config/cfg.rs8
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/abi.rs20
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/ty.rs2
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs3
-rw-r--r--compiler/rustc_target/src/abi/call/loongarch.rs2
-rw-r--r--compiler/rustc_target/src/abi/call/mips64.rs6
-rw-r--r--compiler/rustc_target/src/abi/call/mod.rs2
-rw-r--r--compiler/rustc_target/src/abi/call/riscv.rs2
-rw-r--r--compiler/rustc_target/src/abi/call/sparc64.rs10
-rw-r--r--compiler/rustc_target/src/abi/call/x86_64.rs2
-rw-r--r--compiler/rustc_target/src/abi/mod.rs6
-rw-r--r--compiler/rustc_target/src/lib.rs9
-rw-r--r--compiler/rustc_target/src/spec/base/windows_gnu.rs3
-rw-r--r--compiler/rustc_target/src/spec/mod.rs13
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_be_unknown_netbsd.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_illumos.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_netbsd.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_redox.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_uefi.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_uwp_windows_msvc.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs9
-rw-r--r--compiler/rustc_trait_selection/src/errors.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs22
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs31
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs98
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill.rs99
-rw-r--r--compiler/rustc_trait_selection/src/solve/inspect/analyse.rs99
-rw-r--r--compiler/rustc_trait_selection/src/solve/inspect/build.rs35
-rw-r--r--compiler/rustc_trait_selection/src/solve/normalize.rs10
-rw-r--r--compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs9
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals.rs11
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs147
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs119
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs71
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs36
-rw-r--r--compiler/rustc_trait_selection/src/traits/misc.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs62
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs52
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs13
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/mod.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/structural_normalize.rs5
-rw-r--r--compiler/rustc_trait_selection/src/traits/vtable.rs9
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs48
-rw-r--r--compiler/rustc_traits/src/type_op.rs4
-rw-r--r--compiler/rustc_ty_utils/src/assoc.rs10
-rw-r--r--compiler/rustc_ty_utils/src/implied_bounds.rs3
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs9
-rw-r--r--compiler/rustc_ty_utils/src/representability.rs2
-rw-r--r--compiler/rustc_type_ir/src/binder.rs7
-rw-r--r--compiler/rustc_type_ir/src/canonical.rs3
-rw-r--r--compiler/rustc_type_ir/src/inherent.rs85
-rw-r--r--compiler/rustc_type_ir/src/interner.rs87
-rw-r--r--compiler/rustc_type_ir/src/ir_print.rs28
-rw-r--r--compiler/rustc_type_ir/src/lib.rs8
-rw-r--r--compiler/rustc_type_ir/src/lift.rs21
-rw-r--r--compiler/rustc_type_ir/src/new.rs15
-rw-r--r--compiler/rustc_type_ir/src/trait_ref.rs109
-rw-r--r--compiler/rustc_type_ir/src/visit.rs3
-rw-r--r--compiler/stable_mir/src/abi.rs4
-rw-r--r--config.example.toml4
-rw-r--r--library/alloc/src/lib.rs2
-rw-r--r--library/alloc/src/str.rs10
-rw-r--r--library/alloc/tests/str.rs3
-rw-r--r--library/core/benches/str.rs1
-rw-r--r--library/core/benches/str/debug.rs79
-rw-r--r--library/core/src/iter/adapters/step_by.rs10
-rw-r--r--library/core/src/num/f128.rs195
-rw-r--r--library/core/src/num/f16.rs195
-rw-r--r--library/core/src/num/mod.rs12
-rw-r--r--library/core/src/num/nonzero.rs364
-rw-r--r--library/core/src/num/uint_macros.rs1
-rw-r--r--library/core/src/primitive_docs.rs12
-rw-r--r--library/core/src/ptr/mod.rs4
-rw-r--r--library/core/src/slice/mod.rs14
-rw-r--r--library/profiler_builtins/Cargo.toml2
-rw-r--r--library/std/src/fs.rs19
-rw-r--r--library/std/src/os/unix/net/listener.rs12
-rw-r--r--library/std/src/sys/pal/unix/alloc.rs8
-rw-r--r--library/std/src/sys/pal/unix/fd.rs11
-rw-r--r--library/std/src/sys/pal/unix/fs.rs18
-rw-r--r--library/std/src/sys/pal/unix/mod.rs4
-rw-r--r--library/std/src/sys/pal/unix/net.rs9
-rw-r--r--library/std/src/sys/pal/unix/thread_parking.rs4
-rw-r--r--library/std/src/sys/personality/dwarf/eh.rs9
-rw-r--r--library/std/src/sys/personality/gcc.rs5
-rw-r--r--library/std/tests/builtin-clone.rs (renamed from tests/ui/stdlib-unit-tests/builtin-clone.rs)22
-rw-r--r--library/std/tests/eq-multidispatch.rs51
-rw-r--r--library/std/tests/istr.rs (renamed from tests/ui/stdlib-unit-tests/istr.rs)19
-rw-r--r--library/std/tests/log-knows-the-names-of-variants-in-std.rs (renamed from tests/ui/stdlib-unit-tests/log-knows-the-names-of-variants-in-std.rs)10
-rw-r--r--library/std/tests/minmax-stability-issue-23687.rs (renamed from tests/ui/stdlib-unit-tests/minmax-stability-issue-23687.rs)9
-rw-r--r--library/std/tests/seq-compare.rs (renamed from tests/ui/stdlib-unit-tests/seq-compare.rs)5
-rw-r--r--library/std/tests/slice-from-array-issue-113238.rs (renamed from tests/ui/std/slice-from-array-issue-113238.rs)5
-rw-r--r--library/std/tests/type-name-unsized.rs (renamed from tests/ui/stdlib-unit-tests/issue-21058.rs)28
-rw-r--r--library/std/tests/volatile-fat-ptr.rs (renamed from tests/ui/stdlib-unit-tests/volatile-fat-ptr.rs)6
-rw-r--r--library/test/src/bench.rs23
-rw-r--r--library/test/src/formatters/json.rs4
-rw-r--r--library/unwind/src/libunwind.rs24
-rw-r--r--src/bootstrap/Cargo.lock4
-rw-r--r--src/bootstrap/Cargo.toml8
-rw-r--r--src/bootstrap/src/bin/rustc.rs13
-rw-r--r--src/bootstrap/src/core/build_steps/llvm.rs59
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs7
-rw-r--r--src/bootstrap/src/core/builder.rs17
-rw-r--r--src/bootstrap/src/core/builder/tests.rs110
-rw-r--r--src/bootstrap/src/core/config/config.rs4
-rw-r--r--src/bootstrap/src/core/sanity.rs2
-rw-r--r--src/bootstrap/src/lib.rs4
-rw-r--r--src/bootstrap/src/utils/change_tracker.rs5
-rw-r--r--src/bootstrap/src/utils/helpers.rs9
-rw-r--r--src/bootstrap/src/utils/render_tests.rs8
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh1
-rwxr-xr-xsrc/ci/docker/run.sh74
-rwxr-xr-xsrc/ci/docker/scripts/fuchsia-test-runner.py180
-rwxr-xr-xsrc/ci/github-actions/calculate-job-matrix.py95
-rw-r--r--src/ci/github-actions/jobs.yml22
-rwxr-xr-xsrc/ci/scripts/install-clang.sh16
m---------src/doc/book0
m---------src/doc/embedded-book0
m---------src/doc/reference0
m---------src/doc/rust-by-example0
m---------src/doc/rustc-dev-guide0
-rw-r--r--src/doc/rustc/src/check-cfg.md152
-rw-r--r--src/doc/rustc/src/command-line-arguments.md10
-rw-r--r--src/doc/rustc/src/platform-support/fuchsia.md24
-rw-r--r--src/doc/rustc/src/platform-support/hermit.md10
-rw-r--r--src/doc/rustdoc/src/read-documentation/search.md10
-rw-r--r--src/doc/unstable-book/src/language-features/exclusive-range-pattern.md26
-rw-r--r--src/doc/unstable-book/src/language-features/half-open-range-patterns-in-slices.md3
-rw-r--r--src/doc/unstable-book/src/language-features/result-ffi-guarantees.md14
-rw-r--r--src/etc/lldb_lookup.py3
-rw-r--r--src/etc/lldb_providers.py52
-rw-r--r--src/etc/rust_types.py7
-rw-r--r--src/librustdoc/clean/auto_trait.rs4
-rw-r--r--src/librustdoc/clean/inline.rs47
-rw-r--r--src/librustdoc/clean/mod.rs8
-rw-r--r--src/librustdoc/config.rs4
-rw-r--r--src/librustdoc/externalfiles.rs2
-rw-r--r--src/librustdoc/html/format.rs4
-rw-r--r--src/librustdoc/html/render/mod.rs2
-rw-r--r--src/librustdoc/html/render/search_index.rs61
-rw-r--r--src/librustdoc/html/static/css/noscript.css1
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css4
-rw-r--r--src/librustdoc/html/static/js/search.js31
-rw-r--r--src/librustdoc/html/static/js/storage.js43
-rw-r--r--src/librustdoc/html/templates/page.html27
-rw-r--r--src/tools/build-manifest/src/main.rs2
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_lints/src/default_union_representation.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/derive.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/future_not_send.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_assert.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/mismatching_type_param_order.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_closure_call.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/single_component_path_imports.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/eager_transmute.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/mod.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_non_zero.rs35
-rw-r--r--src/tools/clippy/clippy_lints/src/unnecessary_self_imports.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/ast_utils.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs21
-rw-r--r--src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs6
-rw-r--r--src/tools/clippy/lintcheck/src/config.rs4
-rw-r--r--src/tools/clippy/tests/ui/almost_complete_range.fixed1
-rw-r--r--src/tools/clippy/tests/ui/almost_complete_range.rs1
-rw-r--r--src/tools/clippy/tests/ui/almost_complete_range.stderr54
-rw-r--r--src/tools/clippy/tests/ui/arithmetic_side_effects.rs8
-rw-r--r--src/tools/clippy/tests/ui/eager_transmute.fixed20
-rw-r--r--src/tools/clippy/tests/ui/eager_transmute.rs20
-rw-r--r--src/tools/clippy/tests/ui/eager_transmute.stderr18
-rw-r--r--src/tools/clippy/tests/ui/manual_range_patterns.fixed1
-rw-r--r--src/tools/clippy/tests/ui/manual_range_patterns.rs1
-rw-r--r--src/tools/clippy/tests/ui/manual_range_patterns.stderr38
-rw-r--r--src/tools/clippy/tests/ui/match_overlapping_arm.rs1
-rw-r--r--src/tools/clippy/tests/ui/match_overlapping_arm.stderr32
-rw-r--r--src/tools/clippy/tests/ui/match_wild_err_arm.rs1
-rw-r--r--src/tools/clippy/tests/ui/match_wild_err_arm.stderr8
-rw-r--r--src/tools/clippy/tests/ui/transmute_int_to_non_zero.fixed62
-rw-r--r--src/tools/clippy/tests/ui/transmute_int_to_non_zero.rs62
-rw-r--r--src/tools/clippy/tests/ui/transmute_int_to_non_zero.stderr80
-rw-r--r--src/tools/compiletest/src/header.rs2
-rw-r--r--src/tools/html-checker/main.rs2
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs2
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs2
-rw-r--r--src/tools/miri/src/intrinsics/mod.rs2
-rw-r--r--src/tools/miri/src/intrinsics/simd.rs2
-rw-r--r--src/tools/miri/src/shims/unix/foreign_items.rs3
-rw-r--r--src/tools/miri/src/shims/x86/avx2.rs2
-rw-r--r--src/tools/miri/tests/fail/enum-set-discriminant-niche-variant-wrong.rs4
-rw-r--r--src/tools/miri/tests/fail/function_pointers/abi_mismatch_repr_C.rs6
-rw-r--r--src/tools/miri/tests/fail/function_pointers/abi_mismatch_repr_C.stderr4
-rw-r--r--src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.rs21
-rw-r--r--src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.stderr15
-rw-r--r--src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_ret.rs12
-rw-r--r--src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs14
-rw-r--r--src/tools/miri/tests/pass/function_calls/abi_compat.rs8
-rw-r--r--src/tools/miri/tests/pass/shims/available-parallelism-miri-num-cpus.rs4
-rw-r--r--src/tools/miri/tests/ui.rs4
-rw-r--r--src/tools/opt-dist/Cargo.toml2
-rw-r--r--src/tools/run-make-support/src/cc.rs2
-rw-r--r--src/tools/run-make-support/src/clang.rs2
-rw-r--r--src/tools/run-make-support/src/lib.rs6
-rw-r--r--src/tools/run-make-support/src/llvm_readobj.rs2
-rw-r--r--src/tools/run-make-support/src/rustc.rs11
-rw-r--r--src/tools/run-make-support/src/rustdoc.rs18
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/layout.rs12
-rw-r--r--src/tools/rustfmt/src/imports.rs4
-rw-r--r--src/tools/tidy/src/allowed_run_make_makefiles.txt4
-rw-r--r--src/tools/tidy/src/issues.txt1
-rw-r--r--src/tools/tidy/src/iter_header.rs7
-rw-r--r--src/tools/tidy/src/lib.rs1
-rw-r--r--src/tools/tidy/src/main.rs1
-rw-r--r--src/tools/tidy/src/target_specific_tests.rs2
-rw-r--r--src/tools/tidy/src/tests_revision_unpaired_stdout_stderr.rs2
-rw-r--r--src/tools/tidy/src/unknown_revision.rs114
-rw-r--r--tests/codegen/debug-fndef-size.rs2
-rw-r--r--tests/codegen/debuginfo-constant-locals.rs4
-rw-r--r--tests/codegen/inline-debuginfo.rs2
-rw-r--r--tests/codegen/mir-aggregate-no-alloca.rs123
-rw-r--r--tests/codegen/sroa-fragment-debuginfo.rs12
-rw-r--r--tests/coverage/branch/if-let.cov-map23
-rw-r--r--tests/coverage/branch/if-let.coverage9
-rw-r--r--tests/coverage/branch/let-else.cov-map9
-rw-r--r--tests/coverage/branch/let-else.coverage3
-rw-r--r--tests/crashes/120421.rs12
-rw-r--r--tests/crashes/122989.rs8
-rw-r--r--tests/crashes/123911.rs16
-rw-r--r--tests/crashes/123912.rs15
-rw-r--r--tests/crashes/124436.rs7
-rw-r--r--tests/crashes/124440.rs23
-rw-r--r--tests/crashes/124464.rs17
-rw-r--r--tests/crashes/124490.rs16
-rw-r--r--tests/crashes/124552.rs12
-rw-r--r--tests/crashes/124563.rs46
-rw-r--r--tests/crashes/124583.rs5
-rw-r--r--tests/crashes/124751.rs8
-rw-r--r--tests/debuginfo/borrowed-enum.rs5
-rw-r--r--tests/debuginfo/coroutine-objects.rs16
-rw-r--r--tests/debuginfo/enum-thinlto.rs4
-rw-r--r--tests/debuginfo/issue-57822.rs4
-rw-r--r--tests/debuginfo/msvc-pretty-enums.rs78
-rw-r--r--tests/debuginfo/struct-style-enum.rs7
-rw-r--r--tests/debuginfo/tuple-style-enum.rs6
-rw-r--r--tests/debuginfo/unique-enum.rs5
-rw-r--r--tests/mir-opt/building/match/never_patterns.opt1.SimplifyCfg-initial.after.mir41
-rw-r--r--tests/mir-opt/building/match/never_patterns.opt2.SimplifyCfg-initial.after.mir35
-rw-r--r--tests/mir-opt/building/match/never_patterns.opt3.SimplifyCfg-initial.after.mir35
-rw-r--r--tests/mir-opt/building/match/never_patterns.rs44
-rw-r--r--tests/mir-opt/building/match/sort_candidates.rs1
-rw-r--r--tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff56
-rw-r--r--tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir47
-rw-r--r--tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir47
-rw-r--r--tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-abort.mir10
-rw-r--r--tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-unwind.mir10
-rw-r--r--tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir17
-rw-r--r--tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir17
-rw-r--r--tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs3
-rw-r--r--tests/run-make/alloc-no-oom-handling/Makefile3
-rw-r--r--tests/run-make/alloc-no-rc/Makefile3
-rw-r--r--tests/run-make/alloc-no-sync/Makefile3
-rw-r--r--tests/run-make/allocator-shim-circular-deps/Makefile5
-rw-r--r--tests/run-make/archive-duplicate-names/Makefile4
-rw-r--r--tests/run-make/bare-outfile/Makefile2
-rw-r--r--tests/run-make/c-dynamic-dylib/Makefile3
-rw-r--r--tests/run-make/c-dynamic-rlib/Makefile3
-rw-r--r--tests/run-make/c-link-to-rust-dylib/Makefile3
-rw-r--r--tests/run-make/c-link-to-rust-staticlib/Makefile3
-rw-r--r--tests/run-make/c-static-dylib/Makefile3
-rw-r--r--tests/run-make/c-static-rlib/Makefile3
-rw-r--r--tests/run-make/c-unwind-abi-catch-lib-panic/Makefile3
-rw-r--r--tests/run-make/c-unwind-abi-catch-panic/Makefile3
-rw-r--r--tests/run-make/cat-and-grep-sanity-check/Makefile4
-rw-r--r--tests/run-make/cdylib-dylib-linkage/Makefile3
-rw-r--r--tests/run-make/cdylib-fewer-symbols/Makefile2
-rw-r--r--tests/run-make/cdylib/Makefile3
-rw-r--r--tests/run-make/codegen-options-parsing/Makefile2
-rw-r--r--tests/run-make/comment-section/Makefile3
-rw-r--r--tests/run-make/compile-stdin/Makefile3
-rw-r--r--tests/run-make/compiler-lookup-paths-2/Makefile3
-rw-r--r--tests/run-make/compiler-lookup-paths/Makefile3
-rw-r--r--tests/run-make/doctests-runtool/Makefile20
-rw-r--r--tests/run-make/doctests-runtool/rmake.rs39
-rw-r--r--tests/run-make/exit-code/rmake.rs2
-rw-r--r--tests/run-make/libtest-padding/Makefile2
-rw-r--r--tests/run-make/repr128-dwarf/rmake.rs2
-rw-r--r--tests/run-make/rustdoc-determinism/rmake.rs23
-rw-r--r--tests/run-make/rustdoc-error-lines/Makefile13
-rw-r--r--tests/run-make/rustdoc-error-lines/rmake.rs22
-rw-r--r--tests/run-make/rustdoc-map-file/Makefile5
-rw-r--r--tests/run-make/rustdoc-map-file/rmake.rs15
-rw-r--r--tests/run-make/rustdoc-output-path/Makefile4
-rw-r--r--tests/run-make/rustdoc-output-path/rmake.rs9
-rw-r--r--tests/rustdoc-gui/javascript-disabled.goml2
-rw-r--r--tests/rustdoc-gui/settings-button.goml31
-rw-r--r--tests/rustdoc-gui/settings.goml1
-rw-r--r--tests/rustdoc-gui/sidebar-source-code-display.goml2
-rw-r--r--tests/rustdoc-gui/src/theme_css/custom-theme.css1
-rw-r--r--tests/rustdoc-js-std/parser-reference.js527
-rw-r--r--tests/rustdoc-js/reference.js236
-rw-r--r--tests/rustdoc-js/reference.rs32
-rw-r--r--tests/rustdoc/inline_cross/issue-76736-2.rs6
-rw-r--r--tests/rustdoc/inline_cross/issue-76736-4.rs19
-rw-r--r--tests/ui-fulldeps/pprust-expr-roundtrip.rs5
-rw-r--r--tests/ui-fulldeps/stable-mir/check_abi.rs6
-rw-r--r--tests/ui/abi/debug.stderr4
-rw-r--r--tests/ui/associated-types/bound-lifetime-constrained.ok.stderr8
-rw-r--r--tests/ui/associated-types/bound-lifetime-constrained.rs2
-rw-r--r--tests/ui/async-await/async-block-control-flow-static-semantics.rs4
-rw-r--r--tests/ui/async-await/async-block-control-flow-static-semantics.stderr8
-rw-r--r--tests/ui/attributes/nonterminal-expansion.rs2
-rw-r--r--tests/ui/attributes/nonterminal-expansion.stderr2
-rw-r--r--tests/ui/binding/match-range.rs1
-rw-r--r--tests/ui/borrowck/two-phase-activation-sharing-interference.nll_target.stderr6
-rw-r--r--tests/ui/borrowck/two-phase-activation-sharing-interference.rs8
-rw-r--r--tests/ui/borrowck/two-phase-allow-access-during-reservation.nll_target.stderr4
-rw-r--r--tests/ui/borrowck/two-phase-allow-access-during-reservation.rs1
-rw-r--r--tests/ui/borrowck/two-phase-nonrecv-autoref.base.stderr22
-rw-r--r--tests/ui/borrowck/two-phase-nonrecv-autoref.rs1
-rw-r--r--tests/ui/borrowck/two-phase-reservation-sharing-interference.nll_target.stderr2
-rw-r--r--tests/ui/borrowck/two-phase-reservation-sharing-interference.rs1
-rw-r--r--tests/ui/check-cfg/allow-same-level.stderr2
-rw-r--r--tests/ui/check-cfg/cargo-feature.none.stderr14
-rw-r--r--tests/ui/check-cfg/cargo-feature.some.stderr14
-rw-r--r--tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr2
-rw-r--r--tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr2
-rw-r--r--tests/ui/check-cfg/cfg-value-for-cfg-name.stderr2
-rw-r--r--tests/ui/check-cfg/compact-names.stderr2
-rw-r--r--tests/ui/check-cfg/diagnotics.cargo.stderr18
-rw-r--r--tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr4
-rw-r--r--tests/ui/check-cfg/exhaustive-names-values.feature.stderr2
-rw-r--r--tests/ui/check-cfg/exhaustive-names-values.full.stderr2
-rw-r--r--tests/ui/check-cfg/exhaustive-names-values.rs10
-rw-r--r--tests/ui/check-cfg/exhaustive-names.stderr2
-rw-r--r--tests/ui/check-cfg/invalid-arguments.any_values.stderr5
-rw-r--r--tests/ui/check-cfg/invalid-arguments.anything_else.stderr5
-rw-r--r--tests/ui/check-cfg/invalid-arguments.boolean.stderr6
-rw-r--r--tests/ui/check-cfg/invalid-arguments.cfg_none.stderr6
-rw-r--r--tests/ui/check-cfg/invalid-arguments.giberich.stderr5
-rw-r--r--tests/ui/check-cfg/invalid-arguments.ident_in_values_1.stderr6
-rw-r--r--tests/ui/check-cfg/invalid-arguments.ident_in_values_2.stderr6
-rw-r--r--tests/ui/check-cfg/invalid-arguments.mixed_any.stderr5
-rw-r--r--tests/ui/check-cfg/invalid-arguments.mixed_values_any.stderr5
-rw-r--r--tests/ui/check-cfg/invalid-arguments.multiple_any.stderr5
-rw-r--r--tests/ui/check-cfg/invalid-arguments.multiple_values.stderr5
-rw-r--r--tests/ui/check-cfg/invalid-arguments.multiple_values_any.stderr6
-rw-r--r--tests/ui/check-cfg/invalid-arguments.none_not_empty.stderr6
-rw-r--r--tests/ui/check-cfg/invalid-arguments.not_empty_any.stderr6
-rw-r--r--tests/ui/check-cfg/invalid-arguments.not_empty_values_any.stderr6
-rw-r--r--tests/ui/check-cfg/invalid-arguments.rs3
-rw-r--r--tests/ui/check-cfg/invalid-arguments.string_for_name_1.stderr6
-rw-r--r--tests/ui/check-cfg/invalid-arguments.string_for_name_2.stderr6
-rw-r--r--tests/ui/check-cfg/invalid-arguments.unknown_meta_item_1.stderr5
-rw-r--r--tests/ui/check-cfg/invalid-arguments.unknown_meta_item_2.stderr6
-rw-r--r--tests/ui/check-cfg/invalid-arguments.unknown_meta_item_3.stderr6
-rw-r--r--tests/ui/check-cfg/invalid-arguments.unterminated.stderr5
-rw-r--r--tests/ui/check-cfg/invalid-arguments.values_any_before_ident.stderr5
-rw-r--r--tests/ui/check-cfg/invalid-arguments.values_any_missing_values.stderr5
-rw-r--r--tests/ui/check-cfg/mix.stderr2
-rw-r--r--tests/ui/check-cfg/stmt-no-ice.stderr2
-rw-r--r--tests/ui/check-cfg/values-none.concat_1.stderr13
-rw-r--r--tests/ui/check-cfg/values-none.concat_2.stderr13
-rw-r--r--tests/ui/check-cfg/values-none.rs2
-rw-r--r--tests/ui/check-cfg/values-none.simple.stderr13
-rw-r--r--tests/ui/check-cfg/well-known-names.stderr2
-rw-r--r--tests/ui/check-cfg/well-known-values.rs5
-rw-r--r--tests/ui/check-cfg/well-known-values.stderr49
-rw-r--r--tests/ui/coercion/coerce-loop-issue-122561.rs110
-rw-r--r--tests/ui/coercion/coerce-loop-issue-122561.stderr299
-rw-r--r--tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs4
-rw-r--r--tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr4
-rw-r--r--tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs2
-rw-r--r--tests/ui/consts/offset_from_ub.rs8
-rw-r--r--tests/ui/consts/offset_from_ub.stderr6
-rw-r--r--tests/ui/coroutine/break-inside-coroutine-issue-124495.rs26
-rw-r--r--tests/ui/coroutine/break-inside-coroutine-issue-124495.stderr69
-rw-r--r--tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr2
-rw-r--r--tests/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr2
-rw-r--r--tests/ui/derives/derives-span-PartialEq-enum.stderr2
-rw-r--r--tests/ui/deriving/deriving-all-codegen.rs14
-rw-r--r--tests/ui/deriving/deriving-all-codegen.stdout40
-rw-r--r--tests/ui/diagnostic_namespace/auxiliary/bad_on_unimplemented.rs26
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr20
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr15
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/simple.rs23
-rw-r--r--tests/ui/diagnostic_namespace/malformed_foreign_on_unimplemented.rs31
-rw-r--r--tests/ui/diagnostic_namespace/malformed_foreign_on_unimplemented.stderr134
-rw-r--r--tests/ui/did_you_mean/compatible-variants.stderr3
-rw-r--r--tests/ui/dyn-star/param-env-region-infer.current.stderr2
-rw-r--r--tests/ui/dyn-star/param-env-region-infer.rs3
-rw-r--r--tests/ui/feature-gates/feature-gate-exclusive-range-pattern.rs6
-rw-r--r--tests/ui/feature-gates/feature-gate-exclusive-range-pattern.stderr14
-rw-r--r--tests/ui/feature-gates/feature-gate-result_ffi_guarantees.rs99
-rw-r--r--tests/ui/feature-gates/feature-gate-result_ffi_guarantees.stderr349
-rw-r--r--tests/ui/for-loop-while/break-while-condition.stderr18
-rw-r--r--tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.rs1
-rw-r--r--tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr2
-rw-r--r--tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.rs1
-rw-r--r--tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr4
-rw-r--r--tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.rs2
-rw-r--r--tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr6
-rw-r--r--tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.rs2
-rw-r--r--tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.stderr4
-rw-r--r--tests/ui/half-open-range-patterns/half-open-range-pats-bad-types.rs2
-rw-r--r--tests/ui/half-open-range-patterns/half-open-range-pats-bad-types.stderr6
-rw-r--r--tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs1
-rw-r--r--tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr136
-rw-r--r--tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-pass.rs2
-rw-r--r--tests/ui/half-open-range-patterns/half-open-range-pats-semantics.rs1
-rw-r--r--tests/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs2
-rw-r--r--tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs2
-rw-r--r--tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr26
-rw-r--r--tests/ui/half-open-range-patterns/pat-tuple-4.rs2
-rw-r--r--tests/ui/half-open-range-patterns/pat-tuple-5.rs2
-rw-r--r--tests/ui/half-open-range-patterns/pat-tuple-5.stderr2
-rw-r--r--tests/ui/half-open-range-patterns/range_pat_interactions0.rs1
-rw-r--r--tests/ui/half-open-range-patterns/range_pat_interactions1.rs9
-rw-r--r--tests/ui/half-open-range-patterns/range_pat_interactions1.stderr83
-rw-r--r--tests/ui/half-open-range-patterns/range_pat_interactions2.rs4
-rw-r--r--tests/ui/half-open-range-patterns/range_pat_interactions2.stderr48
-rw-r--r--tests/ui/half-open-range-patterns/range_pat_interactions3.rs4
-rw-r--r--tests/ui/half-open-range-patterns/range_pat_interactions3.stderr48
-rw-r--r--tests/ui/half-open-range-patterns/slice_pattern_syntax_problem0.rs1
-rw-r--r--tests/ui/half-open-range-patterns/slice_pattern_syntax_problem0.stderr2
-rw-r--r--tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs2
-rw-r--r--tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr24
-rw-r--r--tests/ui/impl-trait/dyn-trait-elided-two-inputs-ref-assoc.rs3
-rw-r--r--tests/ui/impl-trait/in-trait/placeholder-implied-bounds.rs3
-rw-r--r--tests/ui/impl-trait/issues/issue-105826.rs3
-rw-r--r--tests/ui/inline-const/const-match-pat-range.rs2
-rw-r--r--tests/ui/instrument-coverage/coverage-options.rs2
-rw-r--r--tests/ui/issues/issue-27042.stderr2
-rw-r--r--tests/ui/issues/issue-50585.stderr6
-rw-r--r--tests/ui/lint/lint-ctypes-enum.rs148
-rw-r--r--tests/ui/lint/lint-ctypes-enum.stderr216
-rw-r--r--tests/ui/lint/reference_casting.rs14
-rw-r--r--tests/ui/macros/genercs-in-path-with-prettry-hir.rs (renamed from tests/crashes/97006.rs)3
-rw-r--r--tests/ui/macros/genercs-in-path-with-prettry-hir.stderr8
-rw-r--r--tests/ui/macros/genercs-in-path-with-prettry-hir.stdout15
-rw-r--r--tests/ui/macros/macro-expand-within-generics-in-path.rs19
-rw-r--r--tests/ui/macros/macro-expand-within-generics-in-path.stderr14
-rw-r--r--tests/ui/match/match-range-fail-2.rs2
-rw-r--r--tests/ui/match/match-range-fail-2.stderr6
-rw-r--r--tests/ui/match/validate-range-endpoints.rs1
-rw-r--r--tests/ui/match/validate-range-endpoints.stderr22
-rw-r--r--tests/ui/meta/meta-expected-error-wrong-rev.a.stderr2
-rw-r--r--tests/ui/meta/meta-expected-error-wrong-rev.rs1
-rw-r--r--tests/ui/methods/method-lookup-order.rs1
-rw-r--r--tests/ui/mir/mir_match_test.rs1
-rw-r--r--tests/ui/mismatched_types/non_zero_assigned_something.rs8
-rw-r--r--tests/ui/mismatched_types/non_zero_assigned_something.stderr24
-rw-r--r--tests/ui/parser/attribute/attr-bad-meta-4.rs9
-rw-r--r--tests/ui/parser/attribute/attr-bad-meta-4.stderr20
-rw-r--r--tests/ui/parser/attribute/attr-unquoted-ident.fixed17
-rw-r--r--tests/ui/parser/attribute/attr-unquoted-ident.rs14
-rw-r--r--tests/ui/parser/attribute/attr-unquoted-ident.stderr21
-rw-r--r--tests/ui/parser/issues/issue-63115-range-pat-interpolated.rs2
-rw-r--r--tests/ui/parser/recover/recover-range-pats.rs1
-rw-r--r--tests/ui/parser/recover/recover-range-pats.stderr140
-rw-r--r--tests/ui/parser/recover/turbofish-arg-with-stray-colon.rs6
-rw-r--r--tests/ui/parser/recover/turbofish-arg-with-stray-colon.stderr14
-rw-r--r--tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.rs1
-rw-r--r--tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.stderr19
-rw-r--r--tests/ui/pattern/usefulness/floats.rs1
-rw-r--r--tests/ui/pattern/usefulness/floats.stderr18
-rw-r--r--tests/ui/pattern/usefulness/guards.rs1
-rw-r--r--tests/ui/pattern/usefulness/guards.stderr2
-rw-r--r--tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.rs1
-rw-r--r--tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr24
-rw-r--r--tests/ui/pattern/usefulness/integer-ranges/gap_between_ranges.rs1
-rw-r--r--tests/ui/pattern/usefulness/integer-ranges/gap_between_ranges.stderr36
-rw-r--r--tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.rs1
-rw-r--r--tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr22
-rw-r--r--tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr24
-rw-r--r--tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.rs1
-rw-r--r--tests/ui/pattern/usefulness/integer-ranges/reachability.rs1
-rw-r--r--tests/ui/pattern/usefulness/integer-ranges/reachability.stderr52
-rw-r--r--tests/ui/range/range-pattern-out-of-bounds-issue-68972.rs1
-rw-r--r--tests/ui/range/range-pattern-out-of-bounds-issue-68972.stderr4
-rw-r--r--tests/ui/resolve/issue-50599.stderr4
-rw-r--r--tests/ui/resolve/issue-73427.stderr4
-rw-r--r--tests/ui/resolve/privacy-enum-ctor.stderr8
-rw-r--r--tests/ui/rfcs/rfc-0000-never_patterns/check.rs1
-rw-r--r--tests/ui/rfcs/rfc-0000-never_patterns/check.stderr12
-rw-r--r--tests/ui/rfcs/rfc-0000-never_patterns/check_place_is_initialized.rs12
-rw-r--r--tests/ui/rfcs/rfc-0000-never_patterns/check_place_is_initialized.stderr16
-rw-r--r--tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs12
-rw-r--r--tests/ui/rfcs/rfc-0000-never_patterns/use-bindings.rs29
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.rs1
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr22
-rw-r--r--tests/ui/rust-2018/async-ident.fixed8
-rw-r--r--tests/ui/rust-2018/async-ident.rs6
-rw-r--r--tests/ui/rust-2018/async-ident.stderr35
-rw-r--r--tests/ui/rust-2024/gen-kw-in-macro.rs13
-rw-r--r--tests/ui/rust-2024/gen-kw.e2015.stderr11
-rw-r--r--tests/ui/rust-2024/gen-kw.e2018.stderr11
-rw-r--r--tests/ui/rust-2024/gen-kw.rs9
-rw-r--r--tests/ui/span/macro-ty-params.rs1
-rw-r--r--tests/ui/span/macro-ty-params.stderr8
-rw-r--r--tests/ui/stdlib-unit-tests/eq-multidispatch.rs30
-rw-r--r--tests/ui/structs/ice-struct-tail-normalization-113272.rs (renamed from tests/crashes/113272.rs)3
-rw-r--r--tests/ui/structs/ice-struct-tail-normalization-113272.stderr19
-rw-r--r--tests/ui/suggestions/unused-imports.fixed35
-rw-r--r--tests/ui/suggestions/unused-imports.rs42
-rw-r--r--tests/ui/suggestions/unused-imports.stderr32
-rw-r--r--tests/ui/target-feature/tied-features-cli.rs2
-rw-r--r--tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.rs9
-rw-r--r--tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr26
-rw-r--r--tests/ui/traits/next-solver/canonical/effect-var.rs (renamed from tests/ui/traits/next-solver/canonicalize-effect-var.rs)0
-rw-r--r--tests/ui/traits/next-solver/canonical/int-var-eq-in-response.rs (renamed from tests/ui/traits/next-solver/canonical-int-var-eq-in-response.rs)0
-rw-r--r--tests/ui/traits/next-solver/canonical/ty-var-eq-in-response.rs (renamed from tests/ui/traits/next-solver/canonical-ty-var-eq-in-response.rs)0
-rw-r--r--tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-1.rs43
-rw-r--r--tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-2.rs19
-rw-r--r--tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-2.stderr11
-rw-r--r--tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs2
-rw-r--r--tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.stderr19
-rw-r--r--tests/ui/traits/next-solver/diagnostics/point-at-failing-nested.rs24
-rw-r--r--tests/ui/traits/next-solver/diagnostics/point-at-failing-nested.stderr23
-rw-r--r--tests/ui/traits/next-solver/diagnostics/where-clause-doesnt-apply.rs22
-rw-r--r--tests/ui/traits/next-solver/diagnostics/where-clause-doesnt-apply.stderr22
-rw-r--r--tests/ui/traits/next-solver/generalize/hr-alias-non-hr-alias-self-ty-1.rs36
-rw-r--r--tests/ui/traits/next-solver/generalize/hr-alias-non-hr-alias-self-ty-2.rs32
-rw-r--r--tests/ui/traits/next-solver/generalize/hr-alias-universe-lowering-ambiguity.rs51
-rw-r--r--tests/ui/traits/next-solver/generalize/occurs-check-nested-alias.rs1
-rw-r--r--tests/ui/traits/next-solver/select-alias-bound-as-param.rs13
-rw-r--r--tests/ui/traits/normalize-supertrait.rs3
-rw-r--r--tests/ui/traits/trait-upcasting/illegal-upcast-from-impl-opaque.next.stderr14
-rw-r--r--tests/ui/traits/trait-upcasting/illegal-upcast-from-impl-opaque.rs29
-rw-r--r--tests/ui/traits/trait-upcasting/upcast-defining-opaque.current.stderr (renamed from tests/ui/traits/trait-upcasting/illegal-upcast-from-impl-opaque.current.stderr)6
-rw-r--r--tests/ui/traits/trait-upcasting/upcast-defining-opaque.rs24
-rw-r--r--tests/ui/transmutability/primitives/bool-mut.rs1
-rw-r--r--tests/ui/transmutability/primitives/bool-mut.stderr4
-rw-r--r--tests/ui/type/pattern_types/range_patterns_usage.rs2
-rw-r--r--tests/ui/typeck/issue-100285.rs4
-rw-r--r--tests/ui/typeck/issue-100285.stderr39
-rw-r--r--tests/ui/typeck/issue-98982.rs4
-rw-r--r--tests/ui/typeck/issue-98982.stderr18
-rw-r--r--tests/ui/version/version-info-flags.rs2
-rw-r--r--tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.rs21
-rw-r--r--tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr179
-rw-r--r--triagebot.toml22
838 files changed, 10665 insertions, 5853 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index a2769a2c274..5364c1e9f46 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -52,6 +52,8 @@ jobs:
       - name: Checkout the source code
         uses: actions/checkout@v4
       - name: Calculate the CI job matrix
+        env:
+          COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
         run: python3 src/ci/github-actions/calculate-job-matrix.py >> $GITHUB_OUTPUT
         id: jobs
   job:
@@ -75,14 +77,6 @@ jobs:
       matrix:
         # Check the `calculate_matrix` job to see how is the matrix defined.
         include: ${{ fromJSON(needs.calculate_matrix.outputs.jobs) }}
-    # GitHub Actions fails the workflow if an empty list of jobs is provided to
-    # the workflow, so we need to skip this job if nothing was produced by
-    # the Python script.
-    #
-    # Unfortunately checking whether a list is empty is not possible in a nice
-    # way due to GitHub Actions expressions limits.
-    # This hack is taken from https://github.com/ferrocene/ferrocene/blob/d43edc6b7697cf1719ec1c17c54904ab94825763/.github/workflows/release.yml#L75-L82
-    if: fromJSON(needs.calculate_matrix.outputs.jobs)[0] != null
     steps:
       - if: contains(matrix.os, 'windows')
         uses: msys2/setup-msys2@v2.22.0
diff --git a/Cargo.lock b/Cargo.lock
index f27bfddd634..aa73df55cb9 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -479,9 +479,9 @@ version = "0.1.0"
 
 [[package]]
 name = "cc"
-version = "1.0.92"
+version = "1.0.97"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2678b2e3449475e95b0aa6f9b506a28e61b3dc8996592b983695e8ebb58a8b41"
+checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4"
 
 [[package]]
 name = "cfg-if"
@@ -2219,7 +2219,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19"
 dependencies = [
  "cfg-if",
- "windows-targets 0.48.5",
+ "windows-targets 0.52.4",
 ]
 
 [[package]]
@@ -2760,7 +2760,7 @@ dependencies = [
  "tabled",
  "tar",
  "tempfile",
- "xz",
+ "xz2",
  "zip",
 ]
 
@@ -3746,8 +3746,10 @@ name = "rustc_codegen_ssa"
 version = "0.0.0"
 dependencies = [
  "ar_archive_writer",
+ "arrayvec",
  "bitflags 2.5.0",
  "cc",
+ "either",
  "itertools 0.12.1",
  "jobserver",
  "libc",
@@ -3976,7 +3978,6 @@ dependencies = [
  "rustc_session",
  "rustc_span",
  "smallvec",
- "termcolor",
  "thin-vec",
  "tracing",
 ]
@@ -4163,6 +4164,7 @@ dependencies = [
  "rustc_ast",
  "rustc_ast_lowering",
  "rustc_ast_passes",
+ "rustc_ast_pretty",
  "rustc_attr",
  "rustc_borrowck",
  "rustc_builtin_macros",
@@ -4464,6 +4466,7 @@ dependencies = [
  "rustc_macros",
  "rustc_session",
  "rustc_span",
+ "termcolor",
  "thin-vec",
  "tracing",
  "unicode-normalization",
@@ -5667,9 +5670,9 @@ version = "0.1.0"
 
 [[package]]
 name = "time"
-version = "0.3.34"
+version = "0.3.36"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749"
+checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
 dependencies = [
  "deranged",
  "itoa",
@@ -5688,9 +5691,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
 
 [[package]]
 name = "time-macros"
-version = "0.2.17"
+version = "0.2.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774"
+checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf"
 dependencies = [
  "num-conv",
  "time-core",
@@ -6586,15 +6589,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "xz"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c887690ff2a2e233e8e49633461521f98ec57fbff9d59a884c9a4f04ec1da34"
-dependencies = [
- "xz2",
-]
-
-[[package]]
 name = "xz2"
 version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs
index a95ef4c460f..c57be5d1106 100644
--- a/compiler/rustc_abi/src/layout.rs
+++ b/compiler/rustc_abi/src/layout.rs
@@ -2,6 +2,7 @@ use std::borrow::{Borrow, Cow};
 use std::cmp;
 use std::fmt::{self, Write};
 use std::iter;
+use std::num::NonZero;
 use std::ops::Bound;
 use std::ops::Deref;
 
@@ -10,8 +11,8 @@ use tracing::debug;
 
 use crate::{
     Abi, AbiAndPrefAlign, Align, FieldsShape, IndexSlice, IndexVec, Integer, LayoutS, Niche,
-    NonZeroUsize, Primitive, ReprOptions, Scalar, Size, StructKind, TagEncoding, TargetDataLayout,
-    Variants, WrappingRange,
+    Primitive, ReprOptions, Scalar, Size, StructKind, TagEncoding, TargetDataLayout, Variants,
+    WrappingRange,
 };
 
 // A variant is absent if it's uninhabited and only has ZST fields.
@@ -327,7 +328,7 @@ pub trait LayoutCalculator {
 
         Some(LayoutS {
             variants: Variants::Single { index: VariantIdx::new(0) },
-            fields: FieldsShape::Union(NonZeroUsize::new(only_variant.len())?),
+            fields: FieldsShape::Union(NonZero::new(only_variant.len())?),
             abi,
             largest_niche: None,
             align,
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index 5e3f64540e4..a8d019c9804 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -4,7 +4,7 @@
 #![cfg_attr(feature = "nightly", feature(rustdoc_internals))]
 
 use std::fmt;
-use std::num::{NonZeroUsize, ParseIntError};
+use std::num::{NonZero, ParseIntError};
 use std::ops::{Add, AddAssign, Mul, RangeInclusive, Sub};
 use std::str::FromStr;
 
@@ -926,6 +926,41 @@ impl Integer {
     }
 }
 
+/// Floating-point types.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
+pub enum Float {
+    F16,
+    F32,
+    F64,
+    F128,
+}
+
+impl Float {
+    pub fn size(self) -> Size {
+        use Float::*;
+
+        match self {
+            F16 => Size::from_bits(16),
+            F32 => Size::from_bits(32),
+            F64 => Size::from_bits(64),
+            F128 => Size::from_bits(128),
+        }
+    }
+
+    pub fn align<C: HasDataLayout>(self, cx: &C) -> AbiAndPrefAlign {
+        use Float::*;
+        let dl = cx.data_layout();
+
+        match self {
+            F16 => dl.f16_align,
+            F32 => dl.f32_align,
+            F64 => dl.f64_align,
+            F128 => dl.f128_align,
+        }
+    }
+}
+
 /// Fundamental unit of memory access and layout.
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
@@ -938,10 +973,7 @@ pub enum Primitive {
     /// a negative integer passed by zero-extension will appear positive in
     /// the callee, and most operations on it will produce the wrong values.
     Int(Integer, bool),
-    F16,
-    F32,
-    F64,
-    F128,
+    Float(Float),
     Pointer(AddressSpace),
 }
 
@@ -952,10 +984,7 @@ impl Primitive {
 
         match self {
             Int(i, _) => i.size(),
-            F16 => Size::from_bits(16),
-            F32 => Size::from_bits(32),
-            F64 => Size::from_bits(64),
-            F128 => Size::from_bits(128),
+            Float(f) => f.size(),
             // FIXME(erikdesjardins): ignoring address space is technically wrong, pointers in
             // different address spaces can have different sizes
             // (but TargetDataLayout doesn't currently parse that part of the DL string)
@@ -969,10 +998,7 @@ impl Primitive {
 
         match self {
             Int(i, _) => i.align(dl),
-            F16 => dl.f16_align,
-            F32 => dl.f32_align,
-            F64 => dl.f64_align,
-            F128 => dl.f128_align,
+            Float(f) => f.align(dl),
             // FIXME(erikdesjardins): ignoring address space is technically wrong, pointers in
             // different address spaces can have different alignments
             // (but TargetDataLayout doesn't currently parse that part of the DL string)
@@ -1149,7 +1175,7 @@ pub enum FieldsShape<FieldIdx: Idx> {
     Primitive,
 
     /// All fields start at no offset. The `usize` is the field count.
-    Union(NonZeroUsize),
+    Union(NonZero<usize>),
 
     /// Array/vector-like placement, with all fields of identical types.
     Array { stride: Size, count: u64 },
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index fa378e19f71..7951b7e7b75 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -1422,7 +1422,7 @@ pub enum ExprKind {
     /// of `if` / `while` expressions. (e.g., `if let 0 = x { .. }`).
     ///
     /// `Span` represents the whole `let pat = expr` statement.
-    Let(P<Pat>, P<Expr>, Span, Option<ErrorGuaranteed>),
+    Let(P<Pat>, P<Expr>, Span, Recovered),
     /// An `if` block, with an optional `else` block.
     ///
     /// `if expr { block } else { expr }`
@@ -2164,7 +2164,7 @@ pub enum TyKind {
     MacCall(P<MacCall>),
     /// Placeholder for a `va_list`.
     CVarArgs,
-    /// Pattern types like `pattern_type!(u32 is 1..=)`, which is the same as `NonZeroU32`,
+    /// Pattern types like `pattern_type!(u32 is 1..=)`, which is the same as `NonZero<u32>`,
     /// just as part of the type system.
     Pat(P<Ty>, P<Pat>),
     /// Sometimes we need a dummy value when no error has occurred.
@@ -2729,7 +2729,7 @@ pub enum UseTreeKind {
     /// `use prefix` or `use prefix as rename`
     Simple(Option<Ident>),
     /// `use prefix::{...}`
-    Nested(ThinVec<(UseTree, NodeId)>),
+    Nested { items: ThinVec<(UseTree, NodeId)>, span: Span },
     /// `use prefix::*`
     Glob,
 }
@@ -2881,17 +2881,20 @@ pub struct FieldDef {
     pub is_placeholder: bool,
 }
 
+/// Was parsing recovery performed?
+#[derive(Copy, Clone, Debug, Encodable, Decodable, HashStable_Generic)]
+pub enum Recovered {
+    No,
+    Yes(ErrorGuaranteed),
+}
+
 /// Fields and constructor ids of enum variants and structs.
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub enum VariantData {
     /// Struct variant.
     ///
     /// E.g., `Bar { .. }` as in `enum Foo { Bar { .. } }`.
-    Struct {
-        fields: ThinVec<FieldDef>,
-        // FIXME: investigate making this a `Option<ErrorGuaranteed>`
-        recovered: bool,
-    },
+    Struct { fields: ThinVec<FieldDef>, recovered: Recovered },
     /// Tuple variant.
     ///
     /// E.g., `Bar(..)` as in `enum Foo { Bar(..) }`.
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 4d28ef56df1..379c2e273eb 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -441,7 +441,7 @@ fn noop_visit_use_tree<T: MutVisitor>(use_tree: &mut UseTree, vis: &mut T) {
     vis.visit_path(prefix);
     match kind {
         UseTreeKind::Simple(rename) => visit_opt(rename, |rename| vis.visit_ident(rename)),
-        UseTreeKind::Nested(items) => {
+        UseTreeKind::Nested { items, .. } => {
             for (tree, id) in items {
                 vis.visit_use_tree(tree);
                 vis.visit_id(id);
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index 6e946530749..72f89737f99 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -167,7 +167,7 @@ impl LitKind {
 
     pub fn descr(self) -> &'static str {
         match self {
-            Bool => panic!("literal token contains `Lit::Bool`"),
+            Bool => "boolean",
             Byte => "byte",
             Char => "char",
             Integer => "integer",
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index aadcfa7fed5..8e80161af1b 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -706,7 +706,7 @@ impl<'t> Iterator for RefTokenTreeCursor<'t> {
 /// involve associated types) for getting individual elements, or
 /// `RefTokenTreeCursor` if you really want an `Iterator`, e.g. in a `for`
 /// loop.
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 pub struct TokenTreeCursor {
     pub stream: TokenStream,
     index: usize,
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 1d8fd63e459..d36193ef7b0 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -517,8 +517,8 @@ pub fn walk_use_tree<'a, V: Visitor<'a>>(
             visit_opt!(visitor, visit_ident, rename);
         }
         UseTreeKind::Glob => {}
-        UseTreeKind::Nested(ref use_trees) => {
-            for &(ref nested_tree, nested_id) in use_trees {
+        UseTreeKind::Nested { ref items, .. } => {
+            for &(ref nested_tree, nested_id) in items {
                 try_visit!(visitor.visit_use_tree(nested_tree, nested_id, true));
             }
         }
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 5cc05d7336e..a5531090928 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -158,13 +158,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     let ohs = self.lower_expr(ohs);
                     hir::ExprKind::AddrOf(*k, *m, ohs)
                 }
-                ExprKind::Let(pat, scrutinee, span, is_recovered) => {
+                ExprKind::Let(pat, scrutinee, span, recovered) => {
                     hir::ExprKind::Let(self.arena.alloc(hir::LetExpr {
                         span: self.lower_span(*span),
                         pat: self.lower_pat(pat),
                         ty: None,
                         init: self.lower_expr(scrutinee),
-                        is_recovered: *is_recovered,
+                        recovered: *recovered,
                     }))
                 }
                 ExprKind::If(cond, then, else_opt) => {
@@ -581,8 +581,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 self.dcx().emit_err(NeverPatternWithGuard { span: g.span });
             }
 
-            // We add a fake `loop {}` arm body so that it typecks to `!`.
-            // FIXME(never_patterns): Desugar into a call to `unreachable_unchecked`.
+            // We add a fake `loop {}` arm body so that it typecks to `!`. The mir lowering of never
+            // patterns ensures this loop is not reachable.
             let block = self.arena.alloc(hir::Block {
                 stmts: &[],
                 expr: None,
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 156e369c458..61fb5c16ad6 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -135,8 +135,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
     fn lower_item_id_use_tree(&mut self, tree: &UseTree, vec: &mut SmallVec<[hir::ItemId; 1]>) {
         match &tree.kind {
-            UseTreeKind::Nested(nested_vec) => {
-                for &(ref nested, id) in nested_vec {
+            UseTreeKind::Nested { items, .. } => {
+                for &(ref nested, id) in items {
                     vec.push(hir::ItemId {
                         owner_id: hir::OwnerId { def_id: self.local_def_id(id) },
                     });
@@ -518,7 +518,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 let path = self.lower_use_path(res, &path, ParamMode::Explicit);
                 hir::ItemKind::Use(path, hir::UseKind::Glob)
             }
-            UseTreeKind::Nested(ref trees) => {
+            UseTreeKind::Nested { items: ref trees, .. } => {
                 // Nested imports are desugared into simple imports.
                 // So, if we start with
                 //
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 6c54363e306..a76935761f0 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -1283,7 +1283,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         fields.iter().enumerate().map(|f| this.lower_field_def(f)),
                     );
                     let span = t.span;
-                    let variant_data = hir::VariantData::Struct { fields, recovered: false };
+                    let variant_data =
+                        hir::VariantData::Struct { fields, recovered: ast::Recovered::No };
                     // FIXME: capture the generics from the outer adt.
                     let generics = hir::Generics::empty();
                     let kind = match t.kind {
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index e0000e354ca..6622caaaab4 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -1,7 +1,7 @@
 use rustc_ast as ast;
 use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
 use rustc_ast::{attr, AssocConstraint, AssocConstraintKind, NodeId};
-use rustc_ast::{token, PatKind, RangeEnd};
+use rustc_ast::{token, PatKind};
 use rustc_feature::{AttributeGate, BuiltinAttribute, Features, GateIssue, BUILTIN_ATTRIBUTE_MAP};
 use rustc_session::parse::{feature_err, feature_err_issue, feature_warn};
 use rustc_session::Session;
@@ -418,15 +418,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
             PatKind::Box(..) => {
                 gate!(&self, box_patterns, pattern.span, "box pattern syntax is experimental");
             }
-            PatKind::Range(_, Some(_), Spanned { node: RangeEnd::Excluded, .. }) => {
-                gate!(
-                    &self,
-                    exclusive_range_pattern,
-                    pattern.span,
-                    "exclusive range pattern syntax is experimental",
-                    "use an inclusive range pattern, like N..=M"
-                );
-            }
             _ => {}
         }
         visit::walk_pat(self, pattern)
@@ -619,10 +610,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
     // be too.
     gate_all_legacy_dont_use!(return_type_notation, "return type notation is experimental");
     gate_all_legacy_dont_use!(decl_macro, "`macro` is experimental");
-    gate_all_legacy_dont_use!(
-        exclusive_range_pattern,
-        "exclusive range pattern syntax is experimental"
-    );
     gate_all_legacy_dont_use!(try_blocks, "`try` blocks are unstable");
     gate_all_legacy_dont_use!(auto_traits, "`auto` traits are unstable");
 
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
index 61398f7d605..09f9ca53a7a 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
@@ -715,7 +715,7 @@ impl<'a> State<'a> {
                 }
                 self.word("*");
             }
-            ast::UseTreeKind::Nested(items) => {
+            ast::UseTreeKind::Nested { items, .. } => {
                 if !tree.prefix.segments.is_empty() {
                     self.print_path(&tree.prefix, false, 0);
                     self.word("::");
@@ -734,7 +734,7 @@ impl<'a> State<'a> {
                         self.print_use_tree(&use_tree.0);
                         if !is_last {
                             self.word(",");
-                            if let ast::UseTreeKind::Nested(_) = use_tree.0.kind {
+                            if let ast::UseTreeKind::Nested { .. } = use_tree.0.kind {
                                 self.hardbreak();
                             } else {
                                 self.space();
diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs
index 64726eacca7..b9fa46ea883 100644
--- a/compiler/rustc_borrowck/src/consumers.rs
+++ b/compiler/rustc_borrowck/src/consumers.rs
@@ -2,7 +2,6 @@
 
 use rustc_hir::def_id::LocalDefId;
 use rustc_index::{IndexSlice, IndexVec};
-use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::mir::{Body, Promoted};
 use rustc_middle::ty::TyCtxt;
 use std::rc::Rc;
@@ -105,8 +104,7 @@ pub fn get_body_with_borrowck_facts(
     options: ConsumerOptions,
 ) -> BodyWithBorrowckFacts<'_> {
     let (input_body, promoted) = tcx.mir_promoted(def);
-    let infcx = tcx.infer_ctxt().with_opaque_type_inference(def).build();
     let input_body: &Body<'_> = &input_body.borrow();
     let promoted: &IndexSlice<_, _> = &promoted.borrow();
-    *super::do_mir_borrowck(&infcx, input_body, promoted, Some(options)).1.unwrap()
+    *super::do_mir_borrowck(tcx, input_body, promoted, Some(options)).1.unwrap()
 }
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 6c82dd1489c..ccc45e2829a 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -22,6 +22,7 @@ use rustc_middle::mir::{
     Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator,
     TerminatorKind, VarBindingForm,
 };
+use rustc_middle::ty::print::PrintTraitRefExt as _;
 use rustc_middle::ty::{
     self, suggest_constraining_type_params, PredicateKind, ToPredicate, Ty, TyCtxt,
     TypeSuperVisitable, TypeVisitor,
@@ -494,7 +495,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 {
                     self.suggest_cloning(err, ty, expr, None, Some(move_spans));
                 } else if self.suggest_hoisting_call_outside_loop(err, expr) {
-                    // The place where the the type moves would be misleading to suggest clone.
+                    // The place where the type moves would be misleading to suggest clone.
                     // #121466
                     self.suggest_cloning(err, ty, expr, None, Some(move_spans));
                 }
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index 5ebdb69050b..e3ad92a5b2b 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -317,36 +317,39 @@ impl<'tcx> BorrowExplanation<'tcx> {
             let mut has_dyn = false;
             let mut failed = false;
 
-            let elaborated_args = std::iter::zip(*args, &generics.params).map(|(arg, param)| {
-                if let Some(ty::Dynamic(obj, _, ty::Dyn)) = arg.as_type().map(Ty::kind) {
-                    let default = tcx.object_lifetime_default(param.def_id);
-
-                    let re_static = tcx.lifetimes.re_static;
-
-                    let implied_region = match default {
-                        // This is not entirely precise.
-                        ObjectLifetimeDefault::Empty => re_static,
-                        ObjectLifetimeDefault::Ambiguous => {
-                            failed = true;
-                            re_static
-                        }
-                        ObjectLifetimeDefault::Param(param_def_id) => {
-                            let index = generics.param_def_id_to_index[&param_def_id] as usize;
-                            args.get(index).and_then(|arg| arg.as_region()).unwrap_or_else(|| {
+            let elaborated_args =
+                std::iter::zip(*args, &generics.own_params).map(|(arg, param)| {
+                    if let Some(ty::Dynamic(obj, _, ty::Dyn)) = arg.as_type().map(Ty::kind) {
+                        let default = tcx.object_lifetime_default(param.def_id);
+
+                        let re_static = tcx.lifetimes.re_static;
+
+                        let implied_region = match default {
+                            // This is not entirely precise.
+                            ObjectLifetimeDefault::Empty => re_static,
+                            ObjectLifetimeDefault::Ambiguous => {
                                 failed = true;
                                 re_static
-                            })
-                        }
-                        ObjectLifetimeDefault::Static => re_static,
-                    };
+                            }
+                            ObjectLifetimeDefault::Param(param_def_id) => {
+                                let index = generics.param_def_id_to_index[&param_def_id] as usize;
+                                args.get(index).and_then(|arg| arg.as_region()).unwrap_or_else(
+                                    || {
+                                        failed = true;
+                                        re_static
+                                    },
+                                )
+                            }
+                            ObjectLifetimeDefault::Static => re_static,
+                        };
 
-                    has_dyn = true;
+                        has_dyn = true;
 
-                    Ty::new_dynamic(tcx, obj, implied_region, ty::Dyn).into()
-                } else {
-                    arg
-                }
-            });
+                        Ty::new_dynamic(tcx, obj, implied_region, ty::Dyn).into()
+                    } else {
+                        arg
+                    }
+                });
             let elaborated_ty = Ty::new_adt(tcx, *def, tcx.mk_args_from_iter(elaborated_args));
 
             if has_dyn && !failed {
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 0b4018a23ce..88172c62a3b 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -1344,7 +1344,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                                     Applicability::MaybeIncorrect,
                                 );
                                 for error in errors {
-                                    if let FulfillmentErrorCode::SelectionError(
+                                    if let FulfillmentErrorCode::Select(
                                         SelectionError::Unimplemented,
                                     ) = error.code
                                         && let ty::PredicateKind::Clause(ty::ClauseKind::Trait(
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 5d74a01aa20..c9a09c19ce6 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -1283,7 +1283,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                                 }
                                 // The type doesn't implement Clone because of unmet obligations.
                                 for error in errors {
-                                    if let traits::FulfillmentErrorCode::SelectionError(
+                                    if let traits::FulfillmentErrorCode::Select(
                                         traits::SelectionError::Unimplemented,
                                     ) = error.code
                                         && let ty::PredicateKind::Clause(ty::ClauseKind::Trait(
@@ -1483,10 +1483,9 @@ fn suggest_ampmut<'tcx>(
     } else {
         // otherwise, suggest that the user annotates the binding; we provide the
         // type of the local.
-        let ty_mut = decl_ty.builtin_deref(true).unwrap();
-        assert_eq!(ty_mut.mutbl, hir::Mutability::Not);
+        let ty = decl_ty.builtin_deref(true).unwrap();
 
-        (false, span, format!("{}mut {}", if decl_ty.is_ref() { "&" } else { "*" }, ty_mut.ty))
+        (false, span, format!("{}mut {}", if decl_ty.is_ref() { "&" } else { "*" }, ty))
     }
 }
 
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 47c83e0bb2b..abe57e26af4 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -23,9 +23,8 @@ use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
 use rustc_index::bit_set::{BitSet, ChunkedBitSet};
 use rustc_index::{IndexSlice, IndexVec};
-use rustc_infer::infer::{
-    InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, TyCtxtInferExt,
-};
+use rustc_infer::infer::TyCtxtInferExt;
+use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin};
 use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::mir::*;
 use rustc_middle::query::Providers;
@@ -123,9 +122,8 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> {
         return tcx.arena.alloc(result);
     }
 
-    let infcx = tcx.infer_ctxt().with_opaque_type_inference(def).build();
     let promoted: &IndexSlice<_, _> = &promoted.borrow();
-    let opt_closure_req = do_mir_borrowck(&infcx, input_body, promoted, None).0;
+    let opt_closure_req = do_mir_borrowck(tcx, input_body, promoted, None).0;
     debug!("mir_borrowck done");
 
     tcx.arena.alloc(opt_closure_req)
@@ -136,18 +134,15 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> {
 /// Use `consumer_options: None` for the default behavior of returning
 /// [`BorrowCheckResult`] only. Otherwise, return [`BodyWithBorrowckFacts`] according
 /// to the given [`ConsumerOptions`].
-#[instrument(skip(infcx, input_body, input_promoted), fields(id=?input_body.source.def_id()), level = "debug")]
+#[instrument(skip(tcx, input_body, input_promoted), fields(id=?input_body.source.def_id()), level = "debug")]
 fn do_mir_borrowck<'tcx>(
-    infcx: &InferCtxt<'tcx>,
+    tcx: TyCtxt<'tcx>,
     input_body: &Body<'tcx>,
     input_promoted: &IndexSlice<Promoted, Body<'tcx>>,
     consumer_options: Option<ConsumerOptions>,
 ) -> (BorrowCheckResult<'tcx>, Option<Box<BodyWithBorrowckFacts<'tcx>>>) {
     let def = input_body.source.def_id().expect_local();
-    debug!(?def);
-
-    let tcx = infcx.tcx;
-    let infcx = BorrowckInferCtxt::new(infcx);
+    let infcx = BorrowckInferCtxt::new(tcx, def);
     let param_env = tcx.param_env(def);
 
     let mut local_names = IndexVec::from_elem(None, &input_body.local_decls);
@@ -187,6 +182,12 @@ fn do_mir_borrowck<'tcx>(
         nll::replace_regions_in_mir(&infcx, param_env, &mut body_owned, &mut promoted);
     let body = &body_owned; // no further changes
 
+    // FIXME(-Znext-solver): A bit dubious that we're only registering
+    // predefined opaques in the typeck root.
+    if infcx.next_trait_solver() && !infcx.tcx.is_typeck_child(body.source.def_id()) {
+        infcx.register_predefined_opaques_for_next_solver(def);
+    }
+
     let location_table = LocationTable::new(body);
 
     let move_data = MoveData::gather_moves(body, tcx, param_env, |_| true);
@@ -440,13 +441,14 @@ fn do_mir_borrowck<'tcx>(
     (result, body_with_facts)
 }
 
-pub struct BorrowckInferCtxt<'cx, 'tcx> {
-    pub(crate) infcx: &'cx InferCtxt<'tcx>,
+pub struct BorrowckInferCtxt<'tcx> {
+    pub(crate) infcx: InferCtxt<'tcx>,
     pub(crate) reg_var_to_origin: RefCell<FxIndexMap<ty::RegionVid, RegionCtxt>>,
 }
 
-impl<'cx, 'tcx> BorrowckInferCtxt<'cx, 'tcx> {
-    pub(crate) fn new(infcx: &'cx InferCtxt<'tcx>) -> Self {
+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();
         BorrowckInferCtxt { infcx, reg_var_to_origin: RefCell::new(Default::default()) }
     }
 
@@ -492,18 +494,40 @@ impl<'cx, 'tcx> BorrowckInferCtxt<'cx, 'tcx> {
 
         next_region
     }
+
+    /// With the new solver we prepopulate the opaque type storage during
+    /// MIR borrowck with the hidden types from HIR typeck. This is necessary
+    /// to avoid ambiguities as earlier goals can rely on the hidden type
+    /// of an opaque which is only constrained by a later goal.
+    fn register_predefined_opaques_for_next_solver(&self, def_id: LocalDefId) {
+        let tcx = self.tcx;
+        // OK to use the identity arguments for each opaque type key, since
+        // we remap opaques from HIR typeck back to their definition params.
+        for data in tcx.typeck(def_id).concrete_opaque_types.iter().map(|(k, v)| (*k, *v)) {
+            // HIR typeck did not infer the regions of the opaque, so we instantiate
+            // them with fresh inference variables.
+            let (key, hidden_ty) = tcx.fold_regions(data, |_, _| {
+                self.next_nll_region_var_in_universe(
+                    NllRegionVariableOrigin::Existential { from_forall: false },
+                    ty::UniverseIndex::ROOT,
+                )
+            });
+
+            self.inject_new_hidden_type_unchecked(key, hidden_ty);
+        }
+    }
 }
 
-impl<'cx, 'tcx> Deref for BorrowckInferCtxt<'cx, 'tcx> {
+impl<'tcx> Deref for BorrowckInferCtxt<'tcx> {
     type Target = InferCtxt<'tcx>;
 
-    fn deref(&self) -> &'cx Self::Target {
-        self.infcx
+    fn deref(&self) -> &Self::Target {
+        &self.infcx
     }
 }
 
 struct MirBorrowckCtxt<'cx, 'tcx> {
-    infcx: &'cx BorrowckInferCtxt<'cx, 'tcx>,
+    infcx: &'cx BorrowckInferCtxt<'tcx>,
     param_env: ParamEnv<'tcx>,
     body: &'cx Body<'tcx>,
     move_data: &'cx MoveData<'tcx>,
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index 4aa32a61f7c..49f50babdcb 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -51,7 +51,7 @@ pub(crate) struct NllOutput<'tcx> {
 /// `compute_regions`.
 #[instrument(skip(infcx, param_env, body, promoted), level = "debug")]
 pub(crate) fn replace_regions_in_mir<'tcx>(
-    infcx: &BorrowckInferCtxt<'_, 'tcx>,
+    infcx: &BorrowckInferCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     body: &mut Body<'tcx>,
     promoted: &mut IndexSlice<Promoted, Body<'tcx>>,
@@ -75,7 +75,7 @@ pub(crate) fn replace_regions_in_mir<'tcx>(
 ///
 /// This may result in errors being reported.
 pub(crate) fn compute_regions<'cx, 'tcx>(
-    infcx: &BorrowckInferCtxt<'_, 'tcx>,
+    infcx: &BorrowckInferCtxt<'tcx>,
     universal_regions: UniversalRegions<'tcx>,
     body: &Body<'tcx>,
     promoted: &IndexSlice<Promoted, Body<'tcx>>,
@@ -202,7 +202,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
 }
 
 pub(super) fn dump_mir_results<'tcx>(
-    infcx: &BorrowckInferCtxt<'_, 'tcx>,
+    infcx: &BorrowckInferCtxt<'tcx>,
     body: &Body<'tcx>,
     regioncx: &RegionInferenceContext<'tcx>,
     closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
@@ -254,7 +254,7 @@ pub(super) fn dump_mir_results<'tcx>(
 #[allow(rustc::diagnostic_outside_of_impl)]
 #[allow(rustc::untranslatable_diagnostic)]
 pub(super) fn dump_annotation<'tcx>(
-    infcx: &BorrowckInferCtxt<'_, 'tcx>,
+    infcx: &BorrowckInferCtxt<'tcx>,
     body: &Body<'tcx>,
     regioncx: &RegionInferenceContext<'tcx>,
     closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 78465ad7975..e58723c2ec9 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -250,10 +250,7 @@ pub enum ExtraConstraintInfo {
 }
 
 #[instrument(skip(infcx, sccs), level = "debug")]
-fn sccs_info<'cx, 'tcx>(
-    infcx: &'cx BorrowckInferCtxt<'cx, 'tcx>,
-    sccs: Rc<Sccs<RegionVid, ConstraintSccIndex>>,
-) {
+fn sccs_info<'tcx>(infcx: &BorrowckInferCtxt<'tcx>, sccs: Rc<Sccs<RegionVid, ConstraintSccIndex>>) {
     use crate::renumber::RegionCtxt;
 
     let var_to_origin = infcx.reg_var_to_origin.borrow();
@@ -322,8 +319,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     ///
     /// The `outlives_constraints` and `type_tests` are an initial set
     /// of constraints produced by the MIR type check.
-    pub(crate) fn new<'cx>(
-        _infcx: &BorrowckInferCtxt<'cx, 'tcx>,
+    pub(crate) fn new(
+        _infcx: &BorrowckInferCtxt<'tcx>,
         var_infos: VarInfos,
         universal_regions: Rc<UniversalRegions<'tcx>>,
         placeholder_indices: Rc<PlaceholderIndices>,
@@ -1329,14 +1326,20 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         })
     }
 
-    // Evaluate whether `sup_region == sub_region`.
-    fn eval_equal(&self, r1: RegionVid, r2: RegionVid) -> bool {
+    /// Evaluate whether `sup_region == sub_region`.
+    ///
+    /// Panics if called before `solve()` executes,
+    // This is `pub` because it's used by unstable external borrowck data users, see `consumers.rs`.
+    pub fn eval_equal(&self, r1: RegionVid, r2: RegionVid) -> bool {
         self.eval_outlives(r1, r2) && self.eval_outlives(r2, r1)
     }
 
-    // Evaluate whether `sup_region: sub_region`.
+    /// Evaluate whether `sup_region: sub_region`.
+    ///
+    /// Panics if called before `solve()` executes,
+    // This is `pub` because it's used by unstable external borrowck data users, see `consumers.rs`.
     #[instrument(skip(self), level = "debug", ret)]
-    fn eval_outlives(&self, sup_region: RegionVid, sub_region: RegionVid) -> bool {
+    pub fn eval_outlives(&self, sup_region: RegionVid, sub_region: RegionVid) -> bool {
         debug!(
             "sup_region's value = {:?} universal={:?}",
             self.region_value_str(sup_region),
@@ -2056,7 +2059,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                     // We currently do not store the `DefId` in the `ConstraintCategory`
                     // for performances reasons. The error reporting code used by NLL only
                     // uses the span, so this doesn't cause any problems at the moment.
-                    Some(ObligationCauseCode::BindingObligation(
+                    Some(ObligationCauseCode::SpannedWhereClause(
                         CRATE_DEF_ID.to_def_id(),
                         predicate_span,
                     ))
@@ -2064,7 +2067,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                     None
                 }
             })
-            .unwrap_or_else(|| ObligationCauseCode::MiscObligation);
+            .unwrap_or_else(|| ObligationCauseCode::Misc);
 
         // Classify each of the constraints along the path.
         let mut categorized_path: Vec<BlameConstraint<'tcx>> = path
@@ -2249,7 +2252,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     }
 
     /// Access to the SCC constraint graph.
-    pub(crate) fn constraint_sccs(&self) -> &Sccs<RegionVid, ConstraintSccIndex> {
+    /// This can be used to quickly under-approximate the regions which are equal to each other
+    /// and their relative orderings.
+    // This is `pub` because it's used by unstable external borrowck data users, see `consumers.rs`.
+    pub fn constraint_sccs(&self) -> &Sccs<RegionVid, ConstraintSccIndex> {
         self.constraint_sccs.as_ref()
     }
 
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index 73ba5bee13b..f601a9d7073 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -40,7 +40,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// compares lifetimes directly, so we need to map the inference variables
     /// back to concrete lifetimes: `'static`, `ReEarlyParam` or `ReLateParam`.
     ///
-    /// First we map the regions in the the generic parameters `_Return<'1>` to
+    /// First we map the regions in the generic parameters `_Return<'1>` to
     /// their `external_name` giving `_Return<'a>`. This step is a bit involved.
     /// See the [rustc-dev-guide chapter] for more info.
     ///
diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs
index dca8df32800..d382f264c37 100644
--- a/compiler/rustc_borrowck/src/renumber.rs
+++ b/compiler/rustc_borrowck/src/renumber.rs
@@ -11,7 +11,7 @@ use rustc_span::Symbol;
 /// inference variables, returning the number of variables created.
 #[instrument(skip(infcx, body, promoted), level = "debug")]
 pub fn renumber_mir<'tcx>(
-    infcx: &BorrowckInferCtxt<'_, 'tcx>,
+    infcx: &BorrowckInferCtxt<'tcx>,
     body: &mut Body<'tcx>,
     promoted: &mut IndexSlice<Promoted, Body<'tcx>>,
 ) {
@@ -26,9 +26,7 @@ pub fn renumber_mir<'tcx>(
     renumberer.visit_body(body);
 }
 
-// FIXME(@lcnr): A lot of these variants overlap and it seems like
-// this type is only used to decide which region should be used
-// as representative. This should be cleaned up.
+// The fields are used only for debugging output in `sccs_info`.
 #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
 pub(crate) enum RegionCtxt {
     Location(Location),
@@ -57,7 +55,7 @@ impl RegionCtxt {
 }
 
 struct RegionRenumberer<'a, 'tcx> {
-    infcx: &'a BorrowckInferCtxt<'a, 'tcx>,
+    infcx: &'a BorrowckInferCtxt<'tcx>,
 }
 
 impl<'a, 'tcx> RegionRenumberer<'a, 'tcx> {
diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs
index 2511a1535af..4e45dc42aa7 100644
--- a/compiler/rustc_borrowck/src/type_check/input_output.rs
+++ b/compiler/rustc_borrowck/src/type_check/input_output.rs
@@ -11,7 +11,6 @@ use std::assert_matches::assert_matches;
 
 use itertools::Itertools;
 use rustc_hir as hir;
-use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::infer::{BoundRegionConversionTime, RegionVariableOrigin};
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, Ty};
@@ -74,9 +73,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 }),
             );
 
-            let next_ty_var = || {
-                self.infcx.next_ty_var(TypeVariableOrigin { span: body.span, param_def_id: None })
-            };
+            let next_ty_var = || self.infcx.next_ty_var(body.span);
             let output_ty = Ty::new_coroutine(
                 self.tcx(),
                 self.tcx().coroutine_for_closure(mir_def_id),
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs
index da5456692ab..ccd9fb25739 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs
@@ -1,4 +1,3 @@
-use rustc_data_structures::vec_linked_list as vll;
 use rustc_index::IndexVec;
 use rustc_middle::mir::visit::{PlaceContext, Visitor};
 use rustc_middle::mir::{Body, Local, Location};
@@ -37,9 +36,12 @@ pub(crate) struct LocalUseMap {
     /// we add for each local variable.
     first_drop_at: IndexVec<Local, Option<AppearanceIndex>>,
 
-    appearances: IndexVec<AppearanceIndex, Appearance>,
+    appearances: Appearances,
 }
 
+// The `Appearance::next` field effectively embeds a linked list within `Appearances`.
+type Appearances = IndexVec<AppearanceIndex, Appearance>;
+
 struct Appearance {
     point_index: PointIndex,
     next: Option<AppearanceIndex>,
@@ -49,14 +51,34 @@ rustc_index::newtype_index! {
     pub struct AppearanceIndex {}
 }
 
-impl vll::LinkElem for Appearance {
-    type LinkIndex = AppearanceIndex;
+fn appearances_iter(
+    first: Option<AppearanceIndex>,
+    appearances: &Appearances,
+) -> impl Iterator<Item = AppearanceIndex> + '_ {
+    AppearancesIter { appearances, current: first }
+}
+
+// Iterates over `Appearances` by following `next` fields.
+struct AppearancesIter<'a> {
+    appearances: &'a Appearances,
+    current: Option<AppearanceIndex>,
+}
 
-    fn next(elem: &Self) -> Option<AppearanceIndex> {
-        elem.next
+impl<'a> Iterator for AppearancesIter<'a> {
+    type Item = AppearanceIndex;
+
+    fn next(&mut self) -> Option<AppearanceIndex> {
+        if let Some(c) = self.current {
+            self.current = self.appearances[c].next;
+            Some(c)
+        } else {
+            None
+        }
     }
 }
 
+//-----------------------------------------------------------------------------
+
 impl LocalUseMap {
     pub(crate) fn build(
         live_locals: &[Local],
@@ -86,17 +108,17 @@ impl LocalUseMap {
     }
 
     pub(crate) fn defs(&self, local: Local) -> impl Iterator<Item = PointIndex> + '_ {
-        vll::iter(self.first_def_at[local], &self.appearances)
+        appearances_iter(self.first_def_at[local], &self.appearances)
             .map(move |aa| self.appearances[aa].point_index)
     }
 
     pub(crate) fn uses(&self, local: Local) -> impl Iterator<Item = PointIndex> + '_ {
-        vll::iter(self.first_use_at[local], &self.appearances)
+        appearances_iter(self.first_use_at[local], &self.appearances)
             .map(move |aa| self.appearances[aa].point_index)
     }
 
     pub(crate) fn drops(&self, local: Local) -> impl Iterator<Item = PointIndex> + '_ {
-        vll::iter(self.first_drop_at[local], &self.appearances)
+        appearances_iter(self.first_drop_at[local], &self.appearances)
             .map(move |aa| self.appearances[aa].point_index)
     }
 }
@@ -146,7 +168,7 @@ impl LocalUseMapBuild<'_> {
     fn insert(
         elements: &DenseLocationMap,
         first_appearance: &mut Option<AppearanceIndex>,
-        appearances: &mut IndexVec<AppearanceIndex, Appearance>,
+        appearances: &mut Appearances,
         location: Location,
     ) {
         let point_index = elements.point_from_location(location);
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index b67c5d85818..2740e9689c5 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -16,7 +16,6 @@ use rustc_index::{IndexSlice, IndexVec};
 use rustc_infer::infer::canonical::QueryRegionConstraints;
 use rustc_infer::infer::outlives::env::RegionBoundPairs;
 use rustc_infer::infer::region_constraints::RegionConstraintData;
-use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::infer::{
     BoundRegion, BoundRegionConversionTime, InferCtxt, NllRegionVariableOrigin,
 };
@@ -24,7 +23,6 @@ use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
 use rustc_middle::traits::query::NoSolution;
-use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::adjustment::PointerCoercion;
 use rustc_middle::ty::cast::CastTy;
 use rustc_middle::ty::visit::TypeVisitableExt;
@@ -122,7 +120,7 @@ mod relate_tys;
 /// - `move_data` -- move-data constructed when performing the maybe-init dataflow analysis
 /// - `elements` -- MIR region map
 pub(crate) fn type_check<'mir, 'tcx>(
-    infcx: &BorrowckInferCtxt<'_, 'tcx>,
+    infcx: &BorrowckInferCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     body: &Body<'tcx>,
     promoted: &IndexSlice<Promoted, Body<'tcx>>,
@@ -402,7 +400,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
             } else if let Some(static_def_id) = constant.check_static_ptr(tcx) {
                 let unnormalized_ty = tcx.type_of(static_def_id).instantiate_identity();
                 let normalized_ty = self.cx.normalize(unnormalized_ty, locations);
-                let literal_ty = constant.const_.ty().builtin_deref(true).unwrap().ty;
+                let literal_ty = constant.const_.ty().builtin_deref(true).unwrap();
 
                 if let Err(terr) = self.cx.eq_types(
                     literal_ty,
@@ -534,8 +532,11 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
 
         if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
             let tcx = self.tcx();
-            let trait_ref =
-                ty::TraitRef::from_lang_item(tcx, LangItem::Copy, self.last_span, [place_ty.ty]);
+            let trait_ref = ty::TraitRef::new(
+                tcx,
+                tcx.require_lang_item(LangItem::Copy, Some(self.last_span)),
+                [place_ty.ty],
+            );
 
             // To have a `Copy` operand, the type `T` of the
             // value must be `Copy`. Note that we prove that `T: Copy`,
@@ -639,7 +640,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
         match pi {
             ProjectionElem::Deref => {
                 let deref_ty = base_ty.builtin_deref(true);
-                PlaceTy::from_ty(deref_ty.map(|t| t.ty).unwrap_or_else(|| {
+                PlaceTy::from_ty(deref_ty.unwrap_or_else(|| {
                     span_mirbug_and_err!(self, place, "deref of non-pointer {:?}", base_ty)
                 }))
             }
@@ -865,7 +866,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
 /// way, it accrues region constraints -- these can later be used by
 /// NLL region checking.
 struct TypeChecker<'a, 'tcx> {
-    infcx: &'a BorrowckInferCtxt<'a, 'tcx>,
+    infcx: &'a BorrowckInferCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     last_span: Span,
     body: &'a Body<'tcx>,
@@ -1020,7 +1021,7 @@ impl Locations {
 
 impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
     fn new(
-        infcx: &'a BorrowckInferCtxt<'a, 'tcx>,
+        infcx: &'a BorrowckInferCtxt<'tcx>,
         body: &'a Body<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
         region_bound_pairs: &'a RegionBoundPairs<'tcx>,
@@ -1028,7 +1029,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         implicit_region_bound: ty::Region<'tcx>,
         borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
     ) -> Self {
-        let mut checker = Self {
+        Self {
             infcx,
             last_span: body.span,
             body,
@@ -1039,74 +1040,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             implicit_region_bound,
             borrowck_context,
             reported_errors: Default::default(),
-        };
-
-        // FIXME(-Znext-solver): A bit dubious that we're only registering
-        // predefined opaques in the typeck root.
-        if infcx.next_trait_solver() && !infcx.tcx.is_typeck_child(body.source.def_id()) {
-            checker.register_predefined_opaques_for_next_solver();
-        }
-
-        checker
-    }
-
-    pub(super) fn register_predefined_opaques_for_next_solver(&mut self) {
-        // OK to use the identity arguments for each opaque type key, since
-        // we remap opaques from HIR typeck back to their definition params.
-        let opaques: Vec<_> = self
-            .infcx
-            .tcx
-            .typeck(self.body.source.def_id().expect_local())
-            .concrete_opaque_types
-            .iter()
-            .map(|(k, v)| (*k, *v))
-            .collect();
-
-        let renumbered_opaques = self.infcx.tcx.fold_regions(opaques, |_, _| {
-            self.infcx.next_nll_region_var_in_universe(
-                NllRegionVariableOrigin::Existential { from_forall: false },
-                ty::UniverseIndex::ROOT,
-            )
-        });
-
-        let param_env = self.param_env;
-        let result = self.fully_perform_op(
-            Locations::All(self.body.span),
-            ConstraintCategory::OpaqueType,
-            CustomTypeOp::new(
-                |ocx| {
-                    let mut obligations = Vec::new();
-                    for (opaque_type_key, hidden_ty) in renumbered_opaques {
-                        let cause = ObligationCause::dummy();
-                        ocx.infcx.insert_hidden_type(
-                            opaque_type_key,
-                            &cause,
-                            param_env,
-                            hidden_ty.ty,
-                            &mut obligations,
-                        )?;
-
-                        ocx.infcx.add_item_bounds_for_hidden_type(
-                            opaque_type_key.def_id.to_def_id(),
-                            opaque_type_key.args,
-                            cause,
-                            param_env,
-                            hidden_ty.ty,
-                            &mut obligations,
-                        );
-                    }
-
-                    ocx.register_obligations(obligations);
-                    Ok(())
-                },
-                "register pre-defined opaques",
-            ),
-        );
-
-        if result.is_err() {
-            self.infcx
-                .dcx()
-                .span_bug(self.body.span, "failed re-defining predefined opaques in mir typeck");
         }
     }
 
@@ -1343,10 +1276,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
 
                 self.check_rvalue(body, rv, location);
                 if !self.unsized_feature_enabled() {
-                    let trait_ref = ty::TraitRef::from_lang_item(
+                    let trait_ref = ty::TraitRef::new(
                         tcx,
-                        LangItem::Sized,
-                        self.last_span,
+                        tcx.require_lang_item(LangItem::Sized, Some(self.last_span)),
                         [place_ty],
                     );
                     self.prove_trait_ref(
@@ -1995,8 +1927,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                         Operand::Move(place) => {
                             // Make sure that repeated elements implement `Copy`.
                             let ty = place.ty(body, tcx).ty;
-                            let trait_ref =
-                                ty::TraitRef::from_lang_item(tcx, LangItem::Copy, span, [ty]);
+                            let trait_ref = ty::TraitRef::new(
+                                tcx,
+                                tcx.require_lang_item(LangItem::Copy, Some(span)),
+                                [ty],
+                            );
 
                             self.prove_trait_ref(
                                 trait_ref,
@@ -2009,7 +1944,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             }
 
             &Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, ty) => {
-                let trait_ref = ty::TraitRef::from_lang_item(tcx, LangItem::Sized, span, [ty]);
+                let trait_ref = ty::TraitRef::new(
+                    tcx,
+                    tcx.require_lang_item(LangItem::Sized, Some(span)),
+                    [ty],
+                );
 
                 self.prove_trait_ref(
                     trait_ref,
@@ -2022,7 +1961,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             Rvalue::ShallowInitBox(operand, ty) => {
                 self.check_operand(operand, location);
 
-                let trait_ref = ty::TraitRef::from_lang_item(tcx, LangItem::Sized, span, [*ty]);
+                let trait_ref = ty::TraitRef::new(
+                    tcx,
+                    tcx.require_lang_item(LangItem::Sized, Some(span)),
+                    [*ty],
+                );
 
                 self.prove_trait_ref(
                     trait_ref,
@@ -2120,10 +2063,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
 
                     CastKind::PointerCoercion(PointerCoercion::Unsize) => {
                         let &ty = ty;
-                        let trait_ref = ty::TraitRef::from_lang_item(
+                        let trait_ref = ty::TraitRef::new(
                             tcx,
-                            LangItem::CoerceUnsized,
-                            span,
+                            tcx.require_lang_item(LangItem::CoerceUnsized, Some(span)),
                             [op.ty(body, tcx), ty],
                         );
 
@@ -2425,10 +2367,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     // Types with regions are comparable if they have a common super-type.
                     ty::RawPtr(_, _) | ty::FnPtr(_) => {
                         let ty_right = right.ty(body, tcx);
-                        let common_ty = self.infcx.next_ty_var(TypeVariableOrigin {
-                            param_def_id: None,
-                            span: body.source_info(location).span,
-                        });
+                        let common_ty = self.infcx.next_ty_var(body.source_info(location).span);
                         self.sub_types(
                             ty_left,
                             common_ty,
diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
index 5e4b3e532c4..493c41e59e3 100644
--- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs
+++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
@@ -1,6 +1,5 @@
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::ErrorGuaranteed;
-use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::infer::NllRegionVariableOrigin;
 use rustc_infer::infer::{ObligationEmittingRelation, StructurallyRelateAliases};
 use rustc_infer::traits::{Obligation, PredicateObligations};
@@ -129,10 +128,7 @@ impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> {
         // by using `ty_vid rel B` and then finally and end by equating `ty_vid` to
         // the opaque.
         let mut enable_subtyping = |ty, opaque_is_expected| {
-            let ty_vid = infcx.next_ty_var_id_in_universe(
-                TypeVariableOrigin { param_def_id: None, span: self.span() },
-                ty::UniverseIndex::ROOT,
-            );
+            let ty_vid = infcx.next_ty_var_id_in_universe(self.span(), ty::UniverseIndex::ROOT);
 
             let variance = if opaque_is_expected {
                 self.ambient_variance
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index 070238fc378..f8123535e2d 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -240,7 +240,7 @@ impl<'tcx> UniversalRegions<'tcx> {
     /// signature. This will also compute the relationships that are
     /// known between those regions.
     pub fn new(
-        infcx: &BorrowckInferCtxt<'_, 'tcx>,
+        infcx: &BorrowckInferCtxt<'tcx>,
         mir_def: LocalDefId,
         param_env: ty::ParamEnv<'tcx>,
     ) -> Self {
@@ -411,7 +411,7 @@ impl<'tcx> UniversalRegions<'tcx> {
 }
 
 struct UniversalRegionsBuilder<'cx, 'tcx> {
-    infcx: &'cx BorrowckInferCtxt<'cx, 'tcx>,
+    infcx: &'cx BorrowckInferCtxt<'tcx>,
     mir_def: LocalDefId,
     param_env: ty::ParamEnv<'tcx>,
 }
@@ -796,7 +796,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
 }
 
 #[extension(trait InferCtxtExt<'tcx>)]
-impl<'cx, 'tcx> BorrowckInferCtxt<'cx, 'tcx> {
+impl<'tcx> BorrowckInferCtxt<'tcx> {
     #[instrument(skip(self), level = "debug")]
     fn replace_free_regions_with_nll_infer_vars<T>(
         &self,
diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs
index 92efeab08eb..085ea3458bb 100644
--- a/compiler/rustc_builtin_macros/src/assert/context.rs
+++ b/compiler/rustc_builtin_macros/src/assert/context.rs
@@ -120,10 +120,13 @@ impl<'cx, 'a> Context<'cx, 'a> {
                 thin_vec![self.cx.attr_nested_word(sym::allow, sym::unused_imports, self.span)],
                 ItemKind::Use(UseTree {
                     prefix: self.cx.path(self.span, self.cx.std_path(&[sym::asserting])),
-                    kind: UseTreeKind::Nested(thin_vec![
-                        nested_tree(self, sym::TryCaptureGeneric),
-                        nested_tree(self, sym::TryCapturePrintable),
-                    ]),
+                    kind: UseTreeKind::Nested {
+                        items: thin_vec![
+                            nested_tree(self, sym::TryCaptureGeneric),
+                            nested_tree(self, sym::TryCapturePrintable),
+                        ],
+                        span: self.span,
+                    },
                     span: self.span,
                 }),
             ),
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
index dc73caa4ad5..a6457f4a433 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
@@ -31,7 +31,7 @@ pub(crate) fn expand_deriving_partial_eq(
                     };
 
                     // We received arguments of type `&T`. Convert them to type `T` by stripping
-                    // any leading `&` or adding `*`. This isn't necessary for type checking, but
+                    // any leading `&`. This isn't necessary for type checking, but
                     // it results in better error messages if something goes wrong.
                     //
                     // Note: for arguments that look like `&{ x }`, which occur with packed
@@ -53,8 +53,7 @@ pub(crate) fn expand_deriving_partial_eq(
                                 inner.clone()
                             }
                         } else {
-                            // No leading `&`: add a leading `*`.
-                            cx.expr_deref(field.span, expr.clone())
+                            expr.clone()
                         }
                     };
                     cx.expr_binary(
diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs
index d6e2d1d4d07..e3a93ae13e4 100644
--- a/compiler/rustc_builtin_macros/src/deriving/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs
@@ -123,7 +123,7 @@ fn assert_ty_bounds(
     span: Span,
     assert_path: &[Symbol],
 ) {
-    // Deny anonymous structs or unions to avoid wierd errors.
+    // Deny anonymous structs or unions to avoid weird errors.
     assert!(!ty.kind.is_anon_adt(), "Anonymous structs or unions cannot be type parameters");
     // Generate statement `let _: assert_path<ty>;`.
     let span = cx.with_def_site_ctxt(span);
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 2450ac8f4b3..a5fc74f1d66 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -7,14 +7,13 @@ use rustc_ast::{token, StmtKind};
 use rustc_ast::{
     Expr, ExprKind, FormatAlignment, FormatArgPosition, FormatArgPositionKind, FormatArgs,
     FormatArgsPiece, FormatArgument, FormatArgumentKind, FormatArguments, FormatCount,
-    FormatDebugHex, FormatOptions, FormatPlaceholder, FormatSign, FormatTrait,
+    FormatDebugHex, FormatOptions, FormatPlaceholder, FormatSign, FormatTrait, Recovered,
 };
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{Applicability, Diag, MultiSpan, PResult, SingleLabelManySpans};
 use rustc_expand::base::*;
 use rustc_lint_defs::builtin::NAMED_ARGUMENTS_USED_POSITIONALLY;
 use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiag, LintId};
-use rustc_parse::parser::Recovered;
 use rustc_parse_format as parse;
 use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::{BytePos, ErrorGuaranteed, InnerSpan, Span};
@@ -112,7 +111,7 @@ fn parse_args<'a>(ecx: &ExtCtxt<'a>, sp: Span, tts: TokenStream) -> PResult<'a,
                         _ => return Err(err),
                     }
                 }
-                Ok(Recovered::Yes) => (),
+                Ok(Recovered::Yes(_)) => (),
                 Ok(Recovered::No) => unreachable!(),
             }
         }
@@ -315,7 +314,7 @@ fn make_format_args(
 
     let mut used = vec![false; args.explicit_args().len()];
     let mut invalid_refs = Vec::new();
-    let mut numeric_refences_to_named_arg = Vec::new();
+    let mut numeric_references_to_named_arg = Vec::new();
 
     enum ArgRef<'a> {
         Index(usize),
@@ -336,7 +335,7 @@ fn make_format_args(
                     used[index] = true;
                     if arg.kind.ident().is_some() {
                         // This was a named argument, but it was used as a positional argument.
-                        numeric_refences_to_named_arg.push((index, span, used_as));
+                        numeric_references_to_named_arg.push((index, span, used_as));
                     }
                     Ok(index)
                 } else {
@@ -544,7 +543,7 @@ fn make_format_args(
     // Only check for unused named argument names if there are no other errors to avoid causing
     // too much noise in output errors, such as when a named argument is entirely unused.
     if invalid_refs.is_empty() && !has_unused && !unnamed_arg_after_named_arg {
-        for &(index, span, used_as) in &numeric_refences_to_named_arg {
+        for &(index, span, used_as) in &numeric_references_to_named_arg {
             let (position_sp_to_replace, position_sp_for_msg) = match used_as {
                 Placeholder(pspan) => (span, pspan),
                 Precision => {
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index e3d050df4cd..8874efadec9 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -670,11 +670,8 @@ fn codegen_stmt<'tcx>(
                     let to_ty = fx.monomorphize(to_ty);
 
                     fn is_fat_ptr<'tcx>(fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> bool {
-                        ty.builtin_deref(true).is_some_and(
-                            |ty::TypeAndMut { ty: pointee_ty, mutbl: _ }| {
-                                has_ptr_meta(fx.tcx, pointee_ty)
-                            },
-                        )
+                        ty.builtin_deref(true)
+                            .is_some_and(|pointee_ty| has_ptr_meta(fx.tcx, pointee_ty))
                     }
 
                     if is_fat_ptr(fx, from_ty) {
diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs
index 2a24d6150bd..21d0cd2d30f 100644
--- a/compiler/rustc_codegen_cranelift/src/common.rs
+++ b/compiler/rustc_codegen_cranelift/src/common.rs
@@ -7,7 +7,7 @@ use rustc_middle::ty::layout::{
 use rustc_middle::ty::TypeFoldable;
 use rustc_span::source_map::Spanned;
 use rustc_target::abi::call::FnAbi;
-use rustc_target::abi::{Integer, Primitive};
+use rustc_target::abi::{Float, Integer, Primitive};
 use rustc_target::spec::{HasTargetSpec, Target};
 
 use crate::constant::ConstantCx;
@@ -32,10 +32,12 @@ pub(crate) fn scalar_to_clif_type(tcx: TyCtxt<'_>, scalar: Scalar) -> Type {
             Integer::I64 => types::I64,
             Integer::I128 => types::I128,
         },
-        Primitive::F16 => unimplemented!("f16_f128"),
-        Primitive::F32 => types::F32,
-        Primitive::F64 => types::F64,
-        Primitive::F128 => unimplemented!("f16_f128"),
+        Primitive::Float(float) => match float {
+            Float::F16 => unimplemented!("f16_f128"),
+            Float::F32 => types::F32,
+            Float::F64 => types::F64,
+            Float::F128 => unimplemented!("f16_f128"),
+        },
         // FIXME(erikdesjardins): handle non-default addrspace ptr sizes
         Primitive::Pointer(_) => pointer_ty(tcx),
     }
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index 79a90507fa2..cafdc051db5 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -586,7 +586,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
             intrinsic_args!(fx, args => (base, offset); intrinsic);
             let offset = offset.load_scalar(fx);
 
-            let pointee_ty = base.layout().ty.builtin_deref(true).unwrap().ty;
+            let pointee_ty = base.layout().ty.builtin_deref(true).unwrap();
             let pointee_size = fx.layout_of(pointee_ty).size.bytes();
             let ptr_diff = if pointee_size != 1 {
                 fx.bcx.ins().imul_imm(offset, pointee_size as i64)
@@ -610,7 +610,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
             let val = val.load_scalar(fx);
             let count = count.load_scalar(fx);
 
-            let pointee_ty = dst.layout().ty.builtin_deref(true).unwrap().ty;
+            let pointee_ty = dst.layout().ty.builtin_deref(true).unwrap();
             let pointee_size = fx.layout_of(pointee_ty).size.bytes();
             let count = if pointee_size != 1 {
                 fx.bcx.ins().imul_imm(count, pointee_size as i64)
@@ -715,7 +715,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
 
             // Cranelift treats loads as volatile by default
             // FIXME correctly handle unaligned_volatile_load
-            let inner_layout = fx.layout_of(ptr.layout().ty.builtin_deref(true).unwrap().ty);
+            let inner_layout = fx.layout_of(ptr.layout().ty.builtin_deref(true).unwrap());
             let val = CValue::by_ref(Pointer::new(ptr.load_scalar(fx)), inner_layout);
             ret.write_cvalue(fx, val);
         }
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
index 67f9d831062..452b5988dab 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
@@ -974,7 +974,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
             intrinsic_args!(fx, args => (ptr, offset); intrinsic);
 
             let (lane_count, ptr_lane_ty) = ptr.layout().ty.simd_size_and_type(fx.tcx);
-            let pointee_ty = ptr_lane_ty.builtin_deref(true).unwrap().ty;
+            let pointee_ty = ptr_lane_ty.builtin_deref(true).unwrap();
             let pointee_size = fx.layout_of(pointee_ty).size.bytes();
             let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);
             let ret_lane_layout = fx.layout_of(ret_lane_ty);
diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs
index c9f84b69997..e72951b6f34 100644
--- a/compiler/rustc_codegen_cranelift/src/lib.rs
+++ b/compiler/rustc_codegen_cranelift/src/lib.rs
@@ -95,7 +95,7 @@ mod prelude {
     pub(crate) use rustc_middle::mir::{self, *};
     pub(crate) use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
     pub(crate) use rustc_middle::ty::{
-        self, FloatTy, Instance, InstanceDef, IntTy, ParamEnv, Ty, TyCtxt, TypeAndMut, UintTy,
+        self, FloatTy, Instance, InstanceDef, IntTy, ParamEnv, Ty, TyCtxt, UintTy,
     };
     pub(crate) use rustc_span::Span;
     pub(crate) use rustc_target::abi::{Abi, FieldIdx, Scalar, Size, VariantIdx, FIRST_VARIANT};
diff --git a/compiler/rustc_codegen_cranelift/src/num.rs b/compiler/rustc_codegen_cranelift/src/num.rs
index 714858084ec..4d96a26ea4f 100644
--- a/compiler/rustc_codegen_cranelift/src/num.rs
+++ b/compiler/rustc_codegen_cranelift/src/num.rs
@@ -388,12 +388,8 @@ pub(crate) fn codegen_ptr_binop<'tcx>(
     in_lhs: CValue<'tcx>,
     in_rhs: CValue<'tcx>,
 ) -> CValue<'tcx> {
-    let is_thin_ptr = in_lhs
-        .layout()
-        .ty
-        .builtin_deref(true)
-        .map(|TypeAndMut { ty, mutbl: _ }| !has_ptr_meta(fx.tcx, ty))
-        .unwrap_or(true);
+    let is_thin_ptr =
+        in_lhs.layout().ty.builtin_deref(true).map(|ty| !has_ptr_meta(fx.tcx, ty)).unwrap_or(true);
 
     if is_thin_ptr {
         match bin_op {
@@ -404,7 +400,7 @@ pub(crate) fn codegen_ptr_binop<'tcx>(
                 codegen_compare_bin_op(fx, bin_op, false, lhs, rhs)
             }
             BinOp::Offset => {
-                let pointee_ty = in_lhs.layout().ty.builtin_deref(true).unwrap().ty;
+                let pointee_ty = in_lhs.layout().ty.builtin_deref(true).unwrap();
                 let (base, offset) = (in_lhs, in_rhs.load_scalar(fx));
                 let pointee_size = fx.layout_of(pointee_ty).size.bytes();
                 let ptr_diff = fx.bcx.ins().imul_imm(offset, pointee_size as i64);
diff --git a/compiler/rustc_codegen_cranelift/src/unsize.rs b/compiler/rustc_codegen_cranelift/src/unsize.rs
index f33bacb99a3..4acbc8a27ed 100644
--- a/compiler/rustc_codegen_cranelift/src/unsize.rs
+++ b/compiler/rustc_codegen_cranelift/src/unsize.rs
@@ -127,7 +127,7 @@ pub(crate) fn coerce_unsized_into<'tcx>(
     let dst_ty = dst.layout().ty;
     let mut coerce_ptr = || {
         let (base, info) =
-            if fx.layout_of(src.layout().ty.builtin_deref(true).unwrap().ty).is_unsized() {
+            if fx.layout_of(src.layout().ty.builtin_deref(true).unwrap()).is_unsized() {
                 let (old_base, old_info) = src.load_scalar_pair(fx);
                 unsize_ptr(fx, old_base, src.layout(), dst.layout(), Some(old_info))
             } else {
diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
index dded6df7771..a11abd0c0e9 100644
--- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs
+++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
@@ -819,7 +819,7 @@ impl<'tcx> CPlace<'tcx> {
     }
 
     pub(crate) fn place_deref(self, fx: &mut FunctionCx<'_, '_, 'tcx>) -> CPlace<'tcx> {
-        let inner_layout = fx.layout_of(self.layout().ty.builtin_deref(true).unwrap().ty);
+        let inner_layout = fx.layout_of(self.layout().ty.builtin_deref(true).unwrap());
         if has_ptr_meta(fx.tcx, inner_layout.ty) {
             let (addr, extra) = self.to_cvalue(fx).load_scalar_pair(fx);
             CPlace::for_ptr_with_extra(Pointer::new(addr), extra, inner_layout)
diff --git a/compiler/rustc_codegen_cranelift/src/vtable.rs b/compiler/rustc_codegen_cranelift/src/vtable.rs
index 04e24320f91..14c607ccad7 100644
--- a/compiler/rustc_codegen_cranelift/src/vtable.rs
+++ b/compiler/rustc_codegen_cranelift/src/vtable.rs
@@ -59,7 +59,7 @@ pub(crate) fn get_ptr_and_method_ref<'tcx>(
 
         if let ty::Ref(_, ty, _) = arg.layout().ty.kind() {
             if ty.is_dyn_star() {
-                let inner_layout = fx.layout_of(arg.layout().ty.builtin_deref(true).unwrap().ty);
+                let inner_layout = fx.layout_of(arg.layout().ty.builtin_deref(true).unwrap());
                 let dyn_star = CPlace::for_ptr(Pointer::new(arg.load_scalar(fx)), inner_layout);
                 let ptr = dyn_star.place_field(fx, FieldIdx::ZERO).to_ptr();
                 let vtable =
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index 23a5e5ff873..4a3b6f678c4 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -1301,19 +1301,13 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     fn memmove(
         &mut self,
         dst: RValue<'gcc>,
-        dst_align: Align,
+        _dst_align: Align,
         src: RValue<'gcc>,
-        src_align: Align,
+        _src_align: Align,
         size: RValue<'gcc>,
         flags: MemFlags,
     ) {
-        if flags.contains(MemFlags::NONTEMPORAL) {
-            // HACK(nox): This is inefficient but there is no nontemporal memmove.
-            let val = self.load(src.get_type().get_pointee().expect("get_pointee"), src, src_align);
-            let ptr = self.pointercast(dst, self.type_ptr_to(self.val_ty(val)));
-            self.store_with_flags(val, ptr, dst_align, flags);
-            return;
-        }
+        assert!(!flags.contains(MemFlags::NONTEMPORAL), "non-temporal memmove not supported");
         let size = self.intcast(size, self.type_size_t(), false);
         let _is_volatile = flags.contains(MemFlags::VOLATILE);
         let dst = self.pointercast(dst, self.type_i8p());
@@ -1335,6 +1329,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         _align: Align,
         flags: MemFlags,
     ) {
+        assert!(!flags.contains(MemFlags::NONTEMPORAL), "non-temporal memset not supported");
         let _is_volatile = flags.contains(MemFlags::VOLATILE);
         let ptr = self.pointercast(ptr, self.type_i8p());
         let memset = self.context.get_builtin_function("memset");
diff --git a/compiler/rustc_codegen_gcc/src/debuginfo.rs b/compiler/rustc_codegen_gcc/src/debuginfo.rs
index aed15769025..1d0a6d9f09b 100644
--- a/compiler/rustc_codegen_gcc/src/debuginfo.rs
+++ b/compiler/rustc_codegen_gcc/src/debuginfo.rs
@@ -1,10 +1,9 @@
-use crate::rustc_index::Idx;
 use gccjit::{Location, RValue};
 use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind};
 use rustc_codegen_ssa::traits::{DebugInfoBuilderMethods, DebugInfoMethods};
 use rustc_data_structures::sync::Lrc;
 use rustc_index::bit_set::BitSet;
-use rustc_index::IndexVec;
+use rustc_index::{Idx, IndexVec};
 use rustc_middle::mir::{self, Body, SourceScope};
 use rustc_middle::ty::{Instance, PolyExistentialTraitRef, Ty};
 use rustc_session::config::DebugInfo;
diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs
index 8f9bfbbd18f..2155cabe171 100644
--- a/compiler/rustc_codegen_gcc/src/type_of.rs
+++ b/compiler/rustc_codegen_gcc/src/type_of.rs
@@ -1,15 +1,15 @@
 use std::fmt::Write;
 
-use crate::rustc_codegen_ssa::traits::{BaseTypeMethods, DerivedTypeMethods, LayoutTypeMethods};
 use gccjit::{Struct, Type};
+use rustc_codegen_ssa::traits::{BaseTypeMethods, DerivedTypeMethods, LayoutTypeMethods};
 use rustc_middle::bug;
 use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self, Ty, TypeVisitableExt};
 use rustc_target::abi::call::{CastTarget, FnAbi, Reg};
 use rustc_target::abi::{
-    self, Abi, Align, FieldsShape, Int, Integer, PointeeInfo, Pointer, Size, TyAbiInterface,
-    Variants, F128, F16, F32, F64,
+    self, Abi, Align, FieldsShape, Float, Int, Integer, PointeeInfo, Pointer, Size, TyAbiInterface,
+    Variants,
 };
 
 use crate::abi::{FnAbiGcc, FnAbiGccExt, GccType};
@@ -205,7 +205,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
     /// of that field's type - this is useful for taking the address of
     /// that field and ensuring the struct has the right alignment.
     fn gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> {
-        use crate::rustc_middle::ty::layout::FnAbiOf;
+        use rustc_middle::ty::layout::FnAbiOf;
         // 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.
@@ -283,10 +283,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
         match scalar.primitive() {
             Int(i, true) => cx.type_from_integer(i),
             Int(i, false) => cx.type_from_unsigned_integer(i),
-            F16 => cx.type_f16(),
-            F32 => cx.type_f32(),
-            F64 => cx.type_f64(),
-            F128 => cx.type_f128(),
+            Float(f) => cx.type_from_float(f),
             Pointer(address_space) => {
                 // If we know the alignment, pick something better than i8.
                 let pointee = if let Some(pointee) = self.pointee_info_at(cx, offset) {
diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs
index 123aef0f310..a6a3f0f9646 100644
--- a/compiler/rustc_codegen_llvm/src/abi.rs
+++ b/compiler/rustc_codegen_llvm/src/abi.rs
@@ -583,7 +583,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
         let element_type_index = unsafe { llvm::LLVMRustGetElementTypeArgIndex(callsite) };
         if element_type_index >= 0 {
             let arg_ty = self.args[element_type_index as usize].layout.ty;
-            let pointee_ty = arg_ty.builtin_deref(true).expect("Must be pointer argument").ty;
+            let pointee_ty = arg_ty.builtin_deref(true).expect("Must be pointer argument");
             let element_type_attr = unsafe {
                 llvm::LLVMRustCreateElementTypeAttr(bx.llcx, bx.layout_of(pointee_ty).llvm_type(bx))
             };
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs
index e09869cf425..71d4343ee07 100644
--- a/compiler/rustc_codegen_llvm/src/asm.rs
+++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -904,8 +904,8 @@ fn llvm_asm_scalar_type<'ll>(cx: &CodegenCx<'ll, '_>, scalar: Scalar) -> &'ll Ty
         Primitive::Int(Integer::I16, _) => cx.type_i16(),
         Primitive::Int(Integer::I32, _) => cx.type_i32(),
         Primitive::Int(Integer::I64, _) => cx.type_i64(),
-        Primitive::F32 => cx.type_f32(),
-        Primitive::F64 => cx.type_f64(),
+        Primitive::Float(Float::F32) => cx.type_f32(),
+        Primitive::Float(Float::F64) => cx.type_f64(),
         // FIXME(erikdesjardins): handle non-default addrspace ptr sizes
         Primitive::Pointer(_) => cx.type_from_integer(dl.ptr_sized_integer()),
         _ => unreachable!(),
@@ -950,7 +950,7 @@ fn llvm_fixup_input<'ll, 'tcx>(
             bx.shuffle_vector(value, bx.const_undef(vec_ty), bx.const_vector(&indices))
         }
         (InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd), Abi::Scalar(s))
-            if s.primitive() == Primitive::F64 =>
+            if s.primitive() == Primitive::Float(Float::F64) =>
         {
             bx.bitcast(value, bx.cx.type_i64())
         }
@@ -986,8 +986,8 @@ fn llvm_fixup_input<'ll, 'tcx>(
             match s.primitive() {
                 // MIPS only supports register-length arithmetics.
                 Primitive::Int(Integer::I8 | Integer::I16, _) => bx.zext(value, bx.cx.type_i32()),
-                Primitive::F32 => bx.bitcast(value, bx.cx.type_i32()),
-                Primitive::F64 => bx.bitcast(value, bx.cx.type_i64()),
+                Primitive::Float(Float::F32) => bx.bitcast(value, bx.cx.type_i32()),
+                Primitive::Float(Float::F64) => bx.bitcast(value, bx.cx.type_i64()),
                 _ => value,
             }
         }
@@ -1027,7 +1027,7 @@ fn llvm_fixup_output<'ll, 'tcx>(
             bx.shuffle_vector(value, bx.const_undef(vec_ty), bx.const_vector(&indices))
         }
         (InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd), Abi::Scalar(s))
-            if s.primitive() == Primitive::F64 =>
+            if s.primitive() == Primitive::Float(Float::F64) =>
         {
             bx.bitcast(value, bx.cx.type_f64())
         }
@@ -1064,8 +1064,8 @@ fn llvm_fixup_output<'ll, 'tcx>(
                 // MIPS only supports register-length arithmetics.
                 Primitive::Int(Integer::I8, _) => bx.trunc(value, bx.cx.type_i8()),
                 Primitive::Int(Integer::I16, _) => bx.trunc(value, bx.cx.type_i16()),
-                Primitive::F32 => bx.bitcast(value, bx.cx.type_f32()),
-                Primitive::F64 => bx.bitcast(value, bx.cx.type_f64()),
+                Primitive::Float(Float::F32) => bx.bitcast(value, bx.cx.type_f32()),
+                Primitive::Float(Float::F64) => bx.bitcast(value, bx.cx.type_f64()),
                 _ => value,
             }
         }
@@ -1100,7 +1100,7 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
             cx.type_vector(elem_ty, count * 2)
         }
         (InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd), Abi::Scalar(s))
-            if s.primitive() == Primitive::F64 =>
+            if s.primitive() == Primitive::Float(Float::F64) =>
         {
             cx.type_i64()
         }
@@ -1136,8 +1136,8 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
             match s.primitive() {
                 // MIPS only supports register-length arithmetics.
                 Primitive::Int(Integer::I8 | Integer::I16, _) => cx.type_i32(),
-                Primitive::F32 => cx.type_i32(),
-                Primitive::F64 => cx.type_i64(),
+                Primitive::Float(Float::F32) => cx.type_i32(),
+                Primitive::Float(Float::F64) => cx.type_i64(),
                 _ => layout.llvm_type(cx),
             }
         }
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 1a1b4ae3831..230c58dfcaf 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -576,7 +576,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
                         }
                     }
                 }
-                abi::F16 | abi::F32 | abi::F64 | abi::F128 => {}
+                abi::Float(_) => {}
             }
         }
 
@@ -976,6 +976,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         align: Align,
         flags: MemFlags,
     ) {
+        assert!(!flags.contains(MemFlags::NONTEMPORAL), "non-temporal memset not supported");
         let is_volatile = flags.contains(MemFlags::VOLATILE);
         unsafe {
             llvm::LLVMRustBuildMemSet(
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 653abb4e41b..53a098d178e 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -133,6 +133,15 @@ pub unsafe fn create_module<'ll>(
         }
     }
 
+    if llvm_version < (19, 0, 0) {
+        if sess.target.arch == "aarch64" || sess.target.arch.starts_with("arm64") {
+            // LLVM 19 sets -Fn32 in its data layout string for 64-bit ARM
+            // Earlier LLVMs leave this default, so remove it.
+            // See https://github.com/llvm/llvm-project/pull/90702
+            target_data_layout = target_data_layout.replace("-Fn32", "");
+        }
+    }
+
     // Ensure the data-layout values hardcoded remain the defaults.
     {
         let tm = crate::back::write::create_informational_target_machine(tcx.sess);
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index e5fecddec52..f44738ba642 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -1281,7 +1281,7 @@ fn build_generic_type_param_di_nodes<'ll, 'tcx>(
         let mut names = generics
             .parent
             .map_or_else(Vec::new, |def_id| get_parameter_names(cx, cx.tcx.generics_of(def_id)));
-        names.extend(generics.params.iter().map(|param| param.name));
+        names.extend(generics.own_params.iter().map(|param| param.name));
         names
     }
 }
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 657e9ce998f..bacd74f430f 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
@@ -122,10 +122,7 @@ fn tag_base_type<'ll, 'tcx>(
             // Niche tags are always normalized to unsized integers of the correct size.
             match tag.primitive() {
                 Primitive::Int(t, _) => t,
-                Primitive::F16 => Integer::I16,
-                Primitive::F32 => Integer::I32,
-                Primitive::F64 => Integer::I64,
-                Primitive::F128 => Integer::I128,
+                Primitive::Float(f) => Integer::from_size(f.size()).unwrap(),
                 // FIXME(erikdesjardins): handle non-default addrspace ptr sizes
                 Primitive::Pointer(_) => {
                     // If the niche is the NULL value of a reference, then `discr_enum_ty` will be
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index 4fdaa59e0e5..6149c18696c 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -512,7 +512,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
             let mut names = generics.parent.map_or_else(Vec::new, |def_id| {
                 get_parameter_names(cx, cx.tcx.generics_of(def_id))
             });
-            names.extend(generics.params.iter().map(|param| param.name));
+            names.extend(generics.own_params.iter().map(|param| param.name));
             names
         }
 
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index 56550dbfa4b..b0b867701a4 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -18,7 +18,7 @@ use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf};
 use rustc_middle::ty::{self, GenericArgsRef, Ty};
 use rustc_middle::{bug, span_bug};
 use rustc_span::{sym, Span, Symbol};
-use rustc_target::abi::{self, Align, HasDataLayout, Primitive, Size};
+use rustc_target::abi::{self, Align, Float, HasDataLayout, Primitive, Size};
 use rustc_target::spec::{HasTargetSpec, PanicStrategy};
 
 use std::cmp::Ordering;
@@ -231,13 +231,17 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
                                     emit_va_arg(self, args[0], ret_ty)
                                 }
                             }
-                            Primitive::F16 => bug!("the va_arg intrinsic does not work with `f16`"),
-                            Primitive::F64 | Primitive::Pointer(_) => {
+                            Primitive::Float(Float::F16) => {
+                                bug!("the va_arg intrinsic does not work with `f16`")
+                            }
+                            Primitive::Float(Float::F64) | Primitive::Pointer(_) => {
                                 emit_va_arg(self, args[0], ret_ty)
                             }
                             // `va_arg` should never be used with the return type f32.
-                            Primitive::F32 => bug!("the va_arg intrinsic does not work with `f32`"),
-                            Primitive::F128 => {
+                            Primitive::Float(Float::F32) => {
+                                bug!("the va_arg intrinsic does not work with `f32`")
+                            }
+                            Primitive::Float(Float::F128) => {
                                 bug!("the va_arg intrinsic does not work with `f128`")
                             }
                         }
@@ -2383,7 +2387,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
         let pointee = in_elem.builtin_deref(true).unwrap_or_else(|| {
             span_bug!(span, "must be called with a vector of pointer types as first argument")
         });
-        let layout = bx.layout_of(pointee.ty);
+        let layout = bx.layout_of(pointee);
         let ptrs = args[0].immediate();
         // The second argument must be a ptr-sized integer.
         // (We don't care about the signedness, this is wrapping anyway.)
diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs
index 40ed6baa610..5f60fd23a5f 100644
--- a/compiler/rustc_codegen_llvm/src/type_of.rs
+++ b/compiler/rustc_codegen_llvm/src/type_of.rs
@@ -6,7 +6,7 @@ use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
 use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
 use rustc_middle::ty::{self, Ty, TypeVisitableExt};
 use rustc_target::abi::{Abi, Align, FieldsShape};
-use rustc_target::abi::{Int, Pointer, F128, F16, F32, F64};
+use rustc_target::abi::{Float, Int, Pointer};
 use rustc_target::abi::{Scalar, Size, Variants};
 
 use std::fmt::Write;
@@ -272,10 +272,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
     fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, scalar: Scalar) -> &'a Type {
         match scalar.primitive() {
             Int(i, _) => cx.type_from_integer(i),
-            F16 => cx.type_f16(),
-            F32 => cx.type_f32(),
-            F64 => cx.type_f64(),
-            F128 => cx.type_f128(),
+            Float(f) => cx.type_from_float(f),
             Pointer(address_space) => cx.type_ptr_ext(address_space),
         }
     }
diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml
index f347a7fb0bb..3771fc6b0a2 100644
--- a/compiler/rustc_codegen_ssa/Cargo.toml
+++ b/compiler/rustc_codegen_ssa/Cargo.toml
@@ -6,8 +6,10 @@ edition = "2021"
 [dependencies]
 # tidy-alphabetical-start
 ar_archive_writer = "0.2.0"
+arrayvec = { version = "0.7", default-features = false }
 bitflags = "2.4.1"
 cc = "1.0.90"
+either = "1.5.0"
 itertools = "0.12"
 jobserver = "0.1.28"
 pathdiff = "0.2.0"
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 1f691d14c53..6939674ce9d 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -3127,7 +3127,13 @@ fn add_lld_args(
 
     // 2. Implement the "linker flavor" part of this feature by asking `cc` to use some kind of
     // `lld` as the linker.
-    cmd.arg("-fuse-ld=lld");
+    //
+    // Note that wasm targets skip this step since the only option there anyway
+    // is to use LLD but the `wasm32-wasip2` target relies on a wrapper around
+    // this, `wasm-component-ld`, which is overridden if this option is passed.
+    if !sess.target.is_like_wasm {
+        cmd.arg("-fuse-ld=lld");
+    }
 
     if !flavor.is_gnu() {
         // Tell clang to use a non-default LLD flavor.
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index be5458523d1..d36972d0d86 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -540,7 +540,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     //                \-------/
                     //
                     let virtual_drop = Instance {
-                        def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0),
+                        def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0), // idx 0: the drop function
                         args: drop_fn.args,
                     };
                     debug!("ty = {:?}", ty);
@@ -581,7 +581,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     //
                     // SO THEN WE CAN USE THE ABOVE CODE.
                     let virtual_drop = Instance {
-                        def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0),
+                        def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0), // idx 0: the drop function
                         args: drop_fn.args,
                     };
                     debug!("ty = {:?}", ty);
@@ -649,8 +649,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             return helper.funclet_br(self, bx, target, mergeable_succ);
         }
 
-        // Pass the condition through llvm.expect for branch hinting.
-        let cond = bx.expect(cond, expected);
+        // Because we're branching to a panic block (either a `#[cold]` one
+        // or an inlined abort), there's no need to `expect` it.
 
         // Create the failure block and the conditional branch to it.
         let lltarget = helper.llbb_with_cleanup(self, target);
@@ -1060,7 +1060,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
                         // Make sure that we've actually unwrapped the rcvr down
                         // to a pointer or ref to `dyn* Trait`.
-                        if !op.layout.ty.builtin_deref(true).unwrap().ty.is_dyn_star() {
+                        if !op.layout.ty.builtin_deref(true).unwrap().is_dyn_star() {
                             span_bug!(span, "can't codegen a virtual call on {:#?}", op);
                         }
                         let place = op.deref(bx.cx());
diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
index 50bf1ef61f3..6b89636b654 100644
--- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
@@ -120,7 +120,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> DebugInfoOffsetLocation<'tcx, Bx>
 {
     fn deref(&self, bx: &mut Bx) -> Self {
         bx.cx().layout_of(
-            self.ty.builtin_deref(true).unwrap_or_else(|| bug!("cannot deref `{}`", self.ty)).ty,
+            self.ty.builtin_deref(true).unwrap_or_else(|| bug!("cannot deref `{}`", self.ty)),
         )
     }
 
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index 38f77f2e646..0479dd11ed0 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -14,6 +14,9 @@ use rustc_target::abi::{self, Abi, Align, Size};
 
 use std::fmt;
 
+use arrayvec::ArrayVec;
+use either::Either;
+
 /// The representation of a Rust value. The enum variant is in fact
 /// uniquely determined by the value's type, but is kept as a
 /// safety check.
@@ -58,6 +61,33 @@ pub enum OperandValue<V> {
     ZeroSized,
 }
 
+impl<V> OperandValue<V> {
+    /// If this is ZeroSized/Immediate/Pair, return an array of the 0/1/2 values.
+    /// If this is Ref, return the place.
+    #[inline]
+    pub fn immediates_or_place(self) -> Either<ArrayVec<V, 2>, PlaceValue<V>> {
+        match self {
+            OperandValue::ZeroSized => Either::Left(ArrayVec::new()),
+            OperandValue::Immediate(a) => Either::Left(ArrayVec::from_iter([a])),
+            OperandValue::Pair(a, b) => Either::Left([a, b].into()),
+            OperandValue::Ref(p) => Either::Right(p),
+        }
+    }
+
+    /// Given an array of 0/1/2 immediate values, return ZeroSized/Immediate/Pair.
+    #[inline]
+    pub fn from_immediates(immediates: ArrayVec<V, 2>) -> Self {
+        let mut it = immediates.into_iter();
+        let Some(a) = it.next() else {
+            return OperandValue::ZeroSized;
+        };
+        let Some(b) = it.next() else {
+            return OperandValue::Immediate(a);
+        };
+        OperandValue::Pair(a, b)
+    }
+}
+
 /// An `OperandRef` is an "SSA" reference to a Rust value, along with
 /// its type.
 ///
@@ -215,8 +245,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
             .layout
             .ty
             .builtin_deref(true)
-            .unwrap_or_else(|| bug!("deref of non-pointer {:?}", self))
-            .ty;
+            .unwrap_or_else(|| bug!("deref of non-pointer {:?}", self));
 
         let (llptr, llextra) = match self.val {
             OperandValue::Immediate(llptr) => (llptr, None),
@@ -455,8 +484,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
             .layout
             .ty
             .builtin_deref(true)
-            .unwrap_or_else(|| bug!("indirect_dest has non-pointer type: {:?}", indirect_dest))
-            .ty;
+            .unwrap_or_else(|| bug!("indirect_dest has non-pointer type: {:?}", indirect_dest));
 
         let OperandValue::Ref(PlaceValue { llval: llptr, llextra: Some(llextra), .. }) = self
         else {
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index 4e7d251a2e9..2976ca14c92 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -8,14 +8,16 @@ use crate::traits::*;
 use crate::MemFlags;
 
 use rustc_hir as hir;
-use rustc_middle::mir::{self, AggregateKind, Operand};
+use rustc_middle::mir;
 use rustc_middle::ty::cast::{CastTy, IntTy};
 use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
 use rustc_middle::ty::{self, adjustment::PointerCoercion, Instance, Ty, TyCtxt};
 use rustc_middle::{bug, span_bug};
 use rustc_session::config::OptLevel;
 use rustc_span::{Span, DUMMY_SP};
-use rustc_target::abi::{self, FIRST_VARIANT};
+use rustc_target::abi::{self, FieldIdx, FIRST_VARIANT};
+
+use arrayvec::ArrayVec;
 
 impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     #[instrument(level = "trace", skip(self, bx))]
@@ -306,17 +308,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         self.assume_scalar_range(bx, imm, from_scalar, from_backend_ty);
 
         imm = match (from_scalar.primitive(), to_scalar.primitive()) {
-            (Int(..) | F16 | F32 | F64 | F128, Int(..) | F16 | F32 | F64 | F128) => {
-                bx.bitcast(imm, to_backend_ty)
-            }
+            (Int(..) | Float(_), Int(..) | Float(_)) => bx.bitcast(imm, to_backend_ty),
             (Pointer(..), Pointer(..)) => bx.pointercast(imm, to_backend_ty),
             (Int(..), Pointer(..)) => bx.ptradd(bx.const_null(bx.type_ptr()), imm),
             (Pointer(..), Int(..)) => bx.ptrtoint(imm, to_backend_ty),
-            (F16 | F32 | F64 | F128, Pointer(..)) => {
+            (Float(_), Pointer(..)) => {
                 let int_imm = bx.bitcast(imm, bx.cx().type_isize());
                 bx.ptradd(bx.const_null(bx.type_ptr()), int_imm)
             }
-            (Pointer(..), F16 | F32 | F64 | F128) => {
+            (Pointer(..), Float(_)) => {
                 let int_imm = bx.ptrtoint(imm, bx.cx().type_isize());
                 bx.bitcast(int_imm, to_backend_ty)
             }
@@ -581,7 +581,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 self.codegen_place_to_pointer(bx, place, mk_ref)
             }
 
-            mir::Rvalue::CopyForDeref(place) => self.codegen_operand(bx, &Operand::Copy(place)),
+            mir::Rvalue::CopyForDeref(place) => {
+                self.codegen_operand(bx, &mir::Operand::Copy(place))
+            }
             mir::Rvalue::AddressOf(mutability, place) => {
                 let mk_ptr =
                     move |tcx: TyCtxt<'tcx>, ty: Ty<'tcx>| Ty::new_ptr(tcx, ty, mutability);
@@ -738,11 +740,41 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     _ => bug!("RawPtr operands {data:?} {meta:?}"),
                 }
             }
-            mir::Rvalue::Repeat(..) | mir::Rvalue::Aggregate(..) => {
-                // According to `rvalue_creates_operand`, only ZST
-                // aggregate rvalues are allowed to be operands.
+            mir::Rvalue::Repeat(..) => bug!("{rvalue:?} in codegen_rvalue_operand"),
+            mir::Rvalue::Aggregate(_, ref fields) => {
                 let ty = rvalue.ty(self.mir, self.cx.tcx());
-                OperandRef::zero_sized(self.cx.layout_of(self.monomorphize(ty)))
+                let ty = self.monomorphize(ty);
+                let layout = self.cx.layout_of(ty);
+
+                // `rvalue_creates_operand` has arranged that we only get here if
+                // we can build the aggregate immediate from the field immediates.
+                let mut inputs = ArrayVec::<Bx::Value, 2>::new();
+                let mut input_scalars = ArrayVec::<abi::Scalar, 2>::new();
+                for field_idx in layout.fields.index_by_increasing_offset() {
+                    let field_idx = FieldIdx::from_usize(field_idx);
+                    let op = self.codegen_operand(bx, &fields[field_idx]);
+                    let values = op.val.immediates_or_place().left_or_else(|p| {
+                        bug!("Field {field_idx:?} is {p:?} making {layout:?}");
+                    });
+                    inputs.extend(values);
+                    let scalars = self.value_kind(op.layout).scalars().unwrap();
+                    input_scalars.extend(scalars);
+                }
+
+                let output_scalars = self.value_kind(layout).scalars().unwrap();
+                itertools::izip!(&mut inputs, input_scalars, output_scalars).for_each(
+                    |(v, in_s, out_s)| {
+                        if in_s != out_s {
+                            // We have to be really careful about bool here, because
+                            // `(bool,)` stays i1 but `Cell<bool>` becomes i8.
+                            *v = bx.from_immediate(*v);
+                            *v = bx.to_immediate_scalar(*v, out_s);
+                        }
+                    },
+                );
+
+                let val = OperandValue::from_immediates(inputs);
+                OperandRef { val, layout }
             }
             mir::Rvalue::ShallowInitBox(ref operand, content_ty) => {
                 let operand = self.codegen_operand(bx, operand);
@@ -870,8 +902,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             mir::BinOp::Offset => {
                 let pointee_type = input_ty
                     .builtin_deref(true)
-                    .unwrap_or_else(|| bug!("deref of non-pointer {:?}", input_ty))
-                    .ty;
+                    .unwrap_or_else(|| bug!("deref of non-pointer {:?}", input_ty));
                 let pointee_layout = bx.cx().layout_of(pointee_type);
                 if pointee_layout.is_zst() {
                     // `Offset` works in terms of the size of pointee,
@@ -1050,14 +1081,29 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             mir::Rvalue::ThreadLocalRef(_) |
             mir::Rvalue::Use(..) => // (*)
                 true,
-            // This always produces a `ty::RawPtr`, so will be Immediate or Pair
-            mir::Rvalue::Aggregate(box AggregateKind::RawPtr(..), ..) => true,
-            mir::Rvalue::Repeat(..) |
-            mir::Rvalue::Aggregate(..) => {
+            // Arrays are always aggregates, so it's not worth checking anything here.
+            // (If it's really `[(); N]` or `[T; 0]` and we use the place path, fine.)
+            mir::Rvalue::Repeat(..) => false,
+            mir::Rvalue::Aggregate(ref kind, _) => {
+                let allowed_kind = match **kind {
+                    // This always produces a `ty::RawPtr`, so will be Immediate or Pair
+                    mir::AggregateKind::RawPtr(..) => true,
+                    mir::AggregateKind::Array(..) => false,
+                    mir::AggregateKind::Tuple => true,
+                    mir::AggregateKind::Adt(def_id, ..) => {
+                        let adt_def = self.cx.tcx().adt_def(def_id);
+                        adt_def.is_struct() && !adt_def.repr().simd()
+                    }
+                    mir::AggregateKind::Closure(..) => true,
+                    // FIXME: Can we do this for simple coroutines too?
+                    mir::AggregateKind::Coroutine(..) | mir::AggregateKind::CoroutineClosure(..) => false,
+                };
+                allowed_kind && {
                 let ty = rvalue.ty(self.mir, self.cx.tcx());
                 let ty = self.monomorphize(ty);
-                // For ZST this can be `OperandValueKind::ZeroSized`.
-                self.cx.spanned_layout_of(ty, span).is_zst()
+                    let layout = self.cx.spanned_layout_of(ty, span);
+                    !self.cx.is_backend_ref(layout)
+                }
             }
         }
 
@@ -1099,3 +1145,14 @@ enum OperandValueKind {
     Pair(abi::Scalar, abi::Scalar),
     ZeroSized,
 }
+
+impl OperandValueKind {
+    fn scalars(self) -> Option<ArrayVec<abi::Scalar, 2>> {
+        Some(match self {
+            OperandValueKind::ZeroSized => ArrayVec::new(),
+            OperandValueKind::Immediate(a) => ArrayVec::from_iter([a]),
+            OperandValueKind::Pair(a, b) => [a, b].into(),
+            OperandValueKind::Ref => return None,
+        })
+    }
+}
diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs
index ccb35629a82..403f6a73277 100644
--- a/compiler/rustc_codegen_ssa/src/traits/type_.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs
@@ -7,7 +7,7 @@ use rustc_middle::bug;
 use rustc_middle::ty::layout::TyAndLayout;
 use rustc_middle::ty::{self, Ty};
 use rustc_target::abi::call::{ArgAbi, CastTarget, FnAbi, Reg};
-use rustc_target::abi::{AddressSpace, Integer};
+use rustc_target::abi::{AddressSpace, Float, Integer};
 
 // This depends on `Backend` and not `BackendTypes`, because consumers will probably want to use
 // `LayoutOf` or `HasTyCtxt`. This way, they don't have to add a constraint on it themselves.
@@ -65,6 +65,16 @@ pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> {
         }
     }
 
+    fn type_from_float(&self, f: Float) -> Self::Type {
+        use Float::*;
+        match f {
+            F16 => self.type_f16(),
+            F32 => self.type_f32(),
+            F64 => self.type_f64(),
+            F128 => self.type_f128(),
+        }
+    }
+
     fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool {
         ty.needs_drop(self.tcx(), ty::ParamEnv::reveal_all())
     }
diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl
index b79d7441aca..20f0f27517f 100644
--- a/compiler/rustc_const_eval/messages.ftl
+++ b/compiler/rustc_const_eval/messages.ftl
@@ -69,9 +69,6 @@ const_eval_deref_function_pointer =
     accessing {$allocation} which contains a function
 const_eval_deref_vtable_pointer =
     accessing {$allocation} which contains a vtable
-const_eval_different_allocations =
-    `{$name}` called on pointers into different allocations
-
 const_eval_division_by_zero =
     dividing by zero
 const_eval_division_overflow =
@@ -234,12 +231,18 @@ const_eval_not_enough_caller_args =
 const_eval_nullary_intrinsic_fail =
     could not evaluate nullary intrinsic
 
+const_eval_offset_from_different_allocations =
+    `{$name}` called on pointers into different allocations
+const_eval_offset_from_different_integers =
+    `{$name}` called on different pointers without provenance (i.e., without an associated allocation)
 const_eval_offset_from_overflow =
     `{$name}` called when first pointer is too far ahead of second
-
-const_eval_offset_from_test = out-of-bounds `offset_from`
+const_eval_offset_from_test =
+    out-of-bounds `offset_from`
 const_eval_offset_from_underflow =
     `{$name}` called when first pointer is too far before second
+const_eval_offset_from_unsigned_overflow =
+    `ptr_offset_from_unsigned` called when first pointer has smaller offset than second: {$a_offset} < {$b_offset}
 
 const_eval_operator_non_const =
     cannot call non-const operator in {const_eval_const_context}s
@@ -381,8 +384,6 @@ const_eval_unreachable = entering unreachable code
 const_eval_unreachable_unwind =
     unwinding past a stack frame that does not allow unwinding
 
-const_eval_unsigned_offset_from_overflow =
-    `ptr_offset_from_unsigned` called when first pointer has smaller offset than second: {$a_offset} < {$b_offset}
 const_eval_unsized_local = unsized locals are not supported
 const_eval_unstable_const_fn = `{$def_path}` is not yet stable as a const fn
 
diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs
index 763344207c4..2c9eb393e4a 100644
--- a/compiler/rustc_const_eval/src/const_eval/error.rs
+++ b/compiler/rustc_const_eval/src/const_eval/error.rs
@@ -7,7 +7,7 @@ use rustc_middle::mir::AssertKind;
 use rustc_middle::query::TyCtxtAt;
 use rustc_middle::ty::TyCtxt;
 use rustc_middle::ty::{layout::LayoutError, ConstInt};
-use rustc_span::{Span, Symbol, DUMMY_SP};
+use rustc_span::{Span, Symbol};
 
 use super::CompileTimeInterpreter;
 use crate::errors::{self, FrameNote, ReportErrorExt};
@@ -121,7 +121,7 @@ where
 pub(super) fn report<'tcx, C, F, E>(
     tcx: TyCtxt<'tcx>,
     error: InterpError<'tcx>,
-    span: Option<Span>,
+    span: Span,
     get_span_and_frames: C,
     mk: F,
 ) -> ErrorHandled
@@ -135,16 +135,16 @@ where
         // Don't emit a new diagnostic for these errors, they are already reported elsewhere or
         // should remain silent.
         err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => {
-            ErrorHandled::TooGeneric(span.unwrap_or(DUMMY_SP))
+            ErrorHandled::TooGeneric(span)
         }
-        err_inval!(AlreadyReported(guar)) => ErrorHandled::Reported(guar, span.unwrap_or(DUMMY_SP)),
+        err_inval!(AlreadyReported(guar)) => ErrorHandled::Reported(guar, span),
         err_inval!(Layout(LayoutError::ReferencesError(guar))) => {
-            ErrorHandled::Reported(guar.into(), span.unwrap_or(DUMMY_SP))
+            ErrorHandled::Reported(guar.into(), span)
         }
         // Report remaining errors.
         _ => {
             let (our_span, frames) = get_span_and_frames();
-            let span = span.unwrap_or(our_span);
+            let span = span.substitute_dummy(our_span);
             let err = mk(span, frames);
             let mut err = tcx.dcx().create_err(err);
 
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 40afd9f162f..d9f329c8b0e 100644
--- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -12,7 +12,7 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_session::lint;
 use rustc_span::def_id::LocalDefId;
-use rustc_span::Span;
+use rustc_span::{Span, DUMMY_SP};
 use rustc_target::abi::{self, Abi};
 
 use super::{CanAccessMutGlobal, CompileTimeEvalContext, CompileTimeInterpreter};
@@ -222,7 +222,7 @@ pub(super) fn op_to_const<'tcx>(
                 // This codepath solely exists for `valtree_to_const_value` to not need to generate
                 // a `ConstValue::Indirect` for wide references, so it is tightly restricted to just
                 // that case.
-                let pointee_ty = imm.layout.ty.builtin_deref(false).unwrap().ty; // `false` = no raw ptrs
+                let pointee_ty = imm.layout.ty.builtin_deref(false).unwrap(); // `false` = no raw ptrs
                 debug_assert!(
                     matches!(
                         ecx.tcx.struct_tail_without_normalization(pointee_ty).kind(),
@@ -298,7 +298,7 @@ pub fn eval_to_const_value_raw_provider<'tcx>(
             super::report(
                 tcx,
                 error.into_kind(),
-                Some(span),
+                span,
                 || (span, vec![]),
                 |span, _| errors::NullaryIntrinsicError { span },
             )
@@ -406,7 +406,7 @@ fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>(
         super::report(
             *ecx.tcx,
             error,
-            None,
+            DUMMY_SP,
             || super::get_span_and_frames(ecx.tcx, ecx.stack()),
             |span, frames| ConstEvalError { span, error_kind: kind, instance, frame_notes: frames },
         )
@@ -461,7 +461,7 @@ fn report_validation_error<'mir, 'tcx>(
     crate::const_eval::report(
         *ecx.tcx,
         error,
-        None,
+        DUMMY_SP,
         || crate::const_eval::get_span_and_frames(ecx.tcx, ecx.stack()),
         move |span, frames| errors::ValidationFailure { span, ub_note, frames, raw_bytes },
     )
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index 88ce5a7cbeb..52c31629d54 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -8,21 +8,16 @@ use rustc_middle::ty::layout::{LayoutOf as _, ValidityRequirement};
 use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{Ty, TyCtxt};
 use rustc_middle::{
-    mir::{
-        self,
-        interpret::{
-            Allocation, ConstAllocation, GlobalId, InterpResult, PointerArithmetic, Scalar,
-        },
-        BinOp, ConstValue, NonDivergingIntrinsic,
-    },
+    mir::{self, BinOp, ConstValue, NonDivergingIntrinsic},
     ty::layout::TyAndLayout,
 };
 use rustc_span::symbol::{sym, Symbol};
 use rustc_target::abi::Size;
 
 use super::{
-    memory::MemoryKind, util::ensure_monomorphic_enough, CheckInAllocMsg, ImmTy, InterpCx,
-    MPlaceTy, Machine, OpTy, Pointer,
+    memory::MemoryKind, util::ensure_monomorphic_enough, Allocation, CheckInAllocMsg,
+    ConstAllocation, GlobalId, ImmTy, InterpCx, InterpResult, MPlaceTy, Machine, OpTy, Pointer,
+    PointerArithmetic, Scalar,
 };
 
 use crate::fluent_generated as fluent;
@@ -249,14 +244,22 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     match (self.ptr_try_get_alloc_id(a), self.ptr_try_get_alloc_id(b)) {
                         (Err(a), Err(b)) => {
                             // Neither pointer points to an allocation.
-                            // If these are inequal or null, this *will* fail the deref check below.
+                            // This is okay only if they are the same.
+                            if a != b {
+                                // We'd catch this below in the "dereferenceable" check, but
+                                // show a nicer error for this particular case.
+                                throw_ub_custom!(
+                                    fluent::const_eval_offset_from_different_integers,
+                                    name = intrinsic_name,
+                                );
+                            }
                             (a, b)
                         }
                         (Err(_), _) | (_, Err(_)) => {
                             // We managed to find a valid allocation for one pointer, but not the other.
                             // That means they are definitely not pointing to the same allocation.
                             throw_ub_custom!(
-                                fluent::const_eval_different_allocations,
+                                fluent::const_eval_offset_from_different_allocations,
                                 name = intrinsic_name,
                             );
                         }
@@ -264,7 +267,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                             // Found allocation for both. They must be into the same allocation.
                             if a_alloc_id != b_alloc_id {
                                 throw_ub_custom!(
-                                    fluent::const_eval_different_allocations,
+                                    fluent::const_eval_offset_from_different_allocations,
                                     name = intrinsic_name,
                                 );
                             }
@@ -286,7 +289,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                         // a < b
                         if intrinsic_name == sym::ptr_offset_from_unsigned {
                             throw_ub_custom!(
-                                fluent::const_eval_unsigned_offset_from_overflow,
+                                fluent::const_eval_offset_from_unsigned_overflow,
                                 a_offset = a_offset,
                                 b_offset = b_offset,
                             );
@@ -602,7 +605,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         nonoverlapping: bool,
     ) -> InterpResult<'tcx> {
         let count = self.read_target_usize(count)?;
-        let layout = self.layout_of(src.layout.ty.builtin_deref(true).unwrap().ty)?;
+        let layout = self.layout_of(src.layout.ty.builtin_deref(true).unwrap())?;
         let (size, align) = (layout.size, layout.align.abi);
         // `checked_mul` enforces a too small bound (the correct one would probably be target_isize_max),
         // but no actual allocation can be big enough for the difference to be noticeable.
@@ -646,7 +649,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         byte: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
         count: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
     ) -> InterpResult<'tcx> {
-        let layout = self.layout_of(dst.layout.ty.builtin_deref(true).unwrap().ty)?;
+        let layout = self.layout_of(dst.layout.ty.builtin_deref(true).unwrap())?;
 
         let dst = self.read_pointer(dst)?;
         let byte = self.read_scalar(byte)?.to_u8()?;
@@ -685,7 +688,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         lhs: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
         rhs: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
     ) -> InterpResult<'tcx, Scalar<M::Provenance>> {
-        let layout = self.layout_of(lhs.layout.ty.builtin_deref(true).unwrap().ty)?;
+        let layout = self.layout_of(lhs.layout.ty.builtin_deref(true).unwrap())?;
         assert!(layout.is_sized());
 
         let get_bytes = |this: &InterpCx<'mir, 'tcx, M>,
diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs
index 9af755e40de..2d5dbbd58b3 100644
--- a/compiler/rustc_const_eval/src/interpret/operator.rs
+++ b/compiler/rustc_const_eval/src/interpret/operator.rs
@@ -357,7 +357,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             Offset => {
                 let ptr = left.to_scalar().to_pointer(self)?;
                 let offset_count = right.to_scalar().to_target_isize(self)?;
-                let pointee_ty = left.layout.ty.builtin_deref(true).unwrap().ty;
+                let pointee_ty = left.layout.ty.builtin_deref(true).unwrap();
 
                 // We cannot overflow i64 as a type's size must be <= isize::MAX.
                 let pointee_size = i64::try_from(self.layout_of(pointee_ty)?.size.bytes()).unwrap();
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs
index e5241f1ba19..809aca18990 100644
--- a/compiler/rustc_const_eval/src/interpret/place.rs
+++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -415,7 +415,7 @@ where
         val: &ImmTy<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> {
         let pointee_type =
-            val.layout.ty.builtin_deref(true).expect("`ref_to_mplace` called on non-ptr type").ty;
+            val.layout.ty.builtin_deref(true).expect("`ref_to_mplace` called on non-ptr type");
         let layout = self.layout_of(pointee_type)?;
         let (ptr, meta) = val.to_scalar_and_meta();
 
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index 07425f9a686..b474003087b 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -169,10 +169,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             }
 
             Drop { place, target, unwind, replace: _ } => {
-                let frame = self.frame();
-                let ty = place.ty(&frame.body.local_decls, *self.tcx).ty;
-                let ty = self.instantiate_from_frame_and_normalize_erasing_regions(frame, ty)?;
-                let instance = Instance::resolve_drop_in_place(*self.tcx, ty);
+                let place = self.eval_place(place)?;
+                let instance = Instance::resolve_drop_in_place(*self.tcx, place.layout.ty);
                 if let ty::InstanceDef::DropGlue(_, None) = instance.def {
                     // This is the branch we enter if and only if the dropped type has no drop glue
                     // whatsoever. This can happen as a result of monomorphizing a drop of a
@@ -181,8 +179,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     self.go_to_block(target);
                     return Ok(());
                 }
-                let place = self.eval_place(place)?;
-                trace!("TerminatorKind::drop: {:?}, type {}", place, ty);
+                trace!("TerminatorKind::drop: {:?}, type {}", place, place.layout.ty);
                 self.drop_in_place(&place, instance, target, unwind)?;
             }
 
@@ -952,6 +949,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // implementation fail -- a problem shared by rustc.
         let place = self.force_allocation(place)?;
 
+        // We behave a bit different from codegen here.
+        // Codegen creates an `InstanceDef::Virtual` with index 0 (the slot of the drop method) and
+        // then dispatches that to the normal call machinery. However, our call machinery currently
+        // only supports calling `VtblEntry::Method`; it would choke on a `MetadataDropInPlace`. So
+        // instead we do the virtual call stuff ourselves. It's easier here than in `eval_fn_call`
+        // since we can just get a place of the underlying type and use `mplace_to_ref`.
         let place = match place.layout.ty.kind() {
             ty::Dynamic(data, _, ty::Dyn) => {
                 // Dropping a trait object. Need to find actual drop fn.
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index f9786acfc6c..d43dc467c0f 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -738,7 +738,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                 let cause = ObligationCause::new(
                     terminator.source_info.span,
                     self.body.source.def_id().expect_local(),
-                    ObligationCauseCode::ItemObligation(callee),
+                    ObligationCauseCode::WhereClause(callee),
                 );
                 let normalized_predicates = ocx.normalize(&cause, param_env, predicates);
                 ocx.register_obligations(traits::predicates_for_generics(
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
index dda8f3ed87d..247a2889dc5 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
@@ -8,7 +8,7 @@ use rustc_hir::def_id::DefId;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
 use rustc_middle::mir::{self, CallSource};
-use rustc_middle::ty::print::with_no_trimmed_paths;
+use rustc_middle::ty::print::{with_no_trimmed_paths, PrintTraitRefExt as _};
 use rustc_middle::ty::{
     self, suggest_constraining_type_param, Closure, FnDef, FnPtr, GenericArgKind, GenericArgsRef,
     Param, TraitRef, Ty,
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index 837c02a5b76..c95166d84e9 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -1291,7 +1291,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
             )) => {
                 let src_ty = src.ty(&self.body.local_decls, self.tcx);
                 let op_src_ty = if let Some(src_deref) = src_ty.builtin_deref(true) {
-                    src_deref.ty
+                    src_deref
                 } else {
                     self.fail(
                         location,
@@ -1301,7 +1301,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                 };
                 let dst_ty = dst.ty(&self.body.local_decls, self.tcx);
                 let op_dst_ty = if let Some(dst_deref) = dst_ty.builtin_deref(true) {
-                    dst_deref.ty
+                    dst_deref
                 } else {
                     self.fail(
                         location,
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 8c4af5e5132..36597507f47 100644
--- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
+++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
@@ -115,7 +115,7 @@ fn might_permit_raw_init_lax<'tcx>(
 
     // Special magic check for references and boxes (i.e., special pointer types).
     if let Some(pointee) = this.ty.builtin_deref(false) {
-        let pointee = cx.layout_of(pointee.ty)?;
+        let pointee = cx.layout_of(pointee)?;
         // We need to ensure that the LLVM attributes `aligned` and `dereferenceable(size)` are satisfied.
         if pointee.align.abi.bytes() > 1 {
             // 0x01-filling is not aligned.
diff --git a/compiler/rustc_data_structures/src/fingerprint.rs b/compiler/rustc_data_structures/src/fingerprint.rs
index 9995c08345c..1bee159489d 100644
--- a/compiler/rustc_data_structures/src/fingerprint.rs
+++ b/compiler/rustc_data_structures/src/fingerprint.rs
@@ -1,3 +1,4 @@
+use crate::stable_hasher::impl_stable_traits_for_trivial_type;
 use crate::stable_hasher::{Hash64, StableHasher, StableHasherResult};
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use std::hash::{Hash, Hasher};
diff --git a/compiler/rustc_data_structures/src/flock/windows.rs b/compiler/rustc_data_structures/src/flock/windows.rs
index 9be1065135a..7dc72661939 100644
--- a/compiler/rustc_data_structures/src/flock/windows.rs
+++ b/compiler/rustc_data_structures/src/flock/windows.rs
@@ -2,6 +2,7 @@ use std::fs::{File, OpenOptions};
 use std::io;
 use std::os::windows::prelude::*;
 use std::path::Path;
+use tracing::debug;
 
 use windows::{
     Win32::Foundation::{ERROR_INVALID_FUNCTION, HANDLE},
diff --git a/compiler/rustc_data_structures/src/graph/implementation/mod.rs b/compiler/rustc_data_structures/src/graph/implementation/mod.rs
index 3910c6fa46d..8cf4b4153db 100644
--- a/compiler/rustc_data_structures/src/graph/implementation/mod.rs
+++ b/compiler/rustc_data_structures/src/graph/implementation/mod.rs
@@ -22,6 +22,7 @@
 
 use rustc_index::bit_set::BitSet;
 use std::fmt::Debug;
+use tracing::debug;
 
 #[cfg(test)]
 mod tests;
diff --git a/compiler/rustc_data_structures/src/graph/implementation/tests.rs b/compiler/rustc_data_structures/src/graph/implementation/tests.rs
index 3ae5f5868f0..b4dbd65db94 100644
--- a/compiler/rustc_data_structures/src/graph/implementation/tests.rs
+++ b/compiler/rustc_data_structures/src/graph/implementation/tests.rs
@@ -1,4 +1,5 @@
 use crate::graph::implementation::*;
+use tracing::debug;
 
 type TestGraph = Graph<&'static str, &'static str>;
 
diff --git a/compiler/rustc_data_structures/src/graph/scc/mod.rs b/compiler/rustc_data_structures/src/graph/scc/mod.rs
index 5021e5e8fc0..914a6a16348 100644
--- a/compiler/rustc_data_structures/src/graph/scc/mod.rs
+++ b/compiler/rustc_data_structures/src/graph/scc/mod.rs
@@ -10,6 +10,7 @@ use crate::graph::vec_graph::VecGraph;
 use crate::graph::{DirectedGraph, NumEdges, Successors};
 use rustc_index::{Idx, IndexSlice, IndexVec};
 use std::ops::Range;
+use tracing::{debug, instrument};
 
 #[cfg(test)]
 mod tests;
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index 8dd85b25e0e..85b5a3cdb7c 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -42,66 +42,59 @@
 #![feature(unwrap_infallible)]
 // tidy-alphabetical-end
 
-#[macro_use]
-extern crate tracing;
-
-use std::fmt;
-
+pub use atomic_ref::AtomicRef;
+pub use ena::snapshot_vec;
+pub use ena::undo_log;
+pub use ena::unify;
 pub use rustc_index::static_assert_size;
 
-/// This calls the passed function while ensuring it won't be inlined into the caller.
-#[inline(never)]
-#[cold]
-pub fn outline<F: FnOnce() -> R, R>(f: F) -> R {
-    f()
-}
+use std::fmt;
 
+pub mod aligned;
 pub mod base_n;
 pub mod binary_search_util;
 pub mod captures;
+pub mod fingerprint;
 pub mod flat_map_in_place;
 pub mod flock;
+pub mod frozen;
 pub mod fx;
 pub mod graph;
 pub mod intern;
 pub mod jobserver;
-pub mod macros;
+pub mod marker;
+pub mod memmap;
 pub mod obligation_forest;
+pub mod owned_slice;
+pub mod packed;
+pub mod profiling;
+pub mod sharded;
 pub mod sip128;
 pub mod small_c_str;
 pub mod snapshot_map;
-pub mod svh;
-pub use ena::snapshot_vec;
-pub mod memmap;
 pub mod sorted_map;
-#[macro_use]
+pub mod sso;
 pub mod stable_hasher;
-mod atomic_ref;
-pub mod fingerprint;
-pub mod marker;
-pub mod profiling;
-pub mod sharded;
 pub mod stack;
-pub mod sync;
-pub mod tiny_list;
-pub mod transitive_relation;
-pub mod vec_linked_list;
-pub mod work_queue;
-pub use atomic_ref::AtomicRef;
-pub mod aligned;
-pub mod frozen;
-mod hashes;
-pub mod owned_slice;
-pub mod packed;
-pub mod sso;
 pub mod steal;
+pub mod svh;
+pub mod sync;
 pub mod tagged_ptr;
 pub mod temp_dir;
+pub mod transitive_relation;
 pub mod unhash;
 pub mod unord;
+pub mod work_queue;
 
-pub use ena::undo_log;
-pub use ena::unify;
+mod atomic_ref;
+mod hashes;
+
+/// This calls the passed function while ensuring it won't be inlined into the caller.
+#[inline(never)]
+#[cold]
+pub fn outline<F: FnOnce() -> R, R>(f: F) -> R {
+    f()
+}
 
 /// Returns a structure that calls `f` when dropped.
 pub fn defer<F: FnOnce()>(f: F) -> OnDrop<F> {
diff --git a/compiler/rustc_data_structures/src/macros.rs b/compiler/rustc_data_structures/src/macros.rs
deleted file mode 100644
index e05491f6ff6..00000000000
--- a/compiler/rustc_data_structures/src/macros.rs
+++ /dev/null
@@ -1,37 +0,0 @@
-#[macro_export]
-macro_rules! enum_from_u32 {
-    ($(#[$attr:meta])* pub enum $name:ident {
-        $($(#[$var_attr:meta])* $variant:ident = $e:expr,)*
-    }) => {
-        $(#[$attr])*
-        pub enum $name {
-            $($(#[$var_attr])* $variant = $e),*
-        }
-
-        impl $name {
-            pub fn from_u32(u: u32) -> Option<$name> {
-                $(if u == $name::$variant as u32 {
-                    return Some($name::$variant)
-                })*
-                None
-            }
-        }
-    };
-    ($(#[$attr:meta])* pub enum $name:ident {
-        $($(#[$var_attr:meta])* $variant:ident,)*
-    }) => {
-        $(#[$attr])*
-        pub enum $name {
-            $($(#[$var_attr])* $variant,)*
-        }
-
-        impl $name {
-            pub fn from_u32(u: u32) -> Option<$name> {
-                $(if u == $name::$variant as u32 {
-                    return Some($name::$variant)
-                })*
-                None
-            }
-        }
-    }
-}
diff --git a/compiler/rustc_data_structures/src/obligation_forest/mod.rs b/compiler/rustc_data_structures/src/obligation_forest/mod.rs
index a47908648ba..d477b86da74 100644
--- a/compiler/rustc_data_structures/src/obligation_forest/mod.rs
+++ b/compiler/rustc_data_structures/src/obligation_forest/mod.rs
@@ -70,12 +70,12 @@
 //! aren't needed anymore.
 
 use crate::fx::{FxHashMap, FxHashSet};
-
 use std::cell::Cell;
 use std::collections::hash_map::Entry;
 use std::fmt::Debug;
 use std::hash;
 use std::marker::PhantomData;
+use tracing::debug;
 
 mod graphviz;
 
diff --git a/compiler/rustc_data_structures/src/packed.rs b/compiler/rustc_data_structures/src/packed.rs
index b8d4b295dfa..0a392d91988 100644
--- a/compiler/rustc_data_structures/src/packed.rs
+++ b/compiler/rustc_data_structures/src/packed.rs
@@ -3,8 +3,10 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use std::cmp::Ordering;
 use std::fmt;
 
-#[repr(packed(8))]
+/// A packed 128-bit integer. Useful for reducing the size of structures in
+/// some cases.
 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
+#[repr(packed(8))]
 pub struct Pu128(pub u128);
 
 impl Pu128 {
diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs
index 2569684df3f..c6d51a5d6b4 100644
--- a/compiler/rustc_data_structures/src/profiling.rs
+++ b/compiler/rustc_data_structures/src/profiling.rs
@@ -99,6 +99,7 @@ pub use measureme::EventId;
 use measureme::{EventIdBuilder, Profiler, SerializableString, StringId};
 use parking_lot::RwLock;
 use smallvec::SmallVec;
+use tracing::warn;
 
 bitflags::bitflags! {
     #[derive(Clone, Copy)]
diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs
index 8418b4bbd47..b5bdf2e1790 100644
--- a/compiler/rustc_data_structures/src/stable_hasher.rs
+++ b/compiler/rustc_data_structures/src/stable_hasher.rs
@@ -296,6 +296,8 @@ macro_rules! impl_stable_traits_for_trivial_type {
     };
 }
 
+pub(crate) use impl_stable_traits_for_trivial_type;
+
 impl_stable_traits_for_trivial_type!(i8);
 impl_stable_traits_for_trivial_type!(i16);
 impl_stable_traits_for_trivial_type!(i32);
diff --git a/compiler/rustc_data_structures/src/tiny_list.rs b/compiler/rustc_data_structures/src/tiny_list.rs
deleted file mode 100644
index 11a408f216a..00000000000
--- a/compiler/rustc_data_structures/src/tiny_list.rs
+++ /dev/null
@@ -1,80 +0,0 @@
-//! A singly-linked list.
-//!
-//! Using this data structure only makes sense under very specific
-//! circumstances:
-//!
-//! - If you have a list that rarely stores more than one element, then this
-//!   data-structure can store the element without allocating and only uses as
-//!   much space as an `Option<(T, usize)>`. If T can double as the `Option`
-//!   discriminant, it will even only be as large as `T, usize`.
-//!
-//! If you expect to store more than 1 element in the common case, steer clear
-//! and use a `Vec<T>`, `Box<[T]>`, or a `SmallVec<T>`.
-
-#[cfg(test)]
-mod tests;
-
-#[derive(Clone)]
-pub struct TinyList<T> {
-    head: Option<Element<T>>,
-}
-
-impl<T: PartialEq> TinyList<T> {
-    #[inline]
-    pub fn new() -> TinyList<T> {
-        TinyList { head: None }
-    }
-
-    #[inline]
-    pub fn new_single(data: T) -> TinyList<T> {
-        TinyList { head: Some(Element { data, next: None }) }
-    }
-
-    #[inline]
-    pub fn insert(&mut self, data: T) {
-        self.head = Some(Element { data, next: self.head.take().map(Box::new) });
-    }
-
-    #[inline]
-    pub fn remove(&mut self, data: &T) -> bool {
-        self.head = match &mut self.head {
-            Some(head) if head.data == *data => head.next.take().map(|x| *x),
-            Some(head) => return head.remove_next(data),
-            None => return false,
-        };
-        true
-    }
-
-    #[inline]
-    pub fn contains(&self, data: &T) -> bool {
-        let mut elem = self.head.as_ref();
-        while let Some(e) = elem {
-            if &e.data == data {
-                return true;
-            }
-            elem = e.next.as_deref();
-        }
-        false
-    }
-}
-
-#[derive(Clone)]
-struct Element<T> {
-    data: T,
-    next: Option<Box<Element<T>>>,
-}
-
-impl<T: PartialEq> Element<T> {
-    fn remove_next(mut self: &mut Self, data: &T) -> bool {
-        loop {
-            match self.next {
-                Some(ref mut next) if next.data == *data => {
-                    self.next = next.next.take();
-                    return true;
-                }
-                Some(ref mut next) => self = next,
-                None => return false,
-            }
-        }
-    }
-}
diff --git a/compiler/rustc_data_structures/src/tiny_list/tests.rs b/compiler/rustc_data_structures/src/tiny_list/tests.rs
deleted file mode 100644
index 4b95e62bef0..00000000000
--- a/compiler/rustc_data_structures/src/tiny_list/tests.rs
+++ /dev/null
@@ -1,155 +0,0 @@
-use super::*;
-
-extern crate test;
-use test::{black_box, Bencher};
-
-impl<T> TinyList<T> {
-    fn len(&self) -> usize {
-        let (mut elem, mut count) = (self.head.as_ref(), 0);
-        while let Some(e) = elem {
-            count += 1;
-            elem = e.next.as_deref();
-        }
-        count
-    }
-}
-
-#[test]
-fn test_contains_and_insert() {
-    fn do_insert(i: u32) -> bool {
-        i % 2 == 0
-    }
-
-    let mut list = TinyList::new();
-
-    for i in 0..10 {
-        for j in 0..i {
-            if do_insert(j) {
-                assert!(list.contains(&j));
-            } else {
-                assert!(!list.contains(&j));
-            }
-        }
-
-        assert!(!list.contains(&i));
-
-        if do_insert(i) {
-            list.insert(i);
-            assert!(list.contains(&i));
-        }
-    }
-}
-
-#[test]
-fn test_remove_first() {
-    let mut list = TinyList::new();
-    list.insert(1);
-    list.insert(2);
-    list.insert(3);
-    list.insert(4);
-    assert_eq!(list.len(), 4);
-
-    assert!(list.remove(&4));
-    assert!(!list.contains(&4));
-
-    assert_eq!(list.len(), 3);
-    assert!(list.contains(&1));
-    assert!(list.contains(&2));
-    assert!(list.contains(&3));
-}
-
-#[test]
-fn test_remove_last() {
-    let mut list = TinyList::new();
-    list.insert(1);
-    list.insert(2);
-    list.insert(3);
-    list.insert(4);
-    assert_eq!(list.len(), 4);
-
-    assert!(list.remove(&1));
-    assert!(!list.contains(&1));
-
-    assert_eq!(list.len(), 3);
-    assert!(list.contains(&2));
-    assert!(list.contains(&3));
-    assert!(list.contains(&4));
-}
-
-#[test]
-fn test_remove_middle() {
-    let mut list = TinyList::new();
-    list.insert(1);
-    list.insert(2);
-    list.insert(3);
-    list.insert(4);
-    assert_eq!(list.len(), 4);
-
-    assert!(list.remove(&2));
-    assert!(!list.contains(&2));
-
-    assert_eq!(list.len(), 3);
-    assert!(list.contains(&1));
-    assert!(list.contains(&3));
-    assert!(list.contains(&4));
-}
-
-#[test]
-fn test_remove_single() {
-    let mut list = TinyList::new();
-    list.insert(1);
-    assert_eq!(list.len(), 1);
-
-    assert!(list.remove(&1));
-    assert!(!list.contains(&1));
-
-    assert_eq!(list.len(), 0);
-}
-
-#[bench]
-fn bench_insert_empty(b: &mut Bencher) {
-    b.iter(|| {
-        let mut list = black_box(TinyList::new());
-        list.insert(1);
-        list
-    })
-}
-
-#[bench]
-fn bench_insert_one(b: &mut Bencher) {
-    b.iter(|| {
-        let mut list = black_box(TinyList::new_single(0));
-        list.insert(1);
-        list
-    })
-}
-
-#[bench]
-fn bench_contains_empty(b: &mut Bencher) {
-    b.iter(|| black_box(TinyList::new()).contains(&1));
-}
-
-#[bench]
-fn bench_contains_unknown(b: &mut Bencher) {
-    b.iter(|| black_box(TinyList::new_single(0)).contains(&1));
-}
-
-#[bench]
-fn bench_contains_one(b: &mut Bencher) {
-    b.iter(|| black_box(TinyList::new_single(1)).contains(&1));
-}
-
-#[bench]
-fn bench_remove_empty(b: &mut Bencher) {
-    b.iter(|| black_box(TinyList::new()).remove(&1));
-}
-
-#[bench]
-fn bench_remove_unknown(b: &mut Bencher) {
-    b.iter(|| black_box(TinyList::new_single(0)).remove(&1));
-}
-
-#[bench]
-fn bench_remove_one(b: &mut Bencher) {
-    b.iter(|| black_box(TinyList::new_single(1)).remove(&1));
-}
diff --git a/compiler/rustc_data_structures/src/vec_linked_list.rs b/compiler/rustc_data_structures/src/vec_linked_list.rs
deleted file mode 100644
index fda72c9a3b2..00000000000
--- a/compiler/rustc_data_structures/src/vec_linked_list.rs
+++ /dev/null
@@ -1,70 +0,0 @@
-use rustc_index::{Idx, IndexVec};
-
-pub fn iter<Ls>(
-    first: Option<Ls::LinkIndex>,
-    links: &Ls,
-) -> impl Iterator<Item = Ls::LinkIndex> + '_
-where
-    Ls: Links,
-{
-    VecLinkedListIterator { links, current: first }
-}
-
-pub struct VecLinkedListIterator<Ls>
-where
-    Ls: Links,
-{
-    links: Ls,
-    current: Option<Ls::LinkIndex>,
-}
-
-impl<Ls> Iterator for VecLinkedListIterator<Ls>
-where
-    Ls: Links,
-{
-    type Item = Ls::LinkIndex;
-
-    fn next(&mut self) -> Option<Ls::LinkIndex> {
-        if let Some(c) = self.current {
-            self.current = <Ls as Links>::next(&self.links, c);
-            Some(c)
-        } else {
-            None
-        }
-    }
-}
-
-pub trait Links {
-    type LinkIndex: Copy;
-
-    fn next(links: &Self, index: Self::LinkIndex) -> Option<Self::LinkIndex>;
-}
-
-impl<Ls> Links for &Ls
-where
-    Ls: Links,
-{
-    type LinkIndex = Ls::LinkIndex;
-
-    fn next(links: &Self, index: Ls::LinkIndex) -> Option<Ls::LinkIndex> {
-        <Ls as Links>::next(links, index)
-    }
-}
-
-pub trait LinkElem {
-    type LinkIndex: Copy;
-
-    fn next(elem: &Self) -> Option<Self::LinkIndex>;
-}
-
-impl<L, E> Links for IndexVec<L, E>
-where
-    E: LinkElem<LinkIndex = L>,
-    L: Idx,
-{
-    type LinkIndex = L;
-
-    fn next(links: &Self, index: L) -> Option<L> {
-        <E as LinkElem>::next(&links[index])
-    }
-}
diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml
index cb37644d570..5f7504add8d 100644
--- a/compiler/rustc_driver_impl/Cargo.toml
+++ b/compiler/rustc_driver_impl/Cargo.toml
@@ -49,7 +49,7 @@ rustc_trait_selection = { path = "../rustc_trait_selection" }
 rustc_ty_utils = { path = "../rustc_ty_utils" }
 serde_json = "1.0.59"
 shlex = "1.0"
-time = { version = "0.3", default-features = false, features = ["alloc", "formatting", "parsing", "macros"] }
+time = { version = "0.3.36", default-features = false, features = ["alloc", "formatting", "parsing", "macros"] }
 tracing = { version = "0.1.35" }
 # tidy-alphabetical-end
 
diff --git a/compiler/rustc_error_codes/src/error_codes/E0579.md b/compiler/rustc_error_codes/src/error_codes/E0579.md
index e7e6fb68256..decf810b8c6 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0579.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0579.md
@@ -3,7 +3,6 @@ A lower range wasn't less than the upper range.
 Erroneous code example:
 
 ```compile_fail,E0579
-#![feature(exclusive_range_pattern)]
 
 fn main() {
     match 5u32 {
diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs
index 4696917554f..40560a5ad79 100644
--- a/compiler/rustc_errors/src/diagnostic_impls.rs
+++ b/compiler/rustc_errors/src/diagnostic_impls.rs
@@ -94,6 +94,12 @@ into_diag_arg_using_display!(
     ErrCode,
 );
 
+impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::TraitRef<I> {
+    fn into_diag_arg(self) -> DiagArgValue {
+        self.to_string().into_diag_arg()
+    }
+}
+
 into_diag_arg_for_number!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize);
 
 impl IntoDiagArg for bool {
diff --git a/compiler/rustc_expand/Cargo.toml b/compiler/rustc_expand/Cargo.toml
index 63247f9d051..ce014364b0d 100644
--- a/compiler/rustc_expand/Cargo.toml
+++ b/compiler/rustc_expand/Cargo.toml
@@ -25,7 +25,6 @@ rustc_serialize = { path = "../rustc_serialize" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-termcolor = "1.2"
 thin-vec = "0.2.12"
 tracing = "0.1"
 # tidy-alphabetical-end
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index f61cebc0256..ddf7b1a007a 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -1194,8 +1194,8 @@ impl InvocationCollectorNode for P<ast::Item> {
                 match &ut.kind {
                     ast::UseTreeKind::Glob => {}
                     ast::UseTreeKind::Simple(_) => idents.push(ut.ident()),
-                    ast::UseTreeKind::Nested(nested) => {
-                        for (ut, _) in nested {
+                    ast::UseTreeKind::Nested { items, .. } => {
+                        for (ut, _) in items {
                             collect_use_tree_leaves(ut, idents);
                         }
                     }
diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs
index c2c3b777699..4222c9fe906 100644
--- a/compiler/rustc_expand/src/lib.rs
+++ b/compiler/rustc_expand/src/lib.rs
@@ -34,24 +34,4 @@ pub mod module;
 #[allow(rustc::untranslatable_diagnostic)]
 pub mod proc_macro;
 
-// HACK(Centril, #64197): These shouldn't really be here.
-// Rather, they should be with their respective modules which are defined in other crates.
-// However, since for now constructing a `ParseSess` sorta requires `config` from this crate,
-// these tests will need to live here in the interim.
-
-#[cfg(test)]
-mod tests;
-#[cfg(test)]
-mod parse {
-    mod tests;
-}
-#[cfg(test)]
-mod tokenstream {
-    mod tests;
-}
-#[cfg(test)]
-mod mut_visit {
-    mod tests;
-}
-
 rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
diff --git a/compiler/rustc_expand/src/parse/tests.rs b/compiler/rustc_expand/src/parse/tests.rs
deleted file mode 100644
index 066afd7a41d..00000000000
--- a/compiler/rustc_expand/src/parse/tests.rs
+++ /dev/null
@@ -1,382 +0,0 @@
-use crate::tests::{
-    matches_codepattern, psess, string_to_stream, with_error_checking_parse,
-    with_expected_parse_error,
-};
-
-use ast::token::IdentIsRaw;
-use rustc_ast::ptr::P;
-use rustc_ast::token::{self, Delimiter, Token};
-use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
-use rustc_ast::visit;
-use rustc_ast::{self as ast, PatKind};
-use rustc_ast_pretty::pprust::item_to_string;
-use rustc_errors::PResult;
-use rustc_parse::new_parser_from_source_str;
-use rustc_parse::parser::ForceCollect;
-use rustc_session::parse::ParseSess;
-use rustc_span::create_default_session_globals_then;
-use rustc_span::symbol::{kw, sym, Symbol};
-use rustc_span::{BytePos, FileName, Pos, Span};
-use std::path::PathBuf;
-
-/// Parses an item.
-///
-/// Returns `Ok(Some(item))` when successful, `Ok(None)` when no item was found, and `Err`
-/// when a syntax error occurred.
-fn parse_item_from_source_str(
-    name: FileName,
-    source: String,
-    psess: &ParseSess,
-) -> PResult<'_, Option<P<ast::Item>>> {
-    new_parser_from_source_str(psess, name, source).parse_item(ForceCollect::No)
-}
-
-// Produces a `rustc_span::span`.
-fn sp(a: u32, b: u32) -> Span {
-    Span::with_root_ctxt(BytePos(a), BytePos(b))
-}
-
-/// Parses a string, return an expression.
-fn string_to_expr(source_str: String) -> P<ast::Expr> {
-    with_error_checking_parse(source_str, &psess(), |p| p.parse_expr())
-}
-
-/// Parses a string, returns an item.
-fn string_to_item(source_str: String) -> Option<P<ast::Item>> {
-    with_error_checking_parse(source_str, &psess(), |p| p.parse_item(ForceCollect::No))
-}
-
-#[test]
-fn bad_path_expr_1() {
-    // This should trigger error: expected identifier, found keyword `return`
-    create_default_session_globals_then(|| {
-        with_expected_parse_error(
-            "::abc::def::return",
-            "expected identifier, found keyword `return`",
-            |p| p.parse_expr(),
-        );
-    })
-}
-
-// Checks the token-tree-ization of macros.
-#[test]
-fn string_to_tts_macro() {
-    create_default_session_globals_then(|| {
-        let stream = string_to_stream("macro_rules! zip (($a)=>($a))".to_string());
-        let tts = &stream.trees().collect::<Vec<_>>()[..];
-
-        match tts {
-            [
-                TokenTree::Token(
-                    Token { kind: token::Ident(name_macro_rules, IdentIsRaw::No), .. },
-                    _,
-                ),
-                TokenTree::Token(Token { kind: token::Not, .. }, _),
-                TokenTree::Token(Token { kind: token::Ident(name_zip, IdentIsRaw::No), .. }, _),
-                TokenTree::Delimited(.., macro_delim, macro_tts),
-            ] if name_macro_rules == &kw::MacroRules && name_zip.as_str() == "zip" => {
-                let tts = &macro_tts.trees().collect::<Vec<_>>();
-                match &tts[..] {
-                    [
-                        TokenTree::Delimited(.., first_delim, first_tts),
-                        TokenTree::Token(Token { kind: token::FatArrow, .. }, _),
-                        TokenTree::Delimited(.., second_delim, second_tts),
-                    ] if macro_delim == &Delimiter::Parenthesis => {
-                        let tts = &first_tts.trees().collect::<Vec<_>>();
-                        match &tts[..] {
-                            [
-                                TokenTree::Token(Token { kind: token::Dollar, .. }, _),
-                                TokenTree::Token(
-                                    Token { kind: token::Ident(name, IdentIsRaw::No), .. },
-                                    _,
-                                ),
-                            ] if first_delim == &Delimiter::Parenthesis && name.as_str() == "a" => {
-                            }
-                            _ => panic!("value 3: {:?} {:?}", first_delim, first_tts),
-                        }
-                        let tts = &second_tts.trees().collect::<Vec<_>>();
-                        match &tts[..] {
-                            [
-                                TokenTree::Token(Token { kind: token::Dollar, .. }, _),
-                                TokenTree::Token(
-                                    Token { kind: token::Ident(name, IdentIsRaw::No), .. },
-                                    _,
-                                ),
-                            ] if second_delim == &Delimiter::Parenthesis
-                                && name.as_str() == "a" => {}
-                            _ => panic!("value 4: {:?} {:?}", second_delim, second_tts),
-                        }
-                    }
-                    _ => panic!("value 2: {:?} {:?}", macro_delim, macro_tts),
-                }
-            }
-            _ => panic!("value: {:?}", tts),
-        }
-    })
-}
-
-#[test]
-fn string_to_tts_1() {
-    create_default_session_globals_then(|| {
-        let tts = string_to_stream("fn a(b: i32) { b; }".to_string());
-
-        let expected = TokenStream::new(vec![
-            TokenTree::token_alone(token::Ident(kw::Fn, IdentIsRaw::No), sp(0, 2)),
-            TokenTree::token_joint_hidden(
-                token::Ident(Symbol::intern("a"), IdentIsRaw::No),
-                sp(3, 4),
-            ),
-            TokenTree::Delimited(
-                DelimSpan::from_pair(sp(4, 5), sp(11, 12)),
-                // `JointHidden` because the `(` is followed immediately by
-                // `b`, `Alone` because the `)` is followed by whitespace.
-                DelimSpacing::new(Spacing::JointHidden, Spacing::Alone),
-                Delimiter::Parenthesis,
-                TokenStream::new(vec![
-                    TokenTree::token_joint(
-                        token::Ident(Symbol::intern("b"), IdentIsRaw::No),
-                        sp(5, 6),
-                    ),
-                    TokenTree::token_alone(token::Colon, sp(6, 7)),
-                    // `JointHidden` because the `i32` is immediately followed by the `)`.
-                    TokenTree::token_joint_hidden(
-                        token::Ident(sym::i32, IdentIsRaw::No),
-                        sp(8, 11),
-                    ),
-                ])
-                .into(),
-            ),
-            TokenTree::Delimited(
-                DelimSpan::from_pair(sp(13, 14), sp(18, 19)),
-                // First `Alone` because the `{` is followed by whitespace,
-                // second `Alone` because the `}` is followed immediately by
-                // EOF.
-                DelimSpacing::new(Spacing::Alone, Spacing::Alone),
-                Delimiter::Brace,
-                TokenStream::new(vec![
-                    TokenTree::token_joint(
-                        token::Ident(Symbol::intern("b"), IdentIsRaw::No),
-                        sp(15, 16),
-                    ),
-                    // `Alone` because the `;` is followed by whitespace.
-                    TokenTree::token_alone(token::Semi, sp(16, 17)),
-                ])
-                .into(),
-            ),
-        ]);
-
-        assert_eq!(tts, expected);
-    })
-}
-
-#[test]
-fn parse_use() {
-    create_default_session_globals_then(|| {
-        let use_s = "use foo::bar::baz;";
-        let vitem = string_to_item(use_s.to_string()).unwrap();
-        let vitem_s = item_to_string(&vitem);
-        assert_eq!(&vitem_s[..], use_s);
-
-        let use_s = "use foo::bar as baz;";
-        let vitem = string_to_item(use_s.to_string()).unwrap();
-        let vitem_s = item_to_string(&vitem);
-        assert_eq!(&vitem_s[..], use_s);
-    })
-}
-
-#[test]
-fn parse_extern_crate() {
-    create_default_session_globals_then(|| {
-        let ex_s = "extern crate foo;";
-        let vitem = string_to_item(ex_s.to_string()).unwrap();
-        let vitem_s = item_to_string(&vitem);
-        assert_eq!(&vitem_s[..], ex_s);
-
-        let ex_s = "extern crate foo as bar;";
-        let vitem = string_to_item(ex_s.to_string()).unwrap();
-        let vitem_s = item_to_string(&vitem);
-        assert_eq!(&vitem_s[..], ex_s);
-    })
-}
-
-fn get_spans_of_pat_idents(src: &str) -> Vec<Span> {
-    let item = string_to_item(src.to_string()).unwrap();
-
-    struct PatIdentVisitor {
-        spans: Vec<Span>,
-    }
-    impl<'a> visit::Visitor<'a> for PatIdentVisitor {
-        fn visit_pat(&mut self, p: &'a ast::Pat) {
-            match &p.kind {
-                PatKind::Ident(_, ident, _) => {
-                    self.spans.push(ident.span);
-                }
-                _ => {
-                    visit::walk_pat(self, p);
-                }
-            }
-        }
-    }
-    let mut v = PatIdentVisitor { spans: Vec::new() };
-    visit::walk_item(&mut v, &item);
-    return v.spans;
-}
-
-#[test]
-fn span_of_self_arg_pat_idents_are_correct() {
-    create_default_session_globals_then(|| {
-        let srcs = [
-            "impl z { fn a (&self, &myarg: i32) {} }",
-            "impl z { fn a (&mut self, &myarg: i32) {} }",
-            "impl z { fn a (&'a self, &myarg: i32) {} }",
-            "impl z { fn a (self, &myarg: i32) {} }",
-            "impl z { fn a (self: Foo, &myarg: i32) {} }",
-        ];
-
-        for src in srcs {
-            let spans = get_spans_of_pat_idents(src);
-            let (lo, hi) = (spans[0].lo(), spans[0].hi());
-            assert!(
-                "self" == &src[lo.to_usize()..hi.to_usize()],
-                "\"{}\" != \"self\". src=\"{}\"",
-                &src[lo.to_usize()..hi.to_usize()],
-                src
-            )
-        }
-    })
-}
-
-#[test]
-fn parse_exprs() {
-    create_default_session_globals_then(|| {
-        // just make sure that they parse....
-        string_to_expr("3 + 4".to_string());
-        string_to_expr("a::z.froob(b,&(987+3))".to_string());
-    })
-}
-
-#[test]
-fn attrs_fix_bug() {
-    create_default_session_globals_then(|| {
-        string_to_item(
-            "pub fn mk_file_writer(path: &Path, flags: &[FileFlag])
-                -> Result<Box<Writer>, String> {
-#[cfg(windows)]
-fn wb() -> c_int {
-    (O_WRONLY | libc::consts::os::extra::O_BINARY) as c_int
-}
-
-#[cfg(unix)]
-fn wb() -> c_int { O_WRONLY as c_int }
-
-let mut fflags: c_int = wb();
-}"
-            .to_string(),
-        );
-    })
-}
-
-#[test]
-fn crlf_doc_comments() {
-    create_default_session_globals_then(|| {
-        let psess = psess();
-
-        let name_1 = FileName::Custom("crlf_source_1".to_string());
-        let source = "/// doc comment\r\nfn foo() {}".to_string();
-        let item = parse_item_from_source_str(name_1, source, &psess).unwrap().unwrap();
-        let doc = item.attrs.iter().filter_map(|at| at.doc_str()).next().unwrap();
-        assert_eq!(doc.as_str(), " doc comment");
-
-        let name_2 = FileName::Custom("crlf_source_2".to_string());
-        let source = "/// doc comment\r\n/// line 2\r\nfn foo() {}".to_string();
-        let item = parse_item_from_source_str(name_2, source, &psess).unwrap().unwrap();
-        let docs = item.attrs.iter().filter_map(|at| at.doc_str()).collect::<Vec<_>>();
-        let b: &[_] = &[Symbol::intern(" doc comment"), Symbol::intern(" line 2")];
-        assert_eq!(&docs[..], b);
-
-        let name_3 = FileName::Custom("clrf_source_3".to_string());
-        let source = "/** doc comment\r\n *  with CRLF */\r\nfn foo() {}".to_string();
-        let item = parse_item_from_source_str(name_3, source, &psess).unwrap().unwrap();
-        let doc = item.attrs.iter().filter_map(|at| at.doc_str()).next().unwrap();
-        assert_eq!(doc.as_str(), " doc comment\n *  with CRLF ");
-    });
-}
-
-#[test]
-fn ttdelim_span() {
-    fn parse_expr_from_source_str(
-        name: FileName,
-        source: String,
-        psess: &ParseSess,
-    ) -> PResult<'_, P<ast::Expr>> {
-        new_parser_from_source_str(psess, name, source).parse_expr()
-    }
-
-    create_default_session_globals_then(|| {
-        let psess = psess();
-        let expr = parse_expr_from_source_str(
-            PathBuf::from("foo").into(),
-            "foo!( fn main() { body } )".to_string(),
-            &psess,
-        )
-        .unwrap();
-
-        let ast::ExprKind::MacCall(mac) = &expr.kind else { panic!("not a macro") };
-        let span = mac.args.tokens.trees().last().unwrap().span();
-
-        match psess.source_map().span_to_snippet(span) {
-            Ok(s) => assert_eq!(&s[..], "{ body }"),
-            Err(_) => panic!("could not get snippet"),
-        }
-    });
-}
-
-// This tests that when parsing a string (rather than a file) we don't try
-// and read in a file for a module declaration and just parse a stub.
-// See `recurse_into_file_modules` in the parser.
-#[test]
-fn out_of_line_mod() {
-    create_default_session_globals_then(|| {
-        let item = parse_item_from_source_str(
-            PathBuf::from("foo").into(),
-            "mod foo { struct S; mod this_does_not_exist; }".to_owned(),
-            &psess(),
-        )
-        .unwrap()
-        .unwrap();
-
-        let ast::ItemKind::Mod(_, mod_kind) = &item.kind else { panic!() };
-        assert!(matches!(mod_kind, ast::ModKind::Loaded(items, ..) if items.len() == 2));
-    });
-}
-
-#[test]
-fn eqmodws() {
-    assert_eq!(matches_codepattern("", ""), true);
-    assert_eq!(matches_codepattern("", "a"), false);
-    assert_eq!(matches_codepattern("a", ""), false);
-    assert_eq!(matches_codepattern("a", "a"), true);
-    assert_eq!(matches_codepattern("a b", "a   \n\t\r  b"), true);
-    assert_eq!(matches_codepattern("a b ", "a   \n\t\r  b"), true);
-    assert_eq!(matches_codepattern("a b", "a   \n\t\r  b "), false);
-    assert_eq!(matches_codepattern("a   b", "a b"), true);
-    assert_eq!(matches_codepattern("ab", "a b"), false);
-    assert_eq!(matches_codepattern("a   b", "ab"), true);
-    assert_eq!(matches_codepattern(" a   b", "ab"), true);
-}
-
-#[test]
-fn pattern_whitespace() {
-    assert_eq!(matches_codepattern("", "\x0C"), false);
-    assert_eq!(matches_codepattern("a b ", "a   \u{0085}\n\t\r  b"), true);
-    assert_eq!(matches_codepattern("a b", "a   \u{0085}\n\t\r  b "), false);
-}
-
-#[test]
-fn non_pattern_whitespace() {
-    // These have the property 'White_Space' but not 'Pattern_White_Space'
-    assert_eq!(matches_codepattern("a b", "a\u{2002}b"), false);
-    assert_eq!(matches_codepattern("a   b", "a\u{2002}b"), false);
-    assert_eq!(matches_codepattern("\u{205F}a   b", "ab"), false);
-    assert_eq!(matches_codepattern("a  \u{3000}b", "ab"), false);
-}
diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs
index 7026425e167..e21f041d69a 100644
--- a/compiler/rustc_expand/src/placeholders.rs
+++ b/compiler/rustc_expand/src/placeholders.rs
@@ -174,7 +174,10 @@ pub(crate) fn placeholder(
         }]),
         AstFragmentKind::Variants => AstFragment::Variants(smallvec![ast::Variant {
             attrs: Default::default(),
-            data: ast::VariantData::Struct { fields: Default::default(), recovered: false },
+            data: ast::VariantData::Struct {
+                fields: Default::default(),
+                recovered: ast::Recovered::No
+            },
             disr_expr: None,
             id,
             ident,
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index 943cc632857..bb6a54fae70 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -162,6 +162,8 @@ declare_features! (
     (accepted, drop_types_in_const, "1.22.0", Some(33156)),
     /// Allows using `dyn Trait` as a syntax for trait objects.
     (accepted, dyn_trait, "1.27.0", Some(44662)),
+    /// Allows `X..Y` patterns.
+    (accepted, exclusive_range_pattern, "CURRENT_RUSTC_VERSION", Some(37854)),
     /// Allows integer match exhaustiveness checking (RFC 2591).
     (accepted, exhaustive_integer_patterns, "1.33.0", Some(50907)),
     /// Allows explicit generic arguments specification with `impl Trait` present.
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 9c33cc8ed0b..dbb88e42a3e 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -518,7 +518,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     // RFC 2397
     gated!(
         do_not_recommend, Normal, template!(Word), WarnFollowing,
-        EncodeCrossCrate::No, experimental!(do_not_recommend)
+        EncodeCrossCrate::Yes, experimental!(do_not_recommend)
     ),
 
     // `#[cfi_encoding = ""]`
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index fe50499db76..60b386acf91 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -454,8 +454,6 @@ declare_features! (
     (incomplete, dyn_star, "1.65.0", Some(102425)),
     /// Uses generic effect parameters for ~const bounds
     (unstable, effects, "1.72.0", Some(102090)),
-    /// Allows `X..Y` patterns.
-    (unstable, exclusive_range_pattern, "1.11.0", Some(37854)),
     /// Allows exhaustive pattern matching on types that contain uninhabited types.
     (unstable, exhaustive_patterns, "1.13.0", Some(51085)),
     /// Allows explicit tail calls via `become` expression.
@@ -581,6 +579,9 @@ declare_features! (
     (incomplete, repr128, "1.16.0", Some(56071)),
     /// Allows `repr(simd)` and importing the various simd intrinsics.
     (unstable, repr_simd, "1.4.0", Some(27731)),
+    /// Allows enums like Result<T, E> to be used across FFI, if T's niche value can
+    /// be used to describe E or vise-versa.
+    (unstable, result_ffi_guarantees, "CURRENT_RUSTC_VERSION", Some(110503)),
     /// Allows bounding the return type of AFIT/RPITIT.
     (incomplete, return_type_notation, "1.70.0", Some(109417)),
     /// Allows `extern "rust-cold"`.
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 244c479120d..7d991e21ff3 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1308,9 +1308,9 @@ pub struct LetExpr<'hir> {
     pub pat: &'hir Pat<'hir>,
     pub ty: Option<&'hir Ty<'hir>>,
     pub init: &'hir Expr<'hir>,
-    /// `Some` when this let expressions is not in a syntanctically valid location.
+    /// `Recovered::Yes` when this let expressions is not in a syntanctically valid location.
     /// Used to prevent building MIR in such situations.
-    pub is_recovered: Option<ErrorGuaranteed>,
+    pub recovered: ast::Recovered,
 }
 
 #[derive(Debug, Clone, Copy, HashStable_Generic)]
@@ -3030,11 +3030,7 @@ pub enum VariantData<'hir> {
     /// A struct variant.
     ///
     /// E.g., `Bar { .. }` as in `enum Foo { Bar { .. } }`.
-    Struct {
-        fields: &'hir [FieldDef<'hir>],
-        // FIXME: investigate making this a `Option<ErrorGuaranteed>`
-        recovered: bool,
-    },
+    Struct { fields: &'hir [FieldDef<'hir>], recovered: ast::Recovered },
     /// A tuple variant.
     ///
     /// E.g., `Bar(..)` as in `enum Foo { Bar(..) }`.
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index fa89a4a44ef..0b095db953b 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -768,7 +768,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
         ExprKind::DropTemps(ref subexpression) => {
             try_visit!(visitor.visit_expr(subexpression));
         }
-        ExprKind::Let(LetExpr { span: _, pat, ty, init, is_recovered: _ }) => {
+        ExprKind::Let(LetExpr { span: _, pat, ty, init, recovered: _ }) => {
             // match the visit order in walk_local
             try_visit!(visitor.visit_expr(init));
             try_visit!(visitor.visit_pat(pat));
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index e870a04127a..c4be67cdd88 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -55,21 +55,27 @@ macro_rules! language_item_table {
     (
         $( $(#[$attr:meta])* $variant:ident, $module:ident :: $name:ident, $method:ident, $target:expr, $generics:expr; )*
     ) => {
-
-        rustc_data_structures::enum_from_u32! {
-            /// A representation of all the valid lang items in Rust.
-            #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable)]
-            pub enum LangItem {
-                $(
-                    #[doc = concat!("The `", stringify!($name), "` lang item.")]
-                    ///
-                    $(#[$attr])*
-                    $variant,
-                )*
-            }
+        /// A representation of all the valid lang items in Rust.
+        #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable)]
+        pub enum LangItem {
+            $(
+                #[doc = concat!("The `", stringify!($name), "` lang item.")]
+                $(#[$attr])*
+                $variant,
+            )*
         }
 
         impl LangItem {
+            fn from_u32(u: u32) -> Option<LangItem> {
+                // This implementation is clumsy, but makes no assumptions
+                // about how discriminant tags are allocated within the
+                // range `0 .. std::mem::variant_count::<LangItem>()`.
+                $(if u == LangItem::$variant as u32 {
+                    return Some(LangItem::$variant)
+                })*
+                None
+            }
+
             /// Returns the `name` symbol in `#[lang = "$name"]`.
             /// For example, [`LangItem::PartialEq`]`.name()`
             /// would result in [`sym::eq`] since it is `#[lang = "eq"]`.
@@ -147,7 +153,7 @@ language_item_table! {
     Clone,                   sym::clone,               clone_trait,                Target::Trait,          GenericRequirement::None;
     Sync,                    sym::sync,                sync_trait,                 Target::Trait,          GenericRequirement::Exact(0);
     DiscriminantKind,        sym::discriminant_kind,   discriminant_kind_trait,    Target::Trait,          GenericRequirement::None;
-    /// The associated item of the [`DiscriminantKind`] trait.
+    /// The associated item of the `DiscriminantKind` trait.
     Discriminant,            sym::discriminant_type,   discriminant_type,          Target::AssocTy,        GenericRequirement::None;
 
     PointeeTrait,            sym::pointee_trait,       pointee_trait,              Target::Trait,          GenericRequirement::None;
diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs
index f101c595bdf..2bf14a2461f 100644
--- a/compiler/rustc_hir_analysis/src/autoderef.rs
+++ b/compiler/rustc_hir_analysis/src/autoderef.rs
@@ -68,28 +68,27 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
         }
 
         // Otherwise, deref if type is derefable:
-        let (kind, new_ty) = if let Some(ty::TypeAndMut { ty, .. }) =
-            self.state.cur_ty.builtin_deref(self.include_raw_pointers)
-        {
-            debug_assert_eq!(ty, self.infcx.resolve_vars_if_possible(ty));
-            // NOTE: we may still need to normalize the built-in deref in case
-            // we have some type like `&<Ty as Trait>::Assoc`, since users of
-            // autoderef expect this type to have been structurally normalized.
-            if self.infcx.next_trait_solver()
-                && let ty::Alias(..) = ty.kind()
-            {
-                let (normalized_ty, obligations) = self.structurally_normalize(ty)?;
-                self.state.obligations.extend(obligations);
-                (AutoderefKind::Builtin, normalized_ty)
+        let (kind, new_ty) =
+            if let Some(ty) = self.state.cur_ty.builtin_deref(self.include_raw_pointers) {
+                debug_assert_eq!(ty, self.infcx.resolve_vars_if_possible(ty));
+                // NOTE: we may still need to normalize the built-in deref in case
+                // we have some type like `&<Ty as Trait>::Assoc`, since users of
+                // autoderef expect this type to have been structurally normalized.
+                if self.infcx.next_trait_solver()
+                    && let ty::Alias(..) = ty.kind()
+                {
+                    let (normalized_ty, obligations) = self.structurally_normalize(ty)?;
+                    self.state.obligations.extend(obligations);
+                    (AutoderefKind::Builtin, normalized_ty)
+                } else {
+                    (AutoderefKind::Builtin, ty)
+                }
+            } else if let Some(ty) = self.overloaded_deref_ty(self.state.cur_ty) {
+                // The overloaded deref check already normalizes the pointee type.
+                (AutoderefKind::Overloaded, ty)
             } else {
-                (AutoderefKind::Builtin, ty)
-            }
-        } else if let Some(ty) = self.overloaded_deref_ty(self.state.cur_ty) {
-            // The overloaded deref check already normalizes the pointee type.
-            (AutoderefKind::Overloaded, ty)
-        } else {
-            return None;
-        };
+                return None;
+            };
 
         self.state.steps.push((self.state.cur_ty, kind));
         debug!(
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 32e1b19eaae..fb9d97ba08b 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -561,7 +561,7 @@ fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDe
         let generics = tcx.generics_of(generics);
         def_id = generics.parent;
 
-        for param in &generics.params {
+        for param in &generics.own_params {
             if expected_captures.contains(&param.def_id) {
                 assert_eq!(
                     variances[param.index as usize],
@@ -778,7 +778,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
                         let def_id = item.id.owner_id.def_id;
                         let generics = tcx.generics_of(def_id);
                         let own_counts = generics.own_counts();
-                        if generics.params.len() - own_counts.lifetimes != 0 {
+                        if generics.own_params.len() - own_counts.lifetimes != 0 {
                             let (kinds, kinds_pl, egs) = match (own_counts.types, own_counts.consts)
                             {
                                 (_, 0) => ("type", "types", Some("u32")),
@@ -1544,7 +1544,7 @@ fn check_type_alias_type_params_are_used<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalD
             .collect::<FxIndexMap<_, _>>()
     });
 
-    let mut params_used = BitSet::new_empty(generics.params.len());
+    let mut params_used = BitSet::new_empty(generics.own_params.len());
     for leaf in ty.walk() {
         if let GenericArgKind::Type(leaf_ty) = leaf.unpack()
             && let ty::Param(param) = leaf_ty.kind()
@@ -1554,7 +1554,7 @@ fn check_type_alias_type_params_are_used<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalD
         }
     }
 
-    for param in &generics.params {
+    for param in &generics.own_params {
         if !params_used.contains(param.index)
             && let ty::GenericParamDefKind::Type { .. } = param.kind
         {
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 d2759087cb4..b2b82670d8b 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -9,7 +9,6 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit;
 use rustc_hir::{GenericParamKind, ImplItemKind};
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
-use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
 use rustc_infer::traits::{util, FulfillmentError};
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
@@ -176,7 +175,7 @@ fn compare_method_predicate_entailment<'tcx>(
     let cause = ObligationCause::new(
         impl_m_span,
         impl_m_def_id,
-        ObligationCauseCode::CompareImplItemObligation {
+        ObligationCauseCode::CompareImplItem {
             impl_item_def_id: impl_m_def_id,
             trait_item_def_id: trait_m.def_id,
             kind: impl_m.kind,
@@ -237,7 +236,7 @@ fn compare_method_predicate_entailment<'tcx>(
         let cause = ObligationCause::new(
             span,
             impl_m_def_id,
-            ObligationCauseCode::CompareImplItemObligation {
+            ObligationCauseCode::CompareImplItem {
                 impl_item_def_id: impl_m_def_id,
                 trait_item_def_id: trait_m.def_id,
                 kind: impl_m.kind,
@@ -465,7 +464,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
     let cause = ObligationCause::new(
         return_span,
         impl_m_def_id,
-        ObligationCauseCode::CompareImplItemObligation {
+        ObligationCauseCode::CompareImplItem {
             impl_item_def_id: impl_m_def_id,
             trait_item_def_id: trait_m.def_id,
             kind: impl_m.kind,
@@ -716,7 +715,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
                 // since we previously enforce that the trait method and impl method have the
                 // same generics.
                 let num_trait_args = trait_to_impl_args.len();
-                let num_impl_args = tcx.generics_of(impl_m.container_id(tcx)).params.len();
+                let num_impl_args = tcx.generics_of(impl_m.container_id(tcx)).own_params.len();
                 let ty = match ty.try_fold_with(&mut RemapHiddenTyRegions {
                     tcx,
                     map,
@@ -800,10 +799,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx> {
                 bug!("FIXME(RPITIT): error here");
             }
             // Replace with infer var
-            let infer_ty = self
-                .ocx
-                .infcx
-                .next_ty_var(TypeVariableOrigin { span: self.span, param_def_id: None });
+            let infer_ty = self.ocx.infcx.next_ty_var(self.span);
             self.types.insert(proj.def_id, (infer_ty, proj.args));
             // Recurse into bounds
             for (pred, pred_span) in self
@@ -823,7 +819,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx> {
                     ObligationCause::new(
                         self.span,
                         self.body_id,
-                        ObligationCauseCode::BindingObligation(proj.def_id, pred_span),
+                        ObligationCauseCode::SpannedWhereClause(proj.def_id, pred_span),
                     ),
                     self.param_env,
                     pred,
@@ -1494,14 +1490,16 @@ fn compare_synthetic_generics<'tcx>(
     let mut error_found = None;
     let impl_m_generics = tcx.generics_of(impl_m.def_id);
     let trait_m_generics = tcx.generics_of(trait_m.def_id);
-    let impl_m_type_params = impl_m_generics.params.iter().filter_map(|param| match param.kind {
-        GenericParamDefKind::Type { synthetic, .. } => Some((param.def_id, synthetic)),
-        GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => None,
-    });
-    let trait_m_type_params = trait_m_generics.params.iter().filter_map(|param| match param.kind {
-        GenericParamDefKind::Type { synthetic, .. } => Some((param.def_id, synthetic)),
-        GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => None,
-    });
+    let impl_m_type_params =
+        impl_m_generics.own_params.iter().filter_map(|param| match param.kind {
+            GenericParamDefKind::Type { synthetic, .. } => Some((param.def_id, synthetic)),
+            GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => None,
+        });
+    let trait_m_type_params =
+        trait_m_generics.own_params.iter().filter_map(|param| match param.kind {
+            GenericParamDefKind::Type { synthetic, .. } => Some((param.def_id, synthetic)),
+            GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => None,
+        });
     for ((impl_def_id, impl_synthetic), (trait_def_id, trait_synthetic)) in
         iter::zip(impl_m_type_params, trait_m_type_params)
     {
@@ -1639,7 +1637,7 @@ fn compare_generic_param_kinds<'tcx>(
     assert_eq!(impl_item.kind, trait_item.kind);
 
     let ty_const_params_of = |def_id| {
-        tcx.generics_of(def_id).params.iter().filter(|param| {
+        tcx.generics_of(def_id).own_params.iter().filter(|param| {
             matches!(
                 param.kind,
                 GenericParamDefKind::Const { .. } | GenericParamDefKind::Type { .. }
@@ -1754,7 +1752,7 @@ fn compare_const_predicate_entailment<'tcx>(
     let impl_ty = tcx.type_of(impl_ct_def_id).instantiate_identity();
 
     let trait_ty = tcx.type_of(trait_ct.def_id).instantiate(tcx, trait_to_impl_args);
-    let code = ObligationCauseCode::CompareImplItemObligation {
+    let code = ObligationCauseCode::CompareImplItem {
         impl_item_def_id: impl_ct_def_id,
         trait_item_def_id: trait_ct.def_id,
         kind: impl_ct.kind,
@@ -1926,7 +1924,7 @@ fn compare_type_predicate_entailment<'tcx>(
         let cause = ObligationCause::new(
             span,
             impl_ty_def_id,
-            ObligationCauseCode::CompareImplItemObligation {
+            ObligationCauseCode::CompareImplItem {
                 impl_item_def_id: impl_ty.def_id.expect_local(),
                 trait_item_def_id: trait_ty.def_id,
                 kind: impl_ty.kind,
@@ -2014,9 +2012,9 @@ pub(super) fn check_type_bounds<'tcx>(
     );
     let mk_cause = |span: Span| {
         let code = if span.is_dummy() {
-            traits::ItemObligation(trait_ty.def_id)
+            ObligationCauseCode::WhereClause(trait_ty.def_id)
         } else {
-            traits::BindingObligation(trait_ty.def_id, span)
+            ObligationCauseCode::SpannedWhereClause(trait_ty.def_id, span)
         };
         ObligationCause::new(impl_ty_span, impl_ty_def_id, code)
     };
@@ -2140,7 +2138,7 @@ fn param_env_with_gat_bounds<'tcx>(
         };
 
         let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> =
-            smallvec::SmallVec::with_capacity(tcx.generics_of(impl_ty.def_id).params.len());
+            smallvec::SmallVec::with_capacity(tcx.generics_of(impl_ty.def_id).own_params.len());
         // Extend the impl's identity args with late-bound GAT vars
         let normalize_impl_ty_args = ty::GenericArgs::identity_for_item(tcx, container_id)
             .extend_to(tcx, impl_ty.def_id, |param, _| match param.kind {
@@ -2253,7 +2251,8 @@ fn try_report_async_mismatch<'tcx>(
     };
 
     for error in errors {
-        if let traits::BindingObligation(def_id, _) = *error.root_obligation.cause.code()
+        if let ObligationCauseCode::SpannedWhereClause(def_id, _) =
+            *error.root_obligation.cause.code()
             && def_id == async_future_def_id
             && let Some(proj) = error.root_obligation.predicate.to_opt_poly_projection_pred()
             && let Some(proj) = proj.no_bound_vars()
diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs
index 82a6b6b6f2c..be412dde968 100644
--- a/compiler/rustc_hir_analysis/src/check/dropck.rs
+++ b/compiler/rustc_hir_analysis/src/check/dropck.rs
@@ -5,6 +5,7 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{codes::*, struct_span_code_err, ErrorGuaranteed};
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
+use rustc_infer::traits::ObligationCauseCode;
 use rustc_middle::ty::util::CheckRegions;
 use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, TyCtxt};
@@ -139,7 +140,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
     for (pred, span) in tcx.predicates_of(drop_impl_def_id).instantiate_identity(tcx) {
         let normalize_cause = traits::ObligationCause::misc(span, adt_def_id);
         let pred = ocx.normalize(&normalize_cause, param_env, pred);
-        let cause = traits::ObligationCause::new(span, adt_def_id, traits::DropImpl);
+        let cause = traits::ObligationCause::new(span, adt_def_id, ObligationCauseCode::DropImpl);
         ocx.register_obligation(traits::Obligation::new(tcx, cause, param_env, pred));
     }
 
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 5b127e0bf49..0578317f914 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -431,7 +431,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) {
             }
             let gat_generics = tcx.generics_of(gat_def_id);
             // FIXME(jackh726): we can also warn in the more general case
-            if gat_generics.params.is_empty() {
+            if gat_generics.own_params.is_empty() {
                 continue;
             }
 
@@ -1136,7 +1136,7 @@ fn check_type_defn<'tcx>(
                     traits::ObligationCause::new(
                         hir_ty.span,
                         wfcx.body_def_id,
-                        traits::FieldSized {
+                        ObligationCauseCode::FieldSized {
                             adt_kind: match &item.kind {
                                 ItemKind::Struct(..) => AdtKind::Struct,
                                 ItemKind::Union(..) => AdtKind::Union,
@@ -1161,7 +1161,7 @@ fn check_type_defn<'tcx>(
                 let cause = traits::ObligationCause::new(
                     tcx.def_span(discr_def_id),
                     wfcx.body_def_id,
-                    traits::MiscObligation,
+                    ObligationCauseCode::Misc,
                 );
                 wfcx.register_obligation(traits::Obligation::new(
                     tcx,
@@ -1278,7 +1278,11 @@ fn check_item_type(
         wfcx.register_wf_obligation(ty_span, Some(WellFormedLoc::Ty(item_id)), item_ty.into());
         if forbid_unsized {
             wfcx.register_bound(
-                traits::ObligationCause::new(ty_span, wfcx.body_def_id, traits::WellFormed(None)),
+                traits::ObligationCause::new(
+                    ty_span,
+                    wfcx.body_def_id,
+                    ObligationCauseCode::WellFormed(None),
+                ),
                 wfcx.param_env,
                 item_ty,
                 tcx.require_lang_item(LangItem::Sized, None),
@@ -1293,7 +1297,11 @@ fn check_item_type(
 
         if should_check_for_sync {
             wfcx.register_bound(
-                traits::ObligationCause::new(ty_span, wfcx.body_def_id, traits::SharedStatic),
+                traits::ObligationCause::new(
+                    ty_span,
+                    wfcx.body_def_id,
+                    ObligationCauseCode::SharedStatic,
+                ),
                 wfcx.param_env,
                 item_ty,
                 tcx.require_lang_item(LangItem::Sync, Some(ty_span)),
@@ -1400,7 +1408,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
     //     struct Foo<T = Vec<[u32]>> { .. }
     //
     // Here, the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold.
-    for param in &generics.params {
+    for param in &generics.own_params {
         match param.kind {
             GenericParamDefKind::Type { .. } => {
                 if is_our_default(param) {
@@ -1542,7 +1550,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
             let cause = traits::ObligationCause::new(
                 sp,
                 wfcx.body_def_id,
-                traits::ItemObligation(def_id.to_def_id()),
+                ObligationCauseCode::WhereClause(def_id.to_def_id()),
             );
             traits::Obligation::new(tcx, cause, wfcx.param_env, pred)
         });
@@ -1879,7 +1887,7 @@ fn check_variances_for_type_defn<'tcx>(
             continue;
         }
 
-        let ty_param = &ty_generics.params[index];
+        let ty_param = &ty_generics.own_params[index];
         let hir_param = &hir_generics.params[index];
 
         if ty_param.def_id != hir_param.def_id.into() {
@@ -1982,7 +1990,11 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
 
                 let obligation = traits::Obligation::new(
                     tcx,
-                    traits::ObligationCause::new(span, self.body_def_id, traits::TrivialBound),
+                    traits::ObligationCause::new(
+                        span,
+                        self.body_def_id,
+                        ObligationCauseCode::TrivialBound,
+                    ),
                     empty_env,
                     pred,
                 );
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index 0b6c60e4ba2..8f0aba1c38c 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -14,6 +14,7 @@ use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::infer::{self, RegionResolutionError};
 use rustc_infer::traits::Obligation;
 use rustc_middle::ty::adjustment::CoerceUnsizedInfo;
+use rustc_middle::ty::print::PrintTraitRefExt as _;
 use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeVisitableExt};
 use rustc_span::{Span, DUMMY_SP};
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index 819e0925f68..8e1b2e8e65c 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -571,7 +571,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for TyVarReplacer<'cx, 'tcx> {
         if let Some(def_id) = origin.param_def_id {
             // The generics of an `impl` don't have a parent, we can index directly.
             let index = self.generics.param_def_id_to_index[&def_id];
-            let name = self.generics.params[index as usize].name;
+            let name = self.generics.own_params[index as usize].name;
 
             Ty::new_param(self.infcx.tcx, index, name)
         } else {
diff --git a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
index 13ce4f07593..28735429210 100644
--- a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
@@ -3,6 +3,7 @@
 
 use rustc_errors::{codes::*, struct_span_code_err};
 use rustc_hir::Unsafety;
+use rustc_middle::ty::print::PrintTraitRefExt as _;
 use rustc_middle::ty::{ImplPolarity::*, ImplTraitHeader, TraitDef, TyCtxt};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::ErrorGuaranteed;
@@ -14,7 +15,7 @@ pub(super) fn check_item(
     trait_def: &TraitDef,
 ) -> Result<(), ErrorGuaranteed> {
     let unsafe_attr =
-        tcx.generics_of(def_id).params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle");
+        tcx.generics_of(def_id).own_params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle");
     let trait_ref = trait_header.trait_ref.instantiate_identity();
 
     match (trait_def.unsafety, unsafe_attr, trait_header.unsafety, trait_header.polarity) {
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 9198ceb8f59..566f818f899 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -14,6 +14,7 @@
 //! At present, however, we do run collection across all items in the
 //! crate as a kind of pass. This should eventually be factored away.
 
+use rustc_ast::Recovered;
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_data_structures::unord::UnordMap;
@@ -1005,10 +1006,7 @@ fn lower_variant(
             vis: tcx.visibility(f.def_id),
         })
         .collect();
-    let recovered = match def {
-        hir::VariantData::Struct { recovered, .. } => *recovered,
-        _ => false,
-    };
+    let recovered = matches!(def, hir::VariantData::Struct { recovered: Recovered::Yes(_), .. });
     ty::VariantDef::new(
         ident.name,
         variant_did.map(LocalDefId::to_def_id),
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index f83ddc51c76..6b41f79cf1e 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -22,28 +22,28 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
         let trait_def_id = tcx.parent(fn_def_id);
         let opaque_ty_generics = tcx.generics_of(opaque_def_id);
         let opaque_ty_parent_count = opaque_ty_generics.parent_count;
-        let mut params = opaque_ty_generics.params.clone();
+        let mut own_params = opaque_ty_generics.own_params.clone();
 
         let parent_generics = tcx.generics_of(trait_def_id);
-        let parent_count = parent_generics.parent_count + parent_generics.params.len();
+        let parent_count = parent_generics.parent_count + parent_generics.own_params.len();
 
-        let mut trait_fn_params = tcx.generics_of(fn_def_id).params.clone();
+        let mut trait_fn_params = tcx.generics_of(fn_def_id).own_params.clone();
 
-        for param in &mut params {
+        for param in &mut own_params {
             param.index = param.index + parent_count as u32 + trait_fn_params.len() as u32
                 - opaque_ty_parent_count as u32;
         }
 
-        trait_fn_params.extend(params);
-        params = trait_fn_params;
+        trait_fn_params.extend(own_params);
+        own_params = trait_fn_params;
 
         let param_def_id_to_index =
-            params.iter().map(|param| (param.def_id, param.index)).collect();
+            own_params.iter().map(|param| (param.def_id, param.index)).collect();
 
         return ty::Generics {
             parent: Some(trait_def_id),
             parent_count,
-            params,
+            own_params,
             param_def_id_to_index,
             has_self: opaque_ty_generics.has_self,
             has_late_bound_regions: opaque_ty_generics.has_late_bound_regions,
@@ -124,9 +124,9 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
                     let generics = tcx.generics_of(parent_def_id.to_def_id());
                     let param_def_idx = generics.param_def_id_to_index[&param_id.to_def_id()];
                     // In the above example this would be .params[..N#0]
-                    let params = generics.params_to(param_def_idx as usize, tcx).to_owned();
+                    let own_params = generics.params_to(param_def_idx as usize, tcx).to_owned();
                     let param_def_id_to_index =
-                        params.iter().map(|param| (param.def_id, param.index)).collect();
+                        own_params.iter().map(|param| (param.def_id, param.index)).collect();
 
                     return ty::Generics {
                         // we set the parent of these generics to be our parent's parent so that we
@@ -134,7 +134,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
                         // struct Foo<const N: usize, const M: usize = { ... }>;
                         parent: generics.parent,
                         parent_count: generics.parent_count,
-                        params,
+                        own_params,
                         param_def_id_to_index,
                         has_self: generics.has_self,
                         has_late_bound_regions: generics.has_late_bound_regions,
@@ -274,17 +274,17 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
         parent_has_self = generics.has_self;
         host_effect_index = generics.host_effect_index;
         own_start = generics.count() as u32;
-        generics.parent_count + generics.params.len()
+        generics.parent_count + generics.own_params.len()
     });
 
-    let mut params: Vec<_> = Vec::with_capacity(hir_generics.params.len() + has_self as usize);
+    let mut own_params: Vec<_> = Vec::with_capacity(hir_generics.params.len() + has_self as usize);
 
     if let Some(opt_self) = opt_self {
-        params.push(opt_self);
+        own_params.push(opt_self);
     }
 
     let early_lifetimes = super::early_bound_lifetimes_from_generics(tcx, hir_generics);
-    params.extend(early_lifetimes.enumerate().map(|(i, param)| ty::GenericParamDef {
+    own_params.extend(early_lifetimes.enumerate().map(|(i, param)| ty::GenericParamDef {
         name: param.name.ident().name,
         index: own_start + i as u32,
         def_id: param.def_id.to_def_id(),
@@ -293,7 +293,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
     }));
 
     // Now create the real type and const parameters.
-    let type_start = own_start - has_self as u32 + params.len() as u32;
+    let type_start = own_start - has_self as u32 + own_params.len() as u32;
     let mut i: u32 = 0;
     let mut next_index = || {
         let prev = i;
@@ -304,7 +304,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
     const TYPE_DEFAULT_NOT_ALLOWED: &'static str = "defaults for type parameters are only allowed in \
     `struct`, `enum`, `type`, or `trait` definitions";
 
-    params.extend(hir_generics.params.iter().filter_map(|param| match param.kind {
+    own_params.extend(hir_generics.params.iter().filter_map(|param| match param.kind {
         GenericParamKind::Lifetime { .. } => None,
         GenericParamKind::Type { default, synthetic, .. } => {
             if default.is_some() {
@@ -404,7 +404,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
             ][..],
         };
 
-        params.extend(dummy_args.iter().map(|&arg| ty::GenericParamDef {
+        own_params.extend(dummy_args.iter().map(|&arg| ty::GenericParamDef {
             index: next_index(),
             name: Symbol::intern(arg),
             def_id: def_id.to_def_id(),
@@ -415,7 +415,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
 
     // provide junk type parameter defs for const blocks.
     if let Node::ConstBlock(_) = node {
-        params.push(ty::GenericParamDef {
+        own_params.push(ty::GenericParamDef {
             index: next_index(),
             name: Symbol::intern("<const_ty>"),
             def_id: def_id.to_def_id(),
@@ -424,12 +424,13 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
         });
     }
 
-    let param_def_id_to_index = params.iter().map(|param| (param.def_id, param.index)).collect();
+    let param_def_id_to_index =
+        own_params.iter().map(|param| (param.def_id, param.index)).collect();
 
     ty::Generics {
         parent: parent_def_id,
         parent_count,
-        params,
+        own_params,
         param_def_id_to_index,
         has_self: has_self || parent_has_self,
         has_late_bound_regions: has_late_bound_regions(tcx, node),
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 472657290ed..7e82571d172 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -73,8 +73,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
             // opaque lifetimes, which explains the slicing below.
             compute_bidirectional_outlives_predicates(
                 tcx,
-                &tcx.generics_of(def_id.to_def_id()).params
-                    [tcx.generics_of(fn_def_id).params.len()..],
+                &tcx.generics_of(def_id.to_def_id()).own_params
+                    [tcx.generics_of(fn_def_id).own_params.len()..],
                 &mut predicates,
             );
 
@@ -300,7 +300,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
         };
         debug!(?lifetimes);
 
-        compute_bidirectional_outlives_predicates(tcx, &generics.params, &mut predicates);
+        compute_bidirectional_outlives_predicates(tcx, &generics.own_params, &mut predicates);
         debug!(?predicates);
     }
 
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 a5f038d383d..3ef132a3e8c 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -1562,7 +1562,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                 ObjectLifetimeDefault::Ambiguous => None,
             };
             generics
-                .params
+                .own_params
                 .iter()
                 .filter_map(|param| {
                     match self.tcx.def_kind(param.def_id) {
@@ -1668,7 +1668,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                         binding.ident,
                         ty::AssocKind::Fn,
                     ) {
-                    bound_vars.extend(self.tcx.generics_of(assoc_fn.def_id).params.iter().map(
+                    bound_vars.extend(self.tcx.generics_of(assoc_fn.def_id).own_params.iter().map(
                         |param| match param.kind {
                             ty::GenericParamDefKind::Lifetime => ty::BoundVariableKind::Region(
                                 ty::BoundRegionKind::BrNamed(param.def_id, param.name),
@@ -2003,7 +2003,8 @@ fn is_late_bound_map(
                     // just consider args to be unconstrained.
                     let generics = self.tcx.generics_of(alias_def);
                     let mut walker = ConstrainedCollectorPostHirTyLowering {
-                        arg_is_constrained: vec![false; generics.params.len()].into_boxed_slice(),
+                        arg_is_constrained: vec![false; generics.own_params.len()]
+                            .into_boxed_slice(),
                     };
                     walker.visit_ty(self.tcx.type_of(alias_def).instantiate_identity());
 
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 5ccfd06f258..24a5349858a 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -255,7 +255,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
     debug!(?parent_node);
     debug!(?generics, ?arg_idx);
     if let Some(param_def_id) = generics
-        .params
+        .own_params
         .iter()
         .filter(|param| param.kind.is_ty_or_const())
         .nth(match generics.has_self && generics.parent.is_none() {
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 11bd3e5282d..de12475678c 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
@@ -5,6 +5,7 @@ use rustc_errors::{codes::*, struct_span_code_err};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_middle::ty::print::PrintTraitRefExt as _;
 use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TyCtxt};
 use rustc_span::symbol::Ident;
 use rustc_span::{ErrorGuaranteed, Span, Symbol};
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
index 8e64a9425bb..38dfa8d57d3 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
@@ -17,6 +17,7 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_infer::traits::FulfillmentError;
 use rustc_middle::query::Key;
+use rustc_middle::ty::print::PrintTraitRefExt as _;
 use rustc_middle::ty::GenericParamDefKind;
 use rustc_middle::ty::{self, suggest_constraining_type_param};
 use rustc_middle::ty::{AdtDef, Ty, TyCtxt, TypeVisitableExt};
@@ -1299,7 +1300,7 @@ pub fn prohibit_assoc_item_binding(
         // same name as the assoc type name in type binding
         let generics = tcx.generics_of(def_id);
         let matching_param =
-            generics.params.iter().find(|p| p.name.as_str() == binding.ident.as_str());
+            generics.own_params.iter().find(|p| p.name.as_str() == binding.ident.as_str());
 
         // Now emit the appropriate suggestion
         if let Some(matching_param) = matching_param {
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
index e6a7dfa759c..749f78e7920 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
@@ -196,7 +196,7 @@ pub fn lower_generic_args<'tcx: 'a, 'a>(
     let mut args: SmallVec<[ty::GenericArg<'tcx>; 8]> = SmallVec::with_capacity(count);
     // Iterate over each segment of the path.
     while let Some((def_id, defs)) = stack.pop() {
-        let mut params = defs.params.iter().peekable();
+        let mut params = defs.own_params.iter().peekable();
 
         // If we have already computed the generic arguments for parents,
         // we can use those directly.
@@ -312,7 +312,7 @@ pub fn lower_generic_args<'tcx: 'a, 'a>(
                                 // We're going to iterate over the parameters to sort them out, and
                                 // show that order to the user as a possible order for the parameters
                                 let mut param_types_present = defs
-                                    .params
+                                    .own_params
                                     .iter()
                                     .map(|param| (param.kind.to_ord(), param.clone()))
                                     .collect::<Vec<(ParamKindOrd, GenericParamDef)>>();
@@ -435,13 +435,13 @@ pub(crate) fn check_generic_arg_count(
     // Subtracting from param count to ensure type params synthesized from `impl Trait`
     // cannot be explicitly specified.
     let synth_type_param_count = gen_params
-        .params
+        .own_params
         .iter()
         .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Type { synthetic: true, .. }))
         .count();
     let named_type_param_count = param_counts.types - has_self as usize - synth_type_param_count;
     let synth_const_param_count = gen_params
-        .params
+        .own_params
         .iter()
         .filter(|param| {
             matches!(param.kind, ty::GenericParamDefKind::Const { is_host_effect: true, .. })
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 f7213442ac2..591d554d335 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -411,7 +411,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         // Traits always have `Self` as a generic parameter, which means they will not return early
         // here and so associated type bindings will be handled regardless of whether there are any
         // non-`Self` generic parameters.
-        if generics.params.is_empty() {
+        if generics.own_params.is_empty() {
             return (tcx.mk_args(parent_args), arg_count);
         }
 
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs
index 97ba946b7e0..297cfe7027e 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs
@@ -227,7 +227,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                     .skip(1) // Remove `Self` for `ExistentialPredicate`.
                     .map(|(index, arg)| {
                         if arg == dummy_self.into() {
-                            let param = &generics.params[index];
+                            let param = &generics.own_params[index];
                             missing_type_params.push(param.name);
                             Ty::new_misc_error(tcx).into()
                         } else if arg.walk().any(|arg| arg == dummy_self.into()) {
diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
index 7014b23ff07..d6ba5fa9b5b 100644
--- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
@@ -163,15 +163,17 @@ fn diagnostic_hir_wf_check<'tcx>(
                 kind: hir::GenericParamKind::Type { default: Some(ty), .. },
                 ..
             }) => vec![*ty],
-            hir::Node::AnonConst(_)
-                if let Some(const_param_id) =
-                    tcx.hir().opt_const_param_default_param_def_id(hir_id)
+            hir::Node::AnonConst(_) => {
+                if let Some(const_param_id) = tcx.hir().opt_const_param_default_param_def_id(hir_id)
                     && let hir::Node::GenericParam(hir::GenericParam {
                         kind: hir::GenericParamKind::Const { ty, .. },
                         ..
-                    }) = tcx.hir_node_by_def_id(const_param_id) =>
-            {
-                vec![*ty]
+                    }) = tcx.hir_node_by_def_id(const_param_id)
+                {
+                    vec![*ty]
+                } else {
+                    vec![]
+                }
             }
             ref node => bug!("Unexpected node {:?}", node),
         },
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
index caa85092415..002be61196a 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
@@ -114,7 +114,7 @@ fn enforce_impl_params_are_constrained(
         .collect();
 
     let mut res = Ok(());
-    for param in &impl_generics.params {
+    for param in &impl_generics.own_params {
         match param.kind {
             // Disallow ANY unconstrained type parameters.
             ty::GenericParamDefKind::Type { .. } => {
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 be1be1a1354..de697b04ebf 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
@@ -212,7 +212,7 @@ fn get_impl_args(
             traits::ObligationCause::new(
                 impl1_span,
                 impl1_def_id,
-                traits::ObligationCauseCode::BindingObligation(impl2_node.def_id(), span),
+                traits::ObligationCauseCode::SpannedWhereClause(impl2_node.def_id(), span),
             )
         },
     );
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index 66b86c9eb02..e75740837f8 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -184,7 +184,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
         let def_kind = tcx.def_kind(item_def_id);
         match def_kind {
             DefKind::Static { .. } => tcx.ensure().eval_static_initializer(item_def_id),
-            DefKind::Const if tcx.generics_of(item_def_id).params.is_empty() => {
+            DefKind::Const if tcx.generics_of(item_def_id).own_params.is_empty() => {
                 let instance = ty::Instance::new(item_def_id.into(), ty::GenericArgs::empty());
                 let cid = GlobalId { instance, promoted: None };
                 let param_env = ty::ParamEnv::reveal_all();
diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
index dcab571eedf..9ddba7a6e7a 100644
--- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
@@ -421,7 +421,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
         // We could not gather enough lifetime parameters in the scope.
         // We use the parameter names from the target type's definition instead.
         self.gen_params
-            .params
+            .own_params
             .iter()
             .skip(self.params_offset + self.num_provided_lifetime_args())
             .take(num_params_to_take)
@@ -464,7 +464,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
             })
         };
         self.gen_params
-            .params
+            .own_params
             .iter()
             .skip(self.params_offset + self.num_provided_type_or_const_args())
             .take(num_params_to_take)
@@ -1076,7 +1076,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
             } else {
                 let params = self
                     .gen_params
-                    .params
+                    .own_params
                     .iter()
                     .skip(self.params_offset)
                     .take(bound)
diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index 42885b0c832..27fdea01c2b 100644
--- a/compiler/rustc_hir_analysis/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
@@ -133,7 +133,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
         let mut generics = generics;
         while let Some(def_id) = generics.parent {
             generics = tcx.generics_of(def_id);
-            for param in &generics.params {
+            for param in &generics.own_params {
                 match param.kind {
                     ty::GenericParamDefKind::Lifetime => {
                         variances[param.index as usize] = ty::Bivariant;
diff --git a/compiler/rustc_hir_analysis/src/variance/solve.rs b/compiler/rustc_hir_analysis/src/variance/solve.rs
index 54da3277026..e64c6721fe0 100644
--- a/compiler/rustc_hir_analysis/src/variance/solve.rs
+++ b/compiler/rustc_hir_analysis/src/variance/solve.rs
@@ -76,7 +76,7 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> {
         let tcx = self.terms_cx.tcx;
 
         // Make all const parameters invariant.
-        for param in generics.params.iter() {
+        for param in generics.own_params.iter() {
             if let ty::GenericParamDefKind::Const { .. } = param.kind {
                 variances[param.index as usize] = ty::Invariant;
             }
diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs
index 4ff6678fc91..c2e62e4c003 100644
--- a/compiler/rustc_hir_typeck/src/_match.rs
+++ b/compiler/rustc_hir_typeck/src/_match.rs
@@ -5,7 +5,6 @@ use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::{self as hir, ExprKind, PatKind};
 use rustc_hir_pretty::ty_to_string;
-use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::Span;
 use rustc_trait_selection::traits::{
@@ -67,7 +66,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // arm for inconsistent arms or to the whole match when a `()` type
                 // is required).
                 Expectation::ExpectHasType(ety) if ety != tcx.types.unit => ety,
-                _ => self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr.span }),
+                _ => self.next_ty_var(expr.span),
             };
             CoerceMany::with_coercion_sites(coerce_first, arms)
         };
@@ -575,8 +574,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // ...but otherwise we want to use any supertype of the
             // scrutinee. This is sort of a workaround, see note (*) in
             // `check_pat` for some details.
-            let scrut_ty =
-                self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: scrut.span });
+            let scrut_ty = self.next_ty_var(scrut.span);
             self.check_expr_has_type_or_error(scrut, scrut_ty, |_| {});
             scrut_ty
         }
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index dfd0b7c2945..defb557867b 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -9,11 +9,11 @@ use rustc_hir as hir;
 use rustc_hir::def::{self, CtorKind, Namespace, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir_analysis::autoderef::Autoderef;
+use rustc_infer::traits::ObligationCauseCode;
 use rustc_infer::{
     infer,
-    traits::{self, Obligation},
+    traits::{self, Obligation, ObligationCause},
 };
-use rustc_infer::{infer::type_variable::TypeVariableOrigin, traits::ObligationCause};
 use rustc_middle::ty::adjustment::{
     Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability,
 };
@@ -118,7 +118,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
 
         // we must check that return type of called functions is WF:
-        self.register_wf_obligation(output.into(), call_expr.span, traits::WellFormed(None));
+        self.register_wf_obligation(
+            output.into(),
+            call_expr.span,
+            ObligationCauseCode::WellFormed(None),
+        );
 
         output
     }
@@ -180,14 +184,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     infer::FnCall,
                     closure_args.coroutine_closure_sig(),
                 );
-                let tupled_upvars_ty = self
-                    .next_ty_var(TypeVariableOrigin { param_def_id: None, span: callee_expr.span });
+                let tupled_upvars_ty = self.next_ty_var(callee_expr.span);
                 // We may actually receive a coroutine back whose kind is different
                 // from the closure that this dispatched from. This is because when
                 // we have no captures, we automatically implement `FnOnce`. This
                 // impl forces the closure kind to `FnOnce` i.e. `u8`.
-                let kind_ty = self
-                    .next_ty_var(TypeVariableOrigin { param_def_id: None, span: callee_expr.span });
+                let kind_ty = self.next_ty_var(callee_expr.span);
                 let call_sig = self.tcx.mk_fn_sig(
                     [coroutine_closure_sig.tupled_inputs_ty],
                     coroutine_closure_sig.to_coroutine(
@@ -298,12 +300,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let Some(trait_def_id) = opt_trait_def_id else { continue };
 
             let opt_input_type = opt_arg_exprs.map(|arg_exprs| {
-                Ty::new_tup_from_iter(
-                    self.tcx,
-                    arg_exprs.iter().map(|e| {
-                        self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: e.span })
-                    }),
-                )
+                Ty::new_tup_from_iter(self.tcx, arg_exprs.iter().map(|e| self.next_ty_var(e.span)))
             });
 
             if let Some(ok) = self.lookup_method_in_trait(
@@ -532,9 +529,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.register_bound(
                     ty,
                     self.tcx.require_lang_item(hir::LangItem::Tuple, Some(sp)),
-                    traits::ObligationCause::new(sp, self.body_id, traits::RustCall),
+                    traits::ObligationCause::new(sp, self.body_id, ObligationCauseCode::RustCall),
                 );
-                self.require_type_is_sized(ty, sp, traits::RustCall);
+                self.require_type_is_sized(ty, sp, ObligationCauseCode::RustCall);
             } else {
                 self.dcx().emit_err(errors::RustCallIncorrectArgs { span: sp });
             }
diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs
index b106eca59c4..89e64cf5f0d 100644
--- a/compiler/rustc_hir_typeck/src/check.rs
+++ b/compiler/rustc_hir_typeck/src/check.rs
@@ -8,14 +8,12 @@ use rustc_hir::def::DefKind;
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir_analysis::check::{check_function_signature, forbid_intrinsic_abi};
-use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::infer::RegionVariableOrigin;
 use rustc_infer::traits::WellFormedLoc;
 use rustc_middle::ty::{self, Binder, Ty, TyCtxt};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::symbol::sym;
 use rustc_target::spec::abi::Abi;
-use rustc_trait_selection::traits;
 use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode};
 
 /// Helper used for fns and closures. Does the grungy work of checking a function
@@ -77,7 +75,7 @@ pub(super) fn check_fn<'a, 'tcx>(
             fcx.register_wf_obligation(
                 param_ty.into(),
                 param.span,
-                traits::WellFormed(Some(WellFormedLoc::Param {
+                ObligationCauseCode::WellFormed(Some(WellFormedLoc::Param {
                     function: fn_def_id,
                     param_idx: idx,
                 })),
@@ -102,7 +100,7 @@ pub(super) fn check_fn<'a, 'tcx>(
                 param.pat.span,
                 // ty.span == binding_span iff this is a closure parameter with no type ascription,
                 // or if it's an implicit `self` parameter
-                traits::SizedArgumentType(
+                ObligationCauseCode::SizedArgumentType(
                     if ty_span == Some(param.span) && tcx.is_closure_like(fn_def_id.into()) {
                         None
                     } else {
@@ -122,10 +120,18 @@ pub(super) fn check_fn<'a, 'tcx>(
         hir::FnRetTy::Return(ty) => ty.span,
     };
 
-    fcx.require_type_is_sized(declared_ret_ty, return_or_body_span, traits::SizedReturnType);
+    fcx.require_type_is_sized(
+        declared_ret_ty,
+        return_or_body_span,
+        ObligationCauseCode::SizedReturnType,
+    );
     // We checked the root's signature during wfcheck, but not the child.
     if fcx.tcx.is_typeck_child(fn_def_id.to_def_id()) {
-        fcx.require_type_is_sized(declared_ret_ty, return_or_body_span, traits::WellFormed(None));
+        fcx.require_type_is_sized(
+            declared_ret_ty,
+            return_or_body_span,
+            ObligationCauseCode::WellFormed(None),
+        );
     }
 
     fcx.is_whole_body.set(true);
@@ -142,7 +148,7 @@ pub(super) fn check_fn<'a, 'tcx>(
         // We have special-cased the case where the function is declared
         // `-> dyn Foo` and we don't actually relate it to the
         // `fcx.ret_coercion`, so just instantiate a type variable.
-        actual_return_ty = fcx.next_ty_var(TypeVariableOrigin { param_def_id: None, span });
+        actual_return_ty = fcx.next_ty_var(span);
         debug!("actual_return_ty replaced with {:?}", actual_return_ty);
     }
 
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index 4883c7aff8b..f52f95db6d3 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -6,9 +6,9 @@ use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
-use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes};
 use rustc_infer::infer::{InferOk, InferResult};
+use rustc_infer::traits::ObligationCauseCode;
 use rustc_macros::{TypeFoldable, TypeVisitable};
 use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
 use rustc_middle::ty::GenericArgs;
@@ -31,6 +31,7 @@ struct ExpectedSig<'tcx> {
     sig: ty::PolyFnSig<'tcx>,
 }
 
+#[derive(Debug)]
 struct ClosureSignatures<'tcx> {
     /// The signature users of the closure see.
     bound_sig: ty::PolyFnSig<'tcx>,
@@ -72,8 +73,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let parent_args =
             GenericArgs::identity_for_item(tcx, tcx.typeck_root_def_id(expr_def_id.to_def_id()));
 
-        let tupled_upvars_ty =
-            self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr_span });
+        let tupled_upvars_ty = self.next_ty_var(expr_span);
 
         // FIXME: We could probably actually just unify this further --
         // instead of having a `FnSig` and a `Option<CoroutineTypes>`,
@@ -100,9 +100,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                     // Create a type variable (for now) to represent the closure kind.
                     // It will be unified during the upvar inference phase (`upvar.rs`)
-                    None => {
-                        self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr_span })
-                    }
+                    None => self.next_ty_var(expr_span),
                 };
 
                 let closure_args = ty::ClosureArgs::new(
@@ -121,11 +119,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let yield_ty = match kind {
                     hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)
                     | hir::CoroutineKind::Coroutine(_) => {
-                        let yield_ty = self.next_ty_var(TypeVariableOrigin {
-                            param_def_id: None,
-                            span: expr_span,
-                        });
-                        self.require_type_is_sized(yield_ty, expr_span, traits::SizedYieldType);
+                        let yield_ty = self.next_ty_var(expr_span);
+                        self.require_type_is_sized(
+                            yield_ty,
+                            expr_span,
+                            ObligationCauseCode::SizedYieldType,
+                        );
                         yield_ty
                     }
                     // HACK(-Ztrait-solver=next): In the *old* trait solver, we must eagerly
@@ -133,11 +132,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     // in this block in projection correctly. In the new trait solver, it is
                     // not a problem.
                     hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _) => {
-                        let yield_ty = self.next_ty_var(TypeVariableOrigin {
-                            param_def_id: None,
-                            span: expr_span,
-                        });
-                        self.require_type_is_sized(yield_ty, expr_span, traits::SizedYieldType);
+                        let yield_ty = self.next_ty_var(expr_span);
+                        self.require_type_is_sized(
+                            yield_ty,
+                            expr_span,
+                            ObligationCauseCode::SizedYieldType,
+                        );
 
                         Ty::new_adt(
                             tcx,
@@ -162,8 +162,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // Resume type defaults to `()` if the coroutine has no argument.
                 let resume_ty = liberated_sig.inputs().get(0).copied().unwrap_or(tcx.types.unit);
 
-                let interior =
-                    self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr_span });
+                let interior = self.next_ty_var(expr_span);
                 self.deferred_coroutine_interiors.borrow_mut().push((
                     expr_def_id,
                     body.id(),
@@ -176,7 +175,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // ty of `().`
                 let kind_ty = match kind {
                     hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure) => {
-                        self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr_span })
+                        self.next_ty_var(expr_span)
                     }
                     _ => tcx.types.unit,
                 };
@@ -211,23 +210,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
                 };
                 // Compute all of the variables that will be used to populate the coroutine.
-                let resume_ty =
-                    self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr_span });
-                let interior =
-                    self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr_span });
+                let resume_ty = self.next_ty_var(expr_span);
+                let interior = self.next_ty_var(expr_span);
 
                 let closure_kind_ty = match expected_kind {
                     Some(kind) => Ty::from_closure_kind(tcx, kind),
 
                     // Create a type variable (for now) to represent the closure kind.
                     // It will be unified during the upvar inference phase (`upvar.rs`)
-                    None => {
-                        self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr_span })
-                    }
+                    None => self.next_ty_var(expr_span),
                 };
 
-                let coroutine_captures_by_ref_ty =
-                    self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr_span });
+                let coroutine_captures_by_ref_ty = self.next_ty_var(expr_span);
                 let closure_args = ty::CoroutineClosureArgs::new(
                     tcx,
                     ty::CoroutineClosureArgsParts {
@@ -259,13 +253,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                     // Create a type variable (for now) to represent the closure kind.
                     // It will be unified during the upvar inference phase (`upvar.rs`)
-                    None => {
-                        self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr_span })
-                    }
+                    None => self.next_ty_var(expr_span),
                 };
 
-                let coroutine_upvars_ty =
-                    self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr_span });
+                let coroutine_upvars_ty = self.next_ty_var(expr_span);
 
                 // We need to turn the liberated signature that we got from HIR, which
                 // looks something like `|Args...| -> T`, into a signature that is suitable
@@ -713,25 +704,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // [c2]: https://github.com/rust-lang/rust/pull/45072#issuecomment-341096796
         self.commit_if_ok(|_| {
             let mut all_obligations = vec![];
-            let inputs: Vec<_> = iter::zip(
-                decl.inputs,
-                supplied_sig.inputs().skip_binder(), // binder moved to (*) below
-            )
-            .map(|(hir_ty, &supplied_ty)| {
-                // Instantiate (this part of..) S to S', i.e., with fresh variables.
-                self.instantiate_binder_with_fresh_vars(
-                    hir_ty.span,
-                    BoundRegionConversionTime::FnCall,
-                    // (*) binder moved to here
-                    supplied_sig.inputs().rebind(supplied_ty),
-                )
-            })
-            .collect();
+            let supplied_sig = self.instantiate_binder_with_fresh_vars(
+                self.tcx.def_span(expr_def_id),
+                BoundRegionConversionTime::FnCall,
+                supplied_sig,
+            );
 
             // The liberated version of this signature should be a subtype
             // of the liberated form of the expectation.
             for ((hir_ty, &supplied_ty), expected_ty) in iter::zip(
-                iter::zip(decl.inputs, &inputs),
+                iter::zip(decl.inputs, supplied_sig.inputs()),
                 expected_sigs.liberated_sig.inputs(), // `liberated_sig` is E'.
             ) {
                 // Check that E' = S'.
@@ -744,11 +726,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 all_obligations.extend(obligations);
             }
 
-            let supplied_output_ty = self.instantiate_binder_with_fresh_vars(
-                decl.output.span(),
-                BoundRegionConversionTime::FnCall,
-                supplied_sig.output(),
-            );
+            let supplied_output_ty = supplied_sig.output();
             let cause = &self.misc(decl.output.span());
             let InferOk { value: (), obligations } = self.at(cause, self.param_env).eq(
                 DefineOpaqueTypes::Yes,
@@ -757,7 +735,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             )?;
             all_obligations.extend(obligations);
 
-            let inputs = inputs.into_iter().map(|ty| self.resolve_vars_if_possible(ty));
+            let inputs =
+                supplied_sig.inputs().into_iter().map(|&ty| self.resolve_vars_if_possible(ty));
 
             expected_sigs.liberated_sig = self.tcx.mk_fn_sig(
                 inputs,
@@ -1013,6 +992,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         result
     }
 
+    #[instrument(level = "debug", skip(self), ret)]
     fn closure_sigs(
         &self,
         expr_def_id: LocalDefId,
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 076c1936ded..88ba937e4b5 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -37,13 +37,10 @@
 
 use crate::errors::SuggestBoxingForReturnImplTrait;
 use crate::FnCtxt;
-use rustc_errors::{codes::*, struct_span_code_err, Applicability, Diag, MultiSpan};
+use rustc_errors::{codes::*, struct_span_code_err, Applicability, Diag};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir::Expr;
 use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
-use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult};
 use rustc_infer::traits::{IfExpressionCause, MatchExpressionArmCause};
 use rustc_infer::traits::{Obligation, PredicateObligation};
@@ -93,22 +90,6 @@ impl<'a, 'tcx> Deref for Coerce<'a, 'tcx> {
 
 type CoerceResult<'tcx> = InferResult<'tcx, (Vec<Adjustment<'tcx>>, Ty<'tcx>)>;
 
-struct CollectRetsVisitor<'tcx> {
-    ret_exprs: Vec<&'tcx hir::Expr<'tcx>>,
-}
-
-impl<'tcx> Visitor<'tcx> for CollectRetsVisitor<'tcx> {
-    fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
-        match expr.kind {
-            hir::ExprKind::Ret(_) => self.ret_exprs.push(expr),
-            // `return` in closures does not return from the outer function
-            hir::ExprKind::Closure(_) => return,
-            _ => {}
-        }
-        intravisit::walk_expr(self, expr);
-    }
-}
-
 /// Coercing a mutable reference to an immutable works, while
 /// coercing `&T` to `&mut T` should be forbidden.
 fn coerce_mutbls<'tcx>(
@@ -275,11 +256,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
 
         if b.is_ty_var() {
             // Two unresolved type variables: create a `Coerce` predicate.
-            let target_ty = if self.use_lub {
-                self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: self.cause.span })
-            } else {
-                b
-            };
+            let target_ty = if self.use_lub { self.next_ty_var(self.cause.span) } else { b };
 
             let mut obligations = Vec::with_capacity(2);
             for &source_ty in &[a, b] {
@@ -575,8 +552,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         // the `CoerceUnsized` target type and the expected type.
         // We only have the latter, so we use an inference variable
         // for the former and let type inference do the rest.
-        let origin = TypeVariableOrigin { param_def_id: None, span: self.cause.span };
-        let coerce_target = self.next_ty_var(origin);
+        let coerce_target = self.next_ty_var(self.cause.span);
         let mut coercion = self.unify_and(coerce_target, target, |target| {
             let unsize = Adjustment { kind: Adjust::Pointer(PointerCoercion::Unsize), target };
             match reborrow {
@@ -782,10 +758,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
             self.tcx,
             self.cause.clone(),
             self.param_env,
-            ty::TraitRef::from_lang_item(
+            ty::TraitRef::new(
                 self.tcx,
-                hir::LangItem::PointerLike,
-                self.cause.span,
+                self.tcx.require_lang_item(hir::LangItem::PointerLike, Some(self.cause.span)),
                 [a],
             ),
         ));
@@ -1597,7 +1572,6 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
 
                 let mut err;
                 let mut unsized_return = false;
-                let mut visitor = CollectRetsVisitor { ret_exprs: vec![] };
                 match *cause.code() {
                     ObligationCauseCode::ReturnNoExpression => {
                         err = struct_span_code_err!(
@@ -1632,11 +1606,6 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
                         if !fcx.tcx.features().unsized_locals {
                             unsized_return = self.is_return_ty_definitely_unsized(fcx);
                         }
-                        if let Some(expression) = expression
-                            && let hir::ExprKind::Loop(loop_blk, ..) = expression.kind
-                        {
-                            intravisit::walk_block(&mut visitor, loop_blk);
-                        }
                     }
                     ObligationCauseCode::ReturnValue(id) => {
                         err = self.report_return_mismatched_types(
@@ -1737,6 +1706,22 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
                 augment_error(&mut err);
 
                 if let Some(expr) = expression {
+                    if let hir::ExprKind::Loop(
+                        _,
+                        _,
+                        loop_src @ (hir::LoopSource::While | hir::LoopSource::ForLoop),
+                        _,
+                    ) = expr.kind
+                    {
+                        let loop_type = if loop_src == hir::LoopSource::While {
+                            "`while` loops"
+                        } else {
+                            "`for` loops"
+                        };
+
+                        err.note(format!("{loop_type} evaluate to unit type `()`"));
+                    }
+
                     fcx.emit_coerce_suggestions(
                         &mut err,
                         expr,
@@ -1745,15 +1730,6 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
                         None,
                         Some(coercion_error),
                     );
-                    if visitor.ret_exprs.len() > 0 {
-                        self.note_unreachable_loop_return(
-                            &mut err,
-                            fcx.tcx,
-                            &expr,
-                            &visitor.ret_exprs,
-                            expected,
-                        );
-                    }
                 }
 
                 let reported = err.emit_unless(unsized_return);
@@ -1827,110 +1803,6 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
         );
     }
 
-    fn note_unreachable_loop_return(
-        &self,
-        err: &mut Diag<'_>,
-        tcx: TyCtxt<'tcx>,
-        expr: &hir::Expr<'tcx>,
-        ret_exprs: &Vec<&'tcx hir::Expr<'tcx>>,
-        ty: Ty<'tcx>,
-    ) {
-        let hir::ExprKind::Loop(_, _, _, loop_span) = expr.kind else {
-            return;
-        };
-        let mut span: MultiSpan = vec![loop_span].into();
-        span.push_span_label(loop_span, "this might have zero elements to iterate on");
-        const MAXITER: usize = 3;
-        let iter = ret_exprs.iter().take(MAXITER);
-        for ret_expr in iter {
-            span.push_span_label(
-                ret_expr.span,
-                "if the loop doesn't execute, this value would never get returned",
-            );
-        }
-        err.span_note(
-            span,
-            "the function expects a value to always be returned, but loops might run zero times",
-        );
-        if MAXITER < ret_exprs.len() {
-            err.note(format!(
-                "if the loop doesn't execute, {} other values would never get returned",
-                ret_exprs.len() - MAXITER
-            ));
-        }
-        let hir = tcx.hir();
-        let item = hir.get_parent_item(expr.hir_id);
-        let ret_msg = "return a value for the case when the loop has zero elements to iterate on";
-        let ret_ty_msg =
-            "otherwise consider changing the return type to account for that possibility";
-        let node = tcx.hir_node(item.into());
-        if let Some(body_id) = node.body_id()
-            && let Some(sig) = node.fn_sig()
-            && let hir::ExprKind::Block(block, _) = hir.body(body_id).value.kind
-            && !ty.is_never()
-        {
-            let indentation = if let None = block.expr
-                && let [.., last] = &block.stmts
-            {
-                tcx.sess.source_map().indentation_before(last.span).unwrap_or_else(String::new)
-            } else if let Some(expr) = block.expr {
-                tcx.sess.source_map().indentation_before(expr.span).unwrap_or_else(String::new)
-            } else {
-                String::new()
-            };
-            if let None = block.expr
-                && let [.., last] = &block.stmts
-            {
-                err.span_suggestion_verbose(
-                    last.span.shrink_to_hi(),
-                    ret_msg,
-                    format!("\n{indentation}/* `{ty}` value */"),
-                    Applicability::MaybeIncorrect,
-                );
-            } else if let Some(expr) = block.expr {
-                err.span_suggestion_verbose(
-                    expr.span.shrink_to_hi(),
-                    ret_msg,
-                    format!("\n{indentation}/* `{ty}` value */"),
-                    Applicability::MaybeIncorrect,
-                );
-            }
-            let mut sugg = match sig.decl.output {
-                hir::FnRetTy::DefaultReturn(span) => {
-                    vec![(span, " -> Option<()>".to_string())]
-                }
-                hir::FnRetTy::Return(ty) => {
-                    vec![
-                        (ty.span.shrink_to_lo(), "Option<".to_string()),
-                        (ty.span.shrink_to_hi(), ">".to_string()),
-                    ]
-                }
-            };
-            for ret_expr in ret_exprs {
-                match ret_expr.kind {
-                    hir::ExprKind::Ret(Some(expr)) => {
-                        sugg.push((expr.span.shrink_to_lo(), "Some(".to_string()));
-                        sugg.push((expr.span.shrink_to_hi(), ")".to_string()));
-                    }
-                    hir::ExprKind::Ret(None) => {
-                        sugg.push((ret_expr.span.shrink_to_hi(), " Some(())".to_string()));
-                    }
-                    _ => {}
-                }
-            }
-            if let None = block.expr
-                && let [.., last] = &block.stmts
-            {
-                sugg.push((last.span.shrink_to_hi(), format!("\n{indentation}None")));
-            } else if let Some(expr) = block.expr {
-                sugg.push((expr.span.shrink_to_hi(), format!("\n{indentation}None")));
-            }
-            err.multipart_suggestion(ret_ty_msg, sugg, Applicability::MaybeIncorrect);
-        } else {
-            err.help(format!("{ret_msg}, {ret_ty_msg}"));
-        }
-    }
-
     fn report_return_mismatched_types<'a>(
         &self,
         cause: &ObligationCause<'tcx>,
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 618d90a07ec..b2112491733 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -57,7 +57,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             || self.suggest_into(err, expr, expr_ty, expected)
             || self.suggest_floating_point_literal(err, expr, expected)
             || self.suggest_null_ptr_for_literal_zero_given_to_ptr_arg(err, expr, expected)
-            || self.suggest_coercing_result_via_try_operator(err, expr, expected, expr_ty);
+            || self.suggest_coercing_result_via_try_operator(err, expr, expected, expr_ty)
+            || self.suggest_returning_value_after_loop(err, expr, expected);
 
         if !suggested {
             self.note_source_of_type_mismatch_constraint(
@@ -329,16 +330,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             hir.body(hir.maybe_body_owned_by(self.body_id).expect("expected item to have body"));
         expr_finder.visit_expr(body.value);
 
-        use rustc_infer::infer::type_variable::*;
-        use rustc_middle::infer::unify_key::*;
         // Replaces all of the variables in the given type with a fresh inference variable.
         let mut fudger = BottomUpFolder {
             tcx: self.tcx,
             ty_op: |ty| {
                 if let ty::Infer(infer) = ty.kind() {
                     match infer {
-                        ty::TyVar(_) => self
-                            .next_ty_var(TypeVariableOrigin { param_def_id: None, span: DUMMY_SP }),
+                        ty::TyVar(_) => self.next_ty_var(DUMMY_SP),
                         ty::IntVar(_) => self.next_int_var(),
                         ty::FloatVar(_) => self.next_float_var(),
                         ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => {
@@ -352,10 +350,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             lt_op: |_| self.tcx.lifetimes.re_erased,
             ct_op: |ct| {
                 if let ty::ConstKind::Infer(_) = ct.kind() {
-                    self.next_const_var(
-                        ct.ty(),
-                        ConstVariableOrigin { param_def_id: None, span: DUMMY_SP },
-                    )
+                    self.next_const_var(ct.ty(), DUMMY_SP)
                 } else {
                     ct
                 }
diff --git a/compiler/rustc_hir_typeck/src/expectation.rs b/compiler/rustc_hir_typeck/src/expectation.rs
index 5106d29091a..91deae4174b 100644
--- a/compiler/rustc_hir_typeck/src/expectation.rs
+++ b/compiler/rustc_hir_typeck/src/expectation.rs
@@ -1,4 +1,3 @@
-use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::Span;
 
@@ -110,7 +109,6 @@ impl<'a, 'tcx> Expectation<'tcx> {
     /// Like `only_has_type`, but instead of returning `None` if no
     /// hard constraint exists, creates a fresh type variable.
     pub(super) fn coercion_target_type(self, fcx: &FnCtxt<'a, 'tcx>, span: Span) -> Ty<'tcx> {
-        self.only_has_type(fcx)
-            .unwrap_or_else(|| fcx.next_ty_var(TypeVariableOrigin { param_def_id: None, span }))
+        self.only_has_type(fcx).unwrap_or_else(|| fcx.next_ty_var(span))
     }
 }
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 7b552bb7077..cdf17f3a113 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -37,7 +37,6 @@ use rustc_hir::lang_items::LangItem;
 use rustc_hir::{ExprKind, HirId, QPath};
 use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer as _;
 use rustc_infer::infer;
-use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::infer::DefineOpaqueTypes;
 use rustc_infer::infer::InferOk;
 use rustc_infer::traits::query::NoSolution;
@@ -80,8 +79,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 return Ty::new_error(self.tcx(), reported);
             }
 
-            let adj_ty =
-                self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr.span });
+            let adj_ty = self.next_ty_var(expr.span);
             self.apply_adjustments(
                 expr,
                 vec![Adjustment { kind: Adjust::NeverToAny, target: adj_ty }],
@@ -575,7 +573,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     self.require_type_is_sized_deferred(
                         input,
                         span,
-                        traits::SizedArgumentType(None),
+                        ObligationCauseCode::SizedArgumentType(None),
                     );
                 }
             }
@@ -593,7 +591,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             self.require_type_is_sized_deferred(
                 output,
                 call.map_or(expr.span, |e| e.span),
-                traits::SizedCallReturnType,
+                ObligationCauseCode::SizedCallReturnType,
             );
         }
 
@@ -1251,7 +1249,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
         });
 
-        self.require_type_is_sized(lhs_ty, lhs.span, traits::AssignmentLhsSized);
+        self.require_type_is_sized(lhs_ty, lhs.span, ObligationCauseCode::AssignmentLhsSized);
 
         if let Err(guar) = (lhs_ty, rhs_ty).error_reported() {
             Ty::new_error(self.tcx, guar)
@@ -1271,7 +1269,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // otherwise check exactly as a let statement
         self.check_decl((let_expr, hir_id).into());
         // but return a bool, for this is a boolean expression
-        if let Some(error_guaranteed) = let_expr.is_recovered {
+        if let ast::Recovered::Yes(error_guaranteed) = let_expr.recovered {
             self.set_tainted_by_errors(error_guaranteed);
             Ty::new_error(self.tcx, error_guaranteed)
         } else {
@@ -1412,9 +1410,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     ty::Array(ty, _) | ty::Slice(ty) => Some(ty),
                     _ => None,
                 })
-                .unwrap_or_else(|| {
-                    self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr.span })
-                });
+                .unwrap_or_else(|| self.next_ty_var(expr.span));
             let mut coerce = CoerceMany::with_coercion_sites(coerce_to, args);
             assert_eq!(self.diverges.get(), Diverges::Maybe);
             for e in args {
@@ -1424,7 +1420,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
             coerce.complete(self)
         } else {
-            self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr.span })
+            self.next_ty_var(expr.span)
         };
         let array_len = args.len() as u64;
         self.suggest_array_len(expr, array_len);
@@ -1475,7 +1471,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         crate::GatherLocalsVisitor::new(&fcx).visit_body(body);
 
         let ty = fcx.check_expr_with_expectation(body.value, expected);
-        fcx.require_type_is_sized(ty, body.value.span, traits::ConstSized);
+        fcx.require_type_is_sized(ty, body.value.span, ObligationCauseCode::ConstSized);
         fcx.write_ty(block.hir_id, ty);
         ty
     }
@@ -1507,8 +1503,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 (uty, uty)
             }
             None => {
-                let ty =
-                    self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: element.span });
+                let ty = self.next_ty_var(element.span);
                 let element_ty = self.check_expr_has_type_or_error(element, ty, |_| {});
                 (element_ty, ty)
             }
@@ -1522,7 +1517,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let ty = Ty::new_array_with_const_len(tcx, t, count);
 
-        self.register_wf_obligation(ty.into(), expr.span, traits::WellFormed(None));
+        self.register_wf_obligation(ty.into(), expr.span, ObligationCauseCode::WellFormed(None));
 
         ty
     }
@@ -1612,7 +1607,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         if let Err(guar) = tuple.error_reported() {
             Ty::new_error(self.tcx, guar)
         } else {
-            self.require_type_is_sized(tuple, expr.span, traits::TupleInitializerSized);
+            self.require_type_is_sized(
+                tuple,
+                expr.span,
+                ObligationCauseCode::TupleInitializerSized,
+            );
             tuple
         }
     }
@@ -1651,7 +1650,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             base_expr,
         );
 
-        self.require_type_is_sized(adt_ty, expr.span, traits::StructInitializerSized);
+        self.require_type_is_sized(adt_ty, expr.span, ObligationCauseCode::StructInitializerSized);
         adt_ty
     }
 
@@ -3084,14 +3083,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             polarity: ty::PredicatePolarity::Positive,
                         }),
                         |derived| {
-                            traits::ImplDerivedObligation(Box::new(
-                                traits::ImplDerivedObligationCause {
-                                    derived,
-                                    impl_or_alias_def_id: impl_def_id,
-                                    impl_def_predicate_index: Some(idx),
-                                    span,
-                                },
-                            ))
+                            ObligationCauseCode::ImplDerived(Box::new(traits::ImplDerivedCause {
+                                derived,
+                                impl_or_alias_def_id: impl_def_id,
+                                impl_def_predicate_index: Some(idx),
+                                span,
+                            }))
                         },
                     )
                 },
@@ -3182,7 +3179,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn check_expr_asm_operand(&self, expr: &'tcx hir::Expr<'tcx>, is_input: bool) {
         let needs = if is_input { Needs::None } else { Needs::MutPlace };
         let ty = self.check_expr_with_needs(expr, needs);
-        self.require_type_is_sized(ty, expr.span, traits::InlineAsmSized);
+        self.require_type_is_sized(ty, expr.span, ObligationCauseCode::InlineAsmSized);
 
         if !is_input && !expr.is_syntactic_place_expr() {
             self.dcx()
@@ -3353,7 +3350,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     let field_ty = self.field_ty(expr.span, field, args);
 
                     // FIXME: DSTs with static alignment should be allowed
-                    self.require_type_is_sized(field_ty, expr.span, traits::MiscObligation);
+                    self.require_type_is_sized(field_ty, expr.span, ObligationCauseCode::Misc);
 
                     if field.vis.is_accessible_from(sub_def_scope, self.tcx) {
                         self.tcx.check_stability(field.did, Some(expr.hir_id), expr.span, None);
@@ -3381,7 +3378,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         let field_ty = self.field_ty(expr.span, field, args);
 
                         // FIXME: DSTs with static alignment should be allowed
-                        self.require_type_is_sized(field_ty, expr.span, traits::MiscObligation);
+                        self.require_type_is_sized(field_ty, expr.span, ObligationCauseCode::Misc);
 
                         if field.vis.is_accessible_from(def_scope, self.tcx) {
                             self.tcx.check_stability(field.did, Some(expr.hir_id), expr.span, None);
@@ -3402,7 +3399,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         && field.name == sym::integer(index)
                     {
                         for ty in tys.iter().take(index + 1) {
-                            self.require_type_is_sized(ty, expr.span, traits::MiscObligation);
+                            self.require_type_is_sized(ty, expr.span, ObligationCauseCode::Misc);
                         }
                         if let Some(&field_ty) = tys.get(index) {
                             field_indices.push((FIRST_VARIANT, index.into()));
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 552747bdc52..881f726e1da 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -409,7 +409,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     pub fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> LoweredTy<'tcx> {
         let ty = self.lowerer().lower_ty(hir_ty);
-        self.register_wf_obligation(ty.into(), hir_ty.span, traits::WellFormed(None));
+        self.register_wf_obligation(ty.into(), hir_ty.span, ObligationCauseCode::WellFormed(None));
         LoweredTy::from_raw(self, hir_ty.span, ty)
     }
 
@@ -520,7 +520,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         for arg in args.iter().filter(|arg| {
             matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..))
         }) {
-            self.register_wf_obligation(arg, expr.span, traits::WellFormed(None));
+            self.register_wf_obligation(arg, expr.span, ObligationCauseCode::WellFormed(None));
         }
     }
 
@@ -624,10 +624,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// returns a type of `&T`, but the actual type we assign to the
     /// *expression* is `T`. So this function just peels off the return
     /// type by one layer to yield `T`.
-    pub(crate) fn make_overloaded_place_return_type(
-        &self,
-        method: MethodCallee<'tcx>,
-    ) -> ty::TypeAndMut<'tcx> {
+    pub(crate) fn make_overloaded_place_return_type(&self, method: MethodCallee<'tcx>) -> Ty<'tcx> {
         // extract method return type, which will be &T;
         let ret_ty = method.sig.output();
 
@@ -775,7 +772,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
         if let Some(&cached_result) = self.typeck_results.borrow().type_dependent_defs().get(hir_id)
         {
-            self.register_wf_obligation(ty.raw.into(), qself.span, traits::WellFormed(None));
+            self.register_wf_obligation(
+                ty.raw.into(),
+                qself.span,
+                ObligationCauseCode::WellFormed(None),
+            );
             // Return directly on cache hit. This is useful to avoid doubly reporting
             // errors with default match binding modes. See #44614.
             let def = cached_result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id));
@@ -814,7 +815,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     self.register_wf_obligation(
                         ty.raw.into(),
                         qself.span,
-                        traits::WellFormed(None),
+                        ObligationCauseCode::WellFormed(None),
                     );
                 }
 
@@ -848,7 +849,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             });
 
         if result.is_ok() {
-            self.register_wf_obligation(ty.raw.into(), qself.span, traits::WellFormed(None));
+            self.register_wf_obligation(
+                ty.raw.into(),
+                qself.span,
+                ObligationCauseCode::WellFormed(None),
+            );
         }
 
         // Write back the new resolution.
@@ -1405,9 +1410,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) {
         self.add_required_obligations_with_code(span, def_id, args, |idx, span| {
             if span.is_dummy() {
-                ObligationCauseCode::ExprItemObligation(def_id, hir_id, idx)
+                ObligationCauseCode::WhereClauseInExpr(def_id, hir_id, idx)
             } else {
-                ObligationCauseCode::ExprBindingObligation(def_id, span, hir_id, idx)
+                ObligationCauseCode::SpannedWhereClauseInExpr(def_id, span, hir_id, idx)
             }
         })
     }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
index a718760f4d8..26996397659 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
@@ -14,8 +14,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         error: &mut traits::FulfillmentError<'tcx>,
     ) -> bool {
-        let (traits::ExprItemObligation(def_id, hir_id, idx)
-        | traits::ExprBindingObligation(def_id, _, hir_id, idx)) =
+        let (ObligationCauseCode::WhereClauseInExpr(def_id, hir_id, idx)
+        | ObligationCauseCode::SpannedWhereClauseInExpr(def_id, _, hir_id, idx)) =
             *error.obligation.cause.code().peel_derives()
         else {
             return false;
@@ -167,7 +167,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     // the method's turbofish segments but still use `FunctionArgumentObligation`
                     // elsewhere. Hopefully this doesn't break something.
                     error.obligation.cause.map_code(|parent_code| {
-                        ObligationCauseCode::FunctionArgumentObligation {
+                        ObligationCauseCode::FunctionArg {
                             arg_hir_id: receiver.hir_id,
                             call_hir_id: hir_id,
                             parent_code,
@@ -360,12 +360,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         error: &traits::FulfillmentError<'tcx>,
         span: Span,
     ) -> bool {
-        if let traits::FulfillmentErrorCode::SelectionError(
-            traits::SelectionError::SignatureMismatch(box traits::SignatureMismatchData {
-                expected_trait_ref,
-                ..
-            }),
-        ) = error.code
+        if let traits::FulfillmentErrorCode::Select(traits::SelectionError::SignatureMismatch(
+            box traits::SignatureMismatchData { expected_trait_ref, .. },
+        )) = error.code
             && let ty::Closure(def_id, _) | ty::Coroutine(def_id, ..) =
                 expected_trait_ref.self_ty().kind()
             && span.overlaps(self.tcx.def_span(*def_id))
@@ -459,12 +456,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.blame_specific_expr_if_possible(error, arg_expr)
             }
 
-            error.obligation.cause.map_code(|parent_code| {
-                ObligationCauseCode::FunctionArgumentObligation {
-                    arg_hir_id: arg.hir_id,
-                    call_hir_id,
-                    parent_code,
-                }
+            error.obligation.cause.map_code(|parent_code| ObligationCauseCode::FunctionArg {
+                arg_hir_id: arg.hir_id,
+                call_hir_id,
+                parent_code,
             });
             return true;
         } else if args_referencing_param.len() > 0 {
@@ -517,12 +512,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expr: &'tcx hir::Expr<'tcx>,
     ) -> Result<&'tcx hir::Expr<'tcx>, &'tcx hir::Expr<'tcx>> {
         match obligation_cause_code {
-            traits::ObligationCauseCode::ExprBindingObligation(_, _, _, _) => {
+            traits::ObligationCauseCode::SpannedWhereClauseInExpr(_, _, _, _) => {
                 // This is the "root"; we assume that the `expr` is already pointing here.
                 // Therefore, we return `Ok` so that this `expr` can be refined further.
                 Ok(expr)
             }
-            traits::ObligationCauseCode::ImplDerivedObligation(impl_derived) => self
+            traits::ObligationCauseCode::ImplDerived(impl_derived) => self
                 .blame_specific_expr_if_possible_for_derived_predicate_obligation(
                     impl_derived,
                     expr,
@@ -560,7 +555,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// only a partial success - but it cannot be refined even further.
     fn blame_specific_expr_if_possible_for_derived_predicate_obligation(
         &self,
-        obligation: &traits::ImplDerivedObligationCause<'tcx>,
+        obligation: &traits::ImplDerivedCause<'tcx>,
         expr: &'tcx hir::Expr<'tcx>,
     ) -> Result<&'tcx hir::Expr<'tcx>, &'tcx hir::Expr<'tcx>> {
         // First, we attempt to refine the `expr` for our span using the parent obligation.
@@ -729,7 +724,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             };
 
             let struct_generic_parameters: &ty::Generics = self.tcx.generics_of(in_ty_adt.did());
-            if drill_generic_index >= struct_generic_parameters.params.len() {
+            if drill_generic_index >= struct_generic_parameters.own_params.len() {
                 return Err(expr);
             }
 
@@ -852,7 +847,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             };
 
             let struct_generic_parameters: &ty::Generics = self.tcx.generics_of(in_ty_adt.did());
-            if drill_generic_index >= struct_generic_parameters.params.len() {
+            if drill_generic_index >= struct_generic_parameters.own_params.len() {
                 return Err(expr);
             }
 
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index e45e0884aff..4bf82355b62 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -31,16 +31,14 @@ use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
 use rustc_hir_analysis::structured_errors::StructuredDiag;
 use rustc_index::IndexVec;
 use rustc_infer::infer::error_reporting::{FailureCode, ObligationCauseExt};
-use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::infer::TypeTrace;
 use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
-use rustc_middle::traits::ObligationCauseCode::ExprBindingObligation;
 use rustc_middle::ty::adjustment::AllowTwoPhase;
 use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt};
 use rustc_session::Session;
 use rustc_span::symbol::{kw, Ident};
-use rustc_span::{sym, BytePos, Span};
+use rustc_span::{sym, BytePos, Span, DUMMY_SP};
 use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext};
 
 use std::iter;
@@ -204,7 +202,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // All the input types from the fn signature must outlive the call
         // so as to validate implied bounds.
         for (&fn_input_ty, arg_expr) in iter::zip(formal_input_tys, provided_args) {
-            self.register_wf_obligation(fn_input_ty.into(), arg_expr.span, traits::MiscObligation);
+            self.register_wf_obligation(
+                fn_input_ty.into(),
+                arg_expr.span,
+                ObligationCauseCode::Misc,
+            );
         }
 
         let mut err_code = E0061;
@@ -2011,7 +2013,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         for (span, code) in errors_causecode {
             self.dcx().try_steal_modify_and_emit_err(span, StashKey::MaybeForgetReturn, |err| {
                 if let Some(fn_sig) = self.body_fn_sig()
-                    && let ExprBindingObligation(_, _, binding_hir_id, ..) = code
+                    && let ObligationCauseCode::SpannedWhereClauseInExpr(_, _, binding_hir_id, ..) =
+                        code
                     && !fn_sig.output().is_unit()
                 {
                     let mut block_num = 0;
@@ -2100,7 +2103,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         //
         // This is because due to normalization, we often register duplicate
         // obligations with misc obligations that are basically impossible to
-        // line back up with a useful ExprBindingObligation.
+        // line back up with a useful SpannedWhereClauseInExpr.
         for error in not_adjusted {
             for (span, predicate, cause) in &remap_cause {
                 if *predicate == error.obligation.predicate
@@ -2180,13 +2183,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         let trait_ref = ty::TraitRef::new(
                             self.tcx,
                             self.tcx.fn_trait_kind_to_def_id(call_kind)?,
-                            [
-                                callee_ty,
-                                self.next_ty_var(TypeVariableOrigin {
-                                    param_def_id: None,
-                                    span: rustc_span::DUMMY_SP,
-                                }),
-                            ],
+                            [callee_ty, self.next_ty_var(DUMMY_SP)],
                         );
                         let obligation = traits::Obligation::new(
                             self.tcx,
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs
index c2068d9f66b..2ef254f644f 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs
@@ -1,9 +1,8 @@
 //! A utility module to inspect currently ambiguous obligations in the current context.
-use crate::rustc_middle::ty::TypeVisitableExt;
 use crate::FnCtxt;
 use rustc_infer::traits::solve::Goal;
 use rustc_infer::traits::{self, ObligationCause};
-use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty::{self, Ty, TypeVisitableExt};
 use rustc_span::Span;
 use rustc_trait_selection::solve::inspect::ProofTreeInferCtxtExt;
 use rustc_trait_selection::solve::inspect::{InspectConfig, InspectGoal, ProofTreeVisitor};
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index 794b854ca5f..afba812a8e7 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -19,8 +19,6 @@ use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
 use rustc_infer::infer;
 use rustc_infer::infer::error_reporting::sub_relations::SubRelations;
 use rustc_infer::infer::error_reporting::TypeErrCtxt;
-use rustc_infer::infer::type_variable::TypeVariableOrigin;
-use rustc_middle::infer::unify_key::ConstVariableOrigin;
 use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitableExt};
 use rustc_session::Session;
 use rustc_span::symbol::Ident;
@@ -156,7 +154,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 
     pub fn misc(&self, span: Span) -> ObligationCause<'tcx> {
-        self.cause(span, ObligationCauseCode::MiscObligation)
+        self.cause(span, ObligationCauseCode::Misc)
     }
 
     pub fn sess(&self) -> &Session {
@@ -239,7 +237,7 @@ impl<'a, 'tcx> HirTyLowerer<'tcx> for FnCtxt<'a, 'tcx> {
     fn ty_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> {
         match param {
             Some(param) => self.var_for_def(span, param).as_type().unwrap(),
-            None => self.next_ty_var(TypeVariableOrigin { param_def_id: None, span }),
+            None => self.next_ty_var(span),
         }
     }
 
@@ -258,7 +256,7 @@ impl<'a, 'tcx> HirTyLowerer<'tcx> for FnCtxt<'a, 'tcx> {
                 },
             ) => self.var_for_effect(param).as_const().unwrap(),
             Some(param) => self.var_for_def(span, param).as_const().unwrap(),
-            None => self.next_const_var(ty, ConstVariableOrigin { span, param_def_id: None }),
+            None => self.next_const_var(ty, span),
         }
     }
 
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 133778a416c..f1b719f24c7 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -6,7 +6,6 @@ use crate::fn_ctxt::rustc_span::BytePos;
 use crate::hir::is_range_literal;
 use crate::method::probe;
 use crate::method::probe::{IsSuggestion, Mode, ProbeScope};
-use crate::rustc_middle::ty::Article;
 use core::cmp::min;
 use core::iter;
 use hir::def_id::LocalDefId;
@@ -18,8 +17,8 @@ use rustc_hir::def::Res;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind};
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{
-    CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, GenericBound, HirId, Node,
-    Path, QPath, Stmt, StmtKind, TyKind, WherePredicate,
+    Arm, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, GenericBound, HirId,
+    Node, Path, QPath, Stmt, StmtKind, TyKind, WherePredicate,
 };
 use rustc_hir_analysis::collect::suggest_impl_trait;
 use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
@@ -28,7 +27,7 @@ use rustc_middle::lint::in_external_macro;
 use rustc_middle::middle::stability::EvalResult;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{
-    self, suggest_constraining_type_params, Binder, IsSuggestable, ToPredicate, Ty,
+    self, suggest_constraining_type_params, Article, Binder, IsSuggestable, ToPredicate, Ty,
     TypeVisitableExt,
 };
 use rustc_session::errors::ExprParenthesesNeeded;
@@ -1701,7 +1700,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         }
                     }
                     for error in errors {
-                        if let traits::FulfillmentErrorCode::SelectionError(
+                        if let traits::FulfillmentErrorCode::Select(
                             traits::SelectionError::Unimplemented,
                         ) = error.code
                             && let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) =
@@ -1942,6 +1941,91 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         false
     }
 
+    // If the expr is a while or for loop and is the tail expr of its
+    // enclosing body suggest returning a value right after it
+    pub fn suggest_returning_value_after_loop(
+        &self,
+        err: &mut Diag<'_>,
+        expr: &hir::Expr<'tcx>,
+        expected: Ty<'tcx>,
+    ) -> bool {
+        let hir = self.tcx.hir();
+        let enclosing_scope =
+            hir.get_enclosing_scope(expr.hir_id).map(|hir_id| self.tcx.hir_node(hir_id));
+
+        // Get tail expr of the enclosing block or body
+        let tail_expr = if let Some(Node::Block(hir::Block { expr, .. })) = enclosing_scope
+            && expr.is_some()
+        {
+            *expr
+        } else {
+            let body_def_id = hir.enclosing_body_owner(expr.hir_id);
+            let body_id = hir.body_owned_by(body_def_id);
+            let body = hir.body(body_id);
+
+            // Get tail expr of the body
+            match body.value.kind {
+                // Regular function body etc.
+                hir::ExprKind::Block(block, _) => block.expr,
+                // Anon const body (there's no block in this case)
+                hir::ExprKind::DropTemps(expr) => Some(expr),
+                _ => None,
+            }
+        };
+
+        let Some(tail_expr) = tail_expr else {
+            return false; // Body doesn't have a tail expr we can compare with
+        };
+
+        // Get the loop expr within the tail expr
+        let loop_expr_in_tail = match expr.kind {
+            hir::ExprKind::Loop(_, _, hir::LoopSource::While, _) => tail_expr,
+            hir::ExprKind::Loop(_, _, hir::LoopSource::ForLoop, _) => {
+                match tail_expr.peel_drop_temps() {
+                    Expr { kind: ExprKind::Match(_, [Arm { body, .. }], _), .. } => body,
+                    _ => return false, // Not really a for loop
+                }
+            }
+            _ => return false, // Not a while or a for loop
+        };
+
+        // If the expr is the loop expr in the tail
+        // then make the suggestion
+        if expr.hir_id == loop_expr_in_tail.hir_id {
+            let span = expr.span;
+
+            let (msg, suggestion) = if expected.is_never() {
+                (
+                    "consider adding a diverging expression here",
+                    "`loop {}` or `panic!(\"...\")`".to_string(),
+                )
+            } else {
+                ("consider returning a value here", format!("`{expected}` value"))
+            };
+
+            let src_map = self.tcx.sess.source_map();
+            let suggestion = if src_map.is_multiline(expr.span) {
+                let indentation = src_map.indentation_before(span).unwrap_or_else(String::new);
+                format!("\n{indentation}/* {suggestion} */")
+            } else {
+                // If the entire expr is on a single line
+                // put the suggestion also on the same line
+                format!(" /* {suggestion} */")
+            };
+
+            err.span_suggestion_verbose(
+                span.shrink_to_hi(),
+                msg,
+                suggestion,
+                Applicability::MaybeIncorrect,
+            );
+
+            true
+        } else {
+            false
+        }
+    }
+
     /// If the expected type is an enum (Issue #55250) with any variants whose
     /// sole field is of the found type, suggest such variants. (Issue #42764)
     pub(crate) fn suggest_compatible_variants(
@@ -2142,7 +2226,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) -> bool {
         let tcx = self.tcx;
         let (adt, args, unwrap) = match expected.kind() {
-            // In case Option<NonZero*> is wanted, but * is provided, suggest calling new
+            // In case `Option<NonZero<T>>` is wanted, but `T` is provided, suggest calling `new`.
             ty::Adt(adt, args) if tcx.is_diagnostic_item(sym::Option, adt.did()) => {
                 let nonzero_type = args.type_at(0); // Unwrap option type.
                 let ty::Adt(adt, args) = nonzero_type.kind() else {
@@ -2150,7 +2234,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 };
                 (adt, args, "")
             }
-            // In case `NonZero<*>` is wanted but `*` is provided, also add `.unwrap()` to satisfy types.
+            // In case `NonZero<T>` is wanted but `T` is provided, also add `.unwrap()` to satisfy types.
             ty::Adt(adt, args) => (adt, args, ".unwrap()"),
             _ => return false,
         };
@@ -2159,32 +2243,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             return false;
         }
 
-        // FIXME: This can be simplified once `NonZero<T>` is stable.
-        let coercable_types = [
-            ("NonZeroU8", tcx.types.u8),
-            ("NonZeroU16", tcx.types.u16),
-            ("NonZeroU32", tcx.types.u32),
-            ("NonZeroU64", tcx.types.u64),
-            ("NonZeroU128", tcx.types.u128),
-            ("NonZeroI8", tcx.types.i8),
-            ("NonZeroI16", tcx.types.i16),
-            ("NonZeroI32", tcx.types.i32),
-            ("NonZeroI64", tcx.types.i64),
-            ("NonZeroI128", tcx.types.i128),
-        ];
-
         let int_type = args.type_at(0);
-
-        let Some(nonzero_alias) = coercable_types.iter().find_map(|(nonzero_alias, t)| {
-            if *t == int_type && self.can_coerce(expr_ty, *t) { Some(nonzero_alias) } else { None }
-        }) else {
+        if !self.can_coerce(expr_ty, int_type) {
             return false;
-        };
+        }
 
         err.multipart_suggestion(
-            format!("consider calling `{nonzero_alias}::new`"),
+            format!("consider calling `{}::new`", sym::NonZero),
             vec![
-                (expr.span.shrink_to_lo(), format!("{nonzero_alias}::new(")),
+                (expr.span.shrink_to_lo(), format!("{}::new(", sym::NonZero)),
                 (expr.span.shrink_to_hi(), format!("){unwrap}")),
             ],
             Applicability::MaybeIncorrect,
diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs
index fe0a46924de..13e4b625e2d 100644
--- a/compiler/rustc_hir_typeck/src/gather_locals.rs
+++ b/compiler/rustc_hir_typeck/src/gather_locals.rs
@@ -2,12 +2,11 @@ use crate::FnCtxt;
 use rustc_hir as hir;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{HirId, PatKind};
-use rustc_infer::infer::type_variable::TypeVariableOrigin;
+use rustc_infer::traits::ObligationCauseCode;
 use rustc_middle::ty::Ty;
 use rustc_middle::ty::UserType;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::Span;
-use rustc_trait_selection::traits;
 
 /// Provides context for checking patterns in declarations. More specifically this
 /// allows us to infer array types if the pattern is irrefutable and allows us to infer
@@ -50,7 +49,7 @@ impl<'a> From<&'a hir::LetStmt<'a>> for Declaration<'a> {
 
 impl<'a> From<(&'a hir::LetExpr<'a>, HirId)> for Declaration<'a> {
     fn from((let_expr, hir_id): (&'a hir::LetExpr<'a>, HirId)) -> Self {
-        let hir::LetExpr { pat, ty, span, init, is_recovered: _ } = *let_expr;
+        let hir::LetExpr { pat, ty, span, init, recovered: _ } = *let_expr;
         Declaration { hir_id, pat, ty, span, init: Some(init), origin: DeclOrigin::LetExpr }
     }
 }
@@ -72,7 +71,7 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
         match ty_opt {
             None => {
                 // Infer the variable's type.
-                let var_ty = self.fcx.next_ty_var(TypeVariableOrigin { param_def_id: None, span });
+                let var_ty = self.fcx.next_ty_var(span);
                 self.fcx.locals.borrow_mut().insert(nid, var_ty);
                 var_ty
             }
@@ -147,7 +146,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
                         p.span,
                         // ty_span == ident.span iff this is a closure parameter with no type
                         // ascription, or if it's an implicit `self` parameter
-                        traits::SizedArgumentType(
+                        ObligationCauseCode::SizedArgumentType(
                             if ty_span == ident.span
                                 && self.fcx.tcx.is_closure_like(self.fcx.body_id.into())
                             {
@@ -160,7 +159,11 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
                 }
             } else {
                 if !self.fcx.tcx.features().unsized_locals {
-                    self.fcx.require_type_is_sized(var_ty, p.span, traits::VariableType(p.hir_id));
+                    self.fcx.require_type_is_sized(
+                        var_ty,
+                        p.span,
+                        ObligationCauseCode::VariableType(p.hir_id),
+                    );
                 }
             }
 
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 8bc070bcd36..e270e589505 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -60,10 +60,8 @@ use rustc_hir::intravisit::Visitor;
 use rustc_hir::{HirId, HirIdMap, Node};
 use rustc_hir_analysis::check::check_abi;
 use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
-use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::traits::{ObligationCauseCode, ObligationInspector, WellFormedLoc};
 use rustc_middle::query::Providers;
-use rustc_middle::traits;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_session::config;
 use rustc_span::def_id::LocalDefId;
@@ -171,7 +169,7 @@ fn typeck_with_fallback<'tcx>(
         let wf_code = ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(def_id)));
         fcx.register_wf_obligation(expected_type.into(), body.value.span, wf_code);
 
-        fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized);
+        fcx.require_type_is_sized(expected_type, body.value.span, ObligationCauseCode::ConstSized);
 
         // Gather locals in statics (because of block expressions).
         GatherLocalsVisitor::new(&fcx).visit_body(body);
@@ -246,7 +244,7 @@ fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Opti
                 tcx.impl_trait_ref(item.container_id(tcx)).unwrap().instantiate_identity().args;
             Some(tcx.type_of(trait_item).instantiate(tcx, args))
         } else {
-            Some(fcx.next_ty_var(TypeVariableOrigin { span, param_def_id: None }))
+            Some(fcx.next_ty_var(span))
         }
     } else if let Node::AnonConst(_) = node {
         let id = tcx.local_def_id_to_hir_id(def_id);
@@ -254,7 +252,7 @@ fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Opti
             Node::Ty(&hir::Ty { kind: hir::TyKind::Typeof(ref anon_const), span, .. })
                 if anon_const.hir_id == id =>
             {
-                Some(fcx.next_ty_var(TypeVariableOrigin { span, param_def_id: None }))
+                Some(fcx.next_ty_var(span))
             }
             Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), span, .. })
             | Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), span, .. }) => {
@@ -264,7 +262,7 @@ fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Opti
                         Some(fcx.next_int_var())
                     }
                     hir::InlineAsmOperand::SymFn { anon_const } if anon_const.hir_id == id => {
-                        Some(fcx.next_ty_var(TypeVariableOrigin { span, param_def_id: None }))
+                        Some(fcx.next_ty_var(span))
                     }
                     _ => None,
                 })
diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs
index b44c2345933..ae71c484f7b 100644
--- a/compiler/rustc_hir_typeck/src/mem_categorization.rs
+++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs
@@ -207,7 +207,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
                     // but what we want here is the type of the underlying value being borrowed.
                     // So peel off one-level, turning the &T into T.
                     match base_ty.builtin_deref(false) {
-                        Some(t) => Ok(t.ty),
+                        Some(ty) => Ok(ty),
                         None => {
                             debug!("By-ref binding of non-derefable type");
                             Err(())
@@ -485,7 +485,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
     ) -> McResult<PlaceWithHirId<'tcx>> {
         let base_curr_ty = base_place.place.ty();
         let deref_ty = match base_curr_ty.builtin_deref(true) {
-            Some(mt) => mt.ty,
+            Some(pointee_ty) => pointee_ty,
             None => {
                 debug!("explicit deref of non-derefable type: {:?}", base_curr_ty);
                 return Err(());
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index d57015282de..56c296fc1c0 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -450,7 +450,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         // `foo.bar::<u32>(...)` -- the `Self` type here will be the
         // type of `foo` (possibly adjusted), but we don't want to
         // include that. We want just the `[_, u32]` part.
-        if !args.is_empty() && !generics.params.is_empty() {
+        if !args.is_empty() && !generics.own_params.is_empty() {
             let user_type_annotation = self.probe(|_| {
                 let user_args = UserArgs {
                     args: GenericArgs::for_item(self.tcx, pick.item.def_id, |param, _| {
@@ -565,9 +565,9 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         for obligation in traits::predicates_for_generics(
             |idx, span| {
                 let code = if span.is_dummy() {
-                    ObligationCauseCode::ExprItemObligation(def_id, self.call_expr.hir_id, idx)
+                    ObligationCauseCode::WhereClauseInExpr(def_id, self.call_expr.hir_id, idx)
                 } else {
-                    ObligationCauseCode::ExprBindingObligation(
+                    ObligationCauseCode::SpannedWhereClauseInExpr(
                         def_id,
                         span,
                         self.call_expr.hir_id,
@@ -589,7 +589,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         // the function type must also be well-formed (this is not
         // implied by the args being well-formed because of inherent
         // impls and late-bound regions - see issue #28609).
-        self.register_wf_obligation(fty.into(), self.span, traits::WellFormed(None));
+        self.register_wf_obligation(fty.into(), self.span, ObligationCauseCode::WellFormed(None));
     }
 
     ///////////////////////////////////////////////////////////////////////////
diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs
index 39d54f1a25e..ec613f3d14e 100644
--- a/compiler/rustc_hir_typeck/src/method/mod.rs
+++ b/compiler/rustc_hir_typeck/src/method/mod.rs
@@ -315,7 +315,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         trait_def_id: DefId,
         self_ty: Ty<'tcx>,
         opt_input_types: Option<&[Ty<'tcx>]>,
-    ) -> (traits::PredicateObligation<'tcx>, &'tcx ty::List<ty::GenericArg<'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 {
@@ -365,7 +365,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         m_name: Ident,
         trait_def_id: DefId,
         obligation: traits::PredicateObligation<'tcx>,
-        args: &'tcx ty::List<ty::GenericArg<'tcx>>,
+        args: ty::GenericArgsRef<'tcx>,
     ) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
         debug!(?obligation);
 
diff --git a/compiler/rustc_hir_typeck/src/method/prelude2021.rs b/compiler/rustc_hir_typeck/src/method/prelude2021.rs
index 22eef8e53da..305aaf3b8dd 100644
--- a/compiler/rustc_hir_typeck/src/method/prelude2021.rs
+++ b/compiler/rustc_hir_typeck/src/method/prelude2021.rs
@@ -7,7 +7,6 @@ use hir::HirId;
 use hir::ItemKind;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
-use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_middle::ty::{self, Ty};
 use rustc_session::lint::builtin::RUST_2021_PRELUDE_COLLISIONS;
 use rustc_span::symbol::kw::{Empty, Underscore};
@@ -218,8 +217,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // If we know it does not, we don't need to warn.
         if method_name.name == sym::from_iter {
             if let Some(trait_def_id) = self.tcx.get_diagnostic_item(sym::FromIterator) {
-                let any_type =
-                    self.infcx.next_ty_var(TypeVariableOrigin { param_def_id: None, span });
+                let any_type = self.infcx.next_ty_var(span);
                 if !self
                     .infcx
                     .type_implements_trait(trait_def_id, [self_ty, any_type], self.param_env)
@@ -251,23 +249,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let trait_path = self.trait_path_or_bare_name(span, expr_id, container_id);
                 let trait_generics = self.tcx.generics_of(container_id);
 
-                let trait_name = if trait_generics.params.len() <= trait_generics.has_self as usize
-                {
-                    trait_path
-                } else {
-                    let counts = trait_generics.own_counts();
-                    format!(
-                        "{}<{}>",
-                        trait_path,
-                        std::iter::repeat("'_")
-                            .take(counts.lifetimes)
-                            .chain(std::iter::repeat("_").take(
-                                counts.types + counts.consts - trait_generics.has_self as usize
-                            ))
-                            .collect::<Vec<_>>()
-                            .join(", ")
-                    )
-                };
+                let trait_name =
+                    if trait_generics.own_params.len() <= trait_generics.has_self as usize {
+                        trait_path
+                    } else {
+                        let counts = trait_generics.own_counts();
+                        format!(
+                            "{}<{}>",
+                            trait_path,
+                            std::iter::repeat("'_")
+                                .take(counts.lifetimes)
+                                .chain(std::iter::repeat("_").take(
+                                    counts.types + counts.consts - trait_generics.has_self as usize
+                                ))
+                                .collect::<Vec<_>>()
+                                .join(", ")
+                        )
+                    };
 
                 let mut self_ty_name = self_ty_span
                     .find_ancestor_inside(span)
@@ -280,7 +278,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 if !self_ty_name.contains('<') {
                     if let ty::Adt(def, _) = self_ty.kind() {
                         let generics = self.tcx.generics_of(def.did());
-                        if !generics.params.is_empty() {
+                        if !generics.own_params.is_empty() {
                             let counts = generics.own_counts();
                             self_ty_name += &format!(
                                 "<{}>",
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 8a7ebd6478b..434bd957498 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -15,6 +15,7 @@ use rustc_infer::infer::canonical::{Canonical, QueryResponse};
 use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
 use rustc_infer::infer::DefineOpaqueTypes;
 use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
+use rustc_infer::traits::ObligationCauseCode;
 use rustc_middle::middle::stability;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
@@ -1401,9 +1402,13 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                     ocx.register_obligations(traits::predicates_for_generics(
                         |idx, span| {
                             let code = if span.is_dummy() {
-                                traits::ExprItemObligation(impl_def_id, self.scope_expr_id, idx)
+                                ObligationCauseCode::WhereClauseInExpr(
+                                    impl_def_id,
+                                    self.scope_expr_id,
+                                    idx,
+                                )
                             } else {
-                                traits::ExprBindingObligation(
+                                ObligationCauseCode::SpannedWhereClauseInExpr(
                                     impl_def_id,
                                     span,
                                     self.scope_expr_id,
@@ -1735,7 +1740,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         let generics = self.tcx.generics_of(method);
         assert_eq!(args.len(), generics.parent_count);
 
-        let xform_fn_sig = if generics.params.is_empty() {
+        let xform_fn_sig = if generics.own_params.is_empty() {
             fn_sig.instantiate(self.tcx, args)
         } else {
             let args = GenericArgs::for_item(self.tcx, method, |param, _| {
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 078009515e4..d1891a032e1 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -22,11 +22,12 @@ use rustc_hir::lang_items::LangItem;
 use rustc_hir::PatKind::Binding;
 use rustc_hir::PathSegment;
 use rustc_hir::{ExprKind, Node, QPath};
-use rustc_infer::infer::{self, type_variable::TypeVariableOrigin, RegionVariableOrigin};
-use rustc_middle::infer::unify_key::ConstVariableOrigin;
+use rustc_infer::infer::{self, RegionVariableOrigin};
 use rustc_middle::ty::fast_reject::DeepRejectCtxt;
 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
-use rustc_middle::ty::print::{with_crate_prefix, with_forced_trimmed_paths};
+use rustc_middle::ty::print::{
+    with_crate_prefix, with_forced_trimmed_paths, PrintTraitRefExt as _,
+};
 use rustc_middle::ty::IsSuggestable;
 use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeVisitableExt};
 use rustc_span::def_id::DefIdSet;
@@ -75,11 +76,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.autoderef(span, ty).any(|(ty, _)| {
                     info!("check deref {:?} impl FnOnce", ty);
                     self.probe(|_| {
-                        let trait_ref = ty::TraitRef::new(
-                            tcx,
-                            fn_once,
-                            [ty, self.next_ty_var(TypeVariableOrigin { param_def_id: None, span })],
-                        );
+                        let trait_ref =
+                            ty::TraitRef::new(tcx, fn_once, [ty, self.next_ty_var(span)]);
                         let poly_trait_ref = ty::Binder::dummy(trait_ref);
                         let obligation = Obligation::misc(
                             tcx,
@@ -150,7 +148,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             return false;
         };
         let trait_ref = ty::TraitRef::new(self.tcx, into_iterator_trait, [ty]);
-        let cause = ObligationCause::new(span, self.body_id, ObligationCauseCode::MiscObligation);
+        let cause = ObligationCause::new(span, self.body_id, ObligationCauseCode::Misc);
         let obligation = Obligation::new(self.tcx, cause, self.param_env, trait_ref);
         if !self.predicate_must_hold_modulo_regions(&obligation) {
             return false;
@@ -830,12 +828,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // Extract the predicate span and parent def id of the cause,
                 // if we have one.
                 let (item_def_id, cause_span) = match cause.as_ref().map(|cause| cause.code()) {
-                    Some(ObligationCauseCode::ImplDerivedObligation(data)) => {
+                    Some(ObligationCauseCode::ImplDerived(data)) => {
                         (data.impl_or_alias_def_id, data.span)
                     }
                     Some(
-                        ObligationCauseCode::ExprBindingObligation(def_id, span, _, _)
-                        | ObligationCauseCode::BindingObligation(def_id, span),
+                        ObligationCauseCode::SpannedWhereClauseInExpr(def_id, span, _, _)
+                        | ObligationCauseCode::SpannedWhereClause(def_id, span),
                     ) => (*def_id, *span),
                     _ => continue,
                 };
@@ -1259,12 +1257,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             args.map(|args| {
                 args.iter()
                     .map(|expr| {
-                        self.node_ty_opt(expr.hir_id).unwrap_or_else(|| {
-                            self.next_ty_var(TypeVariableOrigin {
-                                param_def_id: None,
-                                span: expr.span,
-                            })
-                        })
+                        self.node_ty_opt(expr.hir_id).unwrap_or_else(|| self.next_ty_var(expr.span))
                     })
                     .collect()
             }),
@@ -1846,18 +1839,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             GenericArgKind::Lifetime(_) => self
                                 .next_region_var(RegionVariableOrigin::MiscVariable(DUMMY_SP))
                                 .into(),
-                            GenericArgKind::Type(_) => self
-                                .next_ty_var(TypeVariableOrigin {
-                                    span: DUMMY_SP,
-                                    param_def_id: None,
-                                })
-                                .into(),
-                            GenericArgKind::Const(arg) => self
-                                .next_const_var(
-                                    arg.ty(),
-                                    ConstVariableOrigin { span: DUMMY_SP, param_def_id: None },
-                                )
-                                .into(),
+                            GenericArgKind::Type(_) => self.next_ty_var(DUMMY_SP).into(),
+                            GenericArgKind::Const(arg) => {
+                                self.next_const_var(arg.ty(), DUMMY_SP).into()
+                            }
                         }
                     } else {
                         arg
diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs
index a4f840d849d..dca1cda0694 100644
--- a/compiler/rustc_hir_typeck/src/op.rs
+++ b/compiler/rustc_hir_typeck/src/op.rs
@@ -7,7 +7,6 @@ use rustc_ast as ast;
 use rustc_data_structures::packed::Pu128;
 use rustc_errors::{codes::*, struct_span_code_err, Applicability, Diag};
 use rustc_hir as hir;
-use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::traits::ObligationCauseCode;
 use rustc_middle::ty::adjustment::{
     Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability,
@@ -20,7 +19,7 @@ use rustc_span::symbol::{sym, Ident};
 use rustc_span::Span;
 use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt as _;
-use rustc_trait_selection::traits::{self, FulfillmentError, ObligationCtxt};
+use rustc_trait_selection::traits::{FulfillmentError, ObligationCtxt};
 use rustc_type_ir::TyKind::*;
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -219,8 +218,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // e.g., adding `&'a T` and `&'b T`, given `&'x T: Add<&'x T>`, will result
                 // in `&'a T <: &'x T` and `&'b T <: &'x T`, instead of `'a = 'b = 'x`.
                 let lhs_ty = self.check_expr(lhs_expr);
-                let fresh_var = self
-                    .next_ty_var(TypeVariableOrigin { param_def_id: None, span: lhs_expr.span });
+                let fresh_var = self.next_ty_var(lhs_expr.span);
                 self.demand_coerce(lhs_expr, lhs_ty, fresh_var, Some(rhs_expr), AllowTwoPhase::No)
             }
             IsAssign::Yes => {
@@ -239,8 +237,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // using this variable as the expected type, which sometimes lets
         // us do better coercions than we would be able to do otherwise,
         // particularly for things like `String + &String`.
-        let rhs_ty_var =
-            self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: rhs_expr.span });
+        let rhs_ty_var = self.next_ty_var(rhs_expr.span);
 
         let result = self.lookup_op_method(
             (lhs_expr, lhs_ty),
@@ -887,7 +884,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let input_types = opt_rhs_ty.as_slice();
         let cause = self.cause(
             span,
-            traits::BinOp {
+            ObligationCauseCode::BinOp {
                 lhs_hir_id: lhs_expr.hir_id,
                 rhs_hir_id: opt_rhs_expr.map(|expr| expr.hir_id),
                 rhs_span: opt_rhs_expr.map(|expr| expr.span),
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 8c7ae7f8e98..b1a0aa689cf 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -9,7 +9,6 @@ use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::pat_util::EnumerateAndAdjustIterator;
 use rustc_hir::{self as hir, BindingMode, ByRef, HirId, Mutability, Pat, PatKind};
 use rustc_infer::infer;
-use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::ty::{self, Ty, TypeVisitableExt};
 use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
@@ -19,7 +18,7 @@ use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::{BytePos, Span, DUMMY_SP};
 use rustc_target::abi::FieldIdx;
-use rustc_trait_selection::traits::{ObligationCause, Pattern};
+use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode};
 use ty::VariantDef;
 
 use std::cmp;
@@ -89,8 +88,11 @@ struct PatInfo<'tcx, 'a> {
 
 impl<'tcx> FnCtxt<'_, 'tcx> {
     fn pattern_cause(&self, ti: TopInfo<'tcx>, cause_span: Span) -> ObligationCause<'tcx> {
-        let code =
-            Pattern { span: ti.span, root_ty: ti.expected, origin_expr: ti.origin_expr.is_some() };
+        let code = ObligationCauseCode::Pattern {
+            span: ti.span,
+            root_ty: ti.expected,
+            origin_expr: ti.origin_expr.is_some(),
+        };
         self.cause(cause_span, code)
     }
 
@@ -919,8 +921,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         inner: &Pat<'_>,
     ) -> Result<(), ErrorGuaranteed> {
         if let PatKind::Binding(..) = inner.kind
-            && let Some(mt) = self.shallow_resolve(expected).builtin_deref(true)
-            && let ty::Dynamic(..) = mt.ty.kind()
+            && let Some(pointee_ty) = self.shallow_resolve(expected).builtin_deref(true)
+            && let ty::Dynamic(..) = pointee_ty.kind()
         {
             // This is "x = dyn SomeTrait" being reduced from
             // "let &x = &dyn SomeTrait" or "let box x = Box<dyn SomeTrait>", an error.
@@ -1419,8 +1421,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
         let max_len = cmp::max(expected_len, elements.len());
 
-        let element_tys_iter =
-            (0..max_len).map(|_| self.next_ty_var(TypeVariableOrigin { param_def_id: None, span }));
+        let element_tys_iter = (0..max_len).map(|_| self.next_ty_var(span));
         let element_tys = tcx.mk_type_list_from_iter(element_tys_iter);
         let pat_ty = Ty::new_tup(tcx, element_tys);
         if let Some(err) = self.demand_eqtype_pat_diag(span, expected, pat_ty, pat_info.top_info) {
@@ -1676,7 +1677,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         unmentioned_fields: &mut Vec<(&'tcx ty::FieldDef, Ident)>,
         pat: &'tcx Pat<'tcx>,
         variant: &ty::VariantDef,
-        args: &'tcx ty::List<ty::GenericArg<'tcx>>,
+        args: ty::GenericArgsRef<'tcx>,
     ) -> Diag<'tcx> {
         let tcx = self.tcx;
         let (field_names, t, plural) = if let [field] = inexistent_fields {
@@ -2046,8 +2047,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             Ok(()) => {
                 // Here, `demand::subtype` is good enough, but I don't
                 // think any errors can be introduced by using `demand::eqtype`.
-                let inner_ty =
-                    self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: inner.span });
+                let inner_ty = self.next_ty_var(inner.span);
                 let box_ty = Ty::new_box(tcx, inner_ty);
                 self.demand_eqtype_pat(span, expected, box_ty, pat_info.top_info);
                 (box_ty, inner_ty)
@@ -2142,10 +2142,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                     .insert(pat.hir_id);
                                 (expected, expected)
                             } else {
-                                let inner_ty = self.next_ty_var(TypeVariableOrigin {
-                                    param_def_id: None,
-                                    span: inner.span,
-                                });
+                                let inner_ty = self.next_ty_var(inner.span);
                                 let ref_ty = self.new_ref_ty(pat.span, mutbl, inner_ty);
                                 debug!("check_pat_ref: demanding {:?} = {:?}", expected, ref_ty);
                                 let err = self.demand_eqtype_pat_diag(
@@ -2194,8 +2191,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let tcx = self.tcx;
         let len = before.len();
-        let ty_var_origin = TypeVariableOrigin { param_def_id: None, span };
-        let inner_ty = self.next_ty_var(ty_var_origin);
+        let inner_ty = self.next_ty_var(span);
 
         Some(Ty::new_array(tcx, inner_ty, len.try_into().unwrap()))
     }
diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs
index bce43b3be34..374279722ba 100644
--- a/compiler/rustc_hir_typeck/src/place_op.rs
+++ b/compiler/rustc_hir_typeck/src/place_op.rs
@@ -4,7 +4,6 @@ use rustc_ast as ast;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir_analysis::autoderef::Autoderef;
-use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::infer::InferOk;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref, PointerCoercion};
 use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
@@ -20,8 +19,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         oprnd_expr: &'tcx hir::Expr<'tcx>,
         oprnd_ty: Ty<'tcx>,
     ) -> Option<Ty<'tcx>> {
-        if let Some(mt) = oprnd_ty.builtin_deref(true) {
-            return Some(mt.ty);
+        if let Some(ty) = oprnd_ty.builtin_deref(true) {
+            return Some(ty);
         }
 
         let ok = self.try_overloaded_deref(expr.span, oprnd_ty)?;
@@ -37,7 +36,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         } else {
             span_bug!(expr.span, "input to deref is not a ref?");
         }
-        let ty = self.make_overloaded_place_return_type(method).ty;
+        let ty = self.make_overloaded_place_return_type(method);
         self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method);
         Some(ty)
     }
@@ -147,8 +146,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // If some lookup succeeds, write callee into table and extract index/element
             // type from the method signature.
             // If some lookup succeeded, install method in table
-            let input_ty =
-                self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: base_expr.span });
+            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);
 
@@ -175,7 +173,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                 self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method);
 
-                return Some((input_ty, self.make_overloaded_place_return_type(method).ty));
+                return Some((input_ty, self.make_overloaded_place_return_type(method)));
             }
         }
 
@@ -344,8 +342,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             .borrow()
             .expr_ty_adjusted(base_expr)
             .builtin_deref(false)
-            .expect("place op takes something that is not a ref")
-            .ty;
+            .expect("place op takes something that is not a ref");
 
         let arg_ty = match op {
             PlaceOp::Deref => None,
diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs
index 70d94873530..c7f07ebed97 100644
--- a/compiler/rustc_infer/src/errors/note_and_explain.rs
+++ b/compiler/rustc_infer/src/errors/note_and_explain.rs
@@ -69,16 +69,8 @@ impl<'a> DescriptionCtx<'a> {
 
             ty::RePlaceholder(_) | ty::ReError(_) => return None,
 
-            // FIXME(#13998) RePlaceholder should probably print like
-            // ReLateParam rather than dumping Debug output on the user.
-            //
-            // We shouldn't really be having unification failures with ReVar
-            // and ReBound though.
-            //
-            // FIXME(@lcnr): figure out why we have to handle `ReBound`
-            // here, this feels somewhat off.
             ty::ReVar(_) | ty::ReBound(..) | ty::ReErased => {
-                (alt_span, "revar", format!("{region:?}"))
+                bug!("unexpected region for DescriptionCtx: {:?}", region);
             }
         };
         Some(DescriptionCtx { span, kind, arg })
diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs
index 734fa919eb5..1abb8086d41 100644
--- a/compiler/rustc_infer/src/infer/canonical/mod.rs
+++ b/compiler/rustc_infer/src/infer/canonical/mod.rs
@@ -21,8 +21,7 @@
 //!
 //! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
 
-use crate::infer::ConstVariableOrigin;
-use crate::infer::{InferCtxt, RegionVariableOrigin, TypeVariableOrigin};
+use crate::infer::{InferCtxt, RegionVariableOrigin};
 use rustc_index::IndexVec;
 use rustc_middle::infer::unify_key::EffectVarValue;
 use rustc_middle::ty::fold::TypeFoldable;
@@ -114,10 +113,9 @@ impl<'tcx> InferCtxt<'tcx> {
         match cv_info.kind {
             CanonicalVarKind::Ty(ty_kind) => {
                 let ty = match ty_kind {
-                    CanonicalTyVarKind::General(ui) => self.next_ty_var_in_universe(
-                        TypeVariableOrigin { param_def_id: None, span },
-                        universe_map(ui),
-                    ),
+                    CanonicalTyVarKind::General(ui) => {
+                        self.next_ty_var_in_universe(span, universe_map(ui))
+                    }
 
                     CanonicalTyVarKind::Int => self.next_int_var(),
 
@@ -145,13 +143,9 @@ impl<'tcx> InferCtxt<'tcx> {
                 ty::Region::new_placeholder(self.tcx, placeholder_mapped).into()
             }
 
-            CanonicalVarKind::Const(ui, ty) => self
-                .next_const_var_in_universe(
-                    ty,
-                    ConstVariableOrigin { param_def_id: None, span },
-                    universe_map(ui),
-                )
-                .into(),
+            CanonicalVarKind::Const(ui, ty) => {
+                self.next_const_var_in_universe(ty, span, universe_map(ui)).into()
+            }
             CanonicalVarKind::Effect => {
                 let vid = self
                     .inner
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 635bbca37ec..46310941113 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -70,7 +70,7 @@ use rustc_hir::intravisit::Visitor;
 use rustc_hir::lang_items::LangItem;
 use rustc_macros::extension;
 use rustc_middle::dep_graph::DepContext;
-use rustc_middle::ty::print::{with_forced_trimmed_paths, PrintError};
+use rustc_middle::ty::print::{with_forced_trimmed_paths, PrintError, PrintTraitRefExt as _};
 use rustc_middle::ty::relate::{self, RelateResult, TypeRelation};
 use rustc_middle::ty::ToPredicate;
 use rustc_middle::ty::{
@@ -172,11 +172,9 @@ pub(super) fn note_and_explain_region<'tcx>(
 
         ty::ReError(_) => return,
 
-        // We shouldn't really be having unification failures with ReVar
-        // and ReBound though.
-        //
-        // FIXME(@lcnr): Figure out whether this is reachable and if so, why.
-        ty::ReVar(_) | ty::ReBound(..) | ty::ReErased => (format!("lifetime `{region}`"), alt_span),
+        ty::ReVar(_) | ty::ReBound(..) | ty::ReErased => {
+            bug!("unexpected region for note_and_explain_region: {:?}", region);
+        }
     };
 
     emit_msg_span(err, prefix, description, span, suffix);
@@ -885,8 +883,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 err.help("...or use `match` instead of `let...else`");
             }
             _ => {
-                if let ObligationCauseCode::BindingObligation(_, span)
-                | ObligationCauseCode::ExprBindingObligation(_, span, ..) =
+                if let ObligationCauseCode::SpannedWhereClause(_, span)
+                | ObligationCauseCode::SpannedWhereClauseInExpr(_, span, ..) =
                     cause.code().peel_derives()
                     && let TypeError::RegionsPlaceholderMismatch = terr
                 {
@@ -2014,7 +2012,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         trace: &TypeTrace<'tcx>,
         terr: TypeError<'tcx>,
     ) -> Vec<TypeErrorAdditionalDiags> {
-        use crate::traits::ObligationCauseCode::{BlockTailExpression, MatchExpressionArm};
         let mut suggestions = Vec::new();
         let span = trace.cause.span();
         let values = self.resolve_vars_if_possible(trace.values);
@@ -2081,8 +2078,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             }
         }
         let code = trace.cause.code();
-        if let &(MatchExpressionArm(box MatchExpressionArmCause { source, .. })
-        | BlockTailExpression(.., source)) = code
+        if let &(ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
+            source,
+            ..
+        })
+        | ObligationCauseCode::BlockTailExpression(.., source)) = code
             && let hir::MatchSource::TryDesugar(_) = source
             && let Some((expected_ty, found_ty, _)) = self.values_str(trace.values)
         {
@@ -2507,7 +2507,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             let generics = self.tcx.generics_of(lifetime_scope);
             let mut used_names =
                 iter::successors(Some(generics), |g| g.parent.map(|p| self.tcx.generics_of(p)))
-                    .flat_map(|g| &g.params)
+                    .flat_map(|g| &g.own_params)
                     .filter(|p| matches!(p.kind, ty::GenericParamDefKind::Lifetime))
                     .map(|p| p.name)
                     .collect::<Vec<_>>();
@@ -2775,19 +2775,17 @@ pub enum FailureCode {
 #[extension(pub trait ObligationCauseExt<'tcx>)]
 impl<'tcx> ObligationCause<'tcx> {
     fn as_failure_code(&self, terr: TypeError<'tcx>) -> FailureCode {
-        use self::FailureCode::*;
-        use crate::traits::ObligationCauseCode::*;
         match self.code() {
-            IfExpressionWithNoElse => Error0317,
-            MainFunctionType => Error0580,
-            CompareImplItemObligation { .. }
-            | MatchExpressionArm(_)
-            | IfExpression { .. }
-            | LetElse
-            | StartFunctionType
-            | LangFunctionType(_)
-            | IntrinsicType
-            | MethodReceiver => Error0308,
+            ObligationCauseCode::IfExpressionWithNoElse => FailureCode::Error0317,
+            ObligationCauseCode::MainFunctionType => FailureCode::Error0580,
+            ObligationCauseCode::CompareImplItem { .. }
+            | ObligationCauseCode::MatchExpressionArm(_)
+            | ObligationCauseCode::IfExpression { .. }
+            | ObligationCauseCode::LetElse
+            | ObligationCauseCode::StartFunctionType
+            | ObligationCauseCode::LangFunctionType(_)
+            | ObligationCauseCode::IntrinsicType
+            | ObligationCauseCode::MethodReceiver => FailureCode::Error0308,
 
             // In the case where we have no more specific thing to
             // say, also take a look at the error code, maybe we can
@@ -2796,10 +2794,10 @@ impl<'tcx> ObligationCause<'tcx> {
                 TypeError::CyclicTy(ty)
                     if ty.is_closure() || ty.is_coroutine() || ty.is_coroutine_closure() =>
                 {
-                    Error0644
+                    FailureCode::Error0644
                 }
-                TypeError::IntrinsicCast => Error0308,
-                _ => Error0308,
+                TypeError::IntrinsicCast => FailureCode::Error0308,
+                _ => FailureCode::Error0308,
             },
         }
     }
@@ -2809,36 +2807,51 @@ impl<'tcx> ObligationCause<'tcx> {
         span: Span,
         subdiags: Vec<TypeErrorAdditionalDiags>,
     ) -> ObligationCauseFailureCode {
-        use crate::traits::ObligationCauseCode::*;
         match self.code() {
-            CompareImplItemObligation { kind: ty::AssocKind::Fn, .. } => {
+            ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Fn, .. } => {
                 ObligationCauseFailureCode::MethodCompat { span, subdiags }
             }
-            CompareImplItemObligation { kind: ty::AssocKind::Type, .. } => {
+            ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Type, .. } => {
                 ObligationCauseFailureCode::TypeCompat { span, subdiags }
             }
-            CompareImplItemObligation { kind: ty::AssocKind::Const, .. } => {
+            ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Const, .. } => {
                 ObligationCauseFailureCode::ConstCompat { span, subdiags }
             }
-            BlockTailExpression(.., hir::MatchSource::TryDesugar(_)) => {
+            ObligationCauseCode::BlockTailExpression(.., hir::MatchSource::TryDesugar(_)) => {
                 ObligationCauseFailureCode::TryCompat { span, subdiags }
             }
-            MatchExpressionArm(box MatchExpressionArmCause { source, .. }) => match source {
+            ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
+                source, ..
+            }) => match source {
                 hir::MatchSource::TryDesugar(_) => {
                     ObligationCauseFailureCode::TryCompat { span, subdiags }
                 }
                 _ => ObligationCauseFailureCode::MatchCompat { span, subdiags },
             },
-            IfExpression { .. } => ObligationCauseFailureCode::IfElseDifferent { span, subdiags },
-            IfExpressionWithNoElse => ObligationCauseFailureCode::NoElse { span },
-            LetElse => ObligationCauseFailureCode::NoDiverge { span, subdiags },
-            MainFunctionType => ObligationCauseFailureCode::FnMainCorrectType { span },
-            StartFunctionType => ObligationCauseFailureCode::FnStartCorrectType { span, subdiags },
-            &LangFunctionType(lang_item_name) => {
+            ObligationCauseCode::IfExpression { .. } => {
+                ObligationCauseFailureCode::IfElseDifferent { span, subdiags }
+            }
+            ObligationCauseCode::IfExpressionWithNoElse => {
+                ObligationCauseFailureCode::NoElse { span }
+            }
+            ObligationCauseCode::LetElse => {
+                ObligationCauseFailureCode::NoDiverge { span, subdiags }
+            }
+            ObligationCauseCode::MainFunctionType => {
+                ObligationCauseFailureCode::FnMainCorrectType { span }
+            }
+            ObligationCauseCode::StartFunctionType => {
+                ObligationCauseFailureCode::FnStartCorrectType { span, subdiags }
+            }
+            &ObligationCauseCode::LangFunctionType(lang_item_name) => {
                 ObligationCauseFailureCode::FnLangCorrectType { span, subdiags, lang_item_name }
             }
-            IntrinsicType => ObligationCauseFailureCode::IntrinsicCorrectType { span, subdiags },
-            MethodReceiver => ObligationCauseFailureCode::MethodCorrectType { span, subdiags },
+            ObligationCauseCode::IntrinsicType => {
+                ObligationCauseFailureCode::IntrinsicCorrectType { span, subdiags }
+            }
+            ObligationCauseCode::MethodReceiver => {
+                ObligationCauseFailureCode::MethodCorrectType { span, subdiags }
+            }
 
             // In the case where we have no more specific thing to
             // say, also take a look at the error code, maybe we can
@@ -2858,22 +2871,21 @@ impl<'tcx> ObligationCause<'tcx> {
     }
 
     fn as_requirement_str(&self) -> &'static str {
-        use crate::traits::ObligationCauseCode::*;
         match self.code() {
-            CompareImplItemObligation { kind: ty::AssocKind::Fn, .. } => {
+            ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Fn, .. } => {
                 "method type is compatible with trait"
             }
-            CompareImplItemObligation { kind: ty::AssocKind::Type, .. } => {
+            ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Type, .. } => {
                 "associated type is compatible with trait"
             }
-            CompareImplItemObligation { kind: ty::AssocKind::Const, .. } => {
+            ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Const, .. } => {
                 "const is compatible with trait"
             }
-            MainFunctionType => "`main` function has the correct type",
-            StartFunctionType => "`#[start]` function has the correct type",
-            LangFunctionType(_) => "lang item function has the correct type",
-            IntrinsicType => "intrinsic has the correct type",
-            MethodReceiver => "method receiver has the correct type",
+            ObligationCauseCode::MainFunctionType => "`main` function has the correct type",
+            ObligationCauseCode::StartFunctionType => "`#[start]` function has the correct type",
+            ObligationCauseCode::LangFunctionType(_) => "lang item function has the correct type",
+            ObligationCauseCode::IntrinsicType => "intrinsic has the correct type",
+            ObligationCauseCode::MethodReceiver => "method receiver has the correct type",
             _ => "types are compatible",
         }
     }
@@ -2884,16 +2896,17 @@ pub struct ObligationCauseAsDiagArg<'tcx>(pub ObligationCause<'tcx>);
 
 impl IntoDiagArg for ObligationCauseAsDiagArg<'_> {
     fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
-        use crate::traits::ObligationCauseCode::*;
         let kind = match self.0.code() {
-            CompareImplItemObligation { kind: ty::AssocKind::Fn, .. } => "method_compat",
-            CompareImplItemObligation { kind: ty::AssocKind::Type, .. } => "type_compat",
-            CompareImplItemObligation { kind: ty::AssocKind::Const, .. } => "const_compat",
-            MainFunctionType => "fn_main_correct_type",
-            StartFunctionType => "fn_start_correct_type",
-            LangFunctionType(_) => "fn_lang_correct_type",
-            IntrinsicType => "intrinsic_correct_type",
-            MethodReceiver => "method_correct_type",
+            ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Fn, .. } => "method_compat",
+            ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Type, .. } => "type_compat",
+            ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Const, .. } => {
+                "const_compat"
+            }
+            ObligationCauseCode::MainFunctionType => "fn_main_correct_type",
+            ObligationCauseCode::StartFunctionType => "fn_start_correct_type",
+            ObligationCauseCode::LangFunctionType(_) => "fn_lang_correct_type",
+            ObligationCauseCode::IntrinsicType => "intrinsic_correct_type",
+            ObligationCauseCode::MethodReceiver => "method_correct_type",
             _ => "other",
         }
         .into();
diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
index a2a38d1c507..415f0eee8c5 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
@@ -3,7 +3,6 @@ use crate::errors::{
     SourceKindMultiSuggestion, SourceKindSubdiag,
 };
 use crate::infer::error_reporting::TypeErrCtxt;
-use crate::infer::type_variable::TypeVariableOrigin;
 use crate::infer::InferCtxt;
 use rustc_errors::{codes::*, Diag, IntoDiagArg};
 use rustc_hir as hir;
@@ -13,7 +12,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{Body, Closure, Expr, ExprKind, FnRetTy, HirId, LetStmt, LocalSource};
 use rustc_middle::hir::nested_filter;
-use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableValue};
+use rustc_middle::infer::unify_key::ConstVariableValue;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
 use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer};
 use rustc_middle::ty::{
@@ -522,7 +521,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 infer_subdiags.push(SourceKindSubdiag::GenericLabel {
                     span,
                     is_type,
-                    param_name: generics.params[argument_index].name.to_string(),
+                    param_name: generics.own_params[argument_index].name.to_string(),
                     parent_exists,
                     parent_prefix,
                     parent_name,
@@ -542,18 +541,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
 
                             match arg.unpack() {
                                 GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
-                                GenericArgKind::Type(_) => self
-                                    .next_ty_var(TypeVariableOrigin {
-                                        span: DUMMY_SP,
-                                        param_def_id: None,
-                                    })
-                                    .into(),
-                                GenericArgKind::Const(arg) => self
-                                    .next_const_var(
-                                        arg.ty(),
-                                        ConstVariableOrigin { span: DUMMY_SP, param_def_id: None },
-                                    )
-                                    .into(),
+                                GenericArgKind::Type(_) => self.next_ty_var(DUMMY_SP).into(),
+                                GenericArgKind::Const(arg) => {
+                                    self.next_const_var(arg.ty(), DUMMY_SP).into()
+                                }
                             }
                         }))
                         .unwrap();
@@ -569,9 +560,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 }
             }
             InferSourceKind::FullyQualifiedMethodCall { receiver, successor, args, def_id } => {
-                let placeholder = Some(
-                    self.next_ty_var(TypeVariableOrigin { span: DUMMY_SP, param_def_id: None }),
-                );
+                let placeholder = Some(self.next_ty_var(DUMMY_SP));
                 if let Some(args) = args.make_suggestable(self.infcx.tcx, true, placeholder) {
                     let mut printer = fmt_printer(self, Namespace::ValueNS);
                     printer.print_def_path(def_id, args).unwrap();
@@ -605,9 +594,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 }
             }
             InferSourceKind::ClosureReturn { ty, data, should_wrap_expr } => {
-                let placeholder = Some(
-                    self.next_ty_var(TypeVariableOrigin { span: DUMMY_SP, param_def_id: None }),
-                );
+                let placeholder = Some(self.next_ty_var(DUMMY_SP));
                 if let Some(ty) = ty.make_suggestable(self.infcx.tcx, true, placeholder) {
                     let ty_info = ty_to_string(self, ty, None);
                     multi_suggestions.push(SourceKindMultiSuggestion::new_closure_return(
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs
index b93b8dc03f8..b6c38739e9a 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs
@@ -32,14 +32,14 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         // If we added a "points at argument expression" obligation, we remove it here, we care
         // about the original obligation only.
         let code = match cause.code() {
-            ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => &*parent_code,
+            ObligationCauseCode::FunctionArg { parent_code, .. } => &*parent_code,
             code => code,
         };
         let ObligationCauseCode::MatchImpl(parent, impl_def_id) = code else {
             return None;
         };
-        let (ObligationCauseCode::BindingObligation(_, binding_span)
-        | ObligationCauseCode::ExprBindingObligation(_, binding_span, ..)) = *parent.code()
+        let (ObligationCauseCode::SpannedWhereClause(_, binding_span)
+        | ObligationCauseCode::SpannedWhereClauseInExpr(_, binding_span, ..)) = *parent.code()
         else {
             return None;
         };
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
index 01e75d59f4d..dbd165c093a 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
@@ -12,7 +12,7 @@ use rustc_errors::{Diag, IntoDiagArg};
 use rustc_hir::def::Namespace;
 use rustc_hir::def_id::DefId;
 use rustc_middle::ty::error::ExpectedFound;
-use rustc_middle::ty::print::{FmtPrinter, Print, RegionHighlightMode};
+use rustc_middle::ty::print::{FmtPrinter, Print, PrintTraitRefExt as _, RegionHighlightMode};
 use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, RePlaceholder, Region, TyCtxt};
 
@@ -240,8 +240,8 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
         let span = cause.span();
 
         let (leading_ellipsis, satisfy_span, where_span, dup_span, def_id) =
-            if let ObligationCauseCode::ItemObligation(def_id)
-            | ObligationCauseCode::ExprItemObligation(def_id, ..) = *cause.code()
+            if let ObligationCauseCode::WhereClause(def_id)
+            | ObligationCauseCode::WhereClauseInExpr(def_id, ..) = *cause.code()
             {
                 (
                     true,
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
index 0bbabefaf95..e5950a7c935 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -214,8 +214,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                 _ => cause.code(),
             }
             && let (
-                &ObligationCauseCode::ItemObligation(item_def_id)
-                | &ObligationCauseCode::ExprItemObligation(item_def_id, ..),
+                &ObligationCauseCode::WhereClause(item_def_id)
+                | &ObligationCauseCode::WhereClauseInExpr(item_def_id, ..),
                 None,
             ) = (code, override_error_code)
         {
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
index b4cf727bf8f..7f3e23716f9 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
@@ -4,13 +4,13 @@ use crate::errors::{ConsiderBorrowingParamHelp, RelationshipHelp, TraitImplDiff}
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::infer::lexical_region_resolve::RegionResolutionError;
 use crate::infer::{Subtype, ValuePairs};
-use crate::traits::ObligationCauseCode::CompareImplItemObligation;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_hir::def::Res;
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::Visitor;
 use rustc_middle::hir::nested_filter;
+use rustc_middle::traits::ObligationCauseCode;
 use rustc_middle::ty::error::ExpectedFound;
 use rustc_middle::ty::print::RegionHighlightMode;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor};
@@ -31,7 +31,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
             _,
         ) = error.clone()
             && let (Subtype(sup_trace), Subtype(sub_trace)) = (&sup_origin, &sub_origin)
-            && let CompareImplItemObligation { trait_item_def_id, .. } = sub_trace.cause.code()
+            && let ObligationCauseCode::CompareImplItem { trait_item_def_id, .. } =
+                sub_trace.cause.code()
             && sub_trace.values == sup_trace.values
             && let ValuePairs::PolySigs(ExpectedFound { expected, found }) = sub_trace.values
         {
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs
index 3ae1165d2a4..ecbe65fe926 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs
@@ -357,13 +357,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             infer::Subtype(box ref trace)
                 if matches!(
                     &trace.cause.code().peel_derives(),
-                    ObligationCauseCode::BindingObligation(..)
-                        | ObligationCauseCode::ExprBindingObligation(..)
+                    ObligationCauseCode::SpannedWhereClause(..)
+                        | ObligationCauseCode::SpannedWhereClauseInExpr(..)
                 ) =>
             {
                 // Hack to get around the borrow checker because trace.cause has an `Rc`.
-                if let ObligationCauseCode::BindingObligation(_, span)
-                | ObligationCauseCode::ExprBindingObligation(_, span, ..) =
+                if let ObligationCauseCode::SpannedWhereClause(_, span)
+                | ObligationCauseCode::SpannedWhereClauseInExpr(_, span, ..) =
                     &trace.cause.code().peel_derives()
                 {
                     let span = *span;
@@ -371,7 +371,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                         .with_span_note(span, "the lifetime requirement is introduced here")
                 } else {
                     unreachable!(
-                        "control flow ensures we have a `BindingObligation` or `ExprBindingObligation` here..."
+                        "control flow ensures we have a `BindingObligation` or `SpannedWhereClauseInExpr` here..."
                     )
                 }
             }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
index 6a42f9b42c3..c24ad1fa1e7 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
@@ -629,8 +629,7 @@ impl<T> Trait<T> for X {
                     | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }),
             )
         );
-        let impl_comparison =
-            matches!(cause_code, ObligationCauseCode::CompareImplItemObligation { .. });
+        let impl_comparison = matches!(cause_code, ObligationCauseCode::CompareImplItem { .. });
         let assoc = tcx.associated_item(proj_ty.def_id);
         if impl_comparison {
             // We do not want to suggest calling functions when the reason of the
diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
index bf470bb1e3f..75479decebc 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
@@ -167,7 +167,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             exp_span, exp_found.expected, exp_found.found,
         );
 
-        if let ObligationCauseCode::CompareImplItemObligation { .. } = cause.code() {
+        if let ObligationCauseCode::CompareImplItem { .. } = cause.code() {
             return;
         }
 
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index bb53aec0b4d..ce82296a8aa 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -528,8 +528,8 @@ pub enum RegionVariableOrigin {
 
     /// Region variables created as the values for early-bound regions.
     ///
-    /// FIXME(@lcnr): This can also store a `DefId`, similar to
-    /// `TypeVariableOriginKind::TypeParameterDefinition`.
+    /// FIXME(@lcnr): This should also store a `DefId`, similar to
+    /// `TypeVariableOrigin`.
     RegionParameterDefinition(Span, Symbol),
 
     /// Region variables created when instantiating a binder with
@@ -989,72 +989,67 @@ impl<'tcx> InferCtxt<'tcx> {
         self.inner.borrow_mut().type_variables().num_vars()
     }
 
-    pub fn next_ty_var_id(&self, origin: TypeVariableOrigin) -> TyVid {
-        self.inner.borrow_mut().type_variables().new_var(self.universe(), origin)
+    pub fn next_ty_var(&self, span: Span) -> Ty<'tcx> {
+        self.next_ty_var_with_origin(TypeVariableOrigin { span, param_def_id: None })
     }
 
-    pub fn next_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
-        Ty::new_var(self.tcx, self.next_ty_var_id(origin))
+    pub fn next_ty_var_with_origin(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
+        let vid = self.inner.borrow_mut().type_variables().new_var(self.universe(), origin);
+        Ty::new_var(self.tcx, vid)
     }
 
-    pub fn next_ty_var_id_in_universe(
-        &self,
-        origin: TypeVariableOrigin,
-        universe: ty::UniverseIndex,
-    ) -> TyVid {
+    pub fn next_ty_var_id_in_universe(&self, span: Span, universe: ty::UniverseIndex) -> TyVid {
+        let origin = TypeVariableOrigin { span, param_def_id: None };
         self.inner.borrow_mut().type_variables().new_var(universe, origin)
     }
 
-    pub fn next_ty_var_in_universe(
-        &self,
-        origin: TypeVariableOrigin,
-        universe: ty::UniverseIndex,
-    ) -> Ty<'tcx> {
-        let vid = self.next_ty_var_id_in_universe(origin, universe);
+    pub fn next_ty_var_in_universe(&self, span: Span, universe: ty::UniverseIndex) -> Ty<'tcx> {
+        let vid = self.next_ty_var_id_in_universe(span, universe);
         Ty::new_var(self.tcx, vid)
     }
 
-    pub fn next_const_var(&self, ty: Ty<'tcx>, origin: ConstVariableOrigin) -> ty::Const<'tcx> {
-        ty::Const::new_var(self.tcx, self.next_const_var_id(origin), ty)
+    pub fn next_const_var(&self, ty: Ty<'tcx>, span: Span) -> ty::Const<'tcx> {
+        self.next_const_var_with_origin(ty, ConstVariableOrigin { span, param_def_id: None })
     }
 
-    pub fn next_const_var_in_universe(
+    pub fn next_const_var_with_origin(
         &self,
         ty: Ty<'tcx>,
         origin: ConstVariableOrigin,
-        universe: ty::UniverseIndex,
     ) -> ty::Const<'tcx> {
         let vid = self
             .inner
             .borrow_mut()
             .const_unification_table()
-            .new_key(ConstVariableValue::Unknown { origin, universe })
+            .new_key(ConstVariableValue::Unknown { origin, universe: self.universe() })
             .vid;
         ty::Const::new_var(self.tcx, vid, ty)
     }
 
-    pub fn next_const_var_id(&self, origin: ConstVariableOrigin) -> ConstVid {
-        self.inner
+    pub fn next_const_var_in_universe(
+        &self,
+        ty: Ty<'tcx>,
+        span: Span,
+        universe: ty::UniverseIndex,
+    ) -> ty::Const<'tcx> {
+        let origin = ConstVariableOrigin { span, param_def_id: None };
+        let vid = self
+            .inner
             .borrow_mut()
             .const_unification_table()
-            .new_key(ConstVariableValue::Unknown { origin, universe: self.universe() })
-            .vid
-    }
-
-    fn next_int_var_id(&self) -> IntVid {
-        self.inner.borrow_mut().int_unification_table().new_key(None)
+            .new_key(ConstVariableValue::Unknown { origin, universe })
+            .vid;
+        ty::Const::new_var(self.tcx, vid, ty)
     }
 
     pub fn next_int_var(&self) -> Ty<'tcx> {
-        Ty::new_int_var(self.tcx, self.next_int_var_id())
-    }
-
-    fn next_float_var_id(&self) -> FloatVid {
-        self.inner.borrow_mut().float_unification_table().new_key(None)
+        let vid = self.inner.borrow_mut().int_unification_table().new_key(None);
+        Ty::new_int_var(self.tcx, vid)
     }
 
     pub fn next_float_var(&self) -> Ty<'tcx> {
-        Ty::new_float_var(self.tcx, self.next_float_var_id())
+        let vid = self.inner.borrow_mut().float_unification_table().new_key(None);
+        Ty::new_float_var(self.tcx, vid)
     }
 
     /// Creates a fresh region variable with the next available index.
@@ -1468,24 +1463,13 @@ impl<'tcx> InferCtxt<'tcx> {
             fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> {
                 self.map
                     .entry(bt.var)
-                    .or_insert_with(|| {
-                        self.infcx
-                            .next_ty_var(TypeVariableOrigin { param_def_id: None, span: self.span })
-                            .into()
-                    })
+                    .or_insert_with(|| self.infcx.next_ty_var(self.span).into())
                     .expect_ty()
             }
             fn replace_const(&mut self, bv: ty::BoundVar, ty: Ty<'tcx>) -> ty::Const<'tcx> {
                 self.map
                     .entry(bv)
-                    .or_insert_with(|| {
-                        self.infcx
-                            .next_const_var(
-                                ty,
-                                ConstVariableOrigin { param_def_id: None, span: self.span },
-                            )
-                            .into()
-                    })
+                    .or_insert_with(|| self.infcx.next_const_var(ty, self.span).into())
                     .expect_const()
             }
         }
@@ -1892,7 +1876,7 @@ impl<'tcx> SubregionOrigin<'tcx> {
                 SubregionOrigin::ReferenceOutlivesReferent(ref_type, cause.span)
             }
 
-            traits::ObligationCauseCode::CompareImplItemObligation {
+            traits::ObligationCauseCode::CompareImplItem {
                 impl_item_def_id,
                 trait_item_def_id,
                 kind: _,
diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs
index 94a546f87ee..703bd5ae90b 100644
--- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs
@@ -1,4 +1,3 @@
-use super::type_variable::TypeVariableOrigin;
 use super::{DefineOpaqueTypes, InferResult};
 use crate::errors::OpaqueHiddenTypeDiag;
 use crate::infer::{InferCtxt, InferOk};
@@ -65,7 +64,7 @@ impl<'tcx> InferCtxt<'tcx> {
                     let span = if span.contains(def_span) { def_span } else { span };
                     let code = traits::ObligationCauseCode::OpaqueReturnType(None);
                     let cause = ObligationCause::new(span, body_id, code);
-                    let ty_var = self.next_ty_var(TypeVariableOrigin { param_def_id: None, span });
+                    let ty_var = self.next_ty_var(span);
                     obligations.extend(
                         self.handle_opaque_type(ty, ty_var, &cause, param_env).unwrap().obligations,
                     );
@@ -485,6 +484,19 @@ impl<'tcx> InferCtxt<'tcx> {
         Ok(InferOk { value: (), obligations })
     }
 
+    /// Insert a hidden type into the opaque type storage, making sure
+    /// it hasn't previously been defined. This does not emit any
+    /// constraints and it's the responsibility of the caller to make
+    /// sure that the item bounds of the opaque are checked.
+    pub fn inject_new_hidden_type_unchecked(
+        &self,
+        opaque_type_key: OpaqueTypeKey<'tcx>,
+        hidden_ty: OpaqueHiddenType<'tcx>,
+    ) {
+        let prev = self.inner.borrow_mut().opaque_types().register(opaque_type_key, hidden_ty);
+        assert_eq!(prev, None);
+    }
+
     /// Insert a hidden type into the opaque type storage, equating it
     /// with any previous entries if necessary.
     ///
diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs
index fe323982ec0..94f8a2664f9 100644
--- a/compiler/rustc_infer/src/infer/outlives/obligations.rs
+++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs
@@ -103,8 +103,8 @@ impl<'tcx> InferCtxt<'tcx> {
                 cause.span,
                 sup_type,
                 match cause.code().peel_derives() {
-                    ObligationCauseCode::BindingObligation(_, span)
-                    | ObligationCauseCode::ExprBindingObligation(_, span, ..) => Some(*span),
+                    ObligationCauseCode::SpannedWhereClause(_, span)
+                    | ObligationCauseCode::SpannedWhereClauseInExpr(_, span, ..) => Some(*span),
                     _ => None,
                 },
             )
diff --git a/compiler/rustc_infer/src/infer/projection.rs b/compiler/rustc_infer/src/infer/projection.rs
index e60efe37fd9..041838ffc16 100644
--- a/compiler/rustc_infer/src/infer/projection.rs
+++ b/compiler/rustc_infer/src/infer/projection.rs
@@ -3,7 +3,6 @@ use rustc_middle::ty::{self, Ty};
 
 use crate::traits::{Obligation, PredicateObligation};
 
-use super::type_variable::TypeVariableOrigin;
 use super::InferCtxt;
 
 impl<'tcx> InferCtxt<'tcx> {
@@ -23,10 +22,7 @@ impl<'tcx> InferCtxt<'tcx> {
     ) -> Ty<'tcx> {
         debug_assert!(!self.next_trait_solver());
         let def_id = projection_ty.def_id;
-        let ty_var = self.next_ty_var(TypeVariableOrigin {
-            param_def_id: None,
-            span: self.tcx.def_span(def_id),
-        });
+        let ty_var = self.next_ty_var(self.tcx.def_span(def_id));
         let projection = ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::Projection(
             ty::ProjectionPredicate { projection_ty, term: ty_var.into() },
         )));
diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs
index 74929daffe2..5880ca788bc 100644
--- a/compiler/rustc_infer/src/infer/relate/generalize.rs
+++ b/compiler/rustc_infer/src/infer/relate/generalize.rs
@@ -1,7 +1,7 @@
 use std::mem;
 
 use super::StructurallyRelateAliases;
-use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableValue};
+use crate::infer::type_variable::TypeVariableValue;
 use crate::infer::{InferCtxt, ObligationEmittingRelation, RegionVariableOrigin};
 use rustc_data_structures::sso::SsoHashMap;
 use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -350,11 +350,14 @@ impl<'tcx> Generalizer<'_, 'tcx> {
         &mut self,
         alias: ty::AliasTy<'tcx>,
     ) -> Result<Ty<'tcx>, TypeError<'tcx>> {
-        if self.infcx.next_trait_solver() && !alias.has_escaping_bound_vars() {
-            return Ok(self.infcx.next_ty_var_in_universe(
-                TypeVariableOrigin { param_def_id: None, span: self.span },
-                self.for_universe,
-            ));
+        // We do not eagerly replace aliases with inference variables if they have
+        // escaping bound vars, see the method comment for details. However, when we
+        // are inside of an alias with escaping bound vars replacing nested aliases
+        // with inference variables can cause incorrect ambiguity.
+        //
+        // cc trait-system-refactor-initiative#110
+        if self.infcx.next_trait_solver() && !alias.has_escaping_bound_vars() && !self.in_alias {
+            return Ok(self.infcx.next_ty_var_in_universe(self.span, self.for_universe));
         }
 
         let is_nested_alias = mem::replace(&mut self.in_alias, true);
@@ -374,10 +377,7 @@ impl<'tcx> Generalizer<'_, 'tcx> {
                     }
 
                     debug!("generalization failure in alias");
-                    Ok(self.infcx.next_ty_var_in_universe(
-                        TypeVariableOrigin { param_def_id: None, span: self.span },
-                        self.for_universe,
-                    ))
+                    Ok(self.infcx.next_ty_var_in_universe(self.span, self.for_universe))
                 }
             }
         };
@@ -492,9 +492,30 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
                             let origin = inner.type_variables().var_origin(vid);
                             let new_var_id =
                                 inner.type_variables().new_var(self.for_universe, origin);
-                            let u = Ty::new_var(self.tcx(), new_var_id);
-                            debug!("replacing original vid={:?} with new={:?}", vid, u);
-                            Ok(u)
+                            // If we're in the new solver and create a new inference
+                            // variable inside of an alias we eagerly constrain that
+                            // inference variable to prevent unexpected ambiguity errors.
+                            //
+                            // This is incomplete as it pulls down the universe of the
+                            // original inference variable, even though the alias could
+                            // normalize to a type which does not refer to that type at
+                            // all. I don't expect this to cause unexpected errors in
+                            // practice.
+                            //
+                            // We only need to do so for type and const variables, as
+                            // region variables do not impact normalization, and will get
+                            // correctly constrained by `AliasRelate` later on.
+                            //
+                            // cc trait-system-refactor-initiative#108
+                            if self.infcx.next_trait_solver()
+                                && !self.infcx.intercrate
+                                && self.in_alias
+                            {
+                                inner.type_variables().equate(vid, new_var_id);
+                            }
+
+                            debug!("replacing original vid={:?} with new={:?}", vid, new_var_id);
+                            Ok(Ty::new_var(self.tcx(), new_var_id))
                         }
                     }
                 }
@@ -614,6 +635,15 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
                                     universe: self.for_universe,
                                 })
                                 .vid;
+
+                            // See the comment for type inference variables
+                            // for more details.
+                            if self.infcx.next_trait_solver()
+                                && !self.infcx.intercrate
+                                && self.in_alias
+                            {
+                                variable_table.union(vid, new_var_id);
+                            }
                             Ok(ty::Const::new_var(self.tcx(), new_var_id, c.ty()))
                         }
                     }
diff --git a/compiler/rustc_infer/src/infer/relate/lattice.rs b/compiler/rustc_infer/src/infer/relate/lattice.rs
index f9470c9b8f6..38e25b0d9b6 100644
--- a/compiler/rustc_infer/src/infer/relate/lattice.rs
+++ b/compiler/rustc_infer/src/infer/relate/lattice.rs
@@ -18,7 +18,6 @@
 //! [lattices]: https://en.wikipedia.org/wiki/Lattice_(order)
 
 use super::combine::ObligationEmittingRelation;
-use crate::infer::type_variable::TypeVariableOrigin;
 use crate::infer::{DefineOpaqueTypes, InferCtxt};
 use crate::traits::ObligationCause;
 
@@ -88,14 +87,12 @@ where
         // iterate on the subtype obligations that are returned, but I
         // think this suffices. -nmatsakis
         (&ty::Infer(TyVar(..)), _) => {
-            let v = infcx
-                .next_ty_var(TypeVariableOrigin { param_def_id: None, span: this.cause().span });
+            let v = infcx.next_ty_var(this.cause().span);
             this.relate_bound(v, b, a)?;
             Ok(v)
         }
         (_, &ty::Infer(TyVar(..))) => {
-            let v = infcx
-                .next_ty_var(TypeVariableOrigin { param_def_id: None, span: this.cause().span });
+            let v = infcx.next_ty_var(this.cause().span);
             this.relate_bound(v, a, b)?;
             Ok(v)
         }
diff --git a/compiler/rustc_infer/src/infer/snapshot/fudge.rs b/compiler/rustc_infer/src/infer/snapshot/fudge.rs
index 83667f7276d..4408251c99d 100644
--- a/compiler/rustc_infer/src/infer/snapshot/fudge.rs
+++ b/compiler/rustc_infer/src/infer/snapshot/fudge.rs
@@ -195,7 +195,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for InferenceFudger<'a, 'tcx> {
                     // Recreate it with a fresh variable here.
                     let idx = vid.as_usize() - self.type_vars.0.start.as_usize();
                     let origin = self.type_vars.1[idx];
-                    self.infcx.next_ty_var(origin)
+                    self.infcx.next_ty_var_with_origin(origin)
                 } else {
                     // This variable was created before the
                     // "fudging". Since we refresh all type
@@ -244,7 +244,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for InferenceFudger<'a, 'tcx> {
                 // Recreate it with a fresh variable here.
                 let idx = vid.index() - self.const_vars.0.start.index();
                 let origin = self.const_vars.1[idx];
-                self.infcx.next_const_var(ct.ty(), origin)
+                self.infcx.next_const_var_with_origin(ct.ty(), origin)
             } else {
                 ct
             }
diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs
index f77a6115861..85510cf2dcc 100644
--- a/compiler/rustc_infer/src/traits/mod.rs
+++ b/compiler/rustc_infer/src/traits/mod.rs
@@ -105,7 +105,7 @@ impl<'tcx> PredicateObligation<'tcx> {
 impl<'tcx> PolyTraitObligation<'tcx> {
     pub fn derived_cause(
         &self,
-        variant: impl FnOnce(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>,
+        variant: impl FnOnce(DerivedCause<'tcx>) -> ObligationCauseCode<'tcx>,
     ) -> ObligationCause<'tcx> {
         self.cause.clone().derived_cause(self.predicate, variant)
     }
@@ -138,10 +138,10 @@ pub enum FulfillmentErrorCode<'tcx> {
     /// Inherently impossible to fulfill; this trait is implemented if and only
     /// if it is already implemented.
     Cycle(Vec<PredicateObligation<'tcx>>),
-    SelectionError(SelectionError<'tcx>),
-    ProjectionError(MismatchedProjectionTypes<'tcx>),
-    SubtypeError(ExpectedFound<Ty<'tcx>>, TypeError<'tcx>), // always comes from a SubtypePredicate
-    ConstEquateError(ExpectedFound<Const<'tcx>>, TypeError<'tcx>),
+    Select(SelectionError<'tcx>),
+    Project(MismatchedProjectionTypes<'tcx>),
+    Subtype(ExpectedFound<Ty<'tcx>>, TypeError<'tcx>), // always comes from a SubtypePredicate
+    ConstEquate(ExpectedFound<Const<'tcx>>, TypeError<'tcx>),
     Ambiguity {
         /// Overflow is only `Some(suggest_recursion_limit)` when using the next generation
         /// trait solver `-Znext-solver`. With the old solver overflow is eagerly handled by
@@ -209,10 +209,10 @@ impl<'tcx> FulfillmentError<'tcx> {
 
     pub fn is_true_error(&self) -> bool {
         match self.code {
-            FulfillmentErrorCode::SelectionError(_)
-            | FulfillmentErrorCode::ProjectionError(_)
-            | FulfillmentErrorCode::SubtypeError(_, _)
-            | FulfillmentErrorCode::ConstEquateError(_, _) => true,
+            FulfillmentErrorCode::Select(_)
+            | FulfillmentErrorCode::Project(_)
+            | FulfillmentErrorCode::Subtype(_, _)
+            | FulfillmentErrorCode::ConstEquate(_, _) => true,
             FulfillmentErrorCode::Cycle(_) | FulfillmentErrorCode::Ambiguity { overflow: _ } => {
                 false
             }
diff --git a/compiler/rustc_infer/src/traits/structural_impls.rs b/compiler/rustc_infer/src/traits/structural_impls.rs
index 064e09b8750..b616d37e5b5 100644
--- a/compiler/rustc_infer/src/traits/structural_impls.rs
+++ b/compiler/rustc_infer/src/traits/structural_impls.rs
@@ -39,12 +39,12 @@ impl<'tcx> fmt::Debug for traits::FulfillmentErrorCode<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         use traits::FulfillmentErrorCode::*;
         match *self {
-            SelectionError(ref e) => write!(f, "{e:?}"),
-            ProjectionError(ref e) => write!(f, "{e:?}"),
-            SubtypeError(ref a, ref b) => {
+            Select(ref e) => write!(f, "{e:?}"),
+            Project(ref e) => write!(f, "{e:?}"),
+            Subtype(ref a, ref b) => {
                 write!(f, "CodeSubtypeError({a:?}, {b:?})")
             }
-            ConstEquateError(ref a, ref b) => {
+            ConstEquate(ref a, ref b) => {
                 write!(f, "CodeConstEquateError({a:?}, {b:?})")
             }
             Ambiguity { overflow: None } => write!(f, "Ambiguity"),
diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs
index 6d43011d33c..d8d84b777e0 100644
--- a/compiler/rustc_infer/src/traits/util.rs
+++ b/compiler/rustc_infer/src/traits/util.rs
@@ -1,7 +1,7 @@
 use smallvec::smallvec;
 
 use crate::infer::outlives::components::{push_outlives_components, Component};
-use crate::traits::{self, Obligation, PredicateObligation};
+use crate::traits::{self, Obligation, ObligationCauseCode, PredicateObligation};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt};
 use rustc_span::symbol::Ident;
@@ -129,7 +129,7 @@ impl<'tcx> Elaboratable<'tcx> for PredicateObligation<'tcx> {
         index: usize,
     ) -> Self {
         let cause = self.cause.clone().derived_cause(parent_trait_pred, |derived| {
-            traits::ImplDerivedObligation(Box::new(traits::ImplDerivedObligationCause {
+            ObligationCauseCode::ImplDerived(Box::new(traits::ImplDerivedCause {
                 derived,
                 impl_or_alias_def_id: parent_trait_pred.def_id(),
                 impl_def_predicate_index: Some(index),
diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml
index 0e90836145e..4b3b0728f38 100644
--- a/compiler/rustc_interface/Cargo.toml
+++ b/compiler/rustc_interface/Cargo.toml
@@ -10,6 +10,7 @@ rustc-rayon-core = { version = "0.5.0", optional = true }
 rustc_ast = { path = "../rustc_ast" }
 rustc_ast_lowering = { path = "../rustc_ast_lowering" }
 rustc_ast_passes = { path = "../rustc_ast_passes" }
+rustc_ast_pretty = { path = "../rustc_ast_pretty" }
 rustc_attr = { path = "../rustc_attr" }
 rustc_borrowck = { path = "../rustc_borrowck" }
 rustc_builtin_macros = { path = "../rustc_builtin_macros" }
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index c5b81dbd679..55304bbbd92 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -120,14 +120,45 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec<String>) -> CheckCfg {
         );
         let filename = FileName::cfg_spec_source_code(&s);
 
+        const VISIT: &str =
+            "visit <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details";
+
         macro_rules! error {
             ($reason:expr) => {
                 #[allow(rustc::untranslatable_diagnostic)]
                 #[allow(rustc::diagnostic_outside_of_impl)]
-                dcx.fatal(format!(
-                    concat!("invalid `--check-cfg` argument: `{}` (", $reason, ")"),
-                    s
-                ))
+                {
+                    let mut diag =
+                        dcx.struct_fatal(format!("invalid `--check-cfg` argument: `{s}`"));
+                    diag.note($reason);
+                    diag.note(VISIT);
+                    diag.emit()
+                }
+            };
+            (in $arg:expr, $reason:expr) => {
+                #[allow(rustc::untranslatable_diagnostic)]
+                #[allow(rustc::diagnostic_outside_of_impl)]
+                {
+                    let mut diag =
+                        dcx.struct_fatal(format!("invalid `--check-cfg` argument: `{s}`"));
+
+                    let pparg = rustc_ast_pretty::pprust::meta_list_item_to_string($arg);
+                    if let Some(lit) = $arg.lit() {
+                        let (lit_kind_article, lit_kind_descr) = {
+                            let lit_kind = lit.as_token_lit().kind;
+                            (lit_kind.article(), lit_kind.descr())
+                        };
+                        diag.note(format!(
+                            "`{pparg}` is {lit_kind_article} {lit_kind_descr} literal"
+                        ));
+                    } else {
+                        diag.note(format!("`{pparg}` is invalid"));
+                    }
+
+                    diag.note($reason);
+                    diag.note(VISIT);
+                    diag.emit()
+                }
             };
         }
 
@@ -183,7 +214,7 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec<String>) -> CheckCfg {
                 }
                 any_specified = true;
                 if !args.is_empty() {
-                    error!("`any()` must be empty");
+                    error!(in arg, "`any()` takes no argument");
                 }
             } else if arg.has_name(sym::values)
                 && let Some(args) = arg.meta_item_list()
@@ -202,25 +233,25 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec<String>) -> CheckCfg {
                         && let Some(args) = arg.meta_item_list()
                     {
                         if values_any_specified {
-                            error!("`any()` in `values()` cannot be specified multiple times");
+                            error!(in arg, "`any()` in `values()` cannot be specified multiple times");
                         }
                         values_any_specified = true;
                         if !args.is_empty() {
-                            error!("`any()` must be empty");
+                            error!(in arg, "`any()` in `values()` takes no argument");
                         }
                     } else if arg.has_name(sym::none)
                         && let Some(args) = arg.meta_item_list()
                     {
                         values.insert(None);
                         if !args.is_empty() {
-                            error!("`none()` must be empty");
+                            error!(in arg, "`none()` in `values()` takes no argument");
                         }
                     } else {
-                        error!("`values()` arguments must be string literals, `none()` or `any()`");
+                        error!(in arg, "`values()` arguments must be string literals, `none()` or `any()`");
                     }
                 }
             } else {
-                error!("`cfg()` arguments must be simple identifiers, `any()` or `values(...)`");
+                error!(in arg, "`cfg()` arguments must be simple identifiers, `any()` or `values(...)`");
             }
         }
 
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index ba316e5eeb0..b9be92b89af 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -40,6 +40,7 @@ use crate::{
     },
     EarlyContext, EarlyLintPass, LateContext, LateLintPass, Level, LintContext,
 };
+use ast::token::TokenKind;
 use rustc_ast::tokenstream::{TokenStream, TokenTree};
 use rustc_ast::visit::{FnCtxt, FnKind};
 use rustc_ast::{self as ast, *};
@@ -1869,16 +1870,24 @@ struct UnderMacro(bool);
 
 impl KeywordIdents {
     fn check_tokens(&mut self, cx: &EarlyContext<'_>, tokens: &TokenStream) {
+        // Check if the preceding token is `$`, because we want to allow `$async`, etc.
+        let mut prev_dollar = false;
         for tt in tokens.trees() {
             match tt {
                 // Only report non-raw idents.
                 TokenTree::Token(token, _) => {
                     if let Some((ident, token::IdentIsRaw::No)) = token.ident() {
-                        self.check_ident_token(cx, UnderMacro(true), ident);
+                        if !prev_dollar {
+                            self.check_ident_token(cx, UnderMacro(true), ident);
+                        }
+                    } else if token.kind == TokenKind::Dollar {
+                        prev_dollar = true;
+                        continue;
                     }
                 }
                 TokenTree::Delimited(.., tts) => self.check_tokens(cx, tts),
             }
+            prev_dollar = false;
         }
     }
 
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 0931bb29963..62ba9ef5c11 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -30,7 +30,7 @@ use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
 use rustc_middle::bug;
 use rustc_middle::middle::privacy::EffectiveVisibilities;
 use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout};
-use rustc_middle::ty::print::{with_no_trimmed_paths, PrintError};
+use rustc_middle::ty::print::{with_no_trimmed_paths, PrintError, PrintTraitRefExt as _};
 use rustc_middle::ty::{self, print::Printer, GenericArg, RegisteredTools, Ty, TyCtxt};
 use rustc_session::lint::{BuiltinLintDiag, LintExpectationId};
 use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintId};
diff --git a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs
index e9a6276192e..3c423b4e2aa 100644
--- a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs
+++ b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs
@@ -164,9 +164,9 @@ pub(super) fn unexpected_cfg_name(
 
     if is_from_cargo {
         if !is_feature_cfg {
-            diag.help(format!("consider using a Cargo feature instead or adding `println!(\"cargo:rustc-check-cfg={inst}\");` to the top of a `build.rs`"));
+            diag.help(format!("consider using a Cargo feature instead or adding `println!(\"cargo::rustc-check-cfg={inst}\");` to the top of the `build.rs`"));
         }
-        diag.note("see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration");
+        diag.note("see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration");
     } else {
         diag.help(format!("to expect this configuration use `--check-cfg={inst}`"));
         diag.note("see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration");
@@ -266,9 +266,9 @@ pub(super) fn unexpected_cfg_value(
                 diag.help("consider defining some features in `Cargo.toml`");
             }
         } else if !is_cfg_a_well_know_name {
-            diag.help(format!("consider using a Cargo feature instead or adding `println!(\"cargo:rustc-check-cfg={inst}\");` to the top of a `build.rs`"));
+            diag.help(format!("consider using a Cargo feature instead or adding `println!(\"cargo::rustc-check-cfg={inst}\");` to the top of the `build.rs`"));
         }
-        diag.note("see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration");
+        diag.note("see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration");
     } else {
         if !is_cfg_a_well_know_name {
             diag.help(format!("to expect this configuration use `--check-cfg={inst}`"));
diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs
index ce3f45a17e9..a6876d8aae7 100644
--- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs
+++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs
@@ -9,7 +9,7 @@ use crate::{
 use hir::{Expr, Pat};
 use rustc_hir as hir;
 use rustc_infer::{infer::TyCtxtInferExt, traits::ObligationCause};
-use rustc_middle::ty::{self, List};
+use rustc_middle::ty;
 use rustc_session::{declare_lint, declare_lint_pass};
 use rustc_span::{sym, Span};
 use rustc_trait_selection::traits::ObligationCtxt;
@@ -123,7 +123,7 @@ fn extract_iterator_next_call<'tcx>(
 fn suggest_question_mark<'tcx>(
     cx: &LateContext<'tcx>,
     adt: ty::AdtDef<'tcx>,
-    args: &List<ty::GenericArg<'tcx>>,
+    args: ty::GenericArgsRef<'tcx>,
     span: Span,
 ) -> bool {
     let Some(body_id) = cx.enclosing_body else { return false };
@@ -150,11 +150,8 @@ fn suggest_question_mark<'tcx>(
     let ocx = ObligationCtxt::new(&infcx);
 
     let body_def_id = cx.tcx.hir().body_owner_def_id(body_id);
-    let cause = ObligationCause::new(
-        span,
-        body_def_id,
-        rustc_infer::traits::ObligationCauseCode::MiscObligation,
-    );
+    let cause =
+        ObligationCause::new(span, body_def_id, rustc_infer::traits::ObligationCauseCode::Misc);
 
     ocx.register_bound(
         cause,
diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs
index 7bdf5ef6af4..885c0bb3a89 100644
--- a/compiler/rustc_lint/src/non_local_def.rs
+++ b/compiler/rustc_lint/src/non_local_def.rs
@@ -1,6 +1,5 @@
 use rustc_hir::{def::DefKind, Body, Item, ItemKind, Node, TyKind};
 use rustc_hir::{Path, QPath};
-use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::infer::InferCtxt;
 use rustc_infer::traits::{Obligation, ObligationCause};
 use rustc_middle::ty::{self, Binder, Ty, TyCtxt, TypeFoldable, TypeFolder};
@@ -337,7 +336,7 @@ impl<'a, 'tcx, F: FnMut(DefId) -> bool> TypeFolder<TyCtxt<'tcx>>
         if let Some(def) = t.ty_adt_def()
             && (self.did_has_local_parent)(def.did())
         {
-            self.infcx.next_ty_var(TypeVariableOrigin { param_def_id: None, span: self.infer_span })
+            self.infcx.next_ty_var(self.infer_span)
         } else {
             t.super_fold_with(self)
         }
diff --git a/compiler/rustc_lint/src/reference_casting.rs b/compiler/rustc_lint/src/reference_casting.rs
index 9fed91f7262..b80e90c25a3 100644
--- a/compiler/rustc_lint/src/reference_casting.rs
+++ b/compiler/rustc_lint/src/reference_casting.rs
@@ -199,6 +199,14 @@ fn is_cast_to_bigger_memory_layout<'tcx>(
     let e_alloc = cx.expr_or_init(e);
     let e_alloc =
         if let ExprKind::AddrOf(_, _, inner_expr) = e_alloc.kind { inner_expr } else { e_alloc };
+
+    // if the current expr looks like this `&mut expr[index]` then just looking
+    // at `expr[index]` won't give us the underlying allocation, so we just skip it
+    // the same logic applies field access like `&mut expr.field`
+    if let ExprKind::Index(..) | ExprKind::Field(..) = e_alloc.kind {
+        return None;
+    }
+
     let alloc_ty = cx.typeck_results().node_type(e_alloc.hir_id);
 
     // if we do not find it we bail out, as this may not be UB
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index 13b6054586c..f9f766f832a 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -1101,6 +1101,32 @@ fn get_nullable_type<'tcx>(
     })
 }
 
+/// A type is niche-optimization candidate iff:
+/// - Is a zero-sized type with alignment 1 (a “1-ZST”).
+/// - Has no fields.
+/// - Does not have the `#[non_exhaustive]` attribute.
+fn is_niche_optimization_candidate<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    ty: Ty<'tcx>,
+) -> bool {
+    if tcx.layout_of(param_env.and(ty)).is_ok_and(|layout| !layout.is_1zst()) {
+        return false;
+    }
+
+    match ty.kind() {
+        ty::Adt(ty_def, _) => {
+            let non_exhaustive = ty_def.is_variant_list_non_exhaustive();
+            let empty = (ty_def.is_struct() && ty_def.all_fields().next().is_none())
+                || (ty_def.is_enum() && ty_def.variants().is_empty());
+
+            !non_exhaustive && empty
+        }
+        ty::Tuple(tys) => tys.is_empty(),
+        _ => false,
+    }
+}
+
 /// Check if this enum can be safely exported based on the "nullable pointer optimization". If it
 /// can, return the type that `ty` can be safely converted to, otherwise return `None`.
 /// Currently restricted to function pointers, boxes, references, `core::num::NonZero`,
@@ -1117,6 +1143,22 @@ pub(crate) fn repr_nullable_ptr<'tcx>(
         let field_ty = match &ty_def.variants().raw[..] {
             [var_one, var_two] => match (&var_one.fields.raw[..], &var_two.fields.raw[..]) {
                 ([], [field]) | ([field], []) => field.ty(tcx, args),
+                ([field1], [field2]) => {
+                    if !tcx.features().result_ffi_guarantees {
+                        return None;
+                    }
+
+                    let ty1 = field1.ty(tcx, args);
+                    let ty2 = field2.ty(tcx, args);
+
+                    if is_niche_optimization_candidate(tcx, param_env, ty1) {
+                        ty2
+                    } else if is_niche_optimization_candidate(tcx, param_env, ty2) {
+                        ty1
+                    } else {
+                        return None;
+                    }
+                }
                 _ => return None,
             },
             _ => return None,
@@ -1202,7 +1244,6 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
         args: GenericArgsRef<'tcx>,
     ) -> FfiResult<'tcx> {
         use FfiResult::*;
-
         let transparent_with_all_zst_fields = if def.repr().transparent() {
             if let Some(field) = transparent_newtype_field(self.cx.tcx, variant) {
                 // Transparent newtypes have at most one non-ZST field which needs to be checked..
@@ -1329,27 +1370,29 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                             return FfiSafe;
                         }
 
+                        if def.is_variant_list_non_exhaustive() && !def.did().is_local() {
+                            return FfiUnsafe {
+                                ty,
+                                reason: fluent::lint_improper_ctypes_non_exhaustive,
+                                help: None,
+                            };
+                        }
+
                         // Check for a repr() attribute to specify the size of the
                         // discriminant.
                         if !def.repr().c() && !def.repr().transparent() && def.repr().int.is_none()
                         {
-                            // Special-case types like `Option<extern fn()>`.
-                            if repr_nullable_ptr(self.cx.tcx, self.cx.param_env, ty, self.mode)
-                                .is_none()
+                            // Special-case types like `Option<extern fn()>` and `Result<extern fn(), ()>`
+                            if let Some(ty) =
+                                repr_nullable_ptr(self.cx.tcx, self.cx.param_env, ty, self.mode)
                             {
-                                return FfiUnsafe {
-                                    ty,
-                                    reason: fluent::lint_improper_ctypes_enum_repr_reason,
-                                    help: Some(fluent::lint_improper_ctypes_enum_repr_help),
-                                };
+                                return self.check_type_for_ffi(cache, ty);
                             }
-                        }
 
-                        if def.is_variant_list_non_exhaustive() && !def.did().is_local() {
                             return FfiUnsafe {
                                 ty,
-                                reason: fluent::lint_improper_ctypes_non_exhaustive,
-                                help: None,
+                                reason: fluent::lint_improper_ctypes_enum_repr_reason,
+                                help: Some(fluent::lint_improper_ctypes_enum_repr_help),
                             };
                         }
 
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 4d372d612e9..2b147e052ae 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -1501,7 +1501,7 @@ declare_lint_pass!(UnusedImportBraces => [UNUSED_IMPORT_BRACES]);
 
 impl UnusedImportBraces {
     fn check_use_tree(&self, cx: &EarlyContext<'_>, use_tree: &ast::UseTree, item: &ast::Item) {
-        if let ast::UseTreeKind::Nested(ref items) = use_tree.kind {
+        if let ast::UseTreeKind::Nested { ref items, .. } = use_tree.kind {
             // Recursively check nested UseTrees
             for (tree, _) in items {
                 self.check_use_tree(cx, tree, item);
@@ -1522,7 +1522,7 @@ impl UnusedImportBraces {
                     rename.unwrap_or(orig_ident).name
                 }
                 ast::UseTreeKind::Glob => Symbol::intern("*"),
-                ast::UseTreeKind::Nested(_) => return,
+                ast::UseTreeKind::Nested { .. } => return,
             };
 
             cx.emit_span_lint(
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index c7996c27c2f..eea3ca44c48 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -844,7 +844,6 @@ declare_lint! {
     /// ### Example
     ///
     /// ```rust
-    /// # #![feature(exclusive_range_pattern)]
     /// let x = 123u32;
     /// match x {
     ///     0..100 => { println!("small"); }
diff --git a/compiler/rustc_llvm/Cargo.toml b/compiler/rustc_llvm/Cargo.toml
index c206380a06f..83fda7ef07c 100644
--- a/compiler/rustc_llvm/Cargo.toml
+++ b/compiler/rustc_llvm/Cargo.toml
@@ -10,5 +10,5 @@ libc = "0.2.73"
 
 [build-dependencies]
 # tidy-alphabetical-start
-cc = "1.0.90"
+cc = "1.0.97"
 # tidy-alphabetical-end
diff --git a/compiler/rustc_macros/src/lift.rs b/compiler/rustc_macros/src/lift.rs
index f7a84ba1510..d41ceb29816 100644
--- a/compiler/rustc_macros/src/lift.rs
+++ b/compiler/rustc_macros/src/lift.rs
@@ -41,7 +41,7 @@ pub fn lift_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStre
 
     s.add_impl_generic(newtcx);
     s.bound_impl(
-        quote!(::rustc_middle::ty::Lift<'__lifted>),
+        quote!(::rustc_middle::ty::Lift<::rustc_middle::ty::TyCtxt<'__lifted>>),
         quote! {
             type Lifted = #lifted;
 
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index c057f7e921e..7c96a6fa9a9 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1402,7 +1402,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                 let inferred_outlives = self.tcx.inferred_outlives_of(def_id);
                 record_defaulted_array!(self.tables.inferred_outlives_of[def_id] <- inferred_outlives);
 
-                for param in &g.params {
+                for param in &g.own_params {
                     if let ty::GenericParamDefKind::Const { has_default: true, .. } = param.kind {
                         let default = self.tcx.const_param_default(param.def_id);
                         record!(self.tables.const_param_default[param.def_id] <- default);
diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs
index f70ef51107f..817ac594627 100644
--- a/compiler/rustc_middle/src/macros.rs
+++ b/compiler/rustc_middle/src/macros.rs
@@ -57,7 +57,7 @@ macro_rules! span_bug {
 macro_rules! TrivialLiftImpls {
     ($($ty:ty),+ $(,)?) => {
         $(
-            impl<'tcx> $crate::ty::Lift<'tcx> for $ty {
+            impl<'tcx> $crate::ty::Lift<$crate::ty::TyCtxt<'tcx>> for $ty {
                 type Lifted = Self;
                 fn lift_to_tcx(self, _: $crate::ty::TyCtxt<'tcx>) -> Option<Self> {
                     Some(self)
diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs
index ee3cdf36820..38cb1d5f9a0 100644
--- a/compiler/rustc_middle/src/mir/interpret/mod.rs
+++ b/compiler/rustc_middle/src/mir/interpret/mod.rs
@@ -125,10 +125,11 @@ use std::io::{Read, Write};
 use std::num::NonZero;
 use std::sync::atomic::{AtomicU32, Ordering};
 
+use smallvec::{smallvec, SmallVec};
+
 use rustc_ast::LitKind;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::{HashMapExt, Lock};
-use rustc_data_structures::tiny_list::TinyList;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
@@ -266,8 +267,8 @@ type DecodingSessionId = NonZero<u32>;
 #[derive(Clone)]
 enum State {
     Empty,
-    InProgressNonAlloc(TinyList<DecodingSessionId>),
-    InProgress(TinyList<DecodingSessionId>, AllocId),
+    InProgressNonAlloc(SmallVec<[DecodingSessionId; 1]>),
+    InProgress(SmallVec<[DecodingSessionId; 1]>, AllocId),
     Done(AllocId),
 }
 
@@ -337,8 +338,7 @@ impl<'s> AllocDecodingSession<'s> {
                             // If this is an allocation, we need to reserve an
                             // `AllocId` so we can decode cyclic graphs.
                             let alloc_id = decoder.interner().reserve_alloc_id();
-                            *entry =
-                                State::InProgress(TinyList::new_single(self.session_id), alloc_id);
+                            *entry = State::InProgress(smallvec![self.session_id], alloc_id);
                             Some(alloc_id)
                         }
                         AllocDiscriminant::Fn
@@ -346,8 +346,7 @@ impl<'s> AllocDecodingSession<'s> {
                         | AllocDiscriminant::VTable => {
                             // Fns and statics cannot be cyclic, and their `AllocId`
                             // is determined later by interning.
-                            *entry =
-                                State::InProgressNonAlloc(TinyList::new_single(self.session_id));
+                            *entry = State::InProgressNonAlloc(smallvec![self.session_id]);
                             None
                         }
                     }
@@ -357,7 +356,7 @@ impl<'s> AllocDecodingSession<'s> {
                         bug!("this should be unreachable");
                     } else {
                         // Start decoding concurrently.
-                        sessions.insert(self.session_id);
+                        sessions.push(self.session_id);
                         None
                     }
                 }
@@ -367,7 +366,7 @@ impl<'s> AllocDecodingSession<'s> {
                         return alloc_id;
                     } else {
                         // Start decoding concurrently.
-                        sessions.insert(self.session_id);
+                        sessions.push(self.session_id);
                         Some(alloc_id)
                     }
                 }
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
index 3881723c5ec..4994679ad5d 100644
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -78,13 +78,9 @@ impl<'tcx> PlaceTy<'tcx> {
         }
         let answer = match *elem {
             ProjectionElem::Deref => {
-                let ty = self
-                    .ty
-                    .builtin_deref(true)
-                    .unwrap_or_else(|| {
-                        bug!("deref projection of non-dereferenceable ty {:?}", self)
-                    })
-                    .ty;
+                let ty = self.ty.builtin_deref(true).unwrap_or_else(|| {
+                    bug!("deref projection of non-dereferenceable ty {:?}", self)
+                });
                 PlaceTy::from_ty(ty)
             }
             ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } => {
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index a7d8ead5677..c68b7a6c9eb 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -682,6 +682,23 @@ impl<'tcx> Pat<'tcx> {
             true
         })
     }
+
+    /// Whether this a never pattern.
+    pub fn is_never_pattern(&self) -> bool {
+        let mut is_never_pattern = false;
+        self.walk(|pat| match &pat.kind {
+            PatKind::Never => {
+                is_never_pattern = true;
+                false
+            }
+            PatKind::Or { pats } => {
+                is_never_pattern = pats.iter().all(|p| p.is_never_pattern());
+                false
+            }
+            _ => true,
+        });
+        is_never_pattern
+    }
 }
 
 impl<'tcx> IntoDiagArg for Pat<'tcx> {
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 1ae037e09a7..6c33a29ea81 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -33,8 +33,6 @@ use std::hash::{Hash, Hasher};
 
 pub use self::select::{EvaluationCache, EvaluationResult, OverflowError, SelectionCache};
 
-pub use self::ObligationCauseCode::*;
-
 /// Depending on the stage of compilation, we want projection to be
 /// more or less conservative.
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, HashStable, Encodable, Decodable)]
@@ -129,7 +127,7 @@ impl<'tcx> ObligationCause<'tcx> {
     }
 
     pub fn misc(span: Span, body_id: LocalDefId) -> ObligationCause<'tcx> {
-        ObligationCause::new(span, body_id, MiscObligation)
+        ObligationCause::new(span, body_id, ObligationCauseCode::Misc)
     }
 
     #[inline(always)]
@@ -167,7 +165,7 @@ impl<'tcx> ObligationCause<'tcx> {
     pub fn derived_cause(
         mut self,
         parent_trait_pred: ty::PolyTraitPredicate<'tcx>,
-        variant: impl FnOnce(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>,
+        variant: impl FnOnce(DerivedCause<'tcx>) -> ObligationCauseCode<'tcx>,
     ) -> ObligationCause<'tcx> {
         /*!
          * Creates a cause for obligations that are derived from
@@ -182,15 +180,14 @@ impl<'tcx> ObligationCause<'tcx> {
         // NOTE(flaper87): As of now, it keeps track of the whole error
         // chain. Ideally, we should have a way to configure this either
         // by using -Z verbose-internals or just a CLI argument.
-        self.code =
-            variant(DerivedObligationCause { parent_trait_pred, parent_code: self.code }).into();
+        self.code = variant(DerivedCause { parent_trait_pred, parent_code: self.code }).into();
         self
     }
 
     pub fn to_constraint_category(&self) -> ConstraintCategory<'tcx> {
         match self.code() {
-            MatchImpl(cause, _) => cause.to_constraint_category(),
-            AscribeUserTypeProvePredicate(predicate_span) => {
+            ObligationCauseCode::MatchImpl(cause, _) => cause.to_constraint_category(),
+            ObligationCauseCode::AscribeUserTypeProvePredicate(predicate_span) => {
                 ConstraintCategory::Predicate(*predicate_span)
             }
             _ => ConstraintCategory::BoringNoLocation,
@@ -209,7 +206,7 @@ pub struct UnifyReceiverContext<'tcx> {
 #[derive(Clone, PartialEq, Eq, Default, HashStable)]
 #[derive(TypeVisitable, TypeFoldable, TyEncodable, TyDecodable)]
 pub struct InternedObligationCauseCode<'tcx> {
-    /// `None` for `ObligationCauseCode::MiscObligation` (a common case, occurs ~60% of
+    /// `None` for `ObligationCauseCode::Misc` (a common case, occurs ~60% of
     /// the time). `Some` otherwise.
     code: Option<Lrc<ObligationCauseCode<'tcx>>>,
 }
@@ -225,11 +222,7 @@ impl<'tcx> ObligationCauseCode<'tcx> {
     #[inline(always)]
     fn into(self) -> InternedObligationCauseCode<'tcx> {
         InternedObligationCauseCode {
-            code: if let ObligationCauseCode::MiscObligation = self {
-                None
-            } else {
-                Some(Lrc::new(self))
-            },
+            code: if let ObligationCauseCode::Misc = self { None } else { Some(Lrc::new(self)) },
         }
     }
 }
@@ -238,7 +231,7 @@ impl<'tcx> std::ops::Deref for InternedObligationCauseCode<'tcx> {
     type Target = ObligationCauseCode<'tcx>;
 
     fn deref(&self) -> &Self::Target {
-        self.code.as_deref().unwrap_or(&ObligationCauseCode::MiscObligation)
+        self.code.as_deref().unwrap_or(&ObligationCauseCode::Misc)
     }
 }
 
@@ -246,7 +239,7 @@ impl<'tcx> std::ops::Deref for InternedObligationCauseCode<'tcx> {
 #[derive(TypeVisitable, TypeFoldable)]
 pub enum ObligationCauseCode<'tcx> {
     /// Not well classified or should be obvious from the span.
-    MiscObligation,
+    Misc,
 
     /// A slice or array is WF only if `T: Sized`.
     SliceOrArrayElem,
@@ -256,20 +249,20 @@ pub enum ObligationCauseCode<'tcx> {
 
     /// Must satisfy all of the where-clause predicates of the
     /// given item.
-    ItemObligation(DefId),
+    WhereClause(DefId),
 
-    /// Like `ItemObligation`, but carries the span of the
+    /// Like `WhereClause`, but carries the span of the
     /// predicate when it can be identified.
-    BindingObligation(DefId, Span),
+    SpannedWhereClause(DefId, Span),
 
-    /// Like `ItemObligation`, but carries the `HirId` of the
+    /// Like `WhereClause`, but carries the `HirId` of the
     /// expression that caused the obligation, and the `usize`
     /// indicates exactly which predicate it is in the list of
     /// instantiated predicates.
-    ExprItemObligation(DefId, HirId, usize),
+    WhereClauseInExpr(DefId, HirId, usize),
 
-    /// Combines `ExprItemObligation` and `BindingObligation`.
-    ExprBindingObligation(DefId, Span, HirId, usize),
+    /// Combines `SpannedWhereClause` and `WhereClauseInExpr`.
+    SpannedWhereClauseInExpr(DefId, Span, HirId, usize),
 
     /// A type like `&'a T` is WF only if `T: 'a`.
     ReferenceOutlivesReferent(Ty<'tcx>),
@@ -333,16 +326,18 @@ pub enum ObligationCauseCode<'tcx> {
 
     /// Derived obligation (i.e. theoretical `where` clause) on a built-in
     /// implementation like `Copy` or `Sized`.
-    BuiltinDerivedObligation(DerivedObligationCause<'tcx>),
+    BuiltinDerived(DerivedCause<'tcx>),
 
     /// Derived obligation (i.e. `where` clause) on an user-provided impl
     /// or a trait alias.
-    ImplDerivedObligation(Box<ImplDerivedObligationCause<'tcx>>),
+    ImplDerived(Box<ImplDerivedCause<'tcx>>),
 
     /// Derived obligation for WF goals.
-    WellFormedDerivedObligation(DerivedObligationCause<'tcx>),
+    WellFormedDerived(DerivedCause<'tcx>),
 
-    FunctionArgumentObligation {
+    /// Derived obligation refined to point at a specific argument in
+    /// a call or method expression.
+    FunctionArg {
         /// The node of the relevant argument in the function call.
         arg_hir_id: HirId,
         /// The node of the function call.
@@ -353,7 +348,7 @@ pub enum ObligationCauseCode<'tcx> {
 
     /// Error derived when checking an impl item is compatible with
     /// its corresponding trait item's definition
-    CompareImplItemObligation {
+    CompareImplItem {
         impl_item_def_id: LocalDefId,
         trait_item_def_id: DefId,
         kind: ty::AssocKind,
@@ -432,8 +427,8 @@ pub enum ObligationCauseCode<'tcx> {
     /// then it will be used to perform HIR-based wf checking
     /// after an error occurs, in order to generate a more precise error span.
     /// This is purely for diagnostic purposes - it is always
-    /// correct to use `MiscObligation` instead, or to specify
-    /// `WellFormed(None)`
+    /// correct to use `Misc` instead, or to specify
+    /// `WellFormed(None)`.
     WellFormed(Option<WellFormedLoc>),
 
     /// From `match_impl`. The cause for us having to match an impl, and the DefId we are matching against.
@@ -501,8 +496,8 @@ pub enum WellFormedLoc {
 
 #[derive(Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
 #[derive(TypeVisitable, TypeFoldable)]
-pub struct ImplDerivedObligationCause<'tcx> {
-    pub derived: DerivedObligationCause<'tcx>,
+pub struct ImplDerivedCause<'tcx> {
+    pub derived: DerivedCause<'tcx>,
     /// The `DefId` of the `impl` that gave rise to the `derived` obligation.
     /// If the `derived` obligation arose from a trait alias, which conceptually has a synthetic impl,
     /// then this will be the `DefId` of that trait alias. Care should therefore be taken to handle
@@ -540,10 +535,10 @@ impl<'tcx> ObligationCauseCode<'tcx> {
 
     pub fn parent(&self) -> Option<(&Self, Option<ty::PolyTraitPredicate<'tcx>>)> {
         match self {
-            FunctionArgumentObligation { parent_code, .. } => Some((parent_code, None)),
-            BuiltinDerivedObligation(derived)
-            | WellFormedDerivedObligation(derived)
-            | ImplDerivedObligation(box ImplDerivedObligationCause { derived, .. }) => {
+            ObligationCauseCode::FunctionArg { parent_code, .. } => Some((parent_code, None)),
+            ObligationCauseCode::BuiltinDerived(derived)
+            | ObligationCauseCode::WellFormedDerived(derived)
+            | ObligationCauseCode::ImplDerived(box ImplDerivedCause { derived, .. }) => {
                 Some((&derived.parent_code, Some(derived.parent_trait_pred)))
             }
             _ => None,
@@ -552,7 +547,7 @@ impl<'tcx> ObligationCauseCode<'tcx> {
 
     pub fn peel_match_impls(&self) -> &Self {
         match self {
-            MatchImpl(cause, _) => cause.code(),
+            ObligationCauseCode::MatchImpl(cause, _) => cause.code(),
             _ => self,
         }
     }
@@ -598,7 +593,7 @@ pub struct IfExpressionCause<'tcx> {
 
 #[derive(Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
 #[derive(TypeVisitable, TypeFoldable)]
-pub struct DerivedObligationCause<'tcx> {
+pub struct DerivedCause<'tcx> {
     /// The trait predicate of the parent obligation that led to the
     /// current obligation. Note that only trait obligations lead to
     /// derived obligations, so we just store the trait predicate here
diff --git a/compiler/rustc_middle/src/traits/solve/inspect.rs b/compiler/rustc_middle/src/traits/solve/inspect.rs
index cddf9d5f874..2ddcb8aab25 100644
--- a/compiler/rustc_middle/src/traits/solve/inspect.rs
+++ b/compiler/rustc_middle/src/traits/solve/inspect.rs
@@ -123,6 +123,8 @@ pub enum ProbeStep<'tcx> {
     /// used whenever there are multiple candidates to prove the
     /// current goalby .
     NestedProbe(Probe<'tcx>),
+    /// A trait goal was satisfied by an impl candidate.
+    RecordImplArgs { impl_args: CanonicalState<'tcx, ty::GenericArgsRef<'tcx>> },
     /// A call to `EvalCtxt::evaluate_added_goals_make_canonical_response` with
     /// `Certainty` was made. This is the certainty passed in, so it's not unified
     /// with the certainty of the `try_evaluate_added_goals` that is done within;
diff --git a/compiler/rustc_middle/src/traits/solve/inspect/format.rs b/compiler/rustc_middle/src/traits/solve/inspect/format.rs
index 11aa0e10931..e652f0586c4 100644
--- a/compiler/rustc_middle/src/traits/solve/inspect/format.rs
+++ b/compiler/rustc_middle/src/traits/solve/inspect/format.rs
@@ -136,6 +136,9 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> {
                     ProbeStep::MakeCanonicalResponse { shallow_certainty } => {
                         writeln!(this.f, "EVALUATE GOALS AND MAKE RESPONSE: {shallow_certainty:?}")?
                     }
+                    ProbeStep::RecordImplArgs { impl_args } => {
+                        writeln!(this.f, "RECORDED IMPL ARGS: {impl_args:?}")?
+                    }
                 }
             }
             Ok(())
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index a65b3a41ade..329d5f34a21 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -8,7 +8,7 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::LocalDefId;
 use rustc_macros::{HashStable, TyDecodable, TyEncodable};
 use rustc_type_ir::ConstKind as IrConstKind;
-use rustc_type_ir::{ConstTy, IntoKind, TypeFlags, WithCachedTypeInfo};
+use rustc_type_ir::{TypeFlags, WithCachedTypeInfo};
 
 mod int;
 mod kind;
@@ -30,7 +30,7 @@ rustc_data_structures::static_assert_size!(ConstKind<'_>, 32);
 #[rustc_pass_by_value]
 pub struct Const<'tcx>(pub(super) Interned<'tcx, WithCachedTypeInfo<ConstData<'tcx>>>);
 
-impl<'tcx> IntoKind for Const<'tcx> {
+impl<'tcx> rustc_type_ir::inherent::IntoKind for Const<'tcx> {
     type Kind = ConstKind<'tcx>;
 
     fn kind(self) -> ConstKind<'tcx> {
@@ -48,12 +48,6 @@ impl<'tcx> rustc_type_ir::visit::Flags for Const<'tcx> {
     }
 }
 
-impl<'tcx> ConstTy<TyCtxt<'tcx>> for Const<'tcx> {
-    fn ty(self) -> Ty<'tcx> {
-        self.ty()
-    }
-}
-
 /// Typed constant value.
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 #[derive(HashStable, TyEncodable, TyDecodable)]
@@ -180,7 +174,7 @@ impl<'tcx> Const<'tcx> {
     }
 }
 
-impl<'tcx> rustc_type_ir::new::Const<TyCtxt<'tcx>> for Const<'tcx> {
+impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> {
     fn new_anon_bound(
         tcx: TyCtxt<'tcx>,
         debruijn: ty::DebruijnIndex,
@@ -189,6 +183,10 @@ impl<'tcx> rustc_type_ir::new::Const<TyCtxt<'tcx>> for Const<'tcx> {
     ) -> Self {
         Const::new_bound(tcx, debruijn, var, ty)
     }
+
+    fn ty(self) -> Ty<'tcx> {
+        self.ty()
+    }
 }
 
 impl<'tcx> Const<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index d2eacdf762f..0464be2df06 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -4,6 +4,8 @@
 
 pub mod tls;
 
+pub use rustc_type_ir::lift::Lift;
+
 use crate::arena::Arena;
 use crate::dep_graph::{DepGraph, DepKindStruct};
 use crate::infer::canonical::{CanonicalParamEnvCache, CanonicalVarInfo, CanonicalVarInfos};
@@ -138,6 +140,19 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
     fn mk_canonical_var_infos(self, infos: &[ty::CanonicalVarInfo<Self>]) -> Self::CanonicalVars {
         self.mk_canonical_var_infos(infos)
     }
+
+    type GenericsOf = &'tcx ty::Generics;
+    fn generics_of(self, def_id: DefId) -> &'tcx ty::Generics {
+        self.generics_of(def_id)
+    }
+
+    fn check_and_mk_args(
+        self,
+        def_id: DefId,
+        args: impl IntoIterator<Item: Into<ty::GenericArg<'tcx>>>,
+    ) -> ty::GenericArgsRef<'tcx> {
+        self.check_and_mk_args(def_id, args)
+    }
 }
 
 type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>;
@@ -917,7 +932,7 @@ impl<'tcx> TyCtxt<'tcx> {
         )
     }
 
-    pub fn lift<T: Lift<'tcx>>(self, value: T) -> Option<T::Lifted> {
+    pub fn lift<T: Lift<TyCtxt<'tcx>>>(self, value: T) -> Option<T::Lifted> {
         value.lift_to_tcx(self)
     }
 
@@ -1524,31 +1539,9 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 }
 
-/// A trait implemented for all `X<'a>` types that can be safely and
-/// efficiently converted to `X<'tcx>` as long as they are part of the
-/// provided `TyCtxt<'tcx>`.
-/// This can be done, for example, for `Ty<'tcx>` or `GenericArgsRef<'tcx>`
-/// by looking them up in their respective interners.
-///
-/// However, this is still not the best implementation as it does
-/// need to compare the components, even for interned values.
-/// It would be more efficient if `TypedArena` provided a way to
-/// determine whether the address is in the allocated range.
-///
-/// `None` is returned if the value or one of the components is not part
-/// of the provided context.
-/// For `Ty`, `None` can be returned if either the type interner doesn't
-/// contain the `TyKind` key or if the address of the interned
-/// pointer differs. The latter case is possible if a primitive type,
-/// e.g., `()` or `u8`, was interned in a different context.
-pub trait Lift<'tcx>: fmt::Debug {
-    type Lifted: fmt::Debug + 'tcx;
-    fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted>;
-}
-
 macro_rules! nop_lift {
     ($set:ident; $ty:ty => $lifted:ty) => {
-        impl<'a, 'tcx> Lift<'tcx> for $ty {
+        impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for $ty {
             type Lifted = $lifted;
             fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
                 // Assert that the set has the right type.
@@ -1583,7 +1576,7 @@ macro_rules! nop_lift {
 
 macro_rules! nop_list_lift {
     ($set:ident; $ty:ty => $lifted:ty) => {
-        impl<'a, 'tcx> Lift<'tcx> for &'a List<$ty> {
+        impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for &'a List<$ty> {
             type Lifted = &'tcx List<$lifted>;
             fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
                 // Assert that the set has the right type.
@@ -1621,7 +1614,7 @@ nop_list_lift! {args; GenericArg<'a> => GenericArg<'tcx>}
 
 macro_rules! nop_slice_lift {
     ($ty:ty => $lifted:ty) => {
-        impl<'a, 'tcx> Lift<'tcx> for &'a [$ty] {
+        impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for &'a [$ty] {
             type Lifted = &'tcx [$lifted];
             fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
                 if self.is_empty() {
@@ -2060,7 +2053,7 @@ impl<'tcx> TyCtxt<'tcx> {
             && let DefKind::AssocTy = self.def_kind(def_id)
             && let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(def_id))
         {
-            if generics.params.len() + 1 != args.len() {
+            if generics.own_params.len() + 1 != args.len() {
                 return false;
             }
 
@@ -2085,7 +2078,7 @@ impl<'tcx> TyCtxt<'tcx> {
             own_args
         };
 
-        for (param, arg) in std::iter::zip(&generics.params, own_args) {
+        for (param, arg) in std::iter::zip(&generics.own_params, own_args) {
             match (&param.kind, arg.unpack()) {
                 (ty::GenericParamDefKind::Type { .. }, ty::GenericArgKind::Type(_))
                 | (ty::GenericParamDefKind::Lifetime, ty::GenericArgKind::Lifetime(_))
@@ -2331,7 +2324,7 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn mk_args_from_iter<I, T>(self, iter: I) -> T::Output
     where
         I: Iterator<Item = T>,
-        T: CollectAndApply<GenericArg<'tcx>, &'tcx List<GenericArg<'tcx>>>,
+        T: CollectAndApply<GenericArg<'tcx>, ty::GenericArgsRef<'tcx>>,
     {
         T::collect_and_apply(iter, |xs| self.mk_args(xs))
     }
@@ -2449,7 +2442,7 @@ impl<'tcx> TyCtxt<'tcx> {
                     span,
                     msg,
                     format!("#![feature({feature})]\n"),
-                    Applicability::MachineApplicable,
+                    Applicability::MaybeIncorrect,
                 );
             } else {
                 diag.help(msg);
diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs
index de2c01c3046..904c0c332a8 100644
--- a/compiler/rustc_middle/src/ty/generic_args.rs
+++ b/compiler/rustc_middle/src/ty/generic_args.rs
@@ -39,6 +39,16 @@ pub struct GenericArg<'tcx> {
     marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>)>,
 }
 
+impl<'tcx> rustc_type_ir::inherent::GenericArgs<TyCtxt<'tcx>> for ty::GenericArgsRef<'tcx> {
+    fn type_at(self, i: usize) -> Ty<'tcx> {
+        self.type_at(i)
+    }
+
+    fn identity_for_item(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::GenericArgsRef<'tcx> {
+        GenericArgs::identity_for_item(tcx, def_id)
+    }
+}
+
 #[cfg(parallel_compiler)]
 unsafe impl<'tcx> rustc_data_structures::sync::DynSend for GenericArg<'tcx> where
     &'tcx (Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>): rustc_data_structures::sync::DynSend
@@ -205,7 +215,7 @@ impl<'tcx> GenericArg<'tcx> {
     }
 }
 
-impl<'a, 'tcx> Lift<'tcx> for GenericArg<'a> {
+impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for GenericArg<'a> {
     type Lifted = GenericArg<'tcx>;
 
     fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
@@ -359,8 +369,8 @@ impl<'tcx> GenericArgs<'tcx> {
     ) where
         F: FnMut(&ty::GenericParamDef, &[GenericArg<'tcx>]) -> GenericArg<'tcx>,
     {
-        args.reserve(defs.params.len());
-        for param in &defs.params {
+        args.reserve(defs.own_params.len());
+        for param in &defs.own_params {
             let kind = mk_kind(param, args);
             assert_eq!(param.index as usize, args.len(), "{args:#?}, {defs:#?}");
             args.push(kind);
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index 6bf2051d67c..04655c5d20b 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -132,7 +132,7 @@ pub struct GenericParamCount {
 pub struct Generics {
     pub parent: Option<DefId>,
     pub parent_count: usize,
-    pub params: Vec<GenericParamDef>,
+    pub own_params: Vec<GenericParamDef>,
 
     /// Reverse map to the `index` field of each `GenericParamDef`.
     #[stable_hasher(ignore)]
@@ -145,6 +145,12 @@ pub struct Generics {
     pub host_effect_index: Option<usize>,
 }
 
+impl<'tcx> rustc_type_ir::inherent::GenericsOf<TyCtxt<'tcx>> for &'tcx Generics {
+    fn count(&self) -> usize {
+        self.parent_count + self.own_params.len()
+    }
+}
+
 impl<'tcx> Generics {
     /// Looks through the generics and all parents to find the index of the
     /// given param def-id. This is in comparison to the `param_def_id_to_index`
@@ -163,7 +169,7 @@ impl<'tcx> Generics {
 
     #[inline]
     pub fn count(&self) -> usize {
-        self.parent_count + self.params.len()
+        self.parent_count + self.own_params.len()
     }
 
     pub fn own_counts(&self) -> GenericParamCount {
@@ -172,7 +178,7 @@ impl<'tcx> Generics {
         // presence of this method will be a constant reminder.
         let mut own_counts = GenericParamCount::default();
 
-        for param in &self.params {
+        for param in &self.own_params {
             match param.kind {
                 GenericParamDefKind::Lifetime => own_counts.lifetimes += 1,
                 GenericParamDefKind::Type { .. } => own_counts.types += 1,
@@ -186,7 +192,7 @@ impl<'tcx> Generics {
     pub fn own_defaults(&self) -> GenericParamCount {
         let mut own_defaults = GenericParamCount::default();
 
-        for param in &self.params {
+        for param in &self.own_params {
             match param.kind {
                 GenericParamDefKind::Lifetime => (),
                 GenericParamDefKind::Type { has_default, .. } => {
@@ -215,7 +221,7 @@ impl<'tcx> Generics {
     }
 
     pub fn own_requires_monomorphization(&self) -> bool {
-        for param in &self.params {
+        for param in &self.own_params {
             match param.kind {
                 GenericParamDefKind::Type { .. }
                 | GenericParamDefKind::Const { is_host_effect: false, .. } => {
@@ -231,7 +237,7 @@ impl<'tcx> Generics {
     /// Returns the `GenericParamDef` with the given index.
     pub fn param_at(&'tcx self, param_index: usize, tcx: TyCtxt<'tcx>) -> &'tcx GenericParamDef {
         if let Some(index) = param_index.checked_sub(self.parent_count) {
-            &self.params[index]
+            &self.own_params[index]
         } else {
             tcx.generics_of(self.parent.expect("parent_count > 0 but no parent?"))
                 .param_at(param_index, tcx)
@@ -245,7 +251,7 @@ impl<'tcx> Generics {
         tcx: TyCtxt<'tcx>,
     ) -> Option<&'tcx GenericParamDef> {
         if let Some(index) = param_index.checked_sub(self.parent_count) {
-            self.params.get(index)
+            self.own_params.get(index)
         } else {
             tcx.generics_of(self.parent.expect("parent_count > 0 but no parent?"))
                 .opt_param_at(param_index, tcx)
@@ -254,7 +260,7 @@ impl<'tcx> Generics {
 
     pub fn params_to(&'tcx self, param_index: usize, tcx: TyCtxt<'tcx>) -> &'tcx [GenericParamDef] {
         if let Some(index) = param_index.checked_sub(self.parent_count) {
-            &self.params[..index]
+            &self.own_params[..index]
         } else {
             tcx.generics_of(self.parent.expect("parent_count > 0 but no parent?"))
                 .params_to(param_index, tcx)
@@ -308,7 +314,7 @@ impl<'tcx> Generics {
 
     /// Returns `true` if `params` has `impl Trait`.
     pub fn has_impl_trait(&'tcx self) -> bool {
-        self.params.iter().any(|param| {
+        self.own_params.iter().any(|param| {
             matches!(param.kind, ty::GenericParamDefKind::Type { synthetic: true, .. })
         })
     }
@@ -336,7 +342,7 @@ impl<'tcx> Generics {
         // good enough for now as this should only be used
         // for diagnostics anyways.
         own_params.end -= self
-            .params
+            .own_params
             .iter()
             .rev()
             .take_while(|param| {
@@ -358,7 +364,7 @@ impl<'tcx> Generics {
         &'tcx self,
         args: &'tcx [ty::GenericArg<'tcx>],
     ) -> &'tcx [ty::GenericArg<'tcx>] {
-        let own = &args[self.parent_count..][..self.params.len()];
+        let own = &args[self.parent_count..][..self.own_params.len()];
         if self.has_self && self.parent.is_none() { &own[1..] } else { own }
     }
 
@@ -372,7 +378,7 @@ impl<'tcx> Generics {
         args: &'tcx [ty::GenericArg<'tcx>],
     ) -> bool {
         let mut default_param_seen = false;
-        for param in self.params.iter() {
+        for param in self.own_params.iter() {
             if let Some(inst) =
                 param.default_value(tcx).map(|default| default.instantiate(tcx, args))
             {
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index f8490e5e15f..cf701f837d8 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -114,16 +114,35 @@ impl Integer {
     }
 }
 
-#[extension(pub trait PrimitiveExt)]
-impl Primitive {
+#[extension(pub trait FloatExt)]
+impl Float {
     #[inline]
     fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
         match *self {
-            Int(i, signed) => i.to_ty(tcx, signed),
             F16 => tcx.types.f16,
             F32 => tcx.types.f32,
             F64 => tcx.types.f64,
             F128 => tcx.types.f128,
+        }
+    }
+
+    fn from_float_ty(fty: ty::FloatTy) -> Self {
+        match fty {
+            ty::FloatTy::F16 => F16,
+            ty::FloatTy::F32 => F32,
+            ty::FloatTy::F64 => F64,
+            ty::FloatTy::F128 => F128,
+        }
+    }
+}
+
+#[extension(pub trait PrimitiveExt)]
+impl Primitive {
+    #[inline]
+    fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
+        match *self {
+            Int(i, signed) => i.to_ty(tcx, signed),
+            Float(f) => f.to_ty(tcx),
             // FIXME(erikdesjardins): handle non-default addrspace ptr sizes
             Pointer(_) => Ty::new_mut_ptr(tcx, tcx.types.unit),
         }
@@ -140,7 +159,7 @@ impl Primitive {
                 let signed = false;
                 tcx.data_layout().ptr_sized_integer().to_ty(tcx, signed)
             }
-            F16 | F32 | F64 | F128 => bug!("floats do not have an int type"),
+            Float(_) => bug!("floats do not have an int type"),
         }
     }
 }
@@ -333,7 +352,23 @@ impl<'tcx> SizeSkeleton<'tcx> {
         match *ty.kind() {
             ty::Ref(_, pointee, _) | ty::RawPtr(pointee, _) => {
                 let non_zero = !ty.is_unsafe_ptr();
-                let tail = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
+
+                let tail = tcx.struct_tail_with_normalize(
+                    pointee,
+                    |ty| match tcx.try_normalize_erasing_regions(param_env, ty) {
+                        Ok(ty) => ty,
+                        Err(e) => Ty::new_error_with_message(
+                            tcx,
+                            DUMMY_SP,
+                            format!(
+                                "normalization failed for {} but no errors reported",
+                                e.get_type_for_failure()
+                            ),
+                        ),
+                    },
+                    || {},
+                );
+
                 match tail.kind() {
                     ty::Param(_) | ty::Alias(ty::Projection | ty::Inherent, _) => {
                         debug_assert!(tail.has_non_region_param());
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 73b20f0485b..12cefc23233 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -530,7 +530,7 @@ pub struct CReaderCacheKey {
 #[rustc_pass_by_value]
 pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>);
 
-impl<'tcx> IntoKind for Ty<'tcx> {
+impl<'tcx> rustc_type_ir::inherent::IntoKind for Ty<'tcx> {
     type Kind = TyKind<'tcx>;
 
     fn kind(self) -> TyKind<'tcx> {
@@ -981,7 +981,7 @@ pub struct Placeholder<T> {
 
 pub type PlaceholderRegion = Placeholder<BoundRegion>;
 
-impl PlaceholderLike for PlaceholderRegion {
+impl rustc_type_ir::inherent::PlaceholderLike for PlaceholderRegion {
     fn universe(self) -> UniverseIndex {
         self.universe
     }
@@ -1001,7 +1001,7 @@ impl PlaceholderLike for PlaceholderRegion {
 
 pub type PlaceholderType = Placeholder<BoundTy>;
 
-impl PlaceholderLike for PlaceholderType {
+impl rustc_type_ir::inherent::PlaceholderLike for PlaceholderType {
     fn universe(self) -> UniverseIndex {
         self.universe
     }
@@ -1028,7 +1028,7 @@ pub struct BoundConst<'tcx> {
 
 pub type PlaceholderConst = Placeholder<BoundVar>;
 
-impl PlaceholderLike for PlaceholderConst {
+impl rustc_type_ir::inherent::PlaceholderLike for PlaceholderConst {
     fn universe(self) -> UniverseIndex {
         self.universe
     }
diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
index 791f27a9789..115cf3eeb22 100644
--- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
+++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
@@ -100,8 +100,7 @@ impl<'tcx> TyCtxt<'tcx> {
     /// codegen, we need to normalize the contents.
     // FIXME(@lcnr): This method should not be necessary, we now normalize
     // inside of binders. We should be able to only use
-    // `tcx.instantiate_bound_regions_with_erased`. Same for the `try_X`
-    // variant.
+    // `tcx.instantiate_bound_regions_with_erased`.
     #[tracing::instrument(level = "debug", skip(self, param_env))]
     pub fn normalize_erasing_late_bound_regions<T>(
         self,
@@ -115,26 +114,6 @@ impl<'tcx> TyCtxt<'tcx> {
         self.normalize_erasing_regions(param_env, value)
     }
 
-    /// If you have a `Binder<'tcx, T>`, you can do this to strip out the
-    /// late-bound regions and then normalize the result, yielding up
-    /// a `T` (with regions erased). This is appropriate when the
-    /// binder is being instantiated at the call site.
-    ///
-    /// N.B., currently, higher-ranked type bounds inhibit
-    /// normalization. Therefore, each time we erase them in
-    /// codegen, we need to normalize the contents.
-    pub fn try_normalize_erasing_late_bound_regions<T>(
-        self,
-        param_env: ty::ParamEnv<'tcx>,
-        value: ty::Binder<'tcx, T>,
-    ) -> Result<T, NormalizationError<'tcx>>
-    where
-        T: TypeFoldable<TyCtxt<'tcx>>,
-    {
-        let value = self.instantiate_bound_regions_with_erased(value);
-        self.try_normalize_erasing_regions(param_env, value)
-    }
-
     /// Monomorphizes a type from the AST by first applying the
     /// in-scope instantiations and then normalizing any associated
     /// types.
diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs
index 56dd52567fd..5387036d409 100644
--- a/compiler/rustc_middle/src/ty/predicate.rs
+++ b/compiler/rustc_middle/src/ty/predicate.rs
@@ -2,19 +2,19 @@ use rustc_data_structures::captures::Captures;
 use rustc_data_structures::intern::Interned;
 use rustc_errors::{DiagArgValue, IntoDiagArg};
 use rustc_hir::def_id::DefId;
-use rustc_hir::LangItem;
 use rustc_macros::{HashStable, Lift, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
-use rustc_span::Span;
 use rustc_type_ir::ClauseKind as IrClauseKind;
 use rustc_type_ir::PredicateKind as IrPredicateKind;
+use rustc_type_ir::TraitRef as IrTraitRef;
 use std::cmp::Ordering;
 
 use crate::ty::visit::TypeVisitableExt;
 use crate::ty::{
-    self, AliasTy, Binder, DebruijnIndex, DebugWithInfcx, EarlyBinder, GenericArg, GenericArgs,
-    GenericArgsRef, PredicatePolarity, Term, Ty, TyCtxt, TypeFlags, WithCachedTypeInfo,
+    self, AliasTy, Binder, DebruijnIndex, DebugWithInfcx, EarlyBinder, GenericArgsRef,
+    PredicatePolarity, Term, Ty, TyCtxt, TypeFlags, WithCachedTypeInfo,
 };
 
+pub type TraitRef<'tcx> = IrTraitRef<TyCtxt<'tcx>>;
 pub type ClauseKind<'tcx> = IrClauseKind<TyCtxt<'tcx>>;
 pub type PredicateKind<'tcx> = IrPredicateKind<TyCtxt<'tcx>>;
 
@@ -30,6 +30,8 @@ pub struct Predicate<'tcx>(
     pub(super) Interned<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>,
 );
 
+impl<'tcx> rustc_type_ir::inherent::Predicate<TyCtxt<'tcx>> for Predicate<'tcx> {}
+
 impl<'tcx> rustc_type_ir::visit::Flags for Predicate<'tcx> {
     fn flags(&self) -> TypeFlags {
         self.0.flags
@@ -250,7 +252,7 @@ impl<'tcx> PolyExistentialPredicate<'tcx> {
             }
             ExistentialPredicate::AutoTrait(did) => {
                 let generics = tcx.generics_of(did);
-                let trait_ref = if generics.params.len() == 1 {
+                let trait_ref = if generics.own_params.len() == 1 {
                     ty::TraitRef::new(tcx, did, [self_ty])
                 } else {
                     // If this is an ill-formed auto trait, then synthesize
@@ -326,76 +328,6 @@ impl<'tcx> ty::List<ty::PolyExistentialPredicate<'tcx>> {
     }
 }
 
-/// A complete reference to a trait. These take numerous guises in syntax,
-/// but perhaps the most recognizable form is in a where-clause:
-/// ```ignore (illustrative)
-/// T: Foo<U>
-/// ```
-/// This would be represented by a trait-reference where the `DefId` is the
-/// `DefId` for the trait `Foo` and the args define `T` as parameter 0,
-/// and `U` as parameter 1.
-///
-/// Trait references also appear in object types like `Foo<U>`, but in
-/// that case the `Self` parameter is absent from the generic parameters.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct TraitRef<'tcx> {
-    pub def_id: DefId,
-    pub args: GenericArgsRef<'tcx>,
-    /// This field exists to prevent the creation of `TraitRef` without
-    /// calling [`TraitRef::new`].
-    pub(super) _use_trait_ref_new_instead: (),
-}
-
-impl<'tcx> TraitRef<'tcx> {
-    pub fn new(
-        tcx: TyCtxt<'tcx>,
-        trait_def_id: DefId,
-        args: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
-    ) -> Self {
-        let args = tcx.check_and_mk_args(trait_def_id, args);
-        Self { def_id: trait_def_id, args, _use_trait_ref_new_instead: () }
-    }
-
-    pub fn from_lang_item(
-        tcx: TyCtxt<'tcx>,
-        trait_lang_item: LangItem,
-        span: Span,
-        args: impl IntoIterator<Item: Into<ty::GenericArg<'tcx>>>,
-    ) -> Self {
-        let trait_def_id = tcx.require_lang_item(trait_lang_item, Some(span));
-        Self::new(tcx, trait_def_id, args)
-    }
-
-    pub fn from_method(
-        tcx: TyCtxt<'tcx>,
-        trait_id: DefId,
-        args: GenericArgsRef<'tcx>,
-    ) -> ty::TraitRef<'tcx> {
-        let defs = tcx.generics_of(trait_id);
-        ty::TraitRef::new(tcx, trait_id, tcx.mk_args(&args[..defs.params.len()]))
-    }
-
-    /// Returns a `TraitRef` of the form `P0: Foo<P1..Pn>` where `Pi`
-    /// are the parameters defined on trait.
-    pub fn identity(tcx: TyCtxt<'tcx>, def_id: DefId) -> TraitRef<'tcx> {
-        ty::TraitRef::new(tcx, def_id, GenericArgs::identity_for_item(tcx, def_id))
-    }
-
-    pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
-        ty::TraitRef::new(
-            tcx,
-            self.def_id,
-            [self_ty.into()].into_iter().chain(self.args.iter().skip(1)),
-        )
-    }
-
-    #[inline]
-    pub fn self_ty(&self) -> Ty<'tcx> {
-        self.args.type_at(0)
-    }
-}
-
 pub type PolyTraitRef<'tcx> = ty::Binder<'tcx, TraitRef<'tcx>>;
 
 impl<'tcx> PolyTraitRef<'tcx> {
@@ -408,12 +340,6 @@ impl<'tcx> PolyTraitRef<'tcx> {
     }
 }
 
-impl<'tcx> IntoDiagArg for TraitRef<'tcx> {
-    fn into_diag_arg(self) -> DiagArgValue {
-        self.to_string().into_diag_arg()
-    }
-}
-
 /// An existential reference to a trait, where `Self` is erased.
 /// For example, the trait object `Trait<'a, 'b, X, Y>` is:
 /// ```ignore (illustrative)
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs
index 9d0e1123e43..e7589737d64 100644
--- a/compiler/rustc_middle/src/ty/print/mod.rs
+++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -1,6 +1,7 @@
 use crate::ty::GenericArg;
 use crate::ty::{self, Ty, TyCtxt};
 
+use hir::def::Namespace;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sso::SsoHashSet;
 use rustc_hir as hir;
@@ -11,6 +12,8 @@ use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
 mod pretty;
 pub use self::pretty::*;
 
+use super::Lift;
+
 pub type PrintError = std::fmt::Error;
 
 pub trait Print<'tcx, P> {
@@ -157,7 +160,7 @@ pub trait Printer<'tcx>: Sized {
                         // If we have any generic arguments to print, we do that
                         // on top of the same path, but without its own generics.
                         _ => {
-                            if !generics.params.is_empty() && args.len() >= generics.count() {
+                            if !generics.own_params.is_empty() && args.len() >= generics.count() {
                                 let args = generics.own_args_no_defaults(self.tcx(), args);
                                 return self.path_generic_args(
                                     |cx| cx.print_def_path(def_id, parent_args),
@@ -334,3 +337,21 @@ pub fn describe_as_module(def_id: impl Into<LocalDefId>, tcx: TyCtxt<'_>) -> Str
         format!("module `{}`", tcx.def_path_str(def_id))
     }
 }
+
+impl<T> rustc_type_ir::ir_print::IrPrint<T> for TyCtxt<'_>
+where
+    T: Copy + for<'a, 'tcx> Lift<TyCtxt<'tcx>, Lifted: Print<'tcx, FmtPrinter<'a, 'tcx>>>,
+{
+    fn print(t: &T, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        ty::tls::with(|tcx| {
+            let mut cx = FmtPrinter::new(tcx, Namespace::TypeNS);
+            tcx.lift(*t).expect("could not lift for printing").print(&mut cx)?;
+            fmt.write_str(&cx.into_buffer())?;
+            Ok(())
+        })
+    }
+
+    fn print_debug(t: &T, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        with_no_trimmed_paths!(Self::print(t, fmt))
+    }
+}
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 5f47aef0f32..14a628ab064 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -16,7 +16,7 @@ use rustc_hir::def::{self, CtorKind, DefKind, Namespace};
 use rustc_hir::def_id::{DefIdMap, DefIdSet, ModDefId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::definitions::{DefKey, DefPathDataName};
 use rustc_hir::LangItem;
-use rustc_macros::Lift;
+use rustc_macros::{extension, Lift};
 use rustc_session::cstore::{ExternCrate, ExternCrateSource};
 use rustc_session::Limit;
 use rustc_span::symbol::{kw, Ident, Symbol};
@@ -977,7 +977,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
     fn pretty_print_opaque_impl_type(
         &mut self,
         def_id: DefId,
-        args: &'tcx ty::List<ty::GenericArg<'tcx>>,
+        args: ty::GenericArgsRef<'tcx>,
     ) -> Result<(), PrintError> {
         let tcx = self.tcx();
 
@@ -2919,16 +2919,17 @@ impl<'tcx> fmt::Debug for TraitRefPrintOnlyTraitName<'tcx> {
     }
 }
 
+#[extension(pub trait PrintTraitRefExt<'tcx>)]
 impl<'tcx> ty::TraitRef<'tcx> {
-    pub fn print_only_trait_path(self) -> TraitRefPrintOnlyTraitPath<'tcx> {
+    fn print_only_trait_path(self) -> TraitRefPrintOnlyTraitPath<'tcx> {
         TraitRefPrintOnlyTraitPath(self)
     }
 
-    pub fn print_trait_sugared(self) -> TraitRefPrintSugared<'tcx> {
+    fn print_trait_sugared(self) -> TraitRefPrintSugared<'tcx> {
         TraitRefPrintSugared(self)
     }
 
-    pub fn print_only_trait_name(self) -> TraitRefPrintOnlyTraitName<'tcx> {
+    fn print_only_trait_name(self) -> TraitRefPrintOnlyTraitName<'tcx> {
         TraitRefPrintOnlyTraitName(self)
     }
 }
@@ -3032,6 +3033,10 @@ forward_display_to_print! {
 define_print! {
     (self, cx):
 
+    ty::TraitRef<'tcx> {
+        p!(write("<{} as {}>", self.self_ty(), self.print_only_trait_path()))
+    }
+
     ty::TypeAndMut<'tcx> {
         p!(write("{}", self.mutbl.prefix_str()), print(self.ty))
     }
@@ -3113,10 +3118,6 @@ define_print_and_forward_display! {
         p!("fn", pretty_fn_sig(self.inputs(), self.c_variadic, self.output()));
     }
 
-    ty::TraitRef<'tcx> {
-        p!(write("<{} as {}>", self.self_ty(), self.print_only_trait_path()))
-    }
-
     TraitRefPrintOnlyTraitPath<'tcx> {
         p!(print_def_path(self.0.def_id, self.0.args));
     }
diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs
index 3d9be15310f..8842ecd12e9 100644
--- a/compiler/rustc_middle/src/ty/region.rs
+++ b/compiler/rustc_middle/src/ty/region.rs
@@ -19,7 +19,7 @@ pub type RegionKind<'tcx> = IrRegionKind<TyCtxt<'tcx>>;
 #[rustc_pass_by_value]
 pub struct Region<'tcx>(pub Interned<'tcx, RegionKind<'tcx>>);
 
-impl<'tcx> rustc_type_ir::IntoKind for Region<'tcx> {
+impl<'tcx> rustc_type_ir::inherent::IntoKind for Region<'tcx> {
     type Kind = RegionKind<'tcx>;
 
     fn kind(self) -> RegionKind<'tcx> {
@@ -137,7 +137,7 @@ impl<'tcx> Region<'tcx> {
     }
 }
 
-impl<'tcx> rustc_type_ir::new::Region<TyCtxt<'tcx>> for Region<'tcx> {
+impl<'tcx> rustc_type_ir::inherent::Region<TyCtxt<'tcx>> for Region<'tcx> {
     fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self {
         Region::new_bound(tcx, debruijn, ty::BoundRegion { var, kind: ty::BoundRegionKind::BrAnon })
     }
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 14a77d4b37e..a7770f71926 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -132,12 +132,6 @@ impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::FnSig<'tcx> {
     }
 }
 
-impl<'tcx> fmt::Debug for ty::TraitRef<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        with_no_trimmed_paths!(fmt::Display::fmt(self, f))
-    }
-}
-
 impl<'tcx> ty::DebugWithInfcx<TyCtxt<'tcx>> for Ty<'tcx> {
     fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>(
         this: WithInfcx<'_, Infcx, &Self>,
@@ -478,7 +472,7 @@ TrivialTypeTraversalAndLiftImpls! {
 ///////////////////////////////////////////////////////////////////////////
 // Lift implementations
 
-impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for Option<T> {
+impl<'tcx, T: Lift<TyCtxt<'tcx>>> Lift<TyCtxt<'tcx>> for Option<T> {
     type Lifted = Option<T::Lifted>;
     fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
         Some(match self {
@@ -488,7 +482,7 @@ impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for Option<T> {
     }
 }
 
-impl<'a, 'tcx> Lift<'tcx> for Term<'a> {
+impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for Term<'a> {
     type Lifted = ty::Term<'tcx>;
     fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
         Some(
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index de70c4f7b65..a97244dda9a 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -942,7 +942,7 @@ where
     }
 }
 
-impl<'tcx, T> rustc_type_ir::BoundVars<TyCtxt<'tcx>> for ty::Binder<'tcx, T> {
+impl<'tcx, T> rustc_type_ir::inherent::BoundVars<TyCtxt<'tcx>> for ty::Binder<'tcx, T> {
     fn bound_vars(&self) -> &'tcx List<ty::BoundVariableKind> {
         self.bound_vars
     }
@@ -1812,7 +1812,7 @@ impl<'tcx> Ty<'tcx> {
     }
 }
 
-impl<'tcx> rustc_type_ir::new::Ty<TyCtxt<'tcx>> for Ty<'tcx> {
+impl<'tcx> rustc_type_ir::inherent::Ty<TyCtxt<'tcx>> for Ty<'tcx> {
     fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self {
         Ty::new_bound(tcx, debruijn, ty::BoundTy { var, kind: ty::BoundTyKind::Anon })
     }
@@ -2164,13 +2164,11 @@ impl<'tcx> Ty<'tcx> {
     ///
     /// The parameter `explicit` indicates if this is an *explicit* dereference.
     /// Some types -- notably unsafe ptrs -- can only be dereferenced explicitly.
-    pub fn builtin_deref(self, explicit: bool) -> Option<TypeAndMut<'tcx>> {
-        match self.kind() {
-            Adt(def, _) if def.is_box() => {
-                Some(TypeAndMut { ty: self.boxed_ty(), mutbl: hir::Mutability::Not })
-            }
-            Ref(_, ty, mutbl) => Some(TypeAndMut { ty: *ty, mutbl: *mutbl }),
-            RawPtr(ty, mutbl) if explicit => Some(TypeAndMut { ty: *ty, mutbl: *mutbl }),
+    pub fn builtin_deref(self, explicit: bool) -> Option<Ty<'tcx>> {
+        match *self.kind() {
+            Adt(def, _) if def.is_box() => Some(self.boxed_ty()),
+            Ref(_, ty, _) => Some(ty),
+            RawPtr(ty, _) if explicit => Some(ty),
             _ => None,
         }
     }
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index f5e973f85da..6ad4f492f74 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -2,7 +2,7 @@
 
 use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use crate::query::{IntoQueryParam, Providers};
-use crate::ty::layout::IntegerExt;
+use crate::ty::layout::{FloatExt, IntegerExt};
 use crate::ty::{
     self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
     TypeVisitableExt,
@@ -20,7 +20,7 @@ use rustc_index::bit_set::GrowableBitSet;
 use rustc_macros::{extension, HashStable, TyDecodable, TyEncodable};
 use rustc_session::Limit;
 use rustc_span::sym;
-use rustc_target::abi::{Integer, IntegerType, Primitive, Size};
+use rustc_target::abi::{Float, Integer, IntegerType, Size};
 use rustc_target::spec::abi::Abi;
 use smallvec::{smallvec, SmallVec};
 use std::{fmt, iter};
@@ -1145,8 +1145,7 @@ impl<'tcx> Ty<'tcx> {
             ty::Char => Size::from_bytes(4),
             ty::Int(ity) => Integer::from_int_ty(&tcx, ity).size(),
             ty::Uint(uty) => Integer::from_uint_ty(&tcx, uty).size(),
-            ty::Float(ty::FloatTy::F32) => Primitive::F32.size(&tcx),
-            ty::Float(ty::FloatTy::F64) => Primitive::F64.size(&tcx),
+            ty::Float(fty) => Float::from_float_ty(fty).size(),
             _ => bug!("non primitive type"),
         }
     }
diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs
index 5c17c0b3088..e3866b27cee 100644
--- a/compiler/rustc_middle/src/values.rs
+++ b/compiler/rustc_middle/src/values.rs
@@ -141,7 +141,7 @@ impl<'tcx> Value<TyCtxt<'tcx>> for &[ty::Variance] {
             && frame.query.dep_kind == dep_kinds::variances_of
             && let Some(def_id) = frame.query.def_id
         {
-            let n = tcx.generics_of(def_id).params.len();
+            let n = tcx.generics_of(def_id).own_params.len();
             vec![ty::Variance::Bivariant; n].leak()
         } else {
             span_bug!(
diff --git a/compiler/rustc_mir_build/src/build/coverageinfo.rs b/compiler/rustc_mir_build/src/build/coverageinfo.rs
index e2a5f97a847..ee9eeb62990 100644
--- a/compiler/rustc_mir_build/src/build/coverageinfo.rs
+++ b/compiler/rustc_mir_build/src/build/coverageinfo.rs
@@ -1,17 +1,18 @@
-mod mcdc;
 use std::assert_matches::assert_matches;
 use std::collections::hash_map::Entry;
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::mir::coverage::{BlockMarkerId, BranchSpan, CoverageKind};
 use rustc_middle::mir::{self, BasicBlock, SourceInfo, UnOp};
-use rustc_middle::thir::{ExprId, ExprKind, Thir};
+use rustc_middle::thir::{ExprId, ExprKind, Pat, Thir};
 use rustc_middle::ty::TyCtxt;
 use rustc_span::def_id::LocalDefId;
 
 use crate::build::coverageinfo::mcdc::MCDCInfoBuilder;
 use crate::build::{Builder, CFG};
 
+mod mcdc;
+
 pub(crate) struct BranchInfoBuilder {
     /// Maps condition expressions to their enclosing `!`, for better instrumentation.
     nots: FxHashMap<ExprId, NotInfo>,
@@ -155,7 +156,7 @@ impl BranchInfoBuilder {
     }
 }
 
-impl Builder<'_, '_> {
+impl<'tcx> Builder<'_, 'tcx> {
     /// If branch coverage is enabled, inject marker statements into `then_block`
     /// and `else_block`, and record their IDs in the table of branch spans.
     pub(crate) fn visit_coverage_branch_condition(
@@ -195,4 +196,23 @@ impl Builder<'_, '_> {
 
         branch_info.add_two_way_branch(&mut self.cfg, source_info, then_block, else_block);
     }
+
+    /// If branch coverage is enabled, inject marker statements into `true_block`
+    /// and `false_block`, and record their IDs in the table of branches.
+    ///
+    /// Used to instrument let-else and if-let (including let-chains) for branch coverage.
+    pub(crate) fn visit_coverage_conditional_let(
+        &mut self,
+        pattern: &Pat<'tcx>, // Pattern that has been matched when the true path is taken
+        true_block: BasicBlock,
+        false_block: BasicBlock,
+    ) {
+        // Bail out if branch coverage is not enabled for this function.
+        let Some(branch_info) = self.coverage_branch_info.as_mut() else { return };
+
+        // FIXME(#124144) This may need special handling when MC/DC is enabled.
+
+        let source_info = SourceInfo { span: pattern.span, scope: self.source_scope };
+        branch_info.add_two_way_branch(&mut self.cfg, source_info, true_block, false_block);
+    }
 }
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index bce15267759..7cf4fac731b 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -1016,6 +1016,9 @@ struct PatternExtraData<'tcx> {
 
     /// Types that must be asserted.
     ascriptions: Vec<Ascription<'tcx>>,
+
+    /// Whether this corresponds to a never pattern.
+    is_never: bool,
 }
 
 impl<'tcx> PatternExtraData<'tcx> {
@@ -1041,12 +1044,14 @@ impl<'tcx, 'pat> FlatPat<'pat, 'tcx> {
         pattern: &'pat Pat<'tcx>,
         cx: &mut Builder<'_, 'tcx>,
     ) -> Self {
+        let is_never = pattern.is_never_pattern();
         let mut flat_pat = FlatPat {
             match_pairs: vec![MatchPair::new(place, pattern, cx)],
             extra_data: PatternExtraData {
                 span: pattern.span,
                 bindings: Vec::new(),
                 ascriptions: Vec::new(),
+                is_never,
             },
         };
         cx.simplify_match_pairs(&mut flat_pat.match_pairs, &mut flat_pat.extra_data);
@@ -1062,6 +1067,8 @@ struct Candidate<'pat, 'tcx> {
     match_pairs: Vec<MatchPair<'pat, 'tcx>>,
 
     /// ...and if this is non-empty, one of these subcandidates also has to match...
+    // Invariant: at the end of the algorithm, this must never contain a `is_never` candidate
+    // because that would break binding consistency.
     subcandidates: Vec<Candidate<'pat, 'tcx>>,
 
     /// ...and the guard must be evaluated if there is one.
@@ -1172,6 +1179,7 @@ enum TestCase<'pat, 'tcx> {
     Range(&'pat PatRange<'tcx>),
     Slice { len: usize, variable_length: bool },
     Deref { temp: Place<'tcx>, mutability: Mutability },
+    Never,
     Or { pats: Box<[FlatPat<'pat, 'tcx>]> },
 }
 
@@ -1238,6 +1246,9 @@ enum TestKind<'tcx> {
         temp: Place<'tcx>,
         mutability: Mutability,
     },
+
+    /// Assert unreachability of never patterns.
+    Never,
 }
 
 /// A test to perform to determine which [`Candidate`] matches a value.
@@ -1662,6 +1673,27 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 self.cfg.goto(or_block, source_info, any_matches);
             }
             candidate.pre_binding_block = Some(any_matches);
+        } else {
+            // Never subcandidates may have a set of bindings inconsistent with their siblings,
+            // which would break later code. So we filter them out. Note that we can't filter out
+            // top-level candidates this way.
+            candidate.subcandidates.retain_mut(|candidate| {
+                if candidate.extra_data.is_never {
+                    candidate.visit_leaves(|subcandidate| {
+                        let block = subcandidate.pre_binding_block.unwrap();
+                        // That block is already unreachable but needs a terminator to make the MIR well-formed.
+                        let source_info = self.source_info(subcandidate.extra_data.span);
+                        self.cfg.terminate(block, source_info, TerminatorKind::Unreachable);
+                    });
+                    false
+                } else {
+                    true
+                }
+            });
+            if candidate.subcandidates.is_empty() {
+                // If `candidate` has become a leaf candidate, ensure it has a `pre_binding_block`.
+                candidate.pre_binding_block = Some(self.cfg.start_new_block());
+            }
         }
     }
 
@@ -1968,6 +2000,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             false,
         );
 
+        // If branch coverage is enabled, record this branch.
+        self.visit_coverage_conditional_let(pat, post_guard_block, otherwise_post_guard_block);
+
         post_guard_block.unit()
     }
 
@@ -2008,6 +2043,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             block = fresh_block;
         }
 
+        if candidate.extra_data.is_never {
+            // This arm has a dummy body, we don't need to generate code for it. `block` is already
+            // unreachable (except via false edge).
+            let source_info = self.source_info(candidate.extra_data.span);
+            self.cfg.terminate(block, source_info, TerminatorKind::Unreachable);
+            return self.cfg.start_new_block();
+        }
+
         self.ascribe_types(
             block,
             parent_data
@@ -2452,6 +2495,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 None,
                 true,
             );
+
+            // If branch coverage is enabled, record this branch.
+            this.visit_coverage_conditional_let(pattern, matching, failure);
+
             this.break_for_else(failure, this.source_info(initializer_span));
             matching.unit()
         });
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index 5dd478aa422..7f65697fa4b 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -44,6 +44,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
             TestCase::Deref { temp, mutability } => TestKind::Deref { temp, mutability },
 
+            TestCase::Never => TestKind::Never,
+
             TestCase::Or { .. } => bug!("or-patterns should have already been handled"),
 
             TestCase::Irrefutable { .. } => span_bug!(
@@ -262,6 +264,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 let target = target_block(TestBranch::Success);
                 self.call_deref(block, target, place, mutability, ty, temp, test.span);
             }
+
+            TestKind::Never => {
+                // Check that the place is initialized.
+                // FIXME(never_patterns): Also assert validity of the data at `place`.
+                self.cfg.push_fake_read(
+                    block,
+                    source_info,
+                    FakeReadCause::ForMatchedPlace(None),
+                    place,
+                );
+                // A never pattern is only allowed on an uninhabited type, so validity of the data
+                // implies unreachability.
+                self.cfg.terminate(block, source_info, TerminatorKind::Unreachable);
+            }
         }
     }
 
@@ -710,6 +726,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 Some(TestBranch::Success)
             }
 
+            (TestKind::Never, _) => {
+                fully_matched = true;
+                Some(TestBranch::Success)
+            }
+
             (
                 TestKind::Switch { .. }
                 | TestKind::SwitchInt { .. }
diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs
index 2f9390c22a8..14c74c761eb 100644
--- a/compiler/rustc_mir_build/src/build/matches/util.rs
+++ b/compiler/rustc_mir_build/src/build/matches/util.rs
@@ -2,7 +2,6 @@ use crate::build::expr::as_place::{PlaceBase, PlaceBuilder};
 use crate::build::matches::{Binding, Candidate, FlatPat, MatchPair, TestCase};
 use crate::build::Builder;
 use rustc_data_structures::fx::FxIndexMap;
-use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_middle::mir::*;
 use rustc_middle::thir::{self, *};
 use rustc_middle::ty::TypeVisitableExt;
@@ -124,7 +123,8 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
         let default_irrefutable = || TestCase::Irrefutable { binding: None, ascription: None };
         let mut subpairs = Vec::new();
         let test_case = match pattern.kind {
-            PatKind::Never | PatKind::Wild | PatKind::Error(_) => default_irrefutable(),
+            PatKind::Wild | PatKind::Error(_) => default_irrefutable(),
+
             PatKind::Or { ref pats } => TestCase::Or {
                 pats: pats.iter().map(|pat| FlatPat::new(place_builder.clone(), pat, cx)).collect(),
             },
@@ -179,9 +179,7 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
                         cx.tcx,
                         ty::InlineConstArgsParts {
                             parent_args: ty::GenericArgs::identity_for_item(cx.tcx, parent_id),
-                            ty: cx
-                                .infcx
-                                .next_ty_var(TypeVariableOrigin { param_def_id: None, span }),
+                            ty: cx.infcx.next_ty_var(span),
                         },
                     )
                     .args;
@@ -260,6 +258,8 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
                 subpairs.push(MatchPair::new(PlaceBuilder::from(temp).deref(), subpattern, cx));
                 TestCase::Deref { temp, mutability }
             }
+
+            PatKind::Never => TestCase::Never,
         };
 
         MatchPair { place, test_case, subpairs, pattern }
diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs
index 0af88729887..5199c41c58c 100644
--- a/compiler/rustc_mir_transform/src/check_alignment.rs
+++ b/compiler/rustc_mir_transform/src/check_alignment.rs
@@ -106,7 +106,7 @@ impl<'tcx, 'a> Visitor<'tcx> for PointerFinder<'tcx, 'a> {
         }
 
         let pointee_ty =
-            pointer_ty.builtin_deref(true).expect("no builtin_deref for an unsafe pointer").ty;
+            pointer_ty.builtin_deref(true).expect("no builtin_deref for an unsafe pointer");
         // Ideally we'd support this in the future, but for now we are limited to sized types.
         if !pointee_ty.is_sized(self.tcx, self.param_env) {
             debug!("Unsafe pointer, but pointee is not known to be sized: {:?}", pointer_ty);
diff --git a/compiler/rustc_mir_transform/src/coverage/mappings.rs b/compiler/rustc_mir_transform/src/coverage/mappings.rs
index d364658efb6..61aabea1d8b 100644
--- a/compiler/rustc_mir_transform/src/coverage/mappings.rs
+++ b/compiler/rustc_mir_transform/src/coverage/mappings.rs
@@ -2,9 +2,8 @@ use std::collections::BTreeSet;
 
 use rustc_data_structures::graph::DirectedGraph;
 use rustc_index::bit_set::BitSet;
-use rustc_middle::mir::coverage::{
-    BlockMarkerId, BranchSpan, ConditionInfo, CoverageKind, MCDCBranchSpan, MCDCDecisionSpan,
-};
+use rustc_index::IndexVec;
+use rustc_middle::mir::coverage::{BlockMarkerId, BranchSpan, ConditionInfo, CoverageKind};
 use rustc_middle::mir::{self, BasicBlock, StatementKind};
 use rustc_span::Span;
 
@@ -13,127 +12,144 @@ use crate::coverage::spans::{
     extract_refined_covspans, unexpand_into_body_span_with_visible_macro,
 };
 use crate::coverage::ExtractedHirInfo;
-use rustc_index::IndexVec;
-
-#[derive(Clone, Debug)]
-pub(super) enum BcbMappingKind {
-    /// Associates an ordinary executable code span with its corresponding BCB.
-    Code(BasicCoverageBlock),
-
-    // Ordinary branch mappings are stored separately, so they don't have a
-    // variant in this enum.
-    //
-    /// Associates a mcdc branch span with condition info besides fields for normal branch.
-    MCDCBranch {
-        true_bcb: BasicCoverageBlock,
-        false_bcb: BasicCoverageBlock,
-        /// If `None`, this actually represents a normal branch mapping inserted
-        /// for code that was too complex for MC/DC.
-        condition_info: Option<ConditionInfo>,
-        decision_depth: u16,
-    },
-    /// Associates a mcdc decision with its join BCB.
-    MCDCDecision {
-        end_bcbs: BTreeSet<BasicCoverageBlock>,
-        bitmap_idx: u32,
-        conditions_num: u16,
-        decision_depth: u16,
-    },
-}
 
+/// Associates an ordinary executable code span with its corresponding BCB.
 #[derive(Debug)]
-pub(super) struct BcbMapping {
-    pub(super) kind: BcbMappingKind,
+pub(super) struct CodeMapping {
     pub(super) span: Span,
+    pub(super) bcb: BasicCoverageBlock,
 }
 
-/// This is separate from [`BcbMappingKind`] to help prepare for larger changes
+/// This is separate from [`MCDCBranch`] to help prepare for larger changes
 /// that will be needed for improved branch coverage in the future.
 /// (See <https://github.com/rust-lang/rust/pull/124217>.)
 #[derive(Debug)]
-pub(super) struct BcbBranchPair {
+pub(super) struct BranchPair {
     pub(super) span: Span,
     pub(super) true_bcb: BasicCoverageBlock,
     pub(super) false_bcb: BasicCoverageBlock,
 }
 
-pub(super) struct CoverageSpans {
-    bcb_has_mappings: BitSet<BasicCoverageBlock>,
-    pub(super) mappings: Vec<BcbMapping>,
-    pub(super) branch_pairs: Vec<BcbBranchPair>,
-    test_vector_bitmap_bytes: u32,
+/// Associates an MC/DC branch span with condition info besides fields for normal branch.
+#[derive(Debug)]
+pub(super) struct MCDCBranch {
+    pub(super) span: Span,
+    pub(super) true_bcb: BasicCoverageBlock,
+    pub(super) false_bcb: BasicCoverageBlock,
+    /// If `None`, this actually represents a normal branch mapping inserted
+    /// for code that was too complex for MC/DC.
+    pub(super) condition_info: Option<ConditionInfo>,
+    pub(super) decision_depth: u16,
 }
 
-impl CoverageSpans {
-    pub(super) fn bcb_has_coverage_spans(&self, bcb: BasicCoverageBlock) -> bool {
-        self.bcb_has_mappings.contains(bcb)
-    }
+/// Associates an MC/DC decision with its join BCBs.
+#[derive(Debug)]
+pub(super) struct MCDCDecision {
+    pub(super) span: Span,
+    pub(super) end_bcbs: BTreeSet<BasicCoverageBlock>,
+    pub(super) bitmap_idx: u32,
+    pub(super) conditions_num: u16,
+    pub(super) decision_depth: u16,
+}
 
-    pub(super) fn test_vector_bitmap_bytes(&self) -> u32 {
-        self.test_vector_bitmap_bytes
-    }
+#[derive(Default)]
+pub(super) struct ExtractedMappings {
+    pub(super) code_mappings: Vec<CodeMapping>,
+    pub(super) branch_pairs: Vec<BranchPair>,
+    pub(super) mcdc_bitmap_bytes: u32,
+    pub(super) mcdc_branches: Vec<MCDCBranch>,
+    pub(super) mcdc_decisions: Vec<MCDCDecision>,
 }
 
 /// Extracts coverage-relevant spans from MIR, and associates them with
 /// their corresponding BCBs.
-///
-/// Returns `None` if no coverage-relevant spans could be extracted.
-pub(super) fn generate_coverage_spans(
+pub(super) fn extract_all_mapping_info_from_mir(
     mir_body: &mir::Body<'_>,
     hir_info: &ExtractedHirInfo,
     basic_coverage_blocks: &CoverageGraph,
-) -> Option<CoverageSpans> {
-    let mut mappings = vec![];
-    let mut branch_pairs = vec![];
-
+) -> ExtractedMappings {
     if hir_info.is_async_fn {
         // An async function desugars into a function that returns a future,
         // with the user code wrapped in a closure. Any spans in the desugared
         // outer function will be unhelpful, so just keep the signature span
         // and ignore all of the spans in the MIR body.
+        let mut mappings = ExtractedMappings::default();
         if let Some(span) = hir_info.fn_sig_span_extended {
-            mappings.push(BcbMapping { kind: BcbMappingKind::Code(START_BCB), span });
+            mappings.code_mappings.push(CodeMapping { span, bcb: START_BCB });
         }
-    } else {
-        extract_refined_covspans(mir_body, hir_info, basic_coverage_blocks, &mut mappings);
+        return mappings;
+    }
 
-        branch_pairs.extend(extract_branch_pairs(mir_body, hir_info, basic_coverage_blocks));
+    let mut code_mappings = vec![];
+    let mut branch_pairs = vec![];
+    let mut mcdc_bitmap_bytes = 0;
+    let mut mcdc_branches = vec![];
+    let mut mcdc_decisions = vec![];
 
-        mappings.extend(extract_mcdc_mappings(mir_body, hir_info.body_span, basic_coverage_blocks));
-    }
+    extract_refined_covspans(mir_body, hir_info, basic_coverage_blocks, &mut code_mappings);
+
+    branch_pairs.extend(extract_branch_pairs(mir_body, hir_info, basic_coverage_blocks));
+
+    extract_mcdc_mappings(
+        mir_body,
+        hir_info.body_span,
+        basic_coverage_blocks,
+        &mut mcdc_bitmap_bytes,
+        &mut mcdc_branches,
+        &mut mcdc_decisions,
+    );
 
-    if mappings.is_empty() && branch_pairs.is_empty() {
-        return None;
+    ExtractedMappings {
+        code_mappings,
+        branch_pairs,
+        mcdc_bitmap_bytes,
+        mcdc_branches,
+        mcdc_decisions,
     }
+}
 
-    // Identify which BCBs have one or more mappings.
-    let mut bcb_has_mappings = BitSet::new_empty(basic_coverage_blocks.num_nodes());
-    let mut insert = |bcb| {
-        bcb_has_mappings.insert(bcb);
-    };
-    let mut test_vector_bitmap_bytes = 0;
-    for BcbMapping { kind, span: _ } in &mappings {
-        match *kind {
-            BcbMappingKind::Code(bcb) => insert(bcb),
-            BcbMappingKind::MCDCBranch { true_bcb, false_bcb, .. } => {
-                insert(true_bcb);
-                insert(false_bcb);
-            }
-            BcbMappingKind::MCDCDecision { bitmap_idx, conditions_num, .. } => {
-                // `bcb_has_mappings` is used for inject coverage counters
-                // but they are not needed for decision BCBs.
-                // While the length of test vector bitmap should be calculated here.
-                test_vector_bitmap_bytes = test_vector_bitmap_bytes
-                    .max(bitmap_idx + (1_u32 << conditions_num as u32).div_ceil(8));
-            }
+impl ExtractedMappings {
+    pub(super) fn all_bcbs_with_counter_mappings(
+        &self,
+        basic_coverage_blocks: &CoverageGraph, // Only used for allocating a correctly-sized set
+    ) -> BitSet<BasicCoverageBlock> {
+        // Fully destructure self to make sure we don't miss any fields that have mappings.
+        let Self {
+            code_mappings,
+            branch_pairs,
+            mcdc_bitmap_bytes: _,
+            mcdc_branches,
+            mcdc_decisions,
+        } = self;
+
+        // Identify which BCBs have one or more mappings.
+        let mut bcbs_with_counter_mappings = BitSet::new_empty(basic_coverage_blocks.num_nodes());
+        let mut insert = |bcb| {
+            bcbs_with_counter_mappings.insert(bcb);
+        };
+
+        for &CodeMapping { span: _, bcb } in code_mappings {
+            insert(bcb);
+        }
+        for &BranchPair { true_bcb, false_bcb, .. } in branch_pairs {
+            insert(true_bcb);
+            insert(false_bcb);
+        }
+        for &MCDCBranch { true_bcb, false_bcb, .. } in mcdc_branches {
+            insert(true_bcb);
+            insert(false_bcb);
+        }
+
+        // MC/DC decisions refer to BCBs, but don't require those BCBs to have counters.
+        if bcbs_with_counter_mappings.is_empty() {
+            debug_assert!(
+                mcdc_decisions.is_empty(),
+                "A function with no counter mappings shouldn't have any decisions: {mcdc_decisions:?}",
+            );
         }
-    }
-    for &BcbBranchPair { true_bcb, false_bcb, .. } in &branch_pairs {
-        insert(true_bcb);
-        insert(false_bcb);
-    }
 
-    Some(CoverageSpans { bcb_has_mappings, mappings, branch_pairs, test_vector_bitmap_bytes })
+        bcbs_with_counter_mappings
+    }
 }
 
 fn resolve_block_markers(
@@ -167,7 +183,7 @@ pub(super) fn extract_branch_pairs(
     mir_body: &mir::Body<'_>,
     hir_info: &ExtractedHirInfo,
     basic_coverage_blocks: &CoverageGraph,
-) -> Vec<BcbBranchPair> {
+) -> Vec<BranchPair> {
     let Some(branch_info) = mir_body.coverage_branch_info.as_deref() else { return vec![] };
 
     let block_markers = resolve_block_markers(branch_info, mir_body);
@@ -190,7 +206,7 @@ pub(super) fn extract_branch_pairs(
             let true_bcb = bcb_from_marker(true_marker)?;
             let false_bcb = bcb_from_marker(false_marker)?;
 
-            Some(BcbBranchPair { span, true_bcb, false_bcb })
+            Some(BranchPair { span, true_bcb, false_bcb })
         })
         .collect::<Vec<_>>()
 }
@@ -199,10 +215,11 @@ pub(super) fn extract_mcdc_mappings(
     mir_body: &mir::Body<'_>,
     body_span: Span,
     basic_coverage_blocks: &CoverageGraph,
-) -> Vec<BcbMapping> {
-    let Some(branch_info) = mir_body.coverage_branch_info.as_deref() else {
-        return vec![];
-    };
+    mcdc_bitmap_bytes: &mut u32,
+    mcdc_branches: &mut impl Extend<MCDCBranch>,
+    mcdc_decisions: &mut impl Extend<MCDCDecision>,
+) {
+    let Some(branch_info) = mir_body.coverage_branch_info.as_deref() else { return };
 
     let block_markers = resolve_block_markers(branch_info, mir_body);
 
@@ -223,53 +240,43 @@ pub(super) fn extract_mcdc_mappings(
             Some((span, true_bcb, false_bcb))
         };
 
-    let mcdc_branch_filter_map = |&MCDCBranchSpan {
-                                      span: raw_span,
-                                      true_marker,
-                                      false_marker,
-                                      condition_info,
-                                      decision_depth,
-                                  }| {
-        check_branch_bcb(raw_span, true_marker, false_marker).map(|(span, true_bcb, false_bcb)| {
-            BcbMapping {
-                kind: BcbMappingKind::MCDCBranch {
-                    true_bcb,
-                    false_bcb,
-                    condition_info,
-                    decision_depth,
-                },
+    mcdc_branches.extend(branch_info.mcdc_branch_spans.iter().filter_map(
+        |&mir::coverage::MCDCBranchSpan {
+             span: raw_span,
+             condition_info,
+             true_marker,
+             false_marker,
+             decision_depth,
+         }| {
+            let (span, true_bcb, false_bcb) =
+                check_branch_bcb(raw_span, true_marker, false_marker)?;
+            Some(MCDCBranch { span, true_bcb, false_bcb, condition_info, decision_depth })
+        },
+    ));
+
+    mcdc_decisions.extend(branch_info.mcdc_decision_spans.iter().filter_map(
+        |decision: &mir::coverage::MCDCDecisionSpan| {
+            let (span, _) = unexpand_into_body_span_with_visible_macro(decision.span, body_span)?;
+
+            let end_bcbs = decision
+                .end_markers
+                .iter()
+                .map(|&marker| bcb_from_marker(marker))
+                .collect::<Option<_>>()?;
+
+            // Each decision containing N conditions needs 2^N bits of space in
+            // the bitmap, rounded up to a whole number of bytes.
+            // The decision's "bitmap index" points to its first byte in the bitmap.
+            let bitmap_idx = *mcdc_bitmap_bytes;
+            *mcdc_bitmap_bytes += (1_u32 << decision.conditions_num).div_ceil(8);
+
+            Some(MCDCDecision {
                 span,
-            }
-        })
-    };
-
-    let mut next_bitmap_idx = 0;
-
-    let decision_filter_map = |decision: &MCDCDecisionSpan| {
-        let (span, _) = unexpand_into_body_span_with_visible_macro(decision.span, body_span)?;
-
-        let end_bcbs = decision
-            .end_markers
-            .iter()
-            .map(|&marker| bcb_from_marker(marker))
-            .collect::<Option<_>>()?;
-
-        let bitmap_idx = next_bitmap_idx;
-        next_bitmap_idx += (1_u32 << decision.conditions_num).div_ceil(8);
-
-        Some(BcbMapping {
-            kind: BcbMappingKind::MCDCDecision {
                 end_bcbs,
                 bitmap_idx,
                 conditions_num: decision.conditions_num as u16,
                 decision_depth: decision.decision_depth,
-            },
-            span,
-        })
-    };
-
-    std::iter::empty()
-        .chain(branch_info.mcdc_branch_spans.iter().filter_map(mcdc_branch_filter_map))
-        .chain(branch_info.mcdc_decision_spans.iter().filter_map(decision_filter_map))
-        .collect::<Vec<_>>()
+            })
+        },
+    ));
 }
diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs
index ffe61e761c5..28e0c633d5a 100644
--- a/compiler/rustc_mir_transform/src/coverage/mod.rs
+++ b/compiler/rustc_mir_transform/src/coverage/mod.rs
@@ -7,13 +7,9 @@ mod spans;
 #[cfg(test)]
 mod tests;
 
-use self::counters::{CounterIncrementSite, CoverageCounters};
-use self::graph::{BasicCoverageBlock, CoverageGraph};
-use self::mappings::{BcbBranchPair, BcbMapping, BcbMappingKind, CoverageSpans};
-
-use crate::MirPass;
-
-use rustc_middle::mir::coverage::*;
+use rustc_middle::mir::coverage::{
+    CodeRegion, CoverageKind, DecisionInfo, FunctionCoverageInfo, Mapping, MappingKind,
+};
 use rustc_middle::mir::{
     self, BasicBlock, BasicBlockData, SourceInfo, Statement, StatementKind, Terminator,
     TerminatorKind,
@@ -23,6 +19,11 @@ use rustc_span::def_id::LocalDefId;
 use rustc_span::source_map::SourceMap;
 use rustc_span::{BytePos, Pos, RelativeBytePos, Span, Symbol};
 
+use crate::coverage::counters::{CounterIncrementSite, CoverageCounters};
+use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph};
+use crate::coverage::mappings::ExtractedMappings;
+use crate::MirPass;
+
 /// Inserts `StatementKind::Coverage` statements that either instrument the binary with injected
 /// counters, via intrinsic `llvm.instrprof.increment`, and/or inject metadata used during codegen
 /// to construct the coverage map.
@@ -69,24 +70,27 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir:
     let basic_coverage_blocks = CoverageGraph::from_mir(mir_body);
 
     ////////////////////////////////////////////////////
-    // Compute coverage spans from the `CoverageGraph`.
-    let Some(coverage_spans) =
-        mappings::generate_coverage_spans(mir_body, &hir_info, &basic_coverage_blocks)
-    else {
-        // No relevant spans were found in MIR, so skip instrumenting this function.
-        return;
-    };
+    // Extract coverage spans and other mapping info from MIR.
+    let extracted_mappings =
+        mappings::extract_all_mapping_info_from_mir(mir_body, &hir_info, &basic_coverage_blocks);
 
     ////////////////////////////////////////////////////
     // Create an optimized mix of `Counter`s and `Expression`s for the `CoverageGraph`. Ensure
     // every coverage span has a `Counter` or `Expression` assigned to its `BasicCoverageBlock`
     // and all `Expression` dependencies (operands) are also generated, for any other
     // `BasicCoverageBlock`s not already associated with a coverage span.
-    let bcb_has_coverage_spans = |bcb| coverage_spans.bcb_has_coverage_spans(bcb);
+    let bcbs_with_counter_mappings =
+        extracted_mappings.all_bcbs_with_counter_mappings(&basic_coverage_blocks);
+    if bcbs_with_counter_mappings.is_empty() {
+        // No relevant spans were found in MIR, so skip instrumenting this function.
+        return;
+    }
+
+    let bcb_has_counter_mappings = |bcb| bcbs_with_counter_mappings.contains(bcb);
     let coverage_counters =
-        CoverageCounters::make_bcb_counters(&basic_coverage_blocks, bcb_has_coverage_spans);
+        CoverageCounters::make_bcb_counters(&basic_coverage_blocks, bcb_has_counter_mappings);
 
-    let mappings = create_mappings(tcx, &hir_info, &coverage_spans, &coverage_counters);
+    let mappings = create_mappings(tcx, &hir_info, &extracted_mappings, &coverage_counters);
     if mappings.is_empty() {
         // No spans could be converted into valid mappings, so skip this function.
         debug!("no spans could be converted into valid mappings; skipping");
@@ -96,26 +100,23 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir:
     inject_coverage_statements(
         mir_body,
         &basic_coverage_blocks,
-        bcb_has_coverage_spans,
+        bcb_has_counter_mappings,
         &coverage_counters,
     );
 
-    inject_mcdc_statements(mir_body, &basic_coverage_blocks, &coverage_spans);
+    inject_mcdc_statements(mir_body, &basic_coverage_blocks, &extracted_mappings);
 
-    let mcdc_num_condition_bitmaps = coverage_spans
-        .mappings
+    let mcdc_num_condition_bitmaps = extracted_mappings
+        .mcdc_decisions
         .iter()
-        .filter_map(|bcb_mapping| match bcb_mapping.kind {
-            BcbMappingKind::MCDCDecision { decision_depth, .. } => Some(decision_depth),
-            _ => None,
-        })
+        .map(|&mappings::MCDCDecision { decision_depth, .. }| decision_depth)
         .max()
         .map_or(0, |max| usize::from(max) + 1);
 
     mir_body.function_coverage_info = Some(Box::new(FunctionCoverageInfo {
         function_source_hash: hir_info.function_source_hash,
         num_counters: coverage_counters.num_counters(),
-        mcdc_bitmap_bytes: coverage_spans.test_vector_bitmap_bytes(),
+        mcdc_bitmap_bytes: extracted_mappings.mcdc_bitmap_bytes,
         expressions: coverage_counters.into_expressions(),
         mappings,
         mcdc_num_condition_bitmaps,
@@ -130,7 +131,7 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir:
 fn create_mappings<'tcx>(
     tcx: TyCtxt<'tcx>,
     hir_info: &ExtractedHirInfo,
-    coverage_spans: &CoverageSpans,
+    extracted_mappings: &ExtractedMappings,
     coverage_counters: &CoverageCounters,
 ) -> Vec<Mapping> {
     let source_map = tcx.sess.source_map();
@@ -149,44 +150,54 @@ fn create_mappings<'tcx>(
             .expect("all BCBs with spans were given counters")
             .as_term()
     };
-
+    let region_for_span = |span: Span| make_code_region(source_map, file_name, span, body_span);
+
+    // Fully destructure the mappings struct to make sure we don't miss any kinds.
+    let ExtractedMappings {
+        code_mappings,
+        branch_pairs,
+        mcdc_bitmap_bytes: _,
+        mcdc_branches,
+        mcdc_decisions,
+    } = extracted_mappings;
     let mut mappings = Vec::new();
 
-    mappings.extend(coverage_spans.mappings.iter().filter_map(
-        |BcbMapping { kind: bcb_mapping_kind, span }| {
-            let kind = match *bcb_mapping_kind {
-                BcbMappingKind::Code(bcb) => MappingKind::Code(term_for_bcb(bcb)),
-                BcbMappingKind::MCDCBranch {
-                    true_bcb, false_bcb, condition_info: None, ..
-                } => MappingKind::Branch {
-                    true_term: term_for_bcb(true_bcb),
-                    false_term: term_for_bcb(false_bcb),
-                },
-                BcbMappingKind::MCDCBranch {
-                    true_bcb,
-                    false_bcb,
-                    condition_info: Some(mcdc_params),
-                    ..
-                } => MappingKind::MCDCBranch {
-                    true_term: term_for_bcb(true_bcb),
-                    false_term: term_for_bcb(false_bcb),
-                    mcdc_params,
-                },
-                BcbMappingKind::MCDCDecision { bitmap_idx, conditions_num, .. } => {
-                    MappingKind::MCDCDecision(DecisionInfo { bitmap_idx, conditions_num })
-                }
-            };
-            let code_region = make_code_region(source_map, file_name, *span, body_span)?;
+    mappings.extend(code_mappings.iter().filter_map(
+        // Ordinary code mappings are the simplest kind.
+        |&mappings::CodeMapping { span, bcb }| {
+            let code_region = region_for_span(span)?;
+            let kind = MappingKind::Code(term_for_bcb(bcb));
             Some(Mapping { kind, code_region })
         },
     ));
 
-    mappings.extend(coverage_spans.branch_pairs.iter().filter_map(
-        |&BcbBranchPair { span, true_bcb, false_bcb }| {
+    mappings.extend(branch_pairs.iter().filter_map(
+        |&mappings::BranchPair { span, true_bcb, false_bcb }| {
             let true_term = term_for_bcb(true_bcb);
             let false_term = term_for_bcb(false_bcb);
             let kind = MappingKind::Branch { true_term, false_term };
-            let code_region = make_code_region(source_map, file_name, span, body_span)?;
+            let code_region = region_for_span(span)?;
+            Some(Mapping { kind, code_region })
+        },
+    ));
+
+    mappings.extend(mcdc_branches.iter().filter_map(
+        |&mappings::MCDCBranch { span, true_bcb, false_bcb, condition_info, decision_depth: _ }| {
+            let code_region = region_for_span(span)?;
+            let true_term = term_for_bcb(true_bcb);
+            let false_term = term_for_bcb(false_bcb);
+            let kind = match condition_info {
+                Some(mcdc_params) => MappingKind::MCDCBranch { true_term, false_term, mcdc_params },
+                None => MappingKind::Branch { true_term, false_term },
+            };
+            Some(Mapping { kind, code_region })
+        },
+    ));
+
+    mappings.extend(mcdc_decisions.iter().filter_map(
+        |&mappings::MCDCDecision { span, bitmap_idx, conditions_num, .. }| {
+            let code_region = region_for_span(span)?;
+            let kind = MappingKind::MCDCDecision(DecisionInfo { bitmap_idx, conditions_num });
             Some(Mapping { kind, code_region })
         },
     ));
@@ -251,20 +262,16 @@ fn inject_coverage_statements<'tcx>(
 fn inject_mcdc_statements<'tcx>(
     mir_body: &mut mir::Body<'tcx>,
     basic_coverage_blocks: &CoverageGraph,
-    coverage_spans: &CoverageSpans,
+    extracted_mappings: &ExtractedMappings,
 ) {
-    if coverage_spans.test_vector_bitmap_bytes() == 0 {
-        return;
-    }
-
     // Inject test vector update first because `inject_statement` always insert new statement at head.
-    for (end_bcbs, bitmap_idx, decision_depth) in
-        coverage_spans.mappings.iter().filter_map(|mapping| match &mapping.kind {
-            BcbMappingKind::MCDCDecision { end_bcbs, bitmap_idx, decision_depth, .. } => {
-                Some((end_bcbs, *bitmap_idx, *decision_depth))
-            }
-            _ => None,
-        })
+    for &mappings::MCDCDecision {
+        span: _,
+        ref end_bcbs,
+        bitmap_idx,
+        conditions_num: _,
+        decision_depth,
+    } in &extracted_mappings.mcdc_decisions
     {
         for end in end_bcbs {
             let end_bb = basic_coverage_blocks[*end].leader_bb();
@@ -276,24 +283,22 @@ fn inject_mcdc_statements<'tcx>(
         }
     }
 
-    for (true_bcb, false_bcb, condition_id, decision_depth) in
-        coverage_spans.mappings.iter().filter_map(|mapping| match mapping.kind {
-            BcbMappingKind::MCDCBranch { true_bcb, false_bcb, condition_info, decision_depth } => {
-                Some((true_bcb, false_bcb, condition_info?.condition_id, decision_depth))
-            }
-            _ => None,
-        })
+    for &mappings::MCDCBranch { span: _, true_bcb, false_bcb, condition_info, decision_depth } in
+        &extracted_mappings.mcdc_branches
     {
+        let Some(condition_info) = condition_info else { continue };
+        let id = condition_info.condition_id;
+
         let true_bb = basic_coverage_blocks[true_bcb].leader_bb();
         inject_statement(
             mir_body,
-            CoverageKind::CondBitmapUpdate { id: condition_id, value: true, decision_depth },
+            CoverageKind::CondBitmapUpdate { id, value: true, decision_depth },
             true_bb,
         );
         let false_bb = basic_coverage_blocks[false_bcb].leader_bb();
         inject_statement(
             mir_body,
-            CoverageKind::CondBitmapUpdate { id: condition_id, value: false, decision_depth },
+            CoverageKind::CondBitmapUpdate { id, value: false, decision_depth },
             false_bb,
         );
     }
diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs
index d6432e2e9d4..a0570c45f96 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans.rs
@@ -2,7 +2,7 @@ use rustc_middle::mir;
 use rustc_span::{BytePos, Span};
 
 use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph};
-use crate::coverage::mappings::{BcbMapping, BcbMappingKind};
+use crate::coverage::mappings;
 use crate::coverage::spans::from_mir::SpanFromMir;
 use crate::coverage::ExtractedHirInfo;
 
@@ -17,14 +17,14 @@ pub(super) fn extract_refined_covspans(
     mir_body: &mir::Body<'_>,
     hir_info: &ExtractedHirInfo,
     basic_coverage_blocks: &CoverageGraph,
-    mappings: &mut impl Extend<BcbMapping>,
+    code_mappings: &mut impl Extend<mappings::CodeMapping>,
 ) {
     let sorted_spans =
         from_mir::mir_to_initial_sorted_coverage_spans(mir_body, hir_info, basic_coverage_blocks);
     let coverage_spans = SpansRefiner::refine_sorted_spans(sorted_spans);
-    mappings.extend(coverage_spans.into_iter().map(|RefinedCovspan { bcb, span, .. }| {
+    code_mappings.extend(coverage_spans.into_iter().map(|RefinedCovspan { bcb, span, .. }| {
         // Each span produced by the generator represents an ordinary code region.
-        BcbMapping { kind: BcbMappingKind::Code(bcb), span }
+        mappings::CodeMapping { span, bcb }
     }));
 }
 
diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
index d0f6ec8f21f..3019b275fb2 100644
--- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
+++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
@@ -202,7 +202,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
                 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.ty.kind()
+                    && let ty::Array(_, len) = operand_ty.kind()
                     && let Some(len) = Const::Ty(*len).try_eval_scalar_int(self.tcx, self.param_env)
                 {
                     state.insert_value_idx(target_len, FlatSet::Elem(len.into()), self.map());
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index 4dd595ce1e1..342d1a1cd5b 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -594,7 +594,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
                 let ty = place.ty(self.local_decls, self.tcx).ty;
                 if let Some(Mutability::Not) = ty.ref_mutability()
                     && let Some(pointee_ty) = ty.builtin_deref(true)
-                    && pointee_ty.ty.is_freeze(self.tcx, self.param_env)
+                    && pointee_ty.is_freeze(self.tcx, self.param_env)
                 {
                     // An immutable borrow `_x` always points to the same value for the
                     // lifetime of the borrow, so we can merge all instances of `*_x`.
@@ -1133,9 +1133,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
         if let Value::Cast { kind, from, to, .. } = self.get(inner)
             && let CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize) = kind
             && let Some(from) = from.builtin_deref(true)
-            && let ty::Array(_, len) = from.ty.kind()
+            && let ty::Array(_, len) = from.kind()
             && let Some(to) = to.builtin_deref(true)
-            && let ty::Slice(..) = to.ty.kind()
+            && let ty::Slice(..) = to.kind()
         {
             return self.insert_constant(Const::from_ty_const(*len, self.tcx));
         }
diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs
index 8be96b6ba8f..e407929c9a7 100644
--- a/compiler/rustc_mir_transform/src/large_enums.rs
+++ b/compiler/rustc_mir_transform/src/large_enums.rs
@@ -1,7 +1,7 @@
-use crate::rustc_middle::ty::util::IntTypeExt;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::mir::interpret::AllocId;
 use rustc_middle::mir::*;
+use rustc_middle::ty::util::IntTypeExt;
 use rustc_middle::ty::{self, AdtDef, ParamEnv, Ty, TyCtxt};
 use rustc_session::Session;
 use rustc_target::abi::{HasDataLayout, Size, TagEncoding, Variants};
diff --git a/compiler/rustc_mir_transform/src/mentioned_items.rs b/compiler/rustc_mir_transform/src/mentioned_items.rs
index 57b6126dece..db2bb60bdac 100644
--- a/compiler/rustc_mir_transform/src/mentioned_items.rs
+++ b/compiler/rustc_mir_transform/src/mentioned_items.rs
@@ -79,8 +79,8 @@ impl<'tcx> Visitor<'tcx> for MentionedItemsVisitor<'_, 'tcx> {
                 // add everything that may involve a vtable.
                 let source_ty = operand.ty(self.body, self.tcx);
                 let may_involve_vtable = match (
-                    source_ty.builtin_deref(true).map(|t| t.ty.kind()),
-                    target_ty.builtin_deref(true).map(|t| t.ty.kind()),
+                    source_ty.builtin_deref(true).map(|t| t.kind()),
+                    target_ty.builtin_deref(true).map(|t| t.kind()),
                 ) {
                     (Some(ty::Array(..)), Some(ty::Str | ty::Slice(..))) => false, // &str/&[T] unsizing
                     _ => true,
diff --git a/compiler/rustc_mir_transform/src/normalize_array_len.rs b/compiler/rustc_mir_transform/src/normalize_array_len.rs
index c26a5461633..2070895c900 100644
--- a/compiler/rustc_mir_transform/src/normalize_array_len.rs
+++ b/compiler/rustc_mir_transform/src/normalize_array_len.rs
@@ -48,9 +48,9 @@ fn compute_slice_length<'tcx>(
                 let operand_ty = operand.ty(body, tcx);
                 debug!(?operand_ty);
                 if let Some(operand_ty) = operand_ty.builtin_deref(true)
-                    && let ty::Array(_, len) = operand_ty.ty.kind()
+                    && let ty::Array(_, len) = operand_ty.kind()
                     && let Some(cast_ty) = cast_ty.builtin_deref(true)
-                    && let ty::Slice(..) = cast_ty.ty.kind()
+                    && let ty::Slice(..) = cast_ty.kind()
                 {
                     slice_lengths[local] = Some(*len);
                 }
diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs
index cbab2006186..ddfb42a6f4a 100644
--- a/compiler/rustc_monomorphize/src/lib.rs
+++ b/compiler/rustc_monomorphize/src/lib.rs
@@ -32,10 +32,9 @@ fn custom_coerce_unsize_info<'tcx>(
     source_ty: Ty<'tcx>,
     target_ty: Ty<'tcx>,
 ) -> Result<CustomCoerceUnsized, ErrorGuaranteed> {
-    let trait_ref = ty::TraitRef::from_lang_item(
+    let trait_ref = ty::TraitRef::new(
         tcx.tcx,
-        LangItem::CoerceUnsized,
-        tcx.span,
+        tcx.require_lang_item(LangItem::CoerceUnsized, Some(tcx.span)),
         [source_ty, target_ty],
     );
 
diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs
index 6d237df073f..6487169d173 100644
--- a/compiler/rustc_monomorphize/src/polymorphize.rs
+++ b/compiler/rustc_monomorphize/src/polymorphize.rs
@@ -131,7 +131,7 @@ fn mark_used_by_default_parameters<'tcx>(
 ) {
     match tcx.def_kind(def_id) {
         DefKind::Closure => {
-            for param in &generics.params {
+            for param in &generics.own_params {
                 debug!(?param, "(closure/gen)");
                 unused_parameters.mark_used(param.index);
             }
@@ -165,7 +165,7 @@ fn mark_used_by_default_parameters<'tcx>(
         | DefKind::LifetimeParam
         | DefKind::GlobalAsm
         | DefKind::Impl { .. } => {
-            for param in &generics.params {
+            for param in &generics.own_params {
                 debug!(?param, "(other)");
                 if let ty::GenericParamDefKind::Lifetime = param.kind {
                     unused_parameters.mark_used(param.index);
@@ -202,7 +202,7 @@ fn emit_unused_generic_params_error<'tcx>(
     let mut param_names = Vec::new();
     let mut next_generics = Some(generics);
     while let Some(generics) = next_generics {
-        for param in &generics.params {
+        for param in &generics.own_params {
             if unused_parameters.is_unused(param.index) {
                 debug!(?param);
                 let def_span = tcx.def_span(param.def_id);
diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
index 6600b92fb31..755f5cfa5a3 100644
--- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs
+++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
@@ -1,11 +1,11 @@
 use std::cmp::Ordering;
 
 use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
-use rustc_type_ir::new::{Const, Region, Ty};
+use rustc_type_ir::inherent::*;
 use rustc_type_ir::visit::TypeVisitableExt;
 use rustc_type_ir::{
-    self as ty, Canonical, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind, ConstTy,
-    InferCtxtLike, Interner, IntoKind, PlaceholderLike,
+    self as ty, Canonical, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind, InferCtxtLike,
+    Interner,
 };
 
 /// Whether we're canonicalizing a query input or the query response.
@@ -455,7 +455,7 @@ impl<I: Interner> TypeFolder<I> for RegionsToStatic<I> {
         I::Binder<T>: TypeSuperFoldable<I>,
     {
         self.binder.shift_in(1);
-        let t = t.fold_with(self);
+        let t = t.super_fold_with(self);
         self.binder.shift_out(1);
         t
     }
diff --git a/compiler/rustc_parse/Cargo.toml b/compiler/rustc_parse/Cargo.toml
index f5623323168..b33896154f2 100644
--- a/compiler/rustc_parse/Cargo.toml
+++ b/compiler/rustc_parse/Cargo.toml
@@ -21,3 +21,7 @@ tracing = "0.1"
 unicode-normalization = "0.1.11"
 unicode-width = "0.1.4"
 # tidy-alphabetical-end
+
+[dev-dependencies]
+termcolor = "1.2"
+
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index 873095dca87..04f855e4f55 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -401,10 +401,8 @@ parse_invalid_logical_operator = `{$incorrect}` is not a logical operator
     .use_amp_amp_for_conjunction = use `&&` to perform logical conjunction
     .use_pipe_pipe_for_disjunction = use `||` to perform logical disjunction
 
-parse_invalid_meta_item = expected unsuffixed literal or identifier, found `{$token}`
-
-parse_invalid_meta_item_unquoted_ident = expected unsuffixed literal, found `{$token}`
-    .suggestion = surround the identifier with quotation marks to parse it as a string
+parse_invalid_meta_item = expected unsuffixed literal, found `{$token}`
+    .quote_ident_sugg = surround the identifier with quotation marks to make it into a string literal
 
 parse_invalid_offset_of = offset_of expects dot-separated field and variant names
 
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index d06f03a7c17..2f68a299f26 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -978,21 +978,13 @@ pub(crate) struct InvalidMetaItem {
     #[primary_span]
     pub span: Span,
     pub token: Token,
-}
-
-#[derive(Diagnostic)]
-#[diag(parse_invalid_meta_item_unquoted_ident)]
-pub(crate) struct InvalidMetaItemUnquotedIdent {
-    #[primary_span]
-    pub span: Span,
-    pub token: Token,
     #[subdiagnostic]
-    pub sugg: InvalidMetaItemSuggQuoteIdent,
+    pub quote_ident_sugg: Option<InvalidMetaItemQuoteIdentSugg>,
 }
 
 #[derive(Subdiagnostic)]
-#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")]
-pub(crate) struct InvalidMetaItemSuggQuoteIdent {
+#[multipart_suggestion(parse_quote_ident_sugg, applicability = "machine-applicable")]
+pub(crate) struct InvalidMetaItemQuoteIdentSugg {
     #[suggestion_part(code = "\"")]
     pub before: Span,
     #[suggestion_part(code = "\"")]
diff --git a/compiler/rustc_parse/src/lexer/diagnostics.rs b/compiler/rustc_parse/src/lexer/diagnostics.rs
index 993ff1b97f5..1247e2e44fb 100644
--- a/compiler/rustc_parse/src/lexer/diagnostics.rs
+++ b/compiler/rustc_parse/src/lexer/diagnostics.rs
@@ -5,7 +5,7 @@ use rustc_span::source_map::SourceMap;
 use rustc_span::Span;
 
 #[derive(Default)]
-pub struct TokenTreeDiagInfo {
+pub(super) struct TokenTreeDiagInfo {
     /// Stack of open delimiters and their spans. Used for error message.
     pub open_braces: Vec<(Delimiter, Span)>,
     pub unmatched_delims: Vec<UnmatchedDelim>,
@@ -21,7 +21,7 @@ pub struct TokenTreeDiagInfo {
     pub matching_block_spans: Vec<(Span, Span)>,
 }
 
-pub fn same_indentation_level(sm: &SourceMap, open_sp: Span, close_sp: Span) -> bool {
+pub(super) fn same_indentation_level(sm: &SourceMap, open_sp: Span, close_sp: Span) -> bool {
     match (sm.span_to_margin(open_sp), sm.span_to_margin(close_sp)) {
         (Some(open_padding), Some(close_padding)) => open_padding == close_padding,
         _ => false,
@@ -30,7 +30,7 @@ pub fn same_indentation_level(sm: &SourceMap, open_sp: Span, close_sp: Span) ->
 
 // When we get a `)` or `]` for `{`, we should emit help message here
 // it's more friendly compared to report `unmatched error` in later phase
-pub fn report_missing_open_delim(err: &mut Diag<'_>, unmatched_delims: &[UnmatchedDelim]) -> bool {
+fn report_missing_open_delim(err: &mut Diag<'_>, unmatched_delims: &[UnmatchedDelim]) -> bool {
     let mut reported_missing_open = false;
     for unmatch_brace in unmatched_delims.iter() {
         if let Some(delim) = unmatch_brace.found_delim
@@ -51,7 +51,7 @@ pub fn report_missing_open_delim(err: &mut Diag<'_>, unmatched_delims: &[Unmatch
     reported_missing_open
 }
 
-pub fn report_suspicious_mismatch_block(
+pub(super) fn report_suspicious_mismatch_block(
     err: &mut Diag<'_>,
     diag_info: &TokenTreeDiagInfo,
     sm: &SourceMap,
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index 1abb1d29562..d2d200a91af 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -112,7 +112,7 @@ struct StringReader<'psess, 'src> {
 }
 
 impl<'psess, 'src> StringReader<'psess, 'src> {
-    pub fn dcx(&self) -> &'psess DiagCtxt {
+    fn dcx(&self) -> &'psess DiagCtxt {
         &self.psess.dcx
     }
 
diff --git a/compiler/rustc_parse/src/lexer/unicode_chars.rs b/compiler/rustc_parse/src/lexer/unicode_chars.rs
index 6b055fc844a..c9470151a7b 100644
--- a/compiler/rustc_parse/src/lexer/unicode_chars.rs
+++ b/compiler/rustc_parse/src/lexer/unicode_chars.rs
@@ -9,7 +9,7 @@ use crate::{
 use rustc_span::{symbol::kw, BytePos, Pos, Span};
 
 #[rustfmt::skip] // for line breaks
-pub(crate) const UNICODE_ARRAY: &[(char, &str, &str)] = &[
+pub(super) const UNICODE_ARRAY: &[(char, &str, &str)] = &[
     ('
', "Line Separator", " "),
     ('
', "Paragraph Separator", " "),
     (' ', "Ogham Space mark", " "),
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index a46372d368f..0f973dfcd79 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -5,6 +5,7 @@
 #![allow(rustc::untranslatable_diagnostic)]
 #![feature(array_windows)]
 #![feature(box_patterns)]
+#![feature(debug_closure_helpers)]
 #![feature(if_let_guard)]
 #![feature(iter_intersperse)]
 #![feature(let_chains)]
diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs
index ab5f51eedc3..d5d8060d909 100644
--- a/compiler/rustc_parse/src/parser/attr.rs
+++ b/compiler/rustc_parse/src/parser/attr.rs
@@ -1,7 +1,4 @@
-use crate::errors::{
-    InvalidMetaItem, InvalidMetaItemSuggQuoteIdent, InvalidMetaItemUnquotedIdent,
-    SuffixedLiteralInAttribute,
-};
+use crate::errors;
 use crate::fluent_generated as fluent;
 use crate::maybe_whole;
 
@@ -318,7 +315,7 @@ impl<'a> Parser<'a> {
         debug!("checking if {:?} is unsuffixed", lit);
 
         if !lit.kind.is_unsuffixed() {
-            self.dcx().emit_err(SuffixedLiteralInAttribute { span: lit.span });
+            self.dcx().emit_err(errors::SuffixedLiteralInAttribute { span: lit.span });
         }
 
         Ok(lit)
@@ -356,10 +353,11 @@ impl<'a> Parser<'a> {
         Ok(nmis)
     }
 
-    /// Matches the following grammar (per RFC 1559).
+    /// Parse a meta item per RFC 1559.
+    ///
     /// ```ebnf
-    /// meta_item : PATH ( '=' UNSUFFIXED_LIT | '(' meta_item_inner? ')' )? ;
-    /// meta_item_inner : (meta_item | UNSUFFIXED_LIT) (',' meta_item_inner)? ;
+    /// MetaItem = SimplePath ( '=' UNSUFFIXED_LIT | '(' MetaSeq? ')' )? ;
+    /// MetaSeq = MetaItemInner (',' MetaItemInner)* ','? ;
     /// ```
     pub fn parse_meta_item(&mut self) -> PResult<'a, ast::MetaItem> {
         // We can't use `maybe_whole` here because it would bump in the `None`
@@ -387,7 +385,6 @@ impl<'a> Parser<'a> {
         Ok(if self.eat(&token::Eq) {
             ast::MetaItemKind::NameValue(self.parse_unsuffixed_meta_item_lit()?)
         } else if self.check(&token::OpenDelim(Delimiter::Parenthesis)) {
-            // Matches `meta_seq = ( COMMASEP(meta_item_inner) )`.
             let (list, _) = self.parse_paren_comma_seq(|p| p.parse_meta_item_inner())?;
             ast::MetaItemKind::List(list)
         } else {
@@ -395,38 +392,45 @@ impl<'a> Parser<'a> {
         })
     }
 
-    /// Matches `meta_item_inner : (meta_item | UNSUFFIXED_LIT) ;`.
+    /// Parse an inner meta item per RFC 1559.
+    ///
+    /// ```ebnf
+    /// MetaItemInner = UNSUFFIXED_LIT | MetaItem ;
+    /// ```
     fn parse_meta_item_inner(&mut self) -> PResult<'a, ast::NestedMetaItem> {
         match self.parse_unsuffixed_meta_item_lit() {
             Ok(lit) => return Ok(ast::NestedMetaItem::Lit(lit)),
-            Err(err) => err.cancel(),
+            Err(err) => err.cancel(), // we provide a better error below
         }
 
         match self.parse_meta_item() {
             Ok(mi) => return Ok(ast::NestedMetaItem::MetaItem(mi)),
-            Err(err) => err.cancel(),
+            Err(err) => err.cancel(), // we provide a better error below
         }
 
-        let token = self.token.clone();
+        let mut err = errors::InvalidMetaItem {
+            span: self.token.span,
+            token: self.token.clone(),
+            quote_ident_sugg: None,
+        };
 
-        // Check for unquoted idents in meta items, e.g.: #[cfg(key = foo)]
-        // `from_expansion()` ensures we don't suggest for cases such as
-        // `#[cfg(feature = $expr)]` in macros
-        if self.prev_token == token::Eq && !self.token.span.from_expansion() {
+        // Suggest quoting idents, e.g. in `#[cfg(key = value)]`. We don't use `Token::ident` and
+        // don't `uninterpolate` the token to avoid suggesting anything butchered or questionable
+        // when macro metavariables are involved.
+        if self.prev_token == token::Eq
+            && let token::Ident(..) = self.token.kind
+        {
             let before = self.token.span.shrink_to_lo();
-            while matches!(self.token.kind, token::Ident(..)) {
+            while let token::Ident(..) = self.token.kind {
                 self.bump();
             }
-            let after = self.prev_token.span.shrink_to_hi();
-            let sugg = InvalidMetaItemSuggQuoteIdent { before, after };
-            return Err(self.dcx().create_err(InvalidMetaItemUnquotedIdent {
-                span: token.span,
-                token,
-                sugg,
-            }));
+            err.quote_ident_sugg = Some(errors::InvalidMetaItemQuoteIdentSugg {
+                before,
+                after: self.prev_token.span.shrink_to_hi(),
+            });
         }
 
-        Err(self.dcx().create_err(InvalidMetaItem { span: token.span, token }))
+        Err(self.dcx().create_err(err))
     }
 }
 
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index f256dbf4360..50698dbf9c1 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -22,7 +22,6 @@ use crate::fluent_generated as fluent;
 use crate::parser;
 use crate::parser::attr::InnerAttrPolicy;
 use ast::token::IdentIsRaw;
-use parser::Recovered;
 use rustc_ast as ast;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter, Lit, LitKind, Token, TokenKind};
@@ -31,7 +30,7 @@ use rustc_ast::util::parser::AssocOp;
 use rustc_ast::{
     AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec, BinOpKind, BindingMode, Block,
     BlockCheckMode, Expr, ExprKind, GenericArg, Generics, HasTokens, Item, ItemKind, Param, Pat,
-    PatKind, Path, PathSegment, QSelf, Ty, TyKind,
+    PatKind, Path, PathSegment, QSelf, Recovered, Ty, TyKind,
 };
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxHashSet;
@@ -527,14 +526,14 @@ impl<'a> Parser<'a> {
                 //
                 //   let x = 32:
                 //   let y = 42;
-                self.dcx().emit_err(ExpectedSemi {
+                let guar = self.dcx().emit_err(ExpectedSemi {
                     span: self.token.span,
                     token: self.token.clone(),
                     unexpected_token_label: None,
                     sugg: ExpectedSemiSugg::ChangeToSemi(self.token.span),
                 });
                 self.bump();
-                return Ok(Recovered::Yes);
+                return Ok(Recovered::Yes(guar));
             } else if self.look_ahead(0, |t| {
                 t == &token::CloseDelim(Delimiter::Brace)
                     || ((t.can_begin_expr() || t.can_begin_item())
@@ -552,13 +551,13 @@ impl<'a> Parser<'a> {
                 //   let x = 32
                 //   let y = 42;
                 let span = self.prev_token.span.shrink_to_hi();
-                self.dcx().emit_err(ExpectedSemi {
+                let guar = self.dcx().emit_err(ExpectedSemi {
                     span,
                     token: self.token.clone(),
                     unexpected_token_label: Some(self.token.span),
                     sugg: ExpectedSemiSugg::AddSemi(span),
                 });
-                return Ok(Recovered::Yes);
+                return Ok(Recovered::Yes(guar));
             }
         }
 
@@ -712,8 +711,8 @@ impl<'a> Parser<'a> {
 
         if self.check_too_many_raw_str_terminators(&mut err) {
             if expected.contains(&TokenType::Token(token::Semi)) && self.eat(&token::Semi) {
-                err.emit();
-                return Ok(Recovered::Yes);
+                let guar = err.emit();
+                return Ok(Recovered::Yes(guar));
             } else {
                 return Err(err);
             }
@@ -1224,7 +1223,11 @@ impl<'a> Parser<'a> {
             let x = self.parse_seq_to_before_end(
                 &token::Gt,
                 SeqSep::trailing_allowed(token::Comma),
-                |p| p.parse_generic_arg(None),
+                |p| match p.parse_generic_arg(None)? {
+                    Some(arg) => Ok(arg),
+                    // If we didn't eat a generic arg, then we should error.
+                    None => p.unexpected_any(),
+                },
             );
             match x {
                 Ok((_, _, Recovered::No)) => {
@@ -1251,7 +1254,7 @@ impl<'a> Parser<'a> {
                         }
                     }
                 }
-                Ok((_, _, Recovered::Yes)) => {}
+                Ok((_, _, Recovered::Yes(_))) => {}
                 Err(err) => {
                     err.cancel();
                 }
@@ -1284,13 +1287,13 @@ impl<'a> Parser<'a> {
 
     /// Check to see if a pair of chained operators looks like an attempt at chained comparison,
     /// e.g. `1 < x <= 3`. If so, suggest either splitting the comparison into two, or
-    /// parenthesising the leftmost comparison.
+    /// parenthesising the leftmost comparison. The return value indicates if recovery happened.
     fn attempt_chained_comparison_suggestion(
         &mut self,
         err: &mut ComparisonOperatorsCannotBeChained,
         inner_op: &Expr,
         outer_op: &Spanned<AssocOp>,
-    ) -> Recovered {
+    ) -> bool {
         if let ExprKind::Binary(op, l1, r1) = &inner_op.kind {
             if let ExprKind::Field(_, ident) = l1.kind
                 && ident.as_str().parse::<i32>().is_err()
@@ -1298,7 +1301,7 @@ impl<'a> Parser<'a> {
             {
                 // The parser has encountered `foo.bar<baz`, the likelihood of the turbofish
                 // suggestion being the only one to apply is high.
-                return Recovered::No;
+                return false;
             }
             return match (op.node, &outer_op.node) {
                 // `x == y == z`
@@ -1317,7 +1320,7 @@ impl<'a> Parser<'a> {
                         span: inner_op.span.shrink_to_hi(),
                         middle_term: expr_to_str(r1),
                     });
-                    Recovered::No // Keep the current parse behavior, where the AST is `(x < y) < z`.
+                    false // Keep the current parse behavior, where the AST is `(x < y) < z`.
                 }
                 // `x == y < z`
                 (BinOpKind::Eq, AssocOp::Less | AssocOp::LessEqual | AssocOp::Greater | AssocOp::GreaterEqual) => {
@@ -1331,12 +1334,12 @@ impl<'a> Parser<'a> {
                                 left: r1.span.shrink_to_lo(),
                                 right: r2.span.shrink_to_hi(),
                             });
-                            Recovered::Yes
+                            true
                         }
                         Err(expr_err) => {
                             expr_err.cancel();
                             self.restore_snapshot(snapshot);
-                            Recovered::Yes
+                            true
                         }
                     }
                 }
@@ -1351,19 +1354,19 @@ impl<'a> Parser<'a> {
                                 left: l1.span.shrink_to_lo(),
                                 right: r1.span.shrink_to_hi(),
                             });
-                            Recovered::Yes
+                            true
                         }
                         Err(expr_err) => {
                             expr_err.cancel();
                             self.restore_snapshot(snapshot);
-                            Recovered::No
+                            false
                         }
                     }
                 }
-                _ => Recovered::No,
+                _ => false
             };
         }
-        Recovered::No
+        false
     }
 
     /// Produces an error if comparison operators are chained (RFC #558).
@@ -1494,7 +1497,7 @@ impl<'a> Parser<'a> {
                         // misformatted turbofish, for instance), suggest a correct form.
                         let recovered = self
                             .attempt_chained_comparison_suggestion(&mut err, inner_op, outer_op);
-                        if matches!(recovered, Recovered::Yes) {
+                        if recovered {
                             let guar = self.dcx().emit_err(err);
                             mk_err_expr(self, inner_op.span.to(self.prev_token.span), guar)
                         } else {
@@ -1503,10 +1506,10 @@ impl<'a> Parser<'a> {
                         }
                     };
                 }
-                let recover =
+                let recovered =
                     self.attempt_chained_comparison_suggestion(&mut err, inner_op, outer_op);
                 let guar = self.dcx().emit_err(err);
-                if matches!(recover, Recovered::Yes) {
+                if recovered {
                     return mk_err_expr(self, inner_op.span.to(self.prev_token.span), guar);
                 }
             }
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 8ed2a6edf1a..577003e94fb 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -3,7 +3,7 @@ use super::diagnostics::SnapshotParser;
 use super::pat::{CommaRecoveryMode, Expected, RecoverColon, RecoverComma};
 use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
 use super::{
-    AttrWrapper, BlockMode, ClosureSpans, ForceCollect, Parser, PathStyle, Recovered, Restrictions,
+    AttrWrapper, BlockMode, ClosureSpans, ForceCollect, Parser, PathStyle, Restrictions,
     SemiColonMode, SeqSep, TokenExpectType, TokenType, Trailing, TrailingToken,
 };
 
@@ -11,7 +11,7 @@ use crate::errors;
 use crate::maybe_recover_from_interpolated_ty_qpath;
 use ast::mut_visit::{noop_visit_expr, MutVisitor};
 use ast::token::IdentIsRaw;
-use ast::{CoroutineKind, ForLoopKind, GenBlockKind, MatchKind, Pat, Path, PathSegment};
+use ast::{CoroutineKind, ForLoopKind, GenBlockKind, MatchKind, Pat, Path, PathSegment, Recovered};
 use core::mem;
 use core::ops::ControlFlow;
 use rustc_ast::ptr::P;
@@ -2629,7 +2629,7 @@ impl<'a> Parser<'a> {
 
         CondChecker::new(self).visit_expr(&mut cond);
 
-        if let ExprKind::Let(_, _, _, None) = cond.kind {
+        if let ExprKind::Let(_, _, _, Recovered::No) = cond.kind {
             // Remove the last feature gating of a `let` expression since it's stable.
             self.psess.gated_spans.ungate_last(sym::let_chains, cond.span);
         }
@@ -2639,7 +2639,7 @@ impl<'a> Parser<'a> {
 
     /// Parses a `let $pat = $expr` pseudo-expression.
     fn parse_expr_let(&mut self, restrictions: Restrictions) -> PResult<'a, P<Expr>> {
-        let is_recovered = if !restrictions.contains(Restrictions::ALLOW_LET) {
+        let recovered = if !restrictions.contains(Restrictions::ALLOW_LET) {
             let err = errors::ExpectedExpressionFoundLet {
                 span: self.token.span,
                 reason: ForbiddenLetReason::OtherForbidden,
@@ -2650,10 +2650,10 @@ impl<'a> Parser<'a> {
                 // This was part of a closure, the that part of the parser recover.
                 return Err(self.dcx().create_err(err));
             } else {
-                Some(self.dcx().emit_err(err))
+                Recovered::Yes(self.dcx().emit_err(err))
             }
         } else {
-            None
+            Recovered::No
         };
         self.bump(); // Eat `let` token
         let lo = self.prev_token.span;
@@ -2674,7 +2674,7 @@ impl<'a> Parser<'a> {
         }
         let expr = self.parse_expr_assoc_with(1 + prec_let_scrutinee_needs_par(), None.into())?;
         let span = lo.to(expr.span);
-        Ok(self.mk_expr(span, ExprKind::Let(pat, expr, span, is_recovered)))
+        Ok(self.mk_expr(span, ExprKind::Let(pat, expr, span, recovered)))
     }
 
     /// Parses an `else { ... }` expression (`else` token already eaten).
@@ -2998,7 +2998,7 @@ impl<'a> Parser<'a> {
         &mut self,
         first_expr: &P<Expr>,
         arrow_span: Span,
-    ) -> Option<P<Expr>> {
+    ) -> Option<(Span, ErrorGuaranteed)> {
         if self.token.kind != token::Semi {
             return None;
         }
@@ -3023,7 +3023,7 @@ impl<'a> Parser<'a> {
                     errors::MatchArmBodyWithoutBracesSugg::UseComma { semicolon: semi_sp }
                 },
             });
-            this.mk_expr_err(span, guar)
+            (span, guar)
         };
         // We might have either a `,` -> `;` typo, or a block without braces. We need
         // a more subtle parsing strategy.
@@ -3143,9 +3143,12 @@ impl<'a> Parser<'a> {
                     arm_body = Some(expr);
                     this.eat(&token::Comma);
                     Ok(Recovered::No)
-                } else if let Some(body) = this.parse_arm_body_missing_braces(&expr, arrow_span) {
+                } else if let Some((span, guar)) =
+                    this.parse_arm_body_missing_braces(&expr, arrow_span)
+                {
+                    let body = this.mk_expr_err(span, guar);
                     arm_body = Some(body);
-                    Ok(Recovered::Yes)
+                    Ok(Recovered::Yes(guar))
                 } else {
                     let expr_span = expr.span;
                     arm_body = Some(expr);
@@ -3223,10 +3226,10 @@ impl<'a> Parser<'a> {
                         .is_ok();
                     if pattern_follows && snapshot.check(&TokenKind::FatArrow) {
                         err.cancel();
-                        this.dcx().emit_err(errors::MissingCommaAfterMatchArm {
+                        let guar = this.dcx().emit_err(errors::MissingCommaAfterMatchArm {
                             span: arm_span.shrink_to_hi(),
                         });
-                        return Ok(Recovered::Yes);
+                        return Ok(Recovered::Yes(guar));
                     }
                     Err(err)
                 });
@@ -3904,15 +3907,16 @@ impl MutVisitor for CondChecker<'_> {
 
         let span = e.span;
         match e.kind {
-            ExprKind::Let(_, _, _, ref mut is_recovered @ None) => {
+            ExprKind::Let(_, _, _, ref mut recovered @ Recovered::No) => {
                 if let Some(reason) = self.forbid_let_reason {
-                    *is_recovered =
-                        Some(self.parser.dcx().emit_err(errors::ExpectedExpressionFoundLet {
+                    *recovered = Recovered::Yes(self.parser.dcx().emit_err(
+                        errors::ExpectedExpressionFoundLet {
                             span,
                             reason,
                             missing_let: self.missing_let,
                             comparison: self.comparison,
-                        }));
+                        },
+                    ));
                 } else {
                     self.parser.psess.gated_spans.gate(sym::let_chains, span);
                 }
@@ -3980,7 +3984,7 @@ impl MutVisitor for CondChecker<'_> {
                 self.visit_expr(op);
                 self.forbid_let_reason = forbid_let_reason;
             }
-            ExprKind::Let(_, _, _, Some(_))
+            ExprKind::Let(_, _, _, Recovered::Yes(_))
             | ExprKind::Array(_)
             | ExprKind::ConstBlock(_)
             | ExprKind::Lit(_)
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 848277c4611..df6996dbc45 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -1,8 +1,7 @@
 use super::diagnostics::{dummy_arg, ConsumeClosingDelim};
 use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
 use super::{
-    AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, Recovered, Trailing,
-    TrailingToken,
+    AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, Trailing, TrailingToken,
 };
 use crate::errors::{self, MacroExpandsToAdtField};
 use crate::fluent_generated as fluent;
@@ -336,7 +335,7 @@ impl<'a> Parser<'a> {
                 UseTreeKind::Glob => {
                     e.note("the wildcard token must be last on the path");
                 }
-                UseTreeKind::Nested(..) => {
+                UseTreeKind::Nested { .. } => {
                     e.note("glob-like brace syntax must be last on the path");
                 }
                 _ => (),
@@ -1056,7 +1055,11 @@ impl<'a> Parser<'a> {
         Ok(if self.eat(&token::BinOp(token::Star)) {
             UseTreeKind::Glob
         } else {
-            UseTreeKind::Nested(self.parse_use_tree_list()?)
+            let lo = self.token.span;
+            UseTreeKind::Nested {
+                items: self.parse_use_tree_list()?,
+                span: lo.to(self.prev_token.span),
+            }
         })
     }
 
@@ -1536,8 +1539,8 @@ impl<'a> Parser<'a> {
                                 this.bump(); // }
                                 err.span_label(span, "while parsing this enum");
                                 err.help(help);
-                                err.emit();
-                                (thin_vec![], Recovered::Yes)
+                                let guar = err.emit();
+                                (thin_vec![], Recovered::Yes(guar))
                             }
                         };
                     VariantData::Struct { fields, recovered: recovered.into() }
@@ -1695,16 +1698,15 @@ impl<'a> Parser<'a> {
         let mut recovered = Recovered::No;
         if self.eat(&token::OpenDelim(Delimiter::Brace)) {
             while self.token != token::CloseDelim(Delimiter::Brace) {
-                let field = self.parse_field_def(adt_ty).map_err(|e| {
-                    self.consume_block(Delimiter::Brace, ConsumeClosingDelim::No);
-                    recovered = Recovered::Yes;
-                    e
-                });
-                match field {
-                    Ok(field) => fields.push(field),
+                match self.parse_field_def(adt_ty) {
+                    Ok(field) => {
+                        fields.push(field);
+                    }
                     Err(mut err) => {
+                        self.consume_block(Delimiter::Brace, ConsumeClosingDelim::No);
                         err.span_label(ident_span, format!("while parsing this {adt_ty}"));
-                        err.emit();
+                        let guar = err.emit();
+                        recovered = Recovered::Yes(guar);
                         break;
                     }
                 }
@@ -2465,7 +2467,7 @@ impl<'a> Parser<'a> {
             // `self.expected_tokens`, therefore, do not use `self.unexpected()` which doesn't
             // account for this.
             match self.expect_one_of(&[], &[]) {
-                Ok(Recovered::Yes) => {}
+                Ok(Recovered::Yes(_)) => {}
                 Ok(Recovered::No) => unreachable!(),
                 Err(mut err) => {
                     // Qualifier keywords ordering check
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 7486da33b21..bfb6c4a3885 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -19,6 +19,7 @@ pub(crate) use item::FnParseMode;
 pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
 pub use path::PathStyle;
 
+use core::fmt;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter, Token, TokenKind};
 use rustc_ast::tokenstream::{AttributesData, DelimSpacing, DelimSpan, Spacing};
@@ -26,13 +27,12 @@ use rustc_ast::tokenstream::{TokenStream, TokenTree, TokenTreeCursor};
 use rustc_ast::util::case::Case;
 use rustc_ast::{
     self as ast, AnonConst, AttrArgs, AttrArgsEq, AttrId, ByRef, Const, CoroutineKind, DelimArgs,
-    Expr, ExprKind, Extern, HasAttrs, HasTokens, Mutability, StrLit, Unsafe, Visibility,
+    Expr, ExprKind, Extern, HasAttrs, HasTokens, Mutability, Recovered, StrLit, Unsafe, Visibility,
     VisibilityKind, DUMMY_NODE_ID,
 };
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::PResult;
-use rustc_errors::{Applicability, Diag, FatalError, MultiSpan};
+use rustc_errors::{Applicability, Diag, FatalError, MultiSpan, PResult};
 use rustc_session::parse::ParseSess;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
@@ -45,8 +45,22 @@ use crate::errors::{
     self, IncorrectVisibilityRestriction, MismatchedClosingDelimiter, NonStringAbiLiteral,
 };
 
+#[cfg(test)]
+mod tests;
+
+// Ideally, these tests would be in `rustc_ast`. But they depend on having a
+// parser, so they are here.
+#[cfg(test)]
+mod tokenstream {
+    mod tests;
+}
+#[cfg(test)]
+mod mut_visit {
+    mod tests;
+}
+
 bitflags::bitflags! {
-    #[derive(Clone, Copy)]
+    #[derive(Clone, Copy, Debug)]
     struct Restrictions: u8 {
         const STMT_EXPR         = 1 << 0;
         const NO_STRUCT_LITERAL = 1 << 1;
@@ -72,7 +86,7 @@ enum BlockMode {
 
 /// Whether or not we should force collection of tokens for an AST node,
 /// regardless of whether or not it has attributes
-#[derive(Clone, Copy, PartialEq)]
+#[derive(Clone, Copy, Debug, PartialEq)]
 pub enum ForceCollect {
     Yes,
     No,
@@ -120,7 +134,7 @@ macro_rules! maybe_recover_from_interpolated_ty_qpath {
     };
 }
 
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
 pub enum Recovery {
     Allowed,
     Forbidden,
@@ -170,7 +184,7 @@ pub struct Parser<'a> {
     capture_state: CaptureState,
     /// This allows us to recover when the user forget to add braces around
     /// multiple statements in the closure body.
-    pub current_closure: Option<ClosureSpans>,
+    current_closure: Option<ClosureSpans>,
     /// Whether the parser is allowed to do recovery.
     /// This is disabled when parsing macro arguments, see #103534
     pub recovery: Recovery,
@@ -182,7 +196,7 @@ pub struct Parser<'a> {
 rustc_data_structures::static_assert_size!(Parser<'_>, 264);
 
 /// Stores span information about a closure.
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 pub struct ClosureSpans {
     pub whole_closure: Span,
     pub closing_pipe: Span,
@@ -211,7 +225,7 @@ pub type ReplaceRange = (Range<u32>, Vec<(FlatToken, Spacing)>);
 /// Controls how we capture tokens. Capturing can be expensive,
 /// so we try to avoid performing capturing in cases where
 /// we will never need an `AttrTokenStream`.
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
 pub enum Capturing {
     /// We aren't performing any capturing - this is the default mode.
     No,
@@ -219,7 +233,7 @@ pub enum Capturing {
     Yes,
 }
 
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 struct CaptureState {
     capturing: Capturing,
     replace_ranges: Vec<ReplaceRange>,
@@ -230,7 +244,7 @@ struct CaptureState {
 /// we (a) lex tokens into a nice tree structure (`TokenStream`), and then (b)
 /// use this type to emit them as a linear sequence. But a linear sequence is
 /// what the parser expects, for the most part.
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 struct TokenCursor {
     // Cursor for the current (innermost) token stream. The delimiters for this
     // token stream are found in `self.stack.last()`; when that is `None` then
@@ -335,6 +349,7 @@ enum TokenExpectType {
 }
 
 /// A sequence separator.
+#[derive(Debug)]
 struct SeqSep {
     /// The separator token.
     sep: Option<TokenKind>,
@@ -352,31 +367,19 @@ impl SeqSep {
     }
 }
 
+#[derive(Debug)]
 pub enum FollowedByType {
     Yes,
     No,
 }
 
-/// Whether a function performed recovery
-#[derive(Copy, Clone, Debug)]
-pub enum Recovered {
-    No,
-    Yes,
-}
-
-impl From<Recovered> for bool {
-    fn from(r: Recovered) -> bool {
-        matches!(r, Recovered::Yes)
-    }
-}
-
 #[derive(Copy, Clone, Debug)]
 pub enum Trailing {
     No,
     Yes,
 }
 
-#[derive(Clone, Copy, PartialEq, Eq)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
 pub enum TokenDescription {
     ReservedIdentifier,
     Keyword,
@@ -839,9 +842,9 @@ impl<'a> Parser<'a> {
                         Ok(Recovered::No) => {
                             self.current_closure.take();
                         }
-                        Ok(Recovered::Yes) => {
+                        Ok(Recovered::Yes(guar)) => {
                             self.current_closure.take();
-                            recovered = Recovered::Yes;
+                            recovered = Recovered::Yes(guar);
                             break;
                         }
                         Err(mut expect_err) => {
@@ -1534,6 +1537,47 @@ impl<'a> Parser<'a> {
             })
     }
 
+    // debug view of the parser's token stream, up to `{lookahead}` tokens
+    pub fn debug_lookahead(&self, lookahead: usize) -> impl fmt::Debug + '_ {
+        struct DebugParser<'dbg> {
+            parser: &'dbg Parser<'dbg>,
+            lookahead: usize,
+        }
+
+        impl fmt::Debug for DebugParser<'_> {
+            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+                let Self { parser, lookahead } = self;
+                let mut dbg_fmt = f.debug_struct("Parser"); // or at least, one view of
+
+                // we don't need N spans, but we want at least one, so print all of prev_token
+                dbg_fmt.field("prev_token", &parser.prev_token);
+                // make it easier to peek farther ahead by taking TokenKinds only until EOF
+                let tokens = (0..*lookahead)
+                    .map(|i| parser.look_ahead(i, |tok| tok.kind.clone()))
+                    .scan(parser.prev_token == TokenKind::Eof, |eof, tok| {
+                        let current = eof.then_some(tok.clone()); // include a trailing EOF token
+                        *eof |= &tok == &TokenKind::Eof;
+                        current
+                    });
+                dbg_fmt.field_with("tokens", |field| field.debug_list().entries(tokens).finish());
+                dbg_fmt.field("approx_token_stream_pos", &parser.num_bump_calls);
+
+                // some fields are interesting for certain values, as they relate to macro parsing
+                if let Some(subparser) = parser.subparser_name {
+                    dbg_fmt.field("subparser_name", &subparser);
+                }
+                if let Recovery::Forbidden = parser.recovery {
+                    dbg_fmt.field("recovery", &parser.recovery);
+                }
+
+                // imply there's "more to know" than this view
+                dbg_fmt.finish_non_exhaustive()
+            }
+        }
+
+        DebugParser { parser: self, lookahead }
+    }
+
     pub fn clear_expected_tokens(&mut self) {
         self.expected_tokens.clear();
     }
diff --git a/compiler/rustc_expand/src/mut_visit/tests.rs b/compiler/rustc_parse/src/parser/mut_visit/tests.rs
index 8974d45b4d8..b3cb28af657 100644
--- a/compiler/rustc_expand/src/mut_visit/tests.rs
+++ b/compiler/rustc_parse/src/parser/mut_visit/tests.rs
@@ -1,5 +1,4 @@
-use crate::tests::{matches_codepattern, string_to_crate};
-
+use crate::parser::tests::{matches_codepattern, string_to_crate};
 use rustc_ast as ast;
 use rustc_ast::mut_visit::MutVisitor;
 use rustc_ast_pretty::pprust;
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index b97ec8c613d..3636a357978 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -160,7 +160,7 @@ impl<'a> Parser<'a> {
         style: PathStyle,
         ty_generics: Option<&Generics>,
     ) -> PResult<'a, Path> {
-        let reject_generics_if_mod_style = |parser: &Parser<'_>, path: &Path| {
+        let reject_generics_if_mod_style = |parser: &Parser<'_>, path: Path| {
             // Ensure generic arguments don't end up in attribute paths, such as:
             //
             //     macro_rules! m {
@@ -178,21 +178,26 @@ impl<'a> Parser<'a> {
                     .map(|arg| arg.span())
                     .collect::<Vec<_>>();
                 parser.dcx().emit_err(errors::GenericsInPath { span });
+                // Ignore these arguments to prevent unexpected behaviors.
+                let segments = path
+                    .segments
+                    .iter()
+                    .map(|segment| PathSegment { ident: segment.ident, id: segment.id, args: None })
+                    .collect();
+                Path { segments, ..path }
+            } else {
+                path
             }
         };
 
-        maybe_whole!(self, NtPath, |path| {
-            reject_generics_if_mod_style(self, &path);
-            path.into_inner()
-        });
+        maybe_whole!(self, NtPath, |path| reject_generics_if_mod_style(self, path.into_inner()));
 
         if let token::Interpolated(nt) = &self.token.kind {
             if let token::NtTy(ty) = &nt.0 {
                 if let ast::TyKind::Path(None, path) = &ty.kind {
                     let path = path.clone();
                     self.bump();
-                    reject_generics_if_mod_style(self, &path);
-                    return Ok(path);
+                    return Ok(reject_generics_if_mod_style(self, path));
                 }
             }
         }
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index 6601011665b..d70afebf1b2 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -11,14 +11,13 @@ use crate::errors;
 use crate::maybe_whole;
 
 use crate::errors::MalformedLoopLabel;
-use crate::parser::Recovered;
 use ast::Label;
 use rustc_ast as ast;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter, TokenKind};
 use rustc_ast::util::classify;
 use rustc_ast::{AttrStyle, AttrVec, LocalKind, MacCall, MacCallStmt, MacStmtStyle};
-use rustc_ast::{Block, BlockCheckMode, Expr, ExprKind, HasAttrs, Local, Stmt};
+use rustc_ast::{Block, BlockCheckMode, Expr, ExprKind, HasAttrs, Local, Recovered, Stmt};
 use rustc_ast::{StmtKind, DUMMY_NODE_ID};
 use rustc_errors::{Applicability, Diag, PResult};
 use rustc_span::symbol::{kw, sym, Ident};
@@ -675,11 +674,8 @@ impl<'a> Parser<'a> {
                 let replace_with_err = 'break_recover: {
                     match expect_result {
                         Ok(Recovered::No) => None,
-                        Ok(Recovered::Yes) => {
+                        Ok(Recovered::Yes(guar)) => {
                             // Skip type error to avoid extra errors.
-                            let guar = self
-                                .dcx()
-                                .span_delayed_bug(self.prev_token.span, "expected `;` or `}`");
                             Some(guar)
                         }
                         Err(e) => {
diff --git a/compiler/rustc_expand/src/tests.rs b/compiler/rustc_parse/src/parser/tests.rs
index 2b0b58eb1d9..a31e350541a 100644
--- a/compiler/rustc_expand/src/tests.rs
+++ b/compiler/rustc_parse/src/parser/tests.rs
@@ -1,25 +1,30 @@
-use rustc_ast as ast;
-use rustc_ast::tokenstream::TokenStream;
-use rustc_parse::{new_parser_from_source_str, parser::Parser, source_file_to_stream};
-use rustc_session::parse::ParseSess;
-use rustc_span::create_default_session_globals_then;
-use rustc_span::source_map::{FilePathMapping, SourceMap};
-use rustc_span::{BytePos, Span};
-
+use crate::parser::ForceCollect;
+use crate::{new_parser_from_source_str, parser::Parser, source_file_to_stream};
+use ast::token::IdentIsRaw;
+use rustc_ast::ptr::P;
+use rustc_ast::token::{self, Delimiter, Token};
+use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
+use rustc_ast::visit;
+use rustc_ast::{self as ast, PatKind};
+use rustc_ast_pretty::pprust::item_to_string;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::emitter::HumanEmitter;
 use rustc_errors::{DiagCtxt, MultiSpan, PResult};
-use termcolor::WriteColor;
-
+use rustc_session::parse::ParseSess;
+use rustc_span::create_default_session_globals_then;
+use rustc_span::source_map::{FilePathMapping, SourceMap};
+use rustc_span::symbol::{kw, sym, Symbol};
+use rustc_span::{BytePos, FileName, Pos, Span};
 use std::io;
 use std::io::prelude::*;
 use std::iter::Peekable;
 use std::path::{Path, PathBuf};
 use std::str;
 use std::sync::{Arc, Mutex};
+use termcolor::WriteColor;
 
-pub(crate) fn psess() -> ParseSess {
-    ParseSess::new(vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE])
+fn psess() -> ParseSess {
+    ParseSess::new(vec![crate::DEFAULT_LOCALE_RESOURCE, crate::DEFAULT_LOCALE_RESOURCE])
 }
 
 /// Map string to parser (via tts).
@@ -31,7 +36,7 @@ fn create_test_handler() -> (DiagCtxt, Lrc<SourceMap>, Arc<Mutex<Vec<u8>>>) {
     let output = Arc::new(Mutex::new(Vec::new()));
     let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty()));
     let fallback_bundle = rustc_errors::fallback_fluent_bundle(
-        vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE],
+        vec![crate::DEFAULT_LOCALE_RESOURCE, crate::DEFAULT_LOCALE_RESOURCE],
         false,
     );
     let emitter = HumanEmitter::new(Box::new(Shared { data: output.clone() }), fallback_bundle)
@@ -44,7 +49,7 @@ fn create_test_handler() -> (DiagCtxt, Lrc<SourceMap>, Arc<Mutex<Vec<u8>>>) {
 /// Returns the result of parsing the given string via the given callback.
 ///
 /// If there are any errors, this will panic.
-pub(crate) fn with_error_checking_parse<'a, T, F>(s: String, psess: &'a ParseSess, f: F) -> T
+fn with_error_checking_parse<'a, T, F>(s: String, psess: &'a ParseSess, f: F) -> T
 where
     F: FnOnce(&mut Parser<'a>) -> PResult<'a, T>,
 {
@@ -56,7 +61,7 @@ where
 
 /// Verifies that parsing the given string using the given callback will
 /// generate an error that contains the given text.
-pub(crate) fn with_expected_parse_error<T, F>(source_str: &str, expected_output: &str, f: F)
+fn with_expected_parse_error<T, F>(source_str: &str, expected_output: &str, f: F)
 where
     F: for<'a> FnOnce(&mut Parser<'a>) -> PResult<'a, T>,
 {
@@ -150,8 +155,8 @@ struct SpanLabel {
     label: &'static str,
 }
 
-pub(crate) struct Shared<T: Write> {
-    pub data: Arc<Mutex<T>>,
+struct Shared<T: Write> {
+    data: Arc<Mutex<T>>,
 }
 
 impl<T: Write> WriteColor for Shared<T> {
@@ -1053,3 +1058,365 @@ error: foo
 "#,
     );
 }
+
+/// Parses an item.
+///
+/// Returns `Ok(Some(item))` when successful, `Ok(None)` when no item was found, and `Err`
+/// when a syntax error occurred.
+fn parse_item_from_source_str(
+    name: FileName,
+    source: String,
+    psess: &ParseSess,
+) -> PResult<'_, Option<P<ast::Item>>> {
+    new_parser_from_source_str(psess, name, source).parse_item(ForceCollect::No)
+}
+
+// Produces a `rustc_span::span`.
+fn sp(a: u32, b: u32) -> Span {
+    Span::with_root_ctxt(BytePos(a), BytePos(b))
+}
+
+/// Parses a string, return an expression.
+fn string_to_expr(source_str: String) -> P<ast::Expr> {
+    with_error_checking_parse(source_str, &psess(), |p| p.parse_expr())
+}
+
+/// Parses a string, returns an item.
+fn string_to_item(source_str: String) -> Option<P<ast::Item>> {
+    with_error_checking_parse(source_str, &psess(), |p| p.parse_item(ForceCollect::No))
+}
+
+#[test]
+fn bad_path_expr_1() {
+    // This should trigger error: expected identifier, found keyword `return`
+    create_default_session_globals_then(|| {
+        with_expected_parse_error(
+            "::abc::def::return",
+            "expected identifier, found keyword `return`",
+            |p| p.parse_expr(),
+        );
+    })
+}
+
+// Checks the token-tree-ization of macros.
+#[test]
+fn string_to_tts_macro() {
+    create_default_session_globals_then(|| {
+        let stream = string_to_stream("macro_rules! zip (($a)=>($a))".to_string());
+        let tts = &stream.trees().collect::<Vec<_>>()[..];
+
+        match tts {
+            [
+                TokenTree::Token(
+                    Token { kind: token::Ident(name_macro_rules, IdentIsRaw::No), .. },
+                    _,
+                ),
+                TokenTree::Token(Token { kind: token::Not, .. }, _),
+                TokenTree::Token(Token { kind: token::Ident(name_zip, IdentIsRaw::No), .. }, _),
+                TokenTree::Delimited(.., macro_delim, macro_tts),
+            ] if name_macro_rules == &kw::MacroRules && name_zip.as_str() == "zip" => {
+                let tts = &macro_tts.trees().collect::<Vec<_>>();
+                match &tts[..] {
+                    [
+                        TokenTree::Delimited(.., first_delim, first_tts),
+                        TokenTree::Token(Token { kind: token::FatArrow, .. }, _),
+                        TokenTree::Delimited(.., second_delim, second_tts),
+                    ] if macro_delim == &Delimiter::Parenthesis => {
+                        let tts = &first_tts.trees().collect::<Vec<_>>();
+                        match &tts[..] {
+                            [
+                                TokenTree::Token(Token { kind: token::Dollar, .. }, _),
+                                TokenTree::Token(
+                                    Token { kind: token::Ident(name, IdentIsRaw::No), .. },
+                                    _,
+                                ),
+                            ] if first_delim == &Delimiter::Parenthesis && name.as_str() == "a" => {
+                            }
+                            _ => panic!("value 3: {:?} {:?}", first_delim, first_tts),
+                        }
+                        let tts = &second_tts.trees().collect::<Vec<_>>();
+                        match &tts[..] {
+                            [
+                                TokenTree::Token(Token { kind: token::Dollar, .. }, _),
+                                TokenTree::Token(
+                                    Token { kind: token::Ident(name, IdentIsRaw::No), .. },
+                                    _,
+                                ),
+                            ] if second_delim == &Delimiter::Parenthesis
+                                && name.as_str() == "a" => {}
+                            _ => panic!("value 4: {:?} {:?}", second_delim, second_tts),
+                        }
+                    }
+                    _ => panic!("value 2: {:?} {:?}", macro_delim, macro_tts),
+                }
+            }
+            _ => panic!("value: {:?}", tts),
+        }
+    })
+}
+
+#[test]
+fn string_to_tts_1() {
+    create_default_session_globals_then(|| {
+        let tts = string_to_stream("fn a(b: i32) { b; }".to_string());
+
+        let expected = TokenStream::new(vec![
+            TokenTree::token_alone(token::Ident(kw::Fn, IdentIsRaw::No), sp(0, 2)),
+            TokenTree::token_joint_hidden(
+                token::Ident(Symbol::intern("a"), IdentIsRaw::No),
+                sp(3, 4),
+            ),
+            TokenTree::Delimited(
+                DelimSpan::from_pair(sp(4, 5), sp(11, 12)),
+                // `JointHidden` because the `(` is followed immediately by
+                // `b`, `Alone` because the `)` is followed by whitespace.
+                DelimSpacing::new(Spacing::JointHidden, Spacing::Alone),
+                Delimiter::Parenthesis,
+                TokenStream::new(vec![
+                    TokenTree::token_joint(
+                        token::Ident(Symbol::intern("b"), IdentIsRaw::No),
+                        sp(5, 6),
+                    ),
+                    TokenTree::token_alone(token::Colon, sp(6, 7)),
+                    // `JointHidden` because the `i32` is immediately followed by the `)`.
+                    TokenTree::token_joint_hidden(
+                        token::Ident(sym::i32, IdentIsRaw::No),
+                        sp(8, 11),
+                    ),
+                ])
+                .into(),
+            ),
+            TokenTree::Delimited(
+                DelimSpan::from_pair(sp(13, 14), sp(18, 19)),
+                // First `Alone` because the `{` is followed by whitespace,
+                // second `Alone` because the `}` is followed immediately by
+                // EOF.
+                DelimSpacing::new(Spacing::Alone, Spacing::Alone),
+                Delimiter::Brace,
+                TokenStream::new(vec![
+                    TokenTree::token_joint(
+                        token::Ident(Symbol::intern("b"), IdentIsRaw::No),
+                        sp(15, 16),
+                    ),
+                    // `Alone` because the `;` is followed by whitespace.
+                    TokenTree::token_alone(token::Semi, sp(16, 17)),
+                ])
+                .into(),
+            ),
+        ]);
+
+        assert_eq!(tts, expected);
+    })
+}
+
+#[test]
+fn parse_use() {
+    create_default_session_globals_then(|| {
+        let use_s = "use foo::bar::baz;";
+        let vitem = string_to_item(use_s.to_string()).unwrap();
+        let vitem_s = item_to_string(&vitem);
+        assert_eq!(&vitem_s[..], use_s);
+
+        let use_s = "use foo::bar as baz;";
+        let vitem = string_to_item(use_s.to_string()).unwrap();
+        let vitem_s = item_to_string(&vitem);
+        assert_eq!(&vitem_s[..], use_s);
+    })
+}
+
+#[test]
+fn parse_extern_crate() {
+    create_default_session_globals_then(|| {
+        let ex_s = "extern crate foo;";
+        let vitem = string_to_item(ex_s.to_string()).unwrap();
+        let vitem_s = item_to_string(&vitem);
+        assert_eq!(&vitem_s[..], ex_s);
+
+        let ex_s = "extern crate foo as bar;";
+        let vitem = string_to_item(ex_s.to_string()).unwrap();
+        let vitem_s = item_to_string(&vitem);
+        assert_eq!(&vitem_s[..], ex_s);
+    })
+}
+
+fn get_spans_of_pat_idents(src: &str) -> Vec<Span> {
+    let item = string_to_item(src.to_string()).unwrap();
+
+    struct PatIdentVisitor {
+        spans: Vec<Span>,
+    }
+    impl<'a> visit::Visitor<'a> for PatIdentVisitor {
+        fn visit_pat(&mut self, p: &'a ast::Pat) {
+            match &p.kind {
+                PatKind::Ident(_, ident, _) => {
+                    self.spans.push(ident.span);
+                }
+                _ => {
+                    visit::walk_pat(self, p);
+                }
+            }
+        }
+    }
+    let mut v = PatIdentVisitor { spans: Vec::new() };
+    visit::walk_item(&mut v, &item);
+    return v.spans;
+}
+
+#[test]
+fn span_of_self_arg_pat_idents_are_correct() {
+    create_default_session_globals_then(|| {
+        let srcs = [
+            "impl z { fn a (&self, &myarg: i32) {} }",
+            "impl z { fn a (&mut self, &myarg: i32) {} }",
+            "impl z { fn a (&'a self, &myarg: i32) {} }",
+            "impl z { fn a (self, &myarg: i32) {} }",
+            "impl z { fn a (self: Foo, &myarg: i32) {} }",
+        ];
+
+        for src in srcs {
+            let spans = get_spans_of_pat_idents(src);
+            let (lo, hi) = (spans[0].lo(), spans[0].hi());
+            assert!(
+                "self" == &src[lo.to_usize()..hi.to_usize()],
+                "\"{}\" != \"self\". src=\"{}\"",
+                &src[lo.to_usize()..hi.to_usize()],
+                src
+            )
+        }
+    })
+}
+
+#[test]
+fn parse_exprs() {
+    create_default_session_globals_then(|| {
+        // just make sure that they parse....
+        string_to_expr("3 + 4".to_string());
+        string_to_expr("a::z.froob(b,&(987+3))".to_string());
+    })
+}
+
+#[test]
+fn attrs_fix_bug() {
+    create_default_session_globals_then(|| {
+        string_to_item(
+            "pub fn mk_file_writer(path: &Path, flags: &[FileFlag])
+                -> Result<Box<Writer>, String> {
+#[cfg(windows)]
+fn wb() -> c_int {
+    (O_WRONLY | libc::consts::os::extra::O_BINARY) as c_int
+}
+
+#[cfg(unix)]
+fn wb() -> c_int { O_WRONLY as c_int }
+
+let mut fflags: c_int = wb();
+}"
+            .to_string(),
+        );
+    })
+}
+
+#[test]
+fn crlf_doc_comments() {
+    create_default_session_globals_then(|| {
+        let psess = psess();
+
+        let name_1 = FileName::Custom("crlf_source_1".to_string());
+        let source = "/// doc comment\r\nfn foo() {}".to_string();
+        let item = parse_item_from_source_str(name_1, source, &psess).unwrap().unwrap();
+        let doc = item.attrs.iter().filter_map(|at| at.doc_str()).next().unwrap();
+        assert_eq!(doc.as_str(), " doc comment");
+
+        let name_2 = FileName::Custom("crlf_source_2".to_string());
+        let source = "/// doc comment\r\n/// line 2\r\nfn foo() {}".to_string();
+        let item = parse_item_from_source_str(name_2, source, &psess).unwrap().unwrap();
+        let docs = item.attrs.iter().filter_map(|at| at.doc_str()).collect::<Vec<_>>();
+        let b: &[_] = &[Symbol::intern(" doc comment"), Symbol::intern(" line 2")];
+        assert_eq!(&docs[..], b);
+
+        let name_3 = FileName::Custom("clrf_source_3".to_string());
+        let source = "/** doc comment\r\n *  with CRLF */\r\nfn foo() {}".to_string();
+        let item = parse_item_from_source_str(name_3, source, &psess).unwrap().unwrap();
+        let doc = item.attrs.iter().filter_map(|at| at.doc_str()).next().unwrap();
+        assert_eq!(doc.as_str(), " doc comment\n *  with CRLF ");
+    });
+}
+
+#[test]
+fn ttdelim_span() {
+    fn parse_expr_from_source_str(
+        name: FileName,
+        source: String,
+        psess: &ParseSess,
+    ) -> PResult<'_, P<ast::Expr>> {
+        new_parser_from_source_str(psess, name, source).parse_expr()
+    }
+
+    create_default_session_globals_then(|| {
+        let psess = psess();
+        let expr = parse_expr_from_source_str(
+            PathBuf::from("foo").into(),
+            "foo!( fn main() { body } )".to_string(),
+            &psess,
+        )
+        .unwrap();
+
+        let ast::ExprKind::MacCall(mac) = &expr.kind else { panic!("not a macro") };
+        let span = mac.args.tokens.trees().last().unwrap().span();
+
+        match psess.source_map().span_to_snippet(span) {
+            Ok(s) => assert_eq!(&s[..], "{ body }"),
+            Err(_) => panic!("could not get snippet"),
+        }
+    });
+}
+
+// This tests that when parsing a string (rather than a file) we don't try
+// and read in a file for a module declaration and just parse a stub.
+// See `recurse_into_file_modules` in the parser.
+#[test]
+fn out_of_line_mod() {
+    create_default_session_globals_then(|| {
+        let item = parse_item_from_source_str(
+            PathBuf::from("foo").into(),
+            "mod foo { struct S; mod this_does_not_exist; }".to_owned(),
+            &psess(),
+        )
+        .unwrap()
+        .unwrap();
+
+        let ast::ItemKind::Mod(_, mod_kind) = &item.kind else { panic!() };
+        assert!(matches!(mod_kind, ast::ModKind::Loaded(items, ..) if items.len() == 2));
+    });
+}
+
+#[test]
+fn eqmodws() {
+    assert_eq!(matches_codepattern("", ""), true);
+    assert_eq!(matches_codepattern("", "a"), false);
+    assert_eq!(matches_codepattern("a", ""), false);
+    assert_eq!(matches_codepattern("a", "a"), true);
+    assert_eq!(matches_codepattern("a b", "a   \n\t\r  b"), true);
+    assert_eq!(matches_codepattern("a b ", "a   \n\t\r  b"), true);
+    assert_eq!(matches_codepattern("a b", "a   \n\t\r  b "), false);
+    assert_eq!(matches_codepattern("a   b", "a b"), true);
+    assert_eq!(matches_codepattern("ab", "a b"), false);
+    assert_eq!(matches_codepattern("a   b", "ab"), true);
+    assert_eq!(matches_codepattern(" a   b", "ab"), true);
+}
+
+#[test]
+fn pattern_whitespace() {
+    assert_eq!(matches_codepattern("", "\x0C"), false);
+    assert_eq!(matches_codepattern("a b ", "a   \u{0085}\n\t\r  b"), true);
+    assert_eq!(matches_codepattern("a b", "a   \u{0085}\n\t\r  b "), false);
+}
+
+#[test]
+fn non_pattern_whitespace() {
+    // These have the property 'White_Space' but not 'Pattern_White_Space'
+    assert_eq!(matches_codepattern("a b", "a\u{2002}b"), false);
+    assert_eq!(matches_codepattern("a   b", "a\u{2002}b"), false);
+    assert_eq!(matches_codepattern("\u{205F}a   b", "ab"), false);
+    assert_eq!(matches_codepattern("a  \u{3000}b", "ab"), false);
+}
diff --git a/compiler/rustc_expand/src/tokenstream/tests.rs b/compiler/rustc_parse/src/parser/tokenstream/tests.rs
index 78795e86fd5..9be00a14791 100644
--- a/compiler/rustc_expand/src/tokenstream/tests.rs
+++ b/compiler/rustc_parse/src/parser/tokenstream/tests.rs
@@ -1,5 +1,4 @@
-use crate::tests::string_to_stream;
-
+use crate::parser::tests::string_to_stream;
 use rustc_ast::token::{self, IdentIsRaw};
 use rustc_ast::tokenstream::{TokenStream, TokenTree};
 use rustc_span::create_default_session_globals_then;
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index 9d58d301e2b..3deefcaa06c 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -52,16 +52,16 @@ passes_attr_only_in_functions =
 passes_both_ffi_const_and_pure =
     `#[ffi_const]` function cannot be `#[ffi_pure]`
 
-passes_break_inside_async_block =
-    `{$name}` inside of an `async` block
-    .label = cannot `{$name}` inside of an `async` block
-    .async_block_label = enclosing `async` block
-
 passes_break_inside_closure =
     `{$name}` inside of a closure
     .label = cannot `{$name}` inside of a closure
     .closure_label = enclosing closure
 
+passes_break_inside_coroutine =
+    `{$name}` inside `{$kind}` {$source}
+    .label = cannot `{$name}` inside `{$kind}` {$source}
+    .coroutine_label = enclosing `{$kind}` {$source}
+
 passes_break_non_loop =
     `break` with value from a `{$kind}` loop
     .label = can only break with a value inside `loop` or breakable block
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 65cad82cc8c..b8586e7e974 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -1086,14 +1086,16 @@ pub struct BreakInsideClosure<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_break_inside_async_block, code = E0267)]
-pub struct BreakInsideAsyncBlock<'a> {
+#[diag(passes_break_inside_coroutine, code = E0267)]
+pub struct BreakInsideCoroutine<'a> {
     #[primary_span]
     #[label]
     pub span: Span,
-    #[label(passes_async_block_label)]
-    pub closure_span: Span,
+    #[label(passes_coroutine_label)]
+    pub coroutine_span: Span,
     pub name: &'a str,
+    pub kind: &'a str,
+    pub source: &'a str,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs
index 4b5c4dfe991..3b20112eab7 100644
--- a/compiler/rustc_passes/src/loops.rs
+++ b/compiler/rustc_passes/src/loops.rs
@@ -13,7 +13,7 @@ use rustc_span::hygiene::DesugaringKind;
 use rustc_span::{BytePos, Span};
 
 use crate::errors::{
-    BreakInsideAsyncBlock, BreakInsideClosure, BreakNonLoop, ContinueLabeledBlock, OutsideLoop,
+    BreakInsideClosure, BreakInsideCoroutine, BreakNonLoop, ContinueLabeledBlock, OutsideLoop,
     OutsideLoopSuggestion, UnlabeledCfInWhileCondition, UnlabeledInLabeledBlock,
 };
 
@@ -23,7 +23,7 @@ enum Context {
     Fn,
     Loop(hir::LoopSource),
     Closure(Span),
-    AsyncClosure(Span),
+    Coroutine { coroutine_span: Span, kind: hir::CoroutineDesugaring, source: hir::CoroutineSource },
     UnlabeledBlock(Span),
     LabeledBlock,
     Constant,
@@ -89,12 +89,10 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
             hir::ExprKind::Closure(&hir::Closure {
                 ref fn_decl, body, fn_decl_span, kind, ..
             }) => {
-                // FIXME(coroutines): This doesn't handle coroutines correctly
                 let cx = match kind {
-                    hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
-                        hir::CoroutineDesugaring::Async,
-                        hir::CoroutineSource::Block,
-                    )) => AsyncClosure(fn_decl_span),
+                    hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(kind, source)) => {
+                        Coroutine { coroutine_span: fn_decl_span, kind, source }
+                    }
                     _ => Closure(fn_decl_span),
                 };
                 self.visit_fn_decl(fn_decl);
@@ -227,8 +225,24 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> {
             Closure(closure_span) => {
                 self.sess.dcx().emit_err(BreakInsideClosure { span, closure_span, name });
             }
-            AsyncClosure(closure_span) => {
-                self.sess.dcx().emit_err(BreakInsideAsyncBlock { span, closure_span, name });
+            Coroutine { coroutine_span, kind, source } => {
+                let kind = match kind {
+                    hir::CoroutineDesugaring::Async => "async",
+                    hir::CoroutineDesugaring::Gen => "gen",
+                    hir::CoroutineDesugaring::AsyncGen => "async gen",
+                };
+                let source = match source {
+                    hir::CoroutineSource::Block => "block",
+                    hir::CoroutineSource::Closure => "closure",
+                    hir::CoroutineSource::Fn => "function",
+                };
+                self.sess.dcx().emit_err(BreakInsideCoroutine {
+                    span,
+                    coroutine_span,
+                    name,
+                    kind,
+                    source,
+                });
             }
             UnlabeledBlock(block_span) if is_break && block_span.eq_ctxt(break_span) => {
                 let suggestion = Some(OutsideLoopSuggestion { block_span, break_span });
diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs
index d5e1a70fd45..55b7c6dce4d 100644
--- a/compiler/rustc_passes/src/reachable.rs
+++ b/compiler/rustc_passes/src/reachable.rs
@@ -1,14 +1,26 @@
-//! Finds local items that are externally reachable, which means that other crates need access to
-//! their compiled machine code or their MIR.
+//! Finds local items that are "reachable", which means that other crates need access to their
+//! compiled code or their *runtime* MIR. (Compile-time MIR is always encoded anyway, so we don't
+//! worry about that here.)
 //!
-//! An item is "externally reachable" if it is relevant for other crates. This obviously includes
-//! all public items. However, some of these items cannot be compiled to machine code (because they
-//! are generic), and for some the machine code is not sufficient (because we want to cross-crate
-//! inline them). These items "need cross-crate MIR". When a reachable function `f` needs
-//! cross-crate MIR, then all the functions it calls also become reachable, as they will be
-//! necessary to use the MIR of `f` from another crate. Furthermore, an item can become "externally
-//! reachable" by having a `const`/`const fn` return a pointer to that item, so we also need to
-//! recurse into reachable `const`/`const fn`.
+//! An item is "reachable" if codegen that happens in downstream crates can end up referencing this
+//! item. This obviously includes all public items. However, some of these items cannot be codegen'd
+//! (because they are generic), and for some the compiled code is not sufficient (because we want to
+//! cross-crate inline them). These items "need cross-crate MIR". When a reachable function `f`
+//! needs cross-crate MIR, then its MIR may be codegen'd in a downstream crate, and hence items it
+//! mentions need to be considered reachable.
+//!
+//! Furthermore, if a `const`/`const fn` is reachable, then it can return pointers to other items,
+//! making those reachable as well. For instance, consider a `const fn` returning a pointer to an
+//! otherwise entirely private function: if a downstream crate calls that `const fn` to compute the
+//! initial value of a `static`, then it needs to generate a direct reference to this function --
+//! i.e., the function is directly reachable from that downstream crate! Hence we have to recurse
+//! into `const` and `const fn`.
+//!
+//! Conversely, reachability *stops* when it hits a monomorphic non-`const` function that we do not
+//! want to cross-crate inline. That function will just be codegen'd in this crate, which means the
+//! monomorphization collector will consider it a root and then do another graph traversal to
+//! codegen everything called by this function -- but that's a very different graph from what we are
+//! considering here as at that point, everything is monomorphic.
 
 use hir::def_id::LocalDefIdSet;
 use rustc_data_structures::stack::ensure_sufficient_stack;
diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs
index 74af9154f85..6e96a93473f 100644
--- a/compiler/rustc_pattern_analysis/src/usefulness.rs
+++ b/compiler/rustc_pattern_analysis/src/usefulness.rs
@@ -42,7 +42,6 @@
 //! This is enough to compute usefulness: a pattern in a `match` expression is redundant iff it is
 //! not useful w.r.t. the patterns above it:
 //! ```compile_fail,E0004
-//! # #![feature(exclusive_range_pattern)]
 //! # fn foo() {
 //! match Some(0u32) {
 //!     Some(0..100) => {},
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index a78f7e65981..c8143015583 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -20,6 +20,7 @@ use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{AssocItemKind, ForeignItemKind, ItemId, ItemKind, PatKind};
 use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level};
 use rustc_middle::query::Providers;
+use rustc_middle::ty::print::PrintTraitRefExt as _;
 use rustc_middle::ty::GenericArgs;
 use rustc_middle::ty::{self, Const, GenericParamDefKind};
 use rustc_middle::ty::{TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
@@ -787,7 +788,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
 
 impl ReachEverythingInTheInterfaceVisitor<'_, '_> {
     fn generics(&mut self) -> &mut Self {
-        for param in &self.ev.tcx.generics_of(self.item_def_id).params {
+        for param in &self.ev.tcx.generics_of(self.item_def_id).own_params {
             match param.kind {
                 GenericParamDefKind::Lifetime => {}
                 GenericParamDefKind::Type { has_default, .. } => {
@@ -1259,7 +1260,7 @@ struct SearchInterfaceForPrivateItemsVisitor<'tcx> {
 impl SearchInterfaceForPrivateItemsVisitor<'_> {
     fn generics(&mut self) -> &mut Self {
         self.in_primary_interface = true;
-        for param in &self.tcx.generics_of(self.item_def_id).params {
+        for param in &self.tcx.generics_of(self.item_def_id).own_params {
             match param.kind {
                 GenericParamDefKind::Lifetime => {}
                 GenericParamDefKind::Type { has_default, .. } => {
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index aa965779731..a7696b1fbaf 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -2,8 +2,6 @@
 //! generate the actual methods on tcx which find and execute the provider,
 //! manage the caches, and so forth.
 
-use crate::rustc_middle::dep_graph::DepContext;
-use crate::rustc_middle::ty::TyEncoder;
 use crate::QueryConfigRestored;
 use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
 use rustc_data_structures::sync::Lock;
@@ -13,14 +11,14 @@ use rustc_errors::DiagInner;
 use rustc_index::Idx;
 use rustc_middle::dep_graph::dep_kinds;
 use rustc_middle::dep_graph::{
-    self, DepKind, DepKindStruct, DepNode, DepNodeIndex, SerializedDepNodeIndex,
+    self, DepContext, DepKind, DepKindStruct, DepNode, DepNodeIndex, SerializedDepNodeIndex,
 };
 use rustc_middle::query::on_disk_cache::AbsoluteBytePos;
 use rustc_middle::query::on_disk_cache::{CacheDecoder, CacheEncoder, EncodedDepNodeIndex};
 use rustc_middle::query::Key;
 use rustc_middle::ty::print::with_reduced_queries;
 use rustc_middle::ty::tls::{self, ImplicitCtxt};
-use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::ty::{self, TyCtxt, TyEncoder};
 use rustc_query_system::dep_graph::{DepNodeParams, HasDepContext};
 use rustc_query_system::ich::StableHashingContext;
 use rustc_query_system::query::{
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 8068ea1a407..3467f1c3edf 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -560,7 +560,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
 
                 self.add_import(prefix, kind, use_tree.span, item, root_span, item.id, vis);
             }
-            ast::UseTreeKind::Nested(ref items) => {
+            ast::UseTreeKind::Nested { ref items, .. } => {
                 // Ensure there is at most one `self` in the list
                 let self_spans = items
                     .iter()
diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs
index f6004fed828..5fe68085d65 100644
--- a/compiler/rustc_resolve/src/check_unused.rs
+++ b/compiler/rustc_resolve/src/check_unused.rs
@@ -128,7 +128,7 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> {
                     self.unused_import(self.base_id).add(id);
                 }
             }
-            ast::UseTreeKind::Nested(ref items) => self.check_imports_as_underscore(items),
+            ast::UseTreeKind::Nested { ref items, .. } => self.check_imports_as_underscore(items),
             _ => {}
         }
     }
@@ -254,7 +254,7 @@ impl<'a, 'b, 'tcx> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
             return;
         }
 
-        if let ast::UseTreeKind::Nested(ref items) = use_tree.kind {
+        if let ast::UseTreeKind::Nested { ref items, .. } = use_tree.kind {
             if items.is_empty() {
                 self.unused_import(self.base_id).add(id);
             }
@@ -268,9 +268,8 @@ impl<'a, 'b, 'tcx> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
 
 enum UnusedSpanResult {
     Used,
-    FlatUnused(Span, Span),
-    NestedFullUnused(Vec<Span>, Span),
-    NestedPartialUnused(Vec<Span>, Vec<Span>),
+    Unused { spans: Vec<Span>, remove: Span },
+    PartialUnused { spans: Vec<Span>, remove: Vec<Span> },
 }
 
 fn calc_unused_spans(
@@ -288,36 +287,33 @@ fn calc_unused_spans(
     match use_tree.kind {
         ast::UseTreeKind::Simple(..) | ast::UseTreeKind::Glob => {
             if unused_import.unused.contains(&use_tree_id) {
-                UnusedSpanResult::FlatUnused(use_tree.span, full_span)
+                UnusedSpanResult::Unused { spans: vec![use_tree.span], remove: full_span }
             } else {
                 UnusedSpanResult::Used
             }
         }
-        ast::UseTreeKind::Nested(ref nested) => {
+        ast::UseTreeKind::Nested { items: ref nested, span: tree_span } => {
             if nested.is_empty() {
-                return UnusedSpanResult::FlatUnused(use_tree.span, full_span);
+                return UnusedSpanResult::Unused { spans: vec![use_tree.span], remove: full_span };
             }
 
             let mut unused_spans = Vec::new();
             let mut to_remove = Vec::new();
-            let mut all_nested_unused = true;
+            let mut used_childs = 0;
+            let mut contains_self = false;
             let mut previous_unused = false;
             for (pos, (use_tree, use_tree_id)) in nested.iter().enumerate() {
                 let remove = match calc_unused_spans(unused_import, use_tree, *use_tree_id) {
                     UnusedSpanResult::Used => {
-                        all_nested_unused = false;
+                        used_childs += 1;
                         None
                     }
-                    UnusedSpanResult::FlatUnused(span, remove) => {
-                        unused_spans.push(span);
-                        Some(remove)
-                    }
-                    UnusedSpanResult::NestedFullUnused(mut spans, remove) => {
+                    UnusedSpanResult::Unused { mut spans, remove } => {
                         unused_spans.append(&mut spans);
                         Some(remove)
                     }
-                    UnusedSpanResult::NestedPartialUnused(mut spans, mut to_remove_extra) => {
-                        all_nested_unused = false;
+                    UnusedSpanResult::PartialUnused { mut spans, remove: mut to_remove_extra } => {
+                        used_childs += 1;
                         unused_spans.append(&mut spans);
                         to_remove.append(&mut to_remove_extra);
                         None
@@ -326,7 +322,7 @@ fn calc_unused_spans(
                 if let Some(remove) = remove {
                     let remove_span = if nested.len() == 1 {
                         remove
-                    } else if pos == nested.len() - 1 || !all_nested_unused {
+                    } else if pos == nested.len() - 1 || used_childs > 0 {
                         // Delete everything from the end of the last import, to delete the
                         // previous comma
                         nested[pos - 1].0.span.shrink_to_hi().to(use_tree.span)
@@ -344,14 +340,38 @@ fn calc_unused_spans(
                         to_remove.push(remove_span);
                     }
                 }
+                contains_self |= use_tree.prefix == kw::SelfLower
+                    && matches!(use_tree.kind, ast::UseTreeKind::Simple(None));
                 previous_unused = remove.is_some();
             }
             if unused_spans.is_empty() {
                 UnusedSpanResult::Used
-            } else if all_nested_unused {
-                UnusedSpanResult::NestedFullUnused(unused_spans, full_span)
+            } else if used_childs == 0 {
+                UnusedSpanResult::Unused { spans: unused_spans, remove: full_span }
             } else {
-                UnusedSpanResult::NestedPartialUnused(unused_spans, to_remove)
+                // If there is only one remaining child that is used, the braces around the use
+                // tree are not needed anymore. In that case, we determine the span of the left
+                // brace and the right brace, and tell rustfix to remove them as well.
+                //
+                // This means that `use a::{B, C};` will be turned into `use a::B;` rather than
+                // `use a::{B};`, removing a rustfmt roundtrip.
+                //
+                // Note that we cannot remove the braces if the only item inside the use tree is
+                // `self`: `use foo::{self};` is valid Rust syntax, while `use foo::self;` errors
+                // out. We also cannot turn `use foo::{self}` into `use foo`, as the former doesn't
+                // import types with the same name as the module.
+                if used_childs == 1 && !contains_self {
+                    // Left brace, from the start of the nested group to the first item.
+                    to_remove.push(
+                        tree_span.shrink_to_lo().to(nested.first().unwrap().0.span.shrink_to_lo()),
+                    );
+                    // Right brace, from the end of the last item to the end of the nested group.
+                    to_remove.push(
+                        nested.last().unwrap().0.span.shrink_to_hi().to(tree_span.shrink_to_hi()),
+                    );
+                }
+
+                UnusedSpanResult::PartialUnused { spans: unused_spans, remove: to_remove }
             }
         }
     }
@@ -417,15 +437,11 @@ impl Resolver<'_, '_> {
             let mut fixes = Vec::new();
             let spans = match calc_unused_spans(unused, &unused.use_tree, unused.use_tree_id) {
                 UnusedSpanResult::Used => continue,
-                UnusedSpanResult::FlatUnused(span, remove) => {
-                    fixes.push((remove, String::new()));
-                    vec![span]
-                }
-                UnusedSpanResult::NestedFullUnused(spans, remove) => {
+                UnusedSpanResult::Unused { spans, remove } => {
                     fixes.push((remove, String::new()));
                     spans
                 }
-                UnusedSpanResult::NestedPartialUnused(spans, remove) => {
+                UnusedSpanResult::PartialUnused { spans, remove } => {
                     for fix in &remove {
                         fixes.push((*fix, String::new()));
                     }
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 6c870ddfd22..5dd95a1896b 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -2347,8 +2347,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                     None => {}
                 }
             }
-        } else if let UseTreeKind::Nested(use_trees) = &use_tree.kind {
-            for (use_tree, _) in use_trees {
+        } else if let UseTreeKind::Nested { items, .. } = &use_tree.kind {
+            for (use_tree, _) in items {
                 self.future_proof_import(use_tree);
             }
         }
@@ -2525,7 +2525,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             ItemKind::Use(ref use_tree) => {
                 let maybe_exported = match use_tree.kind {
                     UseTreeKind::Simple(_) | UseTreeKind::Glob => MaybeExported::Ok(item.id),
-                    UseTreeKind::Nested(_) => MaybeExported::NestedUse(&item.vis),
+                    UseTreeKind::Nested { .. } => MaybeExported::NestedUse(&item.vis),
                 };
                 self.resolve_doc_links(&item.attrs, maybe_exported);
 
diff --git a/compiler/rustc_session/src/config/cfg.rs b/compiler/rustc_session/src/config/cfg.rs
index 31badbd8692..2fa04bbe345 100644
--- a/compiler/rustc_session/src/config/cfg.rs
+++ b/compiler/rustc_session/src/config/cfg.rs
@@ -262,13 +262,15 @@ impl CheckCfg {
 
         ins!(sym::debug_assertions, no_values);
 
-        // These four are never set by rustc, but we set them anyway: they
-        // should not trigger a lint because `cargo clippy`, `cargo doc`,
-        // `cargo test` and `cargo miri run` (respectively) can set them.
+        // These four are never set by rustc, but we set them anyway; they
+        // should not trigger the lint because `cargo clippy`, `cargo doc`,
+        // `cargo test`, `cargo miri run` and `cargo fmt` (respectively)
+        // can set them.
         ins!(sym::clippy, no_values);
         ins!(sym::doc, no_values);
         ins!(sym::doctest, no_values);
         ins!(sym::miri, no_values);
+        ins!(sym::rustfmt, no_values);
 
         ins!(sym::overflow_checks, no_values);
 
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs
index 6fb1560ac6c..cbc3aae1703 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs
@@ -256,10 +256,9 @@ impl<'tcx> Stable<'tcx> for rustc_abi::Primitive {
             rustc_abi::Primitive::Int(length, signed) => {
                 Primitive::Int { length: length.stable(tables), signed: *signed }
             }
-            rustc_abi::Primitive::F16 => Primitive::Float { length: FloatLength::F16 },
-            rustc_abi::Primitive::F32 => Primitive::Float { length: FloatLength::F32 },
-            rustc_abi::Primitive::F64 => Primitive::Float { length: FloatLength::F64 },
-            rustc_abi::Primitive::F128 => Primitive::Float { length: FloatLength::F128 },
+            rustc_abi::Primitive::Float(length) => {
+                Primitive::Float { length: length.stable(tables) }
+            }
             rustc_abi::Primitive::Pointer(space) => Primitive::Pointer(space.stable(tables)),
         }
     }
@@ -287,6 +286,19 @@ impl<'tcx> Stable<'tcx> for rustc_abi::Integer {
     }
 }
 
+impl<'tcx> Stable<'tcx> for rustc_abi::Float {
+    type T = FloatLength;
+
+    fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
+        match self {
+            rustc_abi::Float::F16 => FloatLength::F16,
+            rustc_abi::Float::F32 => FloatLength::F32,
+            rustc_abi::Float::F64 => FloatLength::F64,
+            rustc_abi::Float::F128 => FloatLength::F128,
+        }
+    }
+}
+
 impl<'tcx> Stable<'tcx> for rustc_abi::WrappingRange {
     type T = WrappingRange;
 
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
index 4abf991fba2..c442d33cf86 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
@@ -523,7 +523,7 @@ impl<'tcx> Stable<'tcx> for ty::Generics {
     fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
         use stable_mir::ty::Generics;
 
-        let params: Vec<_> = self.params.iter().map(|param| param.stable(tables)).collect();
+        let params: Vec<_> = self.own_params.iter().map(|param| param.stable(tables)).collect();
         let param_def_id_to_index =
             params.iter().map(|param| (param.def_id, param.index)).collect();
 
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 9c556f1152a..d41059e8c24 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1511,6 +1511,7 @@ symbols! {
         require,
         residual,
         result,
+        result_ffi_guarantees,
         resume,
         return_position_impl_trait_in_trait,
         return_type_notation,
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 5cdfb773b5c..1de2ecbb700 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -630,8 +630,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
                         let pointee_ty = ct
                             .ty()
                             .builtin_deref(true)
-                            .expect("tried to dereference on non-ptr type")
-                            .ty;
+                            .expect("tried to dereference on non-ptr type");
                         // FIXME(const_generics): add an assert that we only do this for valtrees.
                         let dereferenced_const = self.tcx.mk_ct_from_kind(ct.kind(), pointee_ty);
                         dereferenced_const.print(self)?;
diff --git a/compiler/rustc_target/src/abi/call/loongarch.rs b/compiler/rustc_target/src/abi/call/loongarch.rs
index 943b12a9fbf..893818af77c 100644
--- a/compiler/rustc_target/src/abi/call/loongarch.rs
+++ b/compiler/rustc_target/src/abi/call/loongarch.rs
@@ -59,7 +59,7 @@ where
                     _ => return Err(CannotUseFpConv),
                 }
             }
-            abi::F16 | abi::F32 | abi::F64 | abi::F128 => {
+            abi::Float(_) => {
                 if arg_layout.size.bits() > flen {
                     return Err(CannotUseFpConv);
                 }
diff --git a/compiler/rustc_target/src/abi/call/mips64.rs b/compiler/rustc_target/src/abi/call/mips64.rs
index b2a2c34b980..5b52ebbdedd 100644
--- a/compiler/rustc_target/src/abi/call/mips64.rs
+++ b/compiler/rustc_target/src/abi/call/mips64.rs
@@ -26,8 +26,8 @@ where
 {
     match ret.layout.field(cx, i).abi {
         abi::Abi::Scalar(scalar) => match scalar.primitive() {
-            abi::F32 => Some(Reg::f32()),
-            abi::F64 => Some(Reg::f64()),
+            abi::Float(abi::F32) => Some(Reg::f32()),
+            abi::Float(abi::F64) => Some(Reg::f64()),
             _ => None,
         },
         _ => None,
@@ -110,7 +110,7 @@ where
 
                 // We only care about aligned doubles
                 if let abi::Abi::Scalar(scalar) = field.abi {
-                    if let abi::F64 = scalar.primitive() {
+                    if scalar.primitive() == abi::Float(abi::F64) {
                         if offset.is_aligned(dl.f64_align.abi) {
                             // Insert enough integers to cover [last_offset, offset)
                             assert!(last_offset.is_aligned(dl.f64_align.abi));
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index 3ddea42f67b..919fa2140d5 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -443,7 +443,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
             Abi::Scalar(scalar) => {
                 let kind = match scalar.primitive() {
                     abi::Int(..) | abi::Pointer(_) => RegKind::Integer,
-                    abi::F16 | abi::F32 | abi::F64 | abi::F128 => RegKind::Float,
+                    abi::Float(_) => RegKind::Float,
                 };
                 Ok(HomogeneousAggregate::Homogeneous(Reg { kind, size: self.size }))
             }
diff --git a/compiler/rustc_target/src/abi/call/riscv.rs b/compiler/rustc_target/src/abi/call/riscv.rs
index 5d4b3a9d245..84f13f8cc5d 100644
--- a/compiler/rustc_target/src/abi/call/riscv.rs
+++ b/compiler/rustc_target/src/abi/call/riscv.rs
@@ -65,7 +65,7 @@ where
                     _ => return Err(CannotUseFpConv),
                 }
             }
-            abi::F16 | abi::F32 | abi::F64 | abi::F128 => {
+            abi::Float(_) => {
                 if arg_layout.size.bits() > flen {
                     return Err(CannotUseFpConv);
                 }
diff --git a/compiler/rustc_target/src/abi/call/sparc64.rs b/compiler/rustc_target/src/abi/call/sparc64.rs
index acdcd5cc0d4..c0952130e04 100644
--- a/compiler/rustc_target/src/abi/call/sparc64.rs
+++ b/compiler/rustc_target/src/abi/call/sparc64.rs
@@ -20,7 +20,7 @@ where
 {
     let dl = cx.data_layout();
 
-    if !matches!(scalar.primitive(), abi::F32 | abi::F64) {
+    if !matches!(scalar.primitive(), abi::Float(abi::F32 | abi::F64)) {
         return data;
     }
 
@@ -56,7 +56,7 @@ where
         return data;
     }
 
-    if scalar.primitive() == abi::F32 {
+    if scalar.primitive() == abi::Float(abi::F32) {
         data.arg_attribute = ArgAttribute::InReg;
         data.prefix[data.prefix_index] = Some(Reg::f32());
         data.last_offset = offset + Reg::f32().size;
@@ -80,14 +80,14 @@ where
 {
     data = arg_scalar(cx, scalar1, offset, data);
     match (scalar1.primitive(), scalar2.primitive()) {
-        (abi::F32, _) => offset += Reg::f32().size,
-        (_, abi::F64) => offset += Reg::f64().size,
+        (abi::Float(abi::F32), _) => offset += Reg::f32().size,
+        (_, abi::Float(abi::F64)) => offset += Reg::f64().size,
         (abi::Int(i, _signed), _) => offset += i.size(),
         (abi::Pointer(_), _) => offset += Reg::i64().size,
         _ => {}
     }
 
-    if (offset.bytes() % 4) != 0 && matches!(scalar2.primitive(), abi::F32 | abi::F64) {
+    if (offset.bytes() % 4) != 0 && matches!(scalar2.primitive(), abi::Float(abi::F32 | abi::F64)) {
         offset += Size::from_bytes(4 - (offset.bytes() % 4));
     }
     data = arg_scalar(cx, scalar2, offset, data);
diff --git a/compiler/rustc_target/src/abi/call/x86_64.rs b/compiler/rustc_target/src/abi/call/x86_64.rs
index f3208fe5d03..fcd712489fa 100644
--- a/compiler/rustc_target/src/abi/call/x86_64.rs
+++ b/compiler/rustc_target/src/abi/call/x86_64.rs
@@ -51,7 +51,7 @@ where
 
             Abi::Scalar(scalar) => match scalar.primitive() {
                 abi::Int(..) | abi::Pointer(_) => Class::Int,
-                abi::F16 | abi::F32 | abi::F64 | abi::F128 => Class::Sse,
+                abi::Float(_) => Class::Sse,
             },
 
             Abi::Vector { .. } => Class::Sse,
diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs
index 24e49ff648f..666efd9deca 100644
--- a/compiler/rustc_target/src/abi/mod.rs
+++ b/compiler/rustc_target/src/abi/mod.rs
@@ -1,4 +1,5 @@
 use rustc_data_structures::intern::Interned;
+pub use Float::*;
 pub use Integer::*;
 pub use Primitive::*;
 
@@ -11,7 +12,8 @@ use rustc_macros::HashStable_Generic;
 
 pub mod call;
 
-pub use rustc_abi::*;
+// Explicitly import `Float` to avoid ambiguity with `Primitive::Float`.
+pub use rustc_abi::{Float, *};
 
 impl ToJson for Endian {
     fn to_json(&self) -> Json {
@@ -207,7 +209,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
         C: HasDataLayout,
     {
         match self.abi {
-            Abi::Scalar(scalar) => matches!(scalar.primitive(), F32 | F64),
+            Abi::Scalar(scalar) => matches!(scalar.primitive(), Float(F32 | F64)),
             Abi::Aggregate { .. } => {
                 if self.fields.count() == 1 && self.fields.offset(0).bytes() == 0 {
                     self.field(cx, 0).is_single_fp_element(cx)
diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs
index 84d7930663a..46c83be9d95 100644
--- a/compiler/rustc_target/src/lib.rs
+++ b/compiler/rustc_target/src/lib.rs
@@ -7,16 +7,17 @@
 //! more 'stuff' here in the future. It does not have a dependency on
 //! LLVM.
 
+// tidy-alphabetical-start
+#![allow(internal_features)]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
-#![feature(min_exhaustive_patterns)]
-#![feature(rustdoc_internals)]
 #![feature(assert_matches)]
 #![feature(iter_intersperse)]
 #![feature(let_chains)]
+#![feature(min_exhaustive_patterns)]
 #![feature(rustc_attrs)]
-#![feature(step_trait)]
-#![allow(internal_features)]
+#![feature(rustdoc_internals)]
+// tidy-alphabetical-end
 
 use std::path::{Path, PathBuf};
 
diff --git a/compiler/rustc_target/src/spec/base/windows_gnu.rs b/compiler/rustc_target/src/spec/base/windows_gnu.rs
index 25f02dc1451..1357de2dad1 100644
--- a/compiler/rustc_target/src/spec/base/windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/base/windows_gnu.rs
@@ -40,6 +40,9 @@ pub fn opts() -> TargetOptions {
         //
         // See https://github.com/rust-lang/rust/pull/47483 for some more details.
         "-lmsvcrt",
+        // Math functions missing in MSVCRT (they are present in UCRT) require
+        // this dependency cycle: `libmingwex.a` -> `libmsvcrt.a` -> `libmingwex.a`.
+        "-lmingwex",
         "-luser32",
         "-lkernel32",
     ];
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index cbb248a0fc2..8307803676e 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -603,19 +603,6 @@ impl LinkSelfContainedDefault {
         self == LinkSelfContainedDefault::False
     }
 
-    /// Returns whether the target spec explicitly requests self-contained linking, i.e. not via
-    /// inference.
-    pub fn is_linker_enabled(self) -> bool {
-        match self {
-            LinkSelfContainedDefault::True => true,
-            LinkSelfContainedDefault::False => false,
-            LinkSelfContainedDefault::WithComponents(c) => {
-                c.contains(LinkSelfContainedComponents::LINKER)
-            }
-            _ => false,
-        }
-    }
-
     /// Returns the key to use when serializing the setting to json:
     /// - individual components in a `link-self-contained` object value
     /// - the other variants as a backwards-compatible `crt-objects-fallback` string
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
index eff1617a4bf..c59c0ee8f7a 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
@@ -22,7 +22,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: arch.target_arch(),
         options: TargetOptions {
             mcount: "\u{1}mcount".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs
index e9dddc7fae7..4bbd9627738 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs
@@ -19,7 +19,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: arch.target_arch(),
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a7".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs
index 2d89b6083f7..af413e892ce 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs
@@ -15,7 +15,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: arch.target_arch(),
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a12".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs
index fb4ae023250..2c1dd415150 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs
@@ -19,7 +19,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: arch.target_arch(),
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a7".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs
index 0deadbdb028..b5623c89835 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs
@@ -12,7 +12,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: arch.target_arch(),
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a7".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs
index f666c592524..cf4bbb1082c 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs
@@ -12,7 +12,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: arch.target_arch(),
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a7".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs
index 7afe224163b..bacc4671f33 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs
@@ -15,7 +15,7 @@ pub fn target() -> Target {
             std: Some(false),
         },
         pointer_width: 64,
-        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: arch.target_arch(),
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a16".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs
index 422b2d7b922..99df73cb9df 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs
@@ -15,7 +15,7 @@ pub fn target() -> Target {
             std: Some(false),
         },
         pointer_width: 64,
-        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: arch.target_arch(),
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a16".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs
index 5001444e1fa..3fbb7803f8c 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs
@@ -12,7 +12,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: "aarch64".into(),
         options: TargetOptions {
             features: "+v8a,+neon,+fp-armv8,+apple-a7".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs
index 5728f55baba..c13615b8b2a 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs
@@ -16,7 +16,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: arch.target_arch(),
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a7".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs
index 716c9b15c59..88115b81fa5 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs
@@ -11,7 +11,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: "aarch64".into(),
         options: TargetOptions {
             features: "+v8a,+outline-atomics".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs
index f3b6c4c6180..b89c2841dae 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs
@@ -14,7 +14,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 32,
-        data_layout: "E-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "E-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: "aarch64".into(),
         options: TargetOptions {
             abi: "ilp32".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_netbsd.rs
index 54108cc1fe0..d9164f8b052 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_netbsd.rs
@@ -11,7 +11,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: "aarch64".into(),
         options: TargetOptions {
             mcount: "__mcount".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs b/compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs
index aa8c4cd0d08..168f6ad1ac2 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs
@@ -11,7 +11,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: "aarch64".into(),
         options: TargetOptions {
             linker: Some("aarch64-kmc-elf-gcc".into()),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs b/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs
index bb9bab4569b..e9fa482bff1 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs
@@ -13,7 +13,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: "aarch64".into(),
         options: TargetOptions {
             max_atomic_width: Some(128),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding.rs b/compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding.rs
index 15743b9e508..7e7e202b112 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding.rs
@@ -15,7 +15,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: "aarch64".into(),
         options: TargetOptions {
             features: "+v8a".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs
index aed7f94bab7..2cc417ea830 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs
@@ -15,7 +15,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: "aarch64".into(),
         options: base,
     }
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs
index f253b014c31..a5e7dda5fb8 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs
@@ -14,7 +14,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: "aarch64".into(),
         options: base,
     }
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs
index 9fec76b891c..81c9d5927fa 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs
@@ -10,7 +10,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: "aarch64".into(),
         options: TargetOptions {
             features: "+v8a".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs
index 21789e436ca..d740f0b7c97 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs
@@ -10,7 +10,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: "aarch64".into(),
         options: TargetOptions {
             features: "+v8a".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs
index 9ffea48cba7..a466fa05516 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs
@@ -11,7 +11,7 @@ pub fn target() -> Target {
         },
         pointer_width: 64,
         arch: "aarch64".into(),
-        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
         options: TargetOptions {
             features: "+v8a,+strict-align,+neon,+fp-armv8".into(),
             max_atomic_width: Some(128),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_illumos.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_illumos.rs
index 90130880ace..6f253c2a223 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_illumos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_illumos.rs
@@ -18,7 +18,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: "aarch64".into(),
         options: base,
     }
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs
index 703a3206af2..0c4bac0e129 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs
@@ -10,7 +10,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: "aarch64".into(),
         options: TargetOptions {
             features: "+v8a,+outline-atomics".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs
index 81c6a183669..e202ce2f57f 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs
@@ -10,7 +10,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: "aarch64".into(),
         options: TargetOptions {
             abi: "ilp32".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs
index 77689e26380..4a82423bb63 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs
@@ -21,7 +21,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: "aarch64".into(),
         options: TargetOptions { mcount: "\u{1}_mcount".into(), ..base },
     }
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs
index b6b25598bec..3d357bcf3f2 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs
@@ -15,7 +15,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: "aarch64".into(),
         options: TargetOptions {
             features: "+reserve-x18".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_netbsd.rs
index de88b3fe795..ac26aa82271 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_netbsd.rs
@@ -10,7 +10,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: "aarch64".into(),
         options: TargetOptions {
             features: "+v8a".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs
index e5a428aade2..21706aa0b5d 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs
@@ -38,7 +38,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: "aarch64".into(),
         options: opts,
     }
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs
index c75b0d468e8..4f04a7816ce 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs
@@ -32,7 +32,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: "aarch64".into(),
         options: opts,
     }
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs
index f2f1b477ff8..8e448a2fa9a 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs
@@ -19,7 +19,7 @@ pub fn target() -> Target {
         // i128:128  = 128-bit-integer, minimum_alignment=128, preferred_alignment=128
         // n32:64    = 32 and 64 are native integer widths; Elements of this set are considered to support most general arithmetic operations efficiently.
         // S128      = 128 bits are the natural alignment of the stack in bits.
-        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: "aarch64".into(),
         options: TargetOptions {
             features: "+v8a".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs
index f0d79d3c4b7..b51cddafb1a 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs
@@ -10,7 +10,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: "aarch64".into(),
         options: TargetOptions {
             features: "+v8a".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_redox.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_redox.rs
index b7e9d8cb9fc..544709cffe6 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_redox.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_redox.rs
@@ -15,7 +15,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: "aarch64".into(),
         options: base,
     }
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs
index cb48b7417b0..285c5e79cf0 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs
@@ -15,7 +15,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: "aarch64".into(),
         options: base,
     }
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_uefi.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_uefi.rs
index e8d8770546c..de4a56ae03d 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_uefi.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_uefi.rs
@@ -19,7 +19,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: "aarch64".into(),
         options: base,
     }
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/aarch64_uwp_windows_msvc.rs
index 7a89237d0ff..50064e673b3 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_uwp_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_uwp_windows_msvc.rs
@@ -14,7 +14,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: "aarch64".into(),
         options: base,
     }
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs
index ab23ff6ad9b..026b30e9eb7 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs
@@ -10,7 +10,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: "aarch64".into(),
         options: TargetOptions {
             features: "+v8a".into(),
diff --git a/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs
index f842a834c05..38166a88ff3 100644
--- a/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs
@@ -13,7 +13,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 32,
-        data_layout: "e-m:o-p:32:32-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:o-p:32:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: "aarch64".into(),
         options: TargetOptions {
             features: "+v8a,+neon,+fp-armv8,+apple-a7".into(),
diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs
index 11c56cf411c..cf69309e1c0 100644
--- a/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs
@@ -22,7 +22,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: arch.target_arch(),
         options: TargetOptions {
             mcount: "\u{1}mcount".into(),
diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs
index fd8f0ddcb4d..bff40745545 100644
--- a/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs
@@ -19,7 +19,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: arch.target_arch(),
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a12,+v8.3a,+pauth".into(),
diff --git a/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs
index bfd3364acac..aedfb881024 100644
--- a/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs
@@ -19,7 +19,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".into(),
+        data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: "arm64ec".into(),
         options: base,
     }
diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs
index 5ff3f07daae..1259969ac36 100644
--- a/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs
+++ b/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs
@@ -18,7 +18,7 @@
 
 use crate::spec::crt_objects;
 use crate::spec::LinkSelfContainedDefault;
-use crate::spec::{base, Target};
+use crate::spec::{base, RelocModel, Target};
 
 pub fn target() -> Target {
     let mut options = base::wasm::options();
@@ -54,8 +54,13 @@ pub fn target() -> Target {
     // signatures.
     options.entry_name = "__main_void".into();
 
+    // Default to PIC unlike base wasm. This makes precompiled objects such as
+    // the standard library more suitable to be used with shared libaries a la
+    // emscripten's dynamic linking convention.
+    options.relocation_model = RelocModel::Pic;
+
     Target {
-        llvm_target: "wasm32-unknown-unknown".into(),
+        llvm_target: "wasm32-wasip2".into(),
         metadata: crate::spec::TargetMetadata {
             description: None,
             tier: None,
diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs
index 7228a9ba016..b442446f79b 100644
--- a/compiler/rustc_trait_selection/src/errors.rs
+++ b/compiler/rustc_trait_selection/src/errors.rs
@@ -4,7 +4,7 @@ use rustc_errors::{
     SubdiagMessageOp, Subdiagnostic,
 };
 use rustc_macros::{Diagnostic, Subdiagnostic};
-use rustc_middle::ty::{self, ClosureKind, PolyTraitRef, Ty};
+use rustc_middle::ty::{self, print::PrintTraitRefExt as _, ClosureKind, PolyTraitRef, Ty};
 use rustc_span::{Span, Symbol};
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
index d6bf2b596ef..d6010242e4c 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
@@ -19,12 +19,10 @@ use rustc_infer::infer::canonical::query_response::make_query_region_constraints
 use rustc_infer::infer::canonical::CanonicalVarValues;
 use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints};
 use rustc_infer::infer::resolve::EagerResolver;
-use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::infer::RegionVariableOrigin;
 use rustc_infer::infer::{InferCtxt, InferOk};
 use rustc_infer::traits::solve::NestedNormalizationGoals;
 use rustc_middle::infer::canonical::Canonical;
-use rustc_middle::infer::unify_key::ConstVariableOrigin;
 use rustc_middle::traits::query::NoSolution;
 use rustc_middle::traits::solve::{
     ExternalConstraintsData, MaybeCause, PredefinedOpaquesData, QueryInput,
@@ -236,7 +234,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             normalization_nested_goals,
         } = external_constraints.deref();
         self.register_region_constraints(region_constraints);
-        self.register_new_opaque_types(param_env, opaque_types);
+        self.register_new_opaque_types(opaque_types);
         (normalization_nested_goals.clone(), certainty)
     }
 
@@ -368,13 +366,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         assert!(region_constraints.member_constraints.is_empty());
     }
 
-    fn register_new_opaque_types(
-        &mut self,
-        param_env: ty::ParamEnv<'tcx>,
-        opaque_types: &[(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)],
-    ) {
+    fn register_new_opaque_types(&mut self, opaque_types: &[(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)]) {
         for &(key, ty) in opaque_types {
-            self.insert_hidden_type(key, param_env, ty).unwrap();
+            let hidden_ty = ty::OpaqueHiddenType { ty, span: DUMMY_SP };
+            self.infcx.inject_new_hidden_type_unchecked(key, hidden_ty);
         }
     }
 }
@@ -412,6 +407,7 @@ pub(in crate::solve) fn make_canonical_state<'tcx, T: TypeFoldable<TyCtxt<'tcx>>
 /// This currently assumes that unifying the var values trivially succeeds.
 /// Adding any inference constraints which weren't present when originally
 /// computing the canonical query can result in bugs.
+#[instrument(level = "debug", skip(infcx, span, param_env))]
 pub(in crate::solve) fn instantiate_canonical_state<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
     infcx: &InferCtxt<'tcx>,
     span: Span,
@@ -427,12 +423,8 @@ pub(in crate::solve) fn instantiate_canonical_state<'tcx, T: TypeFoldable<TyCtxt
             ty::GenericArgKind::Lifetime(_) => {
                 infcx.next_region_var(RegionVariableOrigin::MiscVariable(span)).into()
             }
-            ty::GenericArgKind::Type(_) => {
-                infcx.next_ty_var(TypeVariableOrigin { param_def_id: None, span }).into()
-            }
-            ty::GenericArgKind::Const(ct) => infcx
-                .next_const_var(ct.ty(), ConstVariableOrigin { param_def_id: None, span })
-                .into(),
+            ty::GenericArgKind::Type(_) => infcx.next_ty_var(span).into(),
+            ty::GenericArgKind::Const(ct) => infcx.next_const_var(ct.ty(), span).into(),
         };
 
         orig_values.push(unconstrained);
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
index bae1c6b6011..9cd1841051d 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
@@ -2,7 +2,6 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::at::ToTrace;
 use rustc_infer::infer::canonical::CanonicalVarValues;
-use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::infer::{
     BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt, InferOk, TyCtxtInferExt,
 };
@@ -11,7 +10,6 @@ use rustc_infer::traits::solve::{MaybeCause, NestedNormalizationGoals};
 use rustc_infer::traits::ObligationCause;
 use rustc_macros::{extension, HashStable};
 use rustc_middle::infer::canonical::CanonicalVarInfos;
-use rustc_middle::infer::unify_key::ConstVariableOrigin;
 use rustc_middle::traits::solve::inspect;
 use rustc_middle::traits::solve::{
     CanonicalInput, CanonicalResponse, Certainty, PredefinedOpaques, PredefinedOpaquesData,
@@ -248,8 +246,8 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
         };
 
         for &(key, ty) in &input.predefined_opaques_in_body.opaque_types {
-            ecx.insert_hidden_type(key, input.goal.param_env, ty)
-                .expect("failed to prepopulate opaque types");
+            let hidden_ty = ty::OpaqueHiddenType { ty, span: DUMMY_SP };
+            ecx.infcx.inject_new_hidden_type_unchecked(key, hidden_ty);
         }
 
         if !ecx.nested_goals.is_empty() {
@@ -587,6 +585,11 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
 
         Ok(unchanged_certainty)
     }
+
+    /// Record impl args in the proof tree for later access by `InspectCandidate`.
+    pub(crate) fn record_impl_args(&mut self, impl_args: ty::GenericArgsRef<'tcx>) {
+        self.inspect.record_impl_args(self.infcx, self.max_input_universe, impl_args)
+    }
 }
 
 impl<'tcx> EvalCtxt<'_, 'tcx> {
@@ -595,15 +598,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
     }
 
     pub(super) fn next_ty_infer(&mut self) -> Ty<'tcx> {
-        let ty = self.infcx.next_ty_var(TypeVariableOrigin { param_def_id: None, span: DUMMY_SP });
+        let ty = self.infcx.next_ty_var(DUMMY_SP);
         self.inspect.add_var_value(ty);
         ty
     }
 
     pub(super) fn next_const_infer(&mut self, ty: Ty<'tcx>) -> ty::Const<'tcx> {
-        let ct = self
-            .infcx
-            .next_const_var(ty, ConstVariableOrigin { param_def_id: None, span: DUMMY_SP });
+        let ct = self.infcx.next_const_var(ty, DUMMY_SP);
         self.inspect.add_var_value(ct);
         ct
     }
@@ -888,8 +889,12 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         self.infcx.resolve_vars_if_possible(value)
     }
 
-    pub(super) fn fresh_args_for_item(&self, def_id: DefId) -> ty::GenericArgsRef<'tcx> {
-        self.infcx.fresh_args_for_item(DUMMY_SP, def_id)
+    pub(super) fn fresh_args_for_item(&mut self, def_id: DefId) -> ty::GenericArgsRef<'tcx> {
+        let args = self.infcx.fresh_args_for_item(DUMMY_SP, def_id);
+        for arg in args {
+            self.inspect.add_var_value(arg);
+        }
+        args
     }
 
     pub(super) fn translate_args(
@@ -1043,12 +1048,12 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         ty: Ty<'tcx>,
     ) -> Option<ty::Const<'tcx>> {
         use rustc_middle::mir::interpret::ErrorHandled;
-        match self.infcx.try_const_eval_resolve(param_env, unevaluated, ty, DUMMY_SP) {
-            Ok(ct) => Some(ct),
+        match self.infcx.const_eval_resolve(param_env, unevaluated, DUMMY_SP) {
+            Ok(Some(val)) => Some(ty::Const::new_value(self.tcx(), val, ty)),
+            Ok(None) | Err(ErrorHandled::TooGeneric(_)) => None,
             Err(ErrorHandled::Reported(e, _)) => {
                 Some(ty::Const::new_error(self.tcx(), e.into(), ty))
             }
-            Err(ErrorHandled::TooGeneric(_)) => None,
         }
     }
 
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
index 16fe045b82d..7efc951135b 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
@@ -1,12 +1,11 @@
 use std::ops::ControlFlow;
 
-use rustc_hir::def_id::DefId;
-use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
+use rustc_infer::infer::InferCtxt;
 use rustc_infer::traits::solve::inspect::ProbeKind;
 use rustc_infer::traits::solve::{CandidateSource, Certainty, Goal};
 use rustc_infer::traits::{
     BuiltinImplSource, ImplSource, ImplSourceUserDefinedData, Obligation, ObligationCause,
-    PolyTraitObligation, PredicateObligation, Selection, SelectionError, SelectionResult,
+    PolyTraitObligation, Selection, SelectionError, SelectionResult,
 };
 use rustc_macros::extension;
 use rustc_span::Span;
@@ -58,6 +57,12 @@ impl<'tcx> inspect::ProofTreeVisitor<'tcx> for Select {
             )));
         }
 
+        // Don't winnow until `Certainty::Yes` -- we don't need to winnow until
+        // codegen, and only on the good path.
+        if matches!(goal.result().unwrap(), Certainty::Maybe(..)) {
+            return ControlFlow::Break(Ok(None));
+        }
+
         // We need to winnow. See comments on `candidate_should_be_dropped_in_favor_of`.
         let mut i = 0;
         while i < candidates.len() {
@@ -86,7 +91,7 @@ fn candidate_should_be_dropped_in_favor_of<'tcx>(
     other: &inspect::InspectCandidate<'_, 'tcx>,
 ) -> bool {
     // Don't winnow until `Certainty::Yes` -- we don't need to winnow until
-    // codegen, technically.
+    // codegen, and only on the good path.
     if matches!(other.result().unwrap(), Certainty::Maybe(..)) {
         return false;
     }
@@ -105,13 +110,15 @@ fn candidate_should_be_dropped_in_favor_of<'tcx>(
             bug!("should not have assembled a CoherenceUnknowable candidate")
         }
 
+        // In the old trait solver, we arbitrarily choose lower vtable candidates
+        // over higher ones.
+        (
+            CandidateSource::BuiltinImpl(BuiltinImplSource::Object { vtable_base: a }),
+            CandidateSource::BuiltinImpl(BuiltinImplSource::Object { vtable_base: b }),
+        ) => a >= b,
         // Prefer dyn candidates over non-dyn candidates. This is necessary to
         // handle the unsoundness between `impl<T: ?Sized> Any for T` and `dyn Any: Any`.
         (
-            CandidateSource::BuiltinImpl(BuiltinImplSource::Object { .. }),
-            CandidateSource::BuiltinImpl(BuiltinImplSource::Object { .. }),
-        ) => false,
-        (
             CandidateSource::Impl(_) | CandidateSource::ParamEnv(_) | CandidateSource::AliasBound,
             CandidateSource::BuiltinImpl(BuiltinImplSource::Object { .. }),
         ) => true,
@@ -133,32 +140,32 @@ fn to_selection<'tcx>(
         return None;
     }
 
-    let make_nested = || {
-        cand.instantiate_nested_goals(span)
-            .into_iter()
-            .map(|nested| {
-                Obligation::new(
-                    nested.infcx().tcx,
-                    ObligationCause::dummy_with_span(span),
-                    nested.goal().param_env,
-                    nested.goal().predicate,
-                )
-            })
-            .collect()
-    };
+    let (nested, impl_args) = cand.instantiate_nested_goals_and_opt_impl_args(span);
+    let nested = nested
+        .into_iter()
+        .map(|nested| {
+            Obligation::new(
+                nested.infcx().tcx,
+                ObligationCause::dummy_with_span(span),
+                nested.goal().param_env,
+                nested.goal().predicate,
+            )
+        })
+        .collect();
 
     Some(match cand.kind() {
         ProbeKind::TraitCandidate { source, result: _ } => match source {
             CandidateSource::Impl(impl_def_id) => {
                 // FIXME: Remove this in favor of storing this in the tree
                 // For impl candidates, we do the rematch manually to compute the args.
-                ImplSource::UserDefined(rematch_impl(cand.goal(), impl_def_id, span))
-            }
-            CandidateSource::BuiltinImpl(builtin) => ImplSource::Builtin(builtin, make_nested()),
-            CandidateSource::ParamEnv(_) => ImplSource::Param(make_nested()),
-            CandidateSource::AliasBound => {
-                ImplSource::Builtin(BuiltinImplSource::Misc, make_nested())
+                ImplSource::UserDefined(ImplSourceUserDefinedData {
+                    impl_def_id,
+                    args: impl_args.expect("expected recorded impl args for impl candidate"),
+                    nested,
+                })
             }
+            CandidateSource::BuiltinImpl(builtin) => ImplSource::Builtin(builtin, nested),
+            CandidateSource::ParamEnv(_) | CandidateSource::AliasBound => ImplSource::Param(nested),
             CandidateSource::CoherenceUnknowable => {
                 span_bug!(span, "didn't expect to select an unknowable candidate")
             }
@@ -173,40 +180,3 @@ fn to_selection<'tcx>(
         }
     })
 }
-
-fn rematch_impl<'tcx>(
-    goal: &inspect::InspectGoal<'_, 'tcx>,
-    impl_def_id: DefId,
-    span: Span,
-) -> ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>> {
-    let infcx = goal.infcx();
-    let goal_trait_ref = infcx
-        .enter_forall_and_leak_universe(goal.goal().predicate.to_opt_poly_trait_pred().unwrap())
-        .trait_ref;
-
-    let args = infcx.fresh_args_for_item(span, impl_def_id);
-    let impl_trait_ref =
-        infcx.tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(infcx.tcx, args);
-
-    let InferOk { value: (), obligations: mut nested } = infcx
-        .at(&ObligationCause::dummy_with_span(span), goal.goal().param_env)
-        .eq(DefineOpaqueTypes::Yes, goal_trait_ref, impl_trait_ref)
-        .expect("rematching impl failed");
-
-    // FIXME(-Znext-solver=coinductive): We need to add supertraits here eventually.
-
-    nested.extend(
-        infcx.tcx.predicates_of(impl_def_id).instantiate(infcx.tcx, args).into_iter().map(
-            |(clause, _)| {
-                Obligation::new(
-                    infcx.tcx,
-                    ObligationCause::dummy_with_span(span),
-                    goal.goal().param_env,
-                    clause,
-                )
-            },
-        ),
-    );
-
-    ImplSourceUserDefinedData { impl_def_id, nested, args }
-}
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
index 796222129f1..4cc041fca8c 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -7,13 +7,14 @@ use rustc_infer::traits::solve::inspect::ProbeKind;
 use rustc_infer::traits::solve::{CandidateSource, GoalSource, MaybeCause};
 use rustc_infer::traits::{
     self, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, Obligation,
-    ObligationCause, PredicateObligation, SelectionError, TraitEngine,
+    ObligationCause, ObligationCauseCode, PredicateObligation, SelectionError, TraitEngine,
 };
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::{self, TyCtxt};
+use rustc_span::symbol::sym;
 
 use super::eval_ctxt::GenerateProofTree;
-use super::inspect::{ProofTreeInferCtxtExt, ProofTreeVisitor};
+use super::inspect::{InspectCandidate, InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor};
 use super::{Certainty, InferCtxtEvalExt};
 
 /// A trait engine using the new trait solver.
@@ -137,7 +138,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
             .collect();
 
         errors.extend(self.obligations.overflowed.drain(..).map(|obligation| FulfillmentError {
-            obligation: find_best_leaf_obligation(infcx, &obligation),
+            obligation: find_best_leaf_obligation(infcx, &obligation, true),
             code: FulfillmentErrorCode::Ambiguity { overflow: Some(true) },
             root_obligation: obligation,
         }));
@@ -198,43 +199,39 @@ fn fulfillment_error_for_no_solution<'tcx>(
     infcx: &InferCtxt<'tcx>,
     root_obligation: PredicateObligation<'tcx>,
 ) -> FulfillmentError<'tcx> {
-    let obligation = find_best_leaf_obligation(infcx, &root_obligation);
+    let obligation = find_best_leaf_obligation(infcx, &root_obligation, false);
 
     let code = match obligation.predicate.kind().skip_binder() {
         ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) => {
-            FulfillmentErrorCode::ProjectionError(
+            FulfillmentErrorCode::Project(
                 // FIXME: This could be a `Sorts` if the term is a type
                 MismatchedProjectionTypes { err: TypeError::Mismatch },
             )
         }
         ty::PredicateKind::NormalizesTo(..) => {
-            FulfillmentErrorCode::ProjectionError(MismatchedProjectionTypes {
-                err: TypeError::Mismatch,
-            })
+            FulfillmentErrorCode::Project(MismatchedProjectionTypes { err: TypeError::Mismatch })
         }
         ty::PredicateKind::AliasRelate(_, _, _) => {
-            FulfillmentErrorCode::ProjectionError(MismatchedProjectionTypes {
-                err: TypeError::Mismatch,
-            })
+            FulfillmentErrorCode::Project(MismatchedProjectionTypes { err: TypeError::Mismatch })
         }
         ty::PredicateKind::Subtype(pred) => {
             let (a, b) = infcx.enter_forall_and_leak_universe(
                 obligation.predicate.kind().rebind((pred.a, pred.b)),
             );
             let expected_found = ExpectedFound::new(true, a, b);
-            FulfillmentErrorCode::SubtypeError(expected_found, TypeError::Sorts(expected_found))
+            FulfillmentErrorCode::Subtype(expected_found, TypeError::Sorts(expected_found))
         }
         ty::PredicateKind::Coerce(pred) => {
             let (a, b) = infcx.enter_forall_and_leak_universe(
                 obligation.predicate.kind().rebind((pred.a, pred.b)),
             );
             let expected_found = ExpectedFound::new(false, a, b);
-            FulfillmentErrorCode::SubtypeError(expected_found, TypeError::Sorts(expected_found))
+            FulfillmentErrorCode::Subtype(expected_found, TypeError::Sorts(expected_found))
         }
         ty::PredicateKind::Clause(_)
         | ty::PredicateKind::ObjectSafe(_)
         | ty::PredicateKind::Ambiguous => {
-            FulfillmentErrorCode::SelectionError(SelectionError::Unimplemented)
+            FulfillmentErrorCode::Select(SelectionError::Unimplemented)
         }
         ty::PredicateKind::ConstEquate(..) => {
             bug!("unexpected goal: {obligation:?}")
@@ -266,7 +263,7 @@ fn fulfillment_error_for_stalled<'tcx>(
     });
 
     FulfillmentError {
-        obligation: find_best_leaf_obligation(infcx, &obligation),
+        obligation: find_best_leaf_obligation(infcx, &obligation, true),
         code,
         root_obligation: obligation,
     }
@@ -275,12 +272,13 @@ fn fulfillment_error_for_stalled<'tcx>(
 fn find_best_leaf_obligation<'tcx>(
     infcx: &InferCtxt<'tcx>,
     obligation: &PredicateObligation<'tcx>,
+    consider_ambiguities: bool,
 ) -> PredicateObligation<'tcx> {
     let obligation = infcx.resolve_vars_if_possible(obligation.clone());
     infcx
         .visit_proof_tree(
             obligation.clone().into(),
-            &mut BestObligation { obligation: obligation.clone() },
+            &mut BestObligation { obligation: obligation.clone(), consider_ambiguities },
         )
         .break_value()
         .unwrap_or(obligation)
@@ -288,6 +286,7 @@ fn find_best_leaf_obligation<'tcx>(
 
 struct BestObligation<'tcx> {
     obligation: PredicateObligation<'tcx>,
+    consider_ambiguities: bool,
 }
 
 impl<'tcx> BestObligation<'tcx> {
@@ -301,6 +300,46 @@ impl<'tcx> BestObligation<'tcx> {
         self.obligation = old_obligation;
         res
     }
+
+    /// Filter out the candidates that aren't either error or ambiguous (depending
+    /// on what we are looking for), and also throw out candidates that have no
+    /// failing WC (or higher-ranked obligations, for which there should only be
+    /// one candidate anyways -- but I digress). This most likely means that the
+    /// goal just didn't unify at all, e.g. a param candidate with an alias in it.
+    fn non_trivial_candidates<'a>(
+        &self,
+        goal: &'a InspectGoal<'a, 'tcx>,
+    ) -> Vec<InspectCandidate<'a, 'tcx>> {
+        let mut candidates = goal
+            .candidates()
+            .into_iter()
+            .filter(|candidate| match self.consider_ambiguities {
+                true => matches!(candidate.result(), Ok(Certainty::Maybe(_))),
+                false => matches!(candidate.result(), Err(_)),
+            })
+            .collect::<Vec<_>>();
+
+        // If we have >1 candidate, one may still be due to "boring" reasons, like
+        // an alias-relate that failed to hold when deeply evaluated. We really
+        // don't care about reasons like this.
+        if candidates.len() > 1 {
+            candidates.retain(|candidate| {
+                goal.infcx().probe(|_| {
+                    candidate.instantiate_nested_goals(self.span()).iter().any(|nested_goal| {
+                        matches!(
+                            nested_goal.source(),
+                            GoalSource::ImplWhereBound | GoalSource::InstantiateHigherRanked
+                        ) && match self.consider_ambiguities {
+                            true => matches!(nested_goal.result(), Ok(Certainty::Maybe(_))),
+                            false => matches!(nested_goal.result(), Err(_)),
+                        }
+                    })
+                })
+            });
+        }
+
+        candidates
+    }
 }
 
 impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
@@ -311,15 +350,19 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
     }
 
     fn visit_goal(&mut self, goal: &super::inspect::InspectGoal<'_, 'tcx>) -> Self::Result {
-        // FIXME: Throw out candidates that have no failing WC and >0 failing misc goal.
-        // This most likely means that the goal just didn't unify at all, e.g. a param
-        // candidate with an alias in it.
-        let candidates = goal.candidates();
-
+        let candidates = self.non_trivial_candidates(goal);
         let [candidate] = candidates.as_slice() else {
             return ControlFlow::Break(self.obligation.clone());
         };
 
+        // Don't walk into impls that have `do_not_recommend`.
+        if let ProbeKind::TraitCandidate { source: CandidateSource::Impl(impl_def_id), result: _ } =
+            candidate.kind()
+            && goal.infcx().tcx.has_attr(impl_def_id, sym::do_not_recommend)
+        {
+            return ControlFlow::Break(self.obligation.clone());
+        }
+
         // FIXME: Could we extract a trait ref from a projection here too?
         // FIXME: Also, what about considering >1 layer up the stack? May be necessary
         // for normalizes-to.
@@ -355,11 +398,11 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
                 }
             }
 
-            // Skip nested goals that hold.
-            //FIXME: We should change the max allowed certainty based on if we're
-            // visiting an ambiguity or error obligation.
-            if matches!(nested_goal.result(), Ok(Certainty::Yes)) {
-                continue;
+            // Skip nested goals that aren't the *reason* for our goal's failure.
+            match self.consider_ambiguities {
+                true if matches!(nested_goal.result(), Ok(Certainty::Maybe(_))) => {}
+                false if matches!(nested_goal.result(), Err(_)) => {}
+                _ => continue,
             }
 
             self.with_derived_obligation(obligation, |this| nested_goal.visit_with(this))?;
@@ -382,7 +425,7 @@ fn derive_cause<'tcx>(
                 tcx.predicates_of(impl_def_id).instantiate_identity(tcx).iter().nth(idx)
             {
                 cause = cause.derived_cause(parent_trait_pred, |derived| {
-                    traits::ImplDerivedObligation(Box::new(traits::ImplDerivedObligationCause {
+                    ObligationCauseCode::ImplDerived(Box::new(traits::ImplDerivedCause {
                         derived,
                         impl_or_alias_def_id: impl_def_id,
                         impl_def_predicate_index: Some(idx),
@@ -392,7 +435,7 @@ fn derive_cause<'tcx>(
             }
         }
         ProbeKind::TraitCandidate { source: CandidateSource::BuiltinImpl(..), result: _ } => {
-            cause = cause.derived_cause(parent_trait_pred, traits::BuiltinDerivedObligation);
+            cause = cause.derived_cause(parent_trait_pred, ObligationCauseCode::BuiltinDerived);
         }
         _ => {}
     };
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
index 4f79f1b2aaf..fd36b7ffd4e 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
@@ -12,10 +12,8 @@
 use rustc_ast_ir::try_visit;
 use rustc_ast_ir::visit::VisitorResult;
 use rustc_infer::infer::resolve::EagerResolver;
-use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
 use rustc_macros::extension;
-use rustc_middle::infer::unify_key::ConstVariableOrigin;
 use rustc_middle::traits::query::NoSolution;
 use rustc_middle::traits::solve::{inspect, QueryResult};
 use rustc_middle::traits::solve::{Certainty, Goal};
@@ -93,6 +91,7 @@ pub struct InspectCandidate<'a, 'tcx> {
     kind: inspect::ProbeKind<'tcx>,
     nested_goals: Vec<(GoalSource, inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>)>,
     final_state: inspect::CanonicalState<'tcx, ()>,
+    impl_args: Option<inspect::CanonicalState<'tcx, ty::GenericArgsRef<'tcx>>>,
     result: QueryResult<'tcx>,
     shallow_certainty: Certainty,
 }
@@ -135,7 +134,25 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
 
     /// Instantiate the nested goals for the candidate without rolling back their
     /// inference constraints. This function modifies the state of the `infcx`.
+    ///
+    /// See [`Self::instantiate_nested_goals_and_opt_impl_args`] if you need the impl args too.
     pub fn instantiate_nested_goals(&self, span: Span) -> Vec<InspectGoal<'a, 'tcx>> {
+        self.instantiate_nested_goals_and_opt_impl_args(span).0
+    }
+
+    /// Instantiate the nested goals for the candidate without rolling back their
+    /// inference constraints, and optionally the args of an impl if this candidate
+    /// came from a `CandidateSource::Impl`. This function modifies the state of the
+    /// `infcx`.
+    #[instrument(
+        level = "debug",
+        skip_all,
+        fields(goal = ?self.goal.goal, nested_goals = ?self.nested_goals)
+    )]
+    pub fn instantiate_nested_goals_and_opt_impl_args(
+        &self,
+        span: Span,
+    ) -> (Vec<InspectGoal<'a, 'tcx>>, Option<ty::GenericArgsRef<'tcx>>) {
         let infcx = self.goal.infcx;
         let param_env = self.goal.goal.param_env;
         let mut orig_values = self.goal.orig_values.to_vec();
@@ -164,6 +181,17 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
             self.final_state,
         );
 
+        let impl_args = self.impl_args.map(|impl_args| {
+            canonical::instantiate_canonical_state(
+                infcx,
+                span,
+                param_env,
+                &mut orig_values,
+                impl_args,
+            )
+            .fold_with(&mut EagerResolver::new(infcx))
+        });
+
         if let Some(term_hack) = self.goal.normalizes_to_term_hack {
             // FIXME: We ignore the expected term of `NormalizesTo` goals
             // when computing the result of its candidates. This is
@@ -171,27 +199,33 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
             let _ = term_hack.constrain(infcx, span, param_env);
         }
 
-        instantiated_goals
+        let goals = instantiated_goals
             .into_iter()
             .map(|(source, goal)| match goal.predicate.kind().no_bound_vars() {
                 Some(ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })) => {
                     let unconstrained_term = match term.unpack() {
-                        ty::TermKind::Ty(_) => infcx
-                            .next_ty_var(TypeVariableOrigin { param_def_id: None, span })
-                            .into(),
-                        ty::TermKind::Const(ct) => infcx
-                            .next_const_var(
-                                ct.ty(),
-                                ConstVariableOrigin { param_def_id: None, span },
-                            )
-                            .into(),
+                        ty::TermKind::Ty(_) => infcx.next_ty_var(span).into(),
+                        ty::TermKind::Const(ct) => infcx.next_const_var(ct.ty(), span).into(),
                     };
                     let goal =
                         goal.with(infcx.tcx, ty::NormalizesTo { alias, term: unconstrained_term });
-                    let proof_tree = EvalCtxt::enter_root(infcx, GenerateProofTree::Yes, |ecx| {
-                        ecx.evaluate_goal_raw(GoalEvaluationKind::Root, GoalSource::Misc, goal)
-                    })
-                    .1;
+                    // We have to use a `probe` here as evaluating a `NormalizesTo` can constrain the
+                    // expected term. This means that candidates which only fail due to nested goals
+                    // and which normalize to a different term then the final result could ICE: when
+                    // building their proof tree, the expected term was unconstrained, but when
+                    // instantiating the candidate it is already constrained to the result of another
+                    // candidate.
+                    let proof_tree = infcx
+                        .probe(|_| {
+                            EvalCtxt::enter_root(infcx, GenerateProofTree::Yes, |ecx| {
+                                ecx.evaluate_goal_raw(
+                                    GoalEvaluationKind::Root,
+                                    GoalSource::Misc,
+                                    goal,
+                                )
+                            })
+                        })
+                        .1;
                     InspectGoal::new(
                         infcx,
                         self.goal.depth + 1,
@@ -200,15 +234,21 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
                         source,
                     )
                 }
-                _ => InspectGoal::new(
-                    infcx,
-                    self.goal.depth + 1,
-                    infcx.evaluate_root_goal(goal, GenerateProofTree::Yes).1.unwrap(),
-                    None,
-                    source,
-                ),
+                _ => {
+                    // We're using a probe here as evaluating a goal could constrain
+                    // inference variables by choosing one candidate. If we then recurse
+                    // into another candidate who ends up with different inference
+                    // constraints, we get an ICE if we already applied the constraints
+                    // from the chosen candidate.
+                    let proof_tree = infcx
+                        .probe(|_| infcx.evaluate_root_goal(goal, GenerateProofTree::Yes).1)
+                        .unwrap();
+                    InspectGoal::new(infcx, self.goal.depth + 1, proof_tree, None, source)
+                }
             })
-            .collect()
+            .collect();
+
+        (goals, impl_args)
     }
 
     /// Visit all nested goals of this candidate, rolling back
@@ -245,9 +285,10 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
         probe: &inspect::Probe<'tcx>,
     ) {
         let mut shallow_certainty = None;
+        let mut impl_args = None;
         for step in &probe.steps {
-            match step {
-                &inspect::ProbeStep::AddGoal(source, goal) => nested_goals.push((source, goal)),
+            match *step {
+                inspect::ProbeStep::AddGoal(source, goal) => nested_goals.push((source, goal)),
                 inspect::ProbeStep::NestedProbe(ref probe) => {
                     // Nested probes have to prove goals added in their parent
                     // but do not leak them, so we truncate the added goals
@@ -257,7 +298,10 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
                     nested_goals.truncate(num_goals);
                 }
                 inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty: c } => {
-                    assert_eq!(shallow_certainty.replace(*c), None);
+                    assert_eq!(shallow_certainty.replace(c), None);
+                }
+                inspect::ProbeStep::RecordImplArgs { impl_args: i } => {
+                    assert_eq!(impl_args.replace(i), None);
                 }
                 inspect::ProbeStep::EvaluateGoals(_) => (),
             }
@@ -284,6 +328,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
                         final_state: probe.final_state,
                         result,
                         shallow_certainty,
+                        impl_args,
                     });
                 }
             }
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/build.rs b/compiler/rustc_trait_selection/src/solve/inspect/build.rs
index 466d0d80060..3c5505055a4 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect/build.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect/build.rs
@@ -242,6 +242,7 @@ enum WipProbeStep<'tcx> {
     EvaluateGoals(WipAddedGoalsEvaluation<'tcx>),
     NestedProbe(WipProbe<'tcx>),
     MakeCanonicalResponse { shallow_certainty: Certainty },
+    RecordImplArgs { impl_args: inspect::CanonicalState<'tcx, ty::GenericArgsRef<'tcx>> },
 }
 
 impl<'tcx> WipProbeStep<'tcx> {
@@ -250,6 +251,9 @@ impl<'tcx> WipProbeStep<'tcx> {
             WipProbeStep::AddGoal(source, goal) => inspect::ProbeStep::AddGoal(source, goal),
             WipProbeStep::EvaluateGoals(eval) => inspect::ProbeStep::EvaluateGoals(eval.finalize()),
             WipProbeStep::NestedProbe(probe) => inspect::ProbeStep::NestedProbe(probe.finalize()),
+            WipProbeStep::RecordImplArgs { impl_args } => {
+                inspect::ProbeStep::RecordImplArgs { impl_args }
+            }
             WipProbeStep::MakeCanonicalResponse { shallow_certainty } => {
                 inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty }
             }
@@ -372,7 +376,10 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
                 (
                     DebugSolver::GoalEvaluation(goal_evaluation),
                     DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation),
-                ) => goal_evaluation.evaluation = Some(canonical_goal_evaluation),
+                ) => {
+                    let prev = goal_evaluation.evaluation.replace(canonical_goal_evaluation);
+                    assert_eq!(prev, None);
+                }
                 _ => unreachable!(),
             }
         }
@@ -534,6 +541,30 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
         }
     }
 
+    pub(crate) fn record_impl_args(
+        &mut self,
+        infcx: &InferCtxt<'tcx>,
+        max_input_universe: ty::UniverseIndex,
+        impl_args: ty::GenericArgsRef<'tcx>,
+    ) {
+        match self.as_mut() {
+            Some(DebugSolver::GoalEvaluationStep(state)) => {
+                let impl_args = canonical::make_canonical_state(
+                    infcx,
+                    &state.var_values,
+                    max_input_universe,
+                    impl_args,
+                );
+                state
+                    .current_evaluation_scope()
+                    .steps
+                    .push(WipProbeStep::RecordImplArgs { impl_args });
+            }
+            None => {}
+            _ => bug!(),
+        }
+    }
+
     pub fn make_canonical_response(&mut self, shallow_certainty: Certainty) {
         match self.as_mut() {
             Some(DebugSolver::GoalEvaluationStep(state)) => {
@@ -543,7 +574,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
                     .push(WipProbeStep::MakeCanonicalResponse { shallow_certainty });
             }
             None => {}
-            _ => {}
+            _ => bug!(),
         }
     }
 
diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs
index 65ef4659907..cd1add9e0fa 100644
--- a/compiler/rustc_trait_selection/src/solve/normalize.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalize.rs
@@ -3,11 +3,9 @@ use crate::traits::query::evaluate_obligation::InferCtxtExt;
 use crate::traits::{BoundVarReplacer, PlaceholderReplacer};
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_infer::infer::at::At;
-use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::infer::InferCtxt;
 use rustc_infer::traits::TraitEngineExt;
 use rustc_infer::traits::{FulfillmentError, Obligation, TraitEngine};
-use rustc_middle::infer::unify_key::ConstVariableOrigin;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::{self, AliasTy, Ty, TyCtxt, UniverseIndex};
 use rustc_middle::ty::{FallibleTypeFolder, TypeFolder, TypeSuperFoldable};
@@ -74,8 +72,7 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> {
 
         self.depth += 1;
 
-        let new_infer_ty =
-            infcx.next_ty_var(TypeVariableOrigin { param_def_id: None, span: self.at.cause.span });
+        let new_infer_ty = infcx.next_ty_var(self.at.cause.span);
         let obligation = Obligation::new(
             tcx,
             self.at.cause.clone(),
@@ -120,10 +117,7 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> {
 
         self.depth += 1;
 
-        let new_infer_ct = infcx.next_const_var(
-            ty,
-            ConstVariableOrigin { param_def_id: None, span: self.at.cause.span },
-        );
+        let new_infer_ct = infcx.next_const_var(ty, self.at.cause.span);
         let obligation = Obligation::new(
             tcx,
             self.at.cause.clone(),
diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
index f886c588650..454c7a5f00f 100644
--- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
@@ -368,7 +368,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
                 }
             };
         let output_is_sized_pred = tupled_inputs_and_output.map_bound(|(_, output)| {
-            ty::TraitRef::from_lang_item(tcx, LangItem::Sized, DUMMY_SP, [output])
+            ty::TraitRef::new(tcx, tcx.require_lang_item(LangItem::Sized, None), [output])
         });
 
         let pred = tupled_inputs_and_output
@@ -414,7 +414,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
             )?;
         let output_is_sized_pred = tupled_inputs_and_output_and_coroutine.map_bound(
             |AsyncCallableRelevantTypes { output_coroutine_ty: output_ty, .. }| {
-                ty::TraitRef::from_lang_item(tcx, LangItem::Sized, DUMMY_SP, [output_ty])
+                ty::TraitRef::new(tcx, tcx.require_lang_item(LangItem::Sized, None), [output_ty])
             },
         );
 
@@ -576,10 +576,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
                     // and opaque types: If the `self_ty` is `Sized`, then the metadata is `()`.
                     // FIXME(ptr_metadata): This impl overlaps with the other impls and shouldn't
                     // exist. Instead, `Pointee<Metadata = ()>` should be a supertrait of `Sized`.
-                    let sized_predicate = ty::TraitRef::from_lang_item(
+                    let sized_predicate = ty::TraitRef::new(
                         tcx,
-                        LangItem::Sized,
-                        DUMMY_SP,
+                        tcx.require_lang_item(LangItem::Sized, None),
                         [ty::GenericArg::from(goal.predicate.self_ty())],
                     );
                     // FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`?
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index d2b893d6383..083cc0aa3c2 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -16,7 +16,7 @@ use rustc_middle::traits::{BuiltinImplSource, Reveal};
 use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
 use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt};
 use rustc_middle::ty::{TraitPredicate, TypeVisitableExt};
-use rustc_span::{ErrorGuaranteed, DUMMY_SP};
+use rustc_span::ErrorGuaranteed;
 
 impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     fn self_ty(self) -> Ty<'tcx> {
@@ -75,6 +75,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
 
         ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| {
             let impl_args = ecx.fresh_args_for_item(impl_def_id);
+            ecx.record_impl_args(impl_args);
             let impl_trait_ref = impl_trait_header.trait_ref.instantiate(tcx, impl_args);
 
             ecx.eq(goal.param_env, goal.predicate.trait_ref, impl_trait_ref)?;
@@ -306,7 +307,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
                 }
             };
         let output_is_sized_pred = tupled_inputs_and_output.map_bound(|(_, output)| {
-            ty::TraitRef::from_lang_item(tcx, LangItem::Sized, DUMMY_SP, [output])
+            ty::TraitRef::new(tcx, tcx.require_lang_item(LangItem::Sized, None), [output])
         });
 
         let pred = tupled_inputs_and_output
@@ -345,7 +346,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
             )?;
         let output_is_sized_pred = tupled_inputs_and_output_and_coroutine.map_bound(
             |AsyncCallableRelevantTypes { output_coroutine_ty, .. }| {
-                ty::TraitRef::from_lang_item(tcx, LangItem::Sized, DUMMY_SP, [output_coroutine_ty])
+                ty::TraitRef::new(
+                    tcx,
+                    tcx.require_lang_item(LangItem::Sized, None),
+                    [output_coroutine_ty],
+                )
             },
         );
 
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs
index 9e5701ffffc..4b5b1d77b30 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs
@@ -1,4 +1,3 @@
-use crate::infer::type_variable::TypeVariableOrigin;
 use crate::infer::InferCtxt;
 use crate::traits::{Obligation, ObligationCause, ObligationCtxt};
 use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, Diag};
@@ -218,8 +217,7 @@ impl<'tcx> InferCtxt<'tcx> {
                 let Some(trait_def_id) = trait_def_id else { continue };
                 // Make a fresh inference variable so we can determine what the generic parameters
                 // of the trait are.
-                let var =
-                    self.next_ty_var(TypeVariableOrigin { span: DUMMY_SP, param_def_id: None });
+                let var = self.next_ty_var(DUMMY_SP);
                 // FIXME(effects)
                 let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, [ty.skip_binder(), var]);
                 let obligation = Obligation::new(
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
index 07bd209e623..040ce450aaf 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
@@ -10,6 +10,7 @@ use rustc_errors::{codes::*, struct_span_code_err, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_macros::{extension, LintDiagnostic};
+use rustc_middle::ty::print::PrintTraitRefExt as _;
 use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt};
 use rustc_parse_format::{ParseMode, Parser, Piece, Position};
@@ -127,9 +128,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         flags.push((sym::ItemContext, enclosure));
 
         match obligation.cause.code() {
-            ObligationCauseCode::BuiltinDerivedObligation(..)
-            | ObligationCauseCode::ImplDerivedObligation(..)
-            | ObligationCauseCode::WellFormedDerivedObligation(..) => {}
+            ObligationCauseCode::BuiltinDerived(..)
+            | ObligationCauseCode::ImplDerived(..)
+            | ObligationCauseCode::WellFormedDerived(..) => {}
             _ => {
                 // this is a "direct", user-specified, rather than derived,
                 // obligation.
@@ -165,7 +166,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 ));
             }
 
-            for param in generics.params.iter() {
+            for param in generics.own_params.iter() {
                 let value = match param.kind {
                     GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
                         args[param.index as usize].to_string()
@@ -350,12 +351,14 @@ impl IgnoredDiagnosticOption {
         option_name: &'static str,
     ) {
         if let (Some(new_item), Some(old_item)) = (new, old) {
-            tcx.emit_node_span_lint(
-                UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
-                tcx.local_def_id_to_hir_id(item_def_id.expect_local()),
-                new_item,
-                IgnoredDiagnosticOption { span: new_item, prev_span: old_item, option_name },
-            );
+            if let Some(item_def_id) = item_def_id.as_local() {
+                tcx.emit_node_span_lint(
+                    UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
+                    tcx.local_def_id_to_hir_id(item_def_id),
+                    new_item,
+                    IgnoredDiagnosticOption { span: new_item, prev_span: old_item, option_name },
+                );
+            }
         }
     }
 }
@@ -499,12 +502,14 @@ impl<'tcx> OnUnimplementedDirective {
             }
 
             if is_diagnostic_namespace_variant {
-                tcx.emit_node_span_lint(
-                    UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
-                    tcx.local_def_id_to_hir_id(item_def_id.expect_local()),
-                    vec![item.span()],
-                    MalformedOnUnimplementedAttrLint::new(item.span()),
-                );
+                if let Some(def_id) = item_def_id.as_local() {
+                    tcx.emit_node_span_lint(
+                        UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
+                        tcx.local_def_id_to_hir_id(def_id),
+                        vec![item.span()],
+                        MalformedOnUnimplementedAttrLint::new(item.span()),
+                    );
+                }
             } else {
                 // nothing found
                 tcx.dcx().emit_err(NoValueInOnUnimplemented { span: item.span() });
@@ -637,30 +642,38 @@ impl<'tcx> OnUnimplementedDirective {
                     AttrArgs::Eq(span, AttrArgsEq::Hir(expr)) => span.to(expr.span),
                 };
 
-                tcx.emit_node_span_lint(
-                    UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
-                    tcx.local_def_id_to_hir_id(item_def_id.expect_local()),
-                    report_span,
-                    MalformedOnUnimplementedAttrLint::new(report_span),
-                );
+                if let Some(item_def_id) = item_def_id.as_local() {
+                    tcx.emit_node_span_lint(
+                        UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
+                        tcx.local_def_id_to_hir_id(item_def_id),
+                        report_span,
+                        MalformedOnUnimplementedAttrLint::new(report_span),
+                    );
+                }
                 Ok(None)
             }
         } else if is_diagnostic_namespace_variant {
             match &attr.kind {
                 AttrKind::Normal(p) if !matches!(p.item.args, AttrArgs::Empty) => {
-                    tcx.emit_node_span_lint(
-                        UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
-                        tcx.local_def_id_to_hir_id(item_def_id.expect_local()),
-                        attr.span,
-                        MalformedOnUnimplementedAttrLint::new(attr.span),
-                    );
+                    if let Some(item_def_id) = item_def_id.as_local() {
+                        tcx.emit_node_span_lint(
+                            UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
+                            tcx.local_def_id_to_hir_id(item_def_id),
+                            attr.span,
+                            MalformedOnUnimplementedAttrLint::new(attr.span),
+                        );
+                    }
+                }
+                _ => {
+                    if let Some(item_def_id) = item_def_id.as_local() {
+                        tcx.emit_node_span_lint(
+                            UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
+                            tcx.local_def_id_to_hir_id(item_def_id),
+                            attr.span,
+                            MissingOptionsForOnUnimplementedAttr,
+                        )
+                    }
                 }
-                _ => tcx.emit_node_span_lint(
-                    UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
-                    tcx.local_def_id_to_hir_id(item_def_id.expect_local()),
-                    attr.span,
-                    MissingOptionsForOnUnimplementedAttr,
-                ),
             };
 
             Ok(None)
@@ -789,12 +802,14 @@ impl<'tcx> OnUnimplementedFormatString {
                             || format_spec.precision_span.is_some()
                             || format_spec.fill_span.is_some())
                     {
-                        tcx.emit_node_span_lint(
-                            UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
-                            tcx.local_def_id_to_hir_id(item_def_id.expect_local()),
-                            self.span,
-                            InvalidFormatSpecifier,
-                        );
+                        if let Some(item_def_id) = item_def_id.as_local() {
+                            tcx.emit_node_span_lint(
+                                UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
+                                tcx.local_def_id_to_hir_id(item_def_id),
+                                self.span,
+                                InvalidFormatSpecifier,
+                            );
+                        }
                     }
                     match a.position {
                         Position::ArgumentNamed(s) => {
@@ -807,18 +822,20 @@ impl<'tcx> OnUnimplementedFormatString {
                                     ()
                                 }
                                 // So is `{A}` if A is a type parameter
-                                s if generics.params.iter().any(|param| param.name == s) => (),
+                                s if generics.own_params.iter().any(|param| param.name == s) => (),
                                 s => {
                                     if self.is_diagnostic_namespace_variant {
-                                        tcx.emit_node_span_lint(
-                                            UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
-                                            tcx.local_def_id_to_hir_id(item_def_id.expect_local()),
-                                            self.span,
-                                            UnknownFormatParameterForOnUnimplementedAttr {
-                                                argument_name: s,
-                                                trait_name,
-                                            },
-                                        );
+                                        if let Some(item_def_id) = item_def_id.as_local() {
+                                            tcx.emit_node_span_lint(
+                                                UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
+                                                tcx.local_def_id_to_hir_id(item_def_id),
+                                                self.span,
+                                                UnknownFormatParameterForOnUnimplementedAttr {
+                                                    argument_name: s,
+                                                    trait_name,
+                                                },
+                                            );
+                                        }
                                     } else {
                                         result = Err(struct_span_code_err!(
                                             tcx.dcx(),
@@ -840,12 +857,14 @@ impl<'tcx> OnUnimplementedFormatString {
                         // `{:1}` and `{}` are not to be used
                         Position::ArgumentIs(..) | Position::ArgumentImplicitlyIs(_) => {
                             if self.is_diagnostic_namespace_variant {
-                                tcx.emit_node_span_lint(
-                                    UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
-                                    tcx.local_def_id_to_hir_id(item_def_id.expect_local()),
-                                    self.span,
-                                    DisallowedPositionalArgument,
-                                );
+                                if let Some(item_def_id) = item_def_id.as_local() {
+                                    tcx.emit_node_span_lint(
+                                        UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
+                                        tcx.local_def_id_to_hir_id(item_def_id),
+                                        self.span,
+                                        DisallowedPositionalArgument,
+                                    );
+                                }
                             } else {
                                 let reported = struct_span_code_err!(
                                     tcx.dcx(),
@@ -868,12 +887,14 @@ impl<'tcx> OnUnimplementedFormatString {
         // so that users are aware that something is not correct
         for e in parser.errors {
             if self.is_diagnostic_namespace_variant {
-                tcx.emit_node_span_lint(
-                    UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
-                    tcx.local_def_id_to_hir_id(item_def_id.expect_local()),
-                    self.span,
-                    WrappedParserError { description: e.description, label: e.label },
-                );
+                if let Some(item_def_id) = item_def_id.as_local() {
+                    tcx.emit_node_span_lint(
+                        UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
+                        tcx.local_def_id_to_hir_id(item_def_id),
+                        self.span,
+                        WrappedParserError { description: e.description, label: e.label },
+                    );
+                }
             } else {
                 let reported =
                     struct_span_code_err!(tcx.dcx(), self.span, E0231, "{}", e.description,).emit();
@@ -895,7 +916,7 @@ impl<'tcx> OnUnimplementedFormatString {
         let trait_str = tcx.def_path_str(trait_ref.def_id);
         let generics = tcx.generics_of(trait_ref.def_id);
         let generic_map = generics
-            .params
+            .own_params
             .iter()
             .filter_map(|param| {
                 let value = match param.kind {
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 3d2574ac92b..597effcbbf0 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -7,7 +7,7 @@ use super::{
 
 use crate::errors;
 use crate::infer::InferCtxt;
-use crate::traits::{ImplDerivedObligationCause, NormalizeExt, ObligationCtxt};
+use crate::traits::{ImplDerivedCause, NormalizeExt, ObligationCtxt};
 
 use hir::def::CtorOf;
 use rustc_data_structures::fx::FxHashSet;
@@ -24,7 +24,6 @@ use rustc_hir::is_range_literal;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, HirId, Node};
 use rustc_infer::infer::error_reporting::TypeErrCtxt;
-use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk};
 use rustc_macros::extension;
 use rustc_middle::hir::map;
@@ -456,8 +455,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) -> bool {
         let mut code = obligation.cause.code();
-        if let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, call_hir_id, .. } =
-            code
+        if let ObligationCauseCode::FunctionArg { arg_hir_id, call_hir_id, .. } = code
             && let Some(typeck_results) = &self.typeck_results
             && let hir::Node::Expr(expr) = self.tcx.hir_node(*arg_hir_id)
             && let Some(arg_ty) = typeck_results.expr_ty_adjusted_opt(expr)
@@ -539,10 +537,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                             self.tcx,
                             obligation.cause.clone(),
                             obligation.param_env,
-                            ty::TraitRef::from_lang_item(
+                            ty::TraitRef::new(
                                 self.tcx,
-                                hir::LangItem::Sized,
-                                obligation.cause.span,
+                                self.tcx.require_lang_item(
+                                    hir::LangItem::Sized,
+                                    Some(obligation.cause.span),
+                                ),
                                 [base_ty],
                             ),
                         );
@@ -847,7 +847,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             .collect::<Vec<_>>()
             .join(", ");
 
-        if matches!(obligation.cause.code(), ObligationCauseCode::FunctionArgumentObligation { .. })
+        if matches!(obligation.cause.code(), ObligationCauseCode::FunctionArg { .. })
             && obligation.cause.span.can_be_used_for_suggestions()
         {
             // When the obligation error has been ensured to have been caused by
@@ -981,8 +981,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             };
             let ty::Ref(_, inner_ty, hir::Mutability::Not) = ty.kind() else { return false };
             let ty::Param(param) = inner_ty.kind() else { return false };
-            let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } =
-                obligation.cause.code()
+            let ObligationCauseCode::FunctionArg { arg_hir_id, .. } = obligation.cause.code()
             else {
                 return false;
             };
@@ -1205,9 +1204,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         let span = obligation.cause.span;
 
         let code = match obligation.cause.code() {
-            ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => parent_code,
-            c @ ObligationCauseCode::ItemObligation(_)
-            | c @ ObligationCauseCode::ExprItemObligation(..) => c,
+            ObligationCauseCode::FunctionArg { parent_code, .. } => parent_code,
+            c @ ObligationCauseCode::WhereClause(_)
+            | c @ ObligationCauseCode::WhereClauseInExpr(..) => c,
             c if matches!(
                 span.ctxt().outer_expn_data().kind,
                 ExpnKind::Desugaring(DesugaringKind::ForLoop)
@@ -1263,8 +1262,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             let mut_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_mut_ref);
 
             let (ref_inner_ty_satisfies_pred, ref_inner_ty_mut) =
-                if let ObligationCauseCode::ItemObligation(_)
-                | ObligationCauseCode::ExprItemObligation(..) = obligation.cause.code()
+                if let ObligationCauseCode::WhereClause(_)
+                | ObligationCauseCode::WhereClauseInExpr(..) = obligation.cause.code()
                     && let ty::Ref(_, ty, mutability) = old_pred.self_ty().skip_binder().kind()
                 {
                     (
@@ -1402,12 +1401,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             return false;
         };
 
-        if let ObligationCauseCode::ImplDerivedObligation(cause) = &*code {
+        if let ObligationCauseCode::ImplDerived(cause) = &*code {
             try_borrowing(cause.derived.parent_trait_pred, &[])
-        } else if let ObligationCauseCode::BindingObligation(_, _)
-        | ObligationCauseCode::ItemObligation(_)
-        | ObligationCauseCode::ExprItemObligation(..)
-        | ObligationCauseCode::ExprBindingObligation(..) = code
+        } else if let ObligationCauseCode::SpannedWhereClause(_, _)
+        | ObligationCauseCode::WhereClause(_)
+        | ObligationCauseCode::WhereClauseInExpr(..)
+        | ObligationCauseCode::SpannedWhereClauseInExpr(..) = code
         {
             try_borrowing(poly_trait_pred, &never_suggest_borrow)
         } else {
@@ -1645,10 +1644,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         err: &mut Diag<'_>,
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) {
-        let points_at_arg = matches!(
-            obligation.cause.code(),
-            ObligationCauseCode::FunctionArgumentObligation { .. },
-        );
+        let points_at_arg =
+            matches!(obligation.cause.code(), ObligationCauseCode::FunctionArg { .. },);
 
         let span = obligation.cause.span;
         if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
@@ -1893,8 +1890,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 ty::Tuple(inputs) if infcx.tcx.is_fn_trait(trait_ref.def_id) => {
                     infcx.tcx.mk_fn_sig(
                         *inputs,
-                        infcx
-                            .next_ty_var(TypeVariableOrigin { span: DUMMY_SP, param_def_id: None }),
+                        infcx.next_ty_var(DUMMY_SP),
                         false,
                         hir::Unsafety::Normal,
                         abi::Abi::Rust,
@@ -1902,7 +1898,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 }
                 _ => infcx.tcx.mk_fn_sig(
                     [inputs],
-                    infcx.next_ty_var(TypeVariableOrigin { span: DUMMY_SP, param_def_id: None }),
+                    infcx.next_ty_var(DUMMY_SP),
                     false,
                     hir::Unsafety::Normal,
                     abi::Abi::Rust,
@@ -1955,7 +1951,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         found: Ty<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
     ) {
-        let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } = cause else {
+        let ObligationCauseCode::FunctionArg { arg_hir_id, .. } = cause else {
             return;
         };
         let ty::FnPtr(expected) = expected.kind() else {
@@ -2106,10 +2102,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         cause: &ObligationCauseCode<'tcx>,
         err: &mut Diag<'tcx>,
     ) {
-        // First, look for an `ExprBindingObligation`, which means we can get
+        // First, look for an `SpannedWhereClauseInExpr`, which means we can get
         // the uninstantiated predicate list of the called function. And check
         // that the predicate that we failed to satisfy is a `Fn`-like trait.
-        if let ObligationCauseCode::ExprBindingObligation(def_id, _, _, idx) = cause
+        if let ObligationCauseCode::SpannedWhereClauseInExpr(def_id, _, _, idx) = cause
             && let predicates = self.tcx.predicates_of(def_id).instantiate_identity(self.tcx)
             && let Some(pred) = predicates.predicates.get(*idx)
             && let ty::ClauseKind::Trait(trait_pred) = pred.kind().skip_binder()
@@ -2263,10 +2259,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         while let Some(code) = next_code {
             debug!(?code);
             match code {
-                ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => {
+                ObligationCauseCode::FunctionArg { parent_code, .. } => {
                     next_code = Some(parent_code);
                 }
-                ObligationCauseCode::ImplDerivedObligation(cause) => {
+                ObligationCauseCode::ImplDerived(cause) => {
                     let ty = cause.derived.parent_trait_pred.skip_binder().self_ty();
                     debug!(
                         parent_trait_ref = ?cause.derived.parent_trait_pred,
@@ -2295,8 +2291,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
 
                     next_code = Some(&cause.derived.parent_code);
                 }
-                ObligationCauseCode::WellFormedDerivedObligation(derived_obligation)
-                | ObligationCauseCode::BuiltinDerivedObligation(derived_obligation) => {
+                ObligationCauseCode::WellFormedDerived(derived_obligation)
+                | ObligationCauseCode::BuiltinDerived(derived_obligation) => {
                     let ty = derived_obligation.parent_trait_pred.skip_binder().self_ty();
                     debug!(
                         parent_trait_ref = ?derived_obligation.parent_trait_pred,
@@ -2721,7 +2717,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             | ObligationCauseCode::MethodReceiver
             | ObligationCauseCode::ReturnNoExpression
             | ObligationCauseCode::UnifyReceiver(..)
-            | ObligationCauseCode::MiscObligation
+            | ObligationCauseCode::Misc
             | ObligationCauseCode::WellFormed(..)
             | ObligationCauseCode::MatchImpl(..)
             | ObligationCauseCode::ReturnValue(_)
@@ -2750,13 +2746,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             ObligationCauseCode::TupleElem => {
                 err.note("only the last element of a tuple may have a dynamically sized type");
             }
-            ObligationCauseCode::ItemObligation(_)
-            | ObligationCauseCode::ExprItemObligation(..) => {
+            ObligationCauseCode::WhereClause(_) | ObligationCauseCode::WhereClauseInExpr(..) => {
                 // We hold the `DefId` of the item introducing the obligation, but displaying it
                 // doesn't add user usable information. It always point at an associated item.
             }
-            ObligationCauseCode::BindingObligation(item_def_id, span)
-            | ObligationCauseCode::ExprBindingObligation(item_def_id, span, ..) => {
+            ObligationCauseCode::SpannedWhereClause(item_def_id, span)
+            | ObligationCauseCode::SpannedWhereClauseInExpr(item_def_id, span, ..) => {
                 let item_name = tcx.def_path_str(item_def_id);
                 let short_item_name = with_forced_trimmed_paths!(tcx.def_path_str(item_def_id));
                 let mut multispan = MultiSpan::from(span);
@@ -2799,7 +2794,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                         // Check if this is an implicit bound, even in foreign crates.
                         if tcx
                             .generics_of(item_def_id)
-                            .params
+                            .own_params
                             .iter()
                             .any(|param| tcx.def_span(param.def_id) == span)
                         {
@@ -3177,7 +3172,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             ObligationCauseCode::SharedStatic => {
                 err.note("shared static variables must have a type that implements `Sync`");
             }
-            ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
+            ObligationCauseCode::BuiltinDerived(ref data) => {
                 let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred);
                 let ty = parent_trait_ref.skip_binder().self_ty();
                 if parent_trait_ref.references_error() {
@@ -3192,8 +3187,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 let is_upvar_tys_infer_tuple = if !matches!(ty.kind(), ty::Tuple(..)) {
                     false
                 } else {
-                    if let ObligationCauseCode::BuiltinDerivedObligation(data) = &*data.parent_code
-                    {
+                    if let ObligationCauseCode::BuiltinDerived(data) = &*data.parent_code {
                         let parent_trait_ref =
                             self.resolve_vars_if_possible(data.parent_trait_pred);
                         let nested_ty = parent_trait_ref.skip_binder().self_ty();
@@ -3299,7 +3293,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     });
                 }
             }
-            ObligationCauseCode::ImplDerivedObligation(ref data) => {
+            ObligationCauseCode::ImplDerived(ref data) => {
                 let mut parent_trait_pred =
                     self.resolve_vars_if_possible(data.derived.parent_trait_pred);
                 let parent_def_id = parent_trait_pred.def_id();
@@ -3369,9 +3363,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 if is_auto_trait {
                     // We don't want to point at the ADT saying "required because it appears within
                     // the type `X`", like we would otherwise do in test `supertrait-auto-trait.rs`.
-                    while let ObligationCauseCode::BuiltinDerivedObligation(derived) =
-                        &*data.parent_code
-                    {
+                    while let ObligationCauseCode::BuiltinDerived(derived) = &*data.parent_code {
                         let child_trait_ref =
                             self.resolve_vars_if_possible(derived.parent_trait_pred);
                         let child_def_id = child_trait_ref.def_id();
@@ -3383,7 +3375,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                         parent_trait_pred = child_trait_ref;
                     }
                 }
-                while let ObligationCauseCode::ImplDerivedObligation(child) = &*data.parent_code {
+                while let ObligationCauseCode::ImplDerived(child) = &*data.parent_code {
                     // Skip redundant recursive obligation notes. See `ui/issue-20413.rs`.
                     let child_trait_pred =
                         self.resolve_vars_if_possible(child.derived.parent_trait_pred);
@@ -3424,7 +3416,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     )
                 });
             }
-            ObligationCauseCode::WellFormedDerivedObligation(ref data) => {
+            ObligationCauseCode::WellFormedDerived(ref data) => {
                 let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred);
                 let parent_predicate = parent_trait_ref;
                 // #74711: avoid a stack overflow
@@ -3460,11 +3452,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     format!("required by a bound on the type alias `{}`", tcx.item_name(def_id)),
                 );
             }
-            ObligationCauseCode::FunctionArgumentObligation {
-                arg_hir_id,
-                call_hir_id,
-                ref parent_code,
-                ..
+            ObligationCauseCode::FunctionArg {
+                arg_hir_id, call_hir_id, ref parent_code, ..
             } => {
                 self.note_function_argument_obligation(
                     body_id,
@@ -3487,7 +3476,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     )
                 });
             }
-            ObligationCauseCode::CompareImplItemObligation { trait_item_def_id, kind, .. } => {
+            ObligationCauseCode::CompareImplItem { trait_item_def_id, kind, .. } => {
                 let item_name = tcx.item_name(trait_item_def_id);
                 let msg = format!(
                     "the requirement `{predicate}` appears on the `impl`'s {kind} \
@@ -3696,7 +3685,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         err: &mut Diag<'_>,
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) {
-        if let ObligationCauseCode::ImplDerivedObligation(_) = obligation.cause.code()
+        if let ObligationCauseCode::ImplDerived(_) = obligation.cause.code()
             && self
                 .tcx
                 .is_diagnostic_item(sym::SliceIndex, trait_pred.skip_binder().trait_ref.def_id)
@@ -3813,7 +3802,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             // to an associated type (as seen from `trait_pred`) in the predicate. Like in
             // trait_pred `S: Sum<<Self as Iterator>::Item>` and predicate `i32: Sum<&()>`
             let mut type_diffs = vec![];
-            if let ObligationCauseCode::ExprBindingObligation(def_id, _, _, idx) = parent_code
+            if let ObligationCauseCode::SpannedWhereClauseInExpr(def_id, _, _, idx) = parent_code
                 && let Some(node_args) = typeck_results.node_args_opt(call_hir_id)
                 && let where_clauses =
                     self.tcx.predicates_of(def_id).instantiate(self.tcx, node_args)
@@ -4046,10 +4035,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                         let node = tcx.hir_node_by_def_id(hir.get_parent_item(expr.hir_id).def_id);
 
                         let pred = ty::Binder::dummy(ty::TraitPredicate {
-                            trait_ref: ty::TraitRef::from_lang_item(
+                            trait_ref: ty::TraitRef::new(
                                 tcx,
-                                LangItem::Clone,
-                                span,
+                                tcx.require_lang_item(LangItem::Clone, Some(span)),
                                 [*ty],
                             ),
                             polarity: ty::PredicatePolarity::Positive,
@@ -4263,7 +4251,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 continue;
             };
 
-            let origin = TypeVariableOrigin { param_def_id: None, span };
             // Make `Self` be equivalent to the type of the call chain
             // expression we're looking at now, so that we can tell what
             // for example `Iterator::Item` is at this point in the chain.
@@ -4277,7 +4264,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             // This will hold the resolved type of the associated type, if the
             // current expression implements the trait that associated type is
             // in. For example, this would be what `Iterator::Item` is here.
-            let ty = self.infcx.next_ty_var(origin);
+            let ty = self.infcx.next_ty_var(span);
             // This corresponds to `<ExprTy as Iterator>::Item = _`.
             let projection = ty::Binder::dummy(ty::PredicateKind::Clause(
                 ty::ClauseKind::Projection(ty::ProjectionPredicate {
@@ -4323,8 +4310,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
     ) {
         // We can only suggest the slice coersion for function and binary operation arguments,
         // since the suggestion would make no sense in turbofish or call
-        let (ObligationCauseCode::BinOp { .. }
-        | ObligationCauseCode::FunctionArgumentObligation { .. }) = obligation.cause.code()
+        let (ObligationCauseCode::BinOp { .. } | ObligationCauseCode::FunctionArg { .. }) =
+            obligation.cause.code()
         else {
             return;
         };
@@ -4410,7 +4397,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     return;
                 }
 
-                if let ObligationCauseCode::FunctionArgumentObligation {
+                if let ObligationCauseCode::FunctionArg {
                     call_hir_id,
                     arg_hir_id,
                     parent_code: _,
@@ -4970,7 +4957,7 @@ fn point_at_assoc_type_restriction<G: EmissionGuarantee>(
     trait_name: &str,
     predicate: ty::Predicate<'_>,
     generics: &hir::Generics<'_>,
-    data: &ImplDerivedObligationCause<'_>,
+    data: &ImplDerivedCause<'_>,
 ) {
     let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder() else {
         return;
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
index e50cb2af4b8..cdde12af8ea 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
@@ -6,7 +6,6 @@ use crate::errors::{
     AsyncClosureNotFn, ClosureFnMutLabel, ClosureFnOnceLabel, ClosureKindMismatch,
 };
 use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
-use crate::infer::type_variable::TypeVariableOrigin;
 use crate::infer::InferCtxtExt as _;
 use crate::infer::{self, InferCtxt};
 use crate::traits::error_reporting::infer_ctxt_ext::InferCtxtExt;
@@ -38,7 +37,9 @@ use rustc_middle::traits::SignatureMismatchData;
 use rustc_middle::ty::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::fold::{BottomUpFolder, TypeFolder, TypeSuperFoldable};
-use rustc_middle::ty::print::{with_forced_trimmed_paths, FmtPrinter, Print};
+use rustc_middle::ty::print::{
+    with_forced_trimmed_paths, FmtPrinter, Print, PrintTraitRefExt as _,
+};
 use rustc_middle::ty::{
     self, SubtypePredicate, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable,
     TypeVisitable, TypeVisitableExt,
@@ -392,7 +393,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     }
                 }
 
-                if let ObligationCauseCode::CompareImplItemObligation {
+                if let ObligationCauseCode::CompareImplItem {
                     impl_item_def_id,
                     trait_item_def_id,
                     kind: _,
@@ -1018,7 +1019,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             if let Some((_, Some(parent))) = obligation.cause.code().parent() {
                 // If we have a derived obligation, then the parent will be a `AsyncFn*` goal.
                 trait_ref = parent.to_poly_trait_ref();
-            } else if let &ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } =
+            } else if let &ObligationCauseCode::FunctionArg { arg_hir_id, .. } =
                 obligation.cause.code()
                 && let Some(typeck_results) = &self.typeck_results
                 && let ty::Closure(closure_def_id, _) | ty::CoroutineClosure(closure_def_id, _) =
@@ -1105,8 +1106,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         &self,
         obligation: &PredicateObligation<'tcx>,
     ) -> Result<(), ErrorGuaranteed> {
-        if let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } =
-            obligation.cause.code()
+        if let ObligationCauseCode::FunctionArg { arg_hir_id, .. } = obligation.cause.code()
             && let Node::Expr(arg) = self.tcx.hir_node(*arg_hir_id)
             && let arg = arg.peel_borrows()
             && let hir::ExprKind::Path(hir::QPath::Resolved(
@@ -1505,13 +1505,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         }
 
         match error.code {
-            FulfillmentErrorCode::SelectionError(ref selection_error) => self
-                .report_selection_error(
-                    error.obligation.clone(),
-                    &error.root_obligation,
-                    selection_error,
-                ),
-            FulfillmentErrorCode::ProjectionError(ref e) => {
+            FulfillmentErrorCode::Select(ref selection_error) => self.report_selection_error(
+                error.obligation.clone(),
+                &error.root_obligation,
+                selection_error,
+            ),
+            FulfillmentErrorCode::Project(ref e) => {
                 self.report_projection_error(&error.obligation, e)
             }
             FulfillmentErrorCode::Ambiguity { overflow: None } => {
@@ -1520,7 +1519,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             FulfillmentErrorCode::Ambiguity { overflow: Some(suggest_increasing_limit) } => {
                 self.report_overflow_no_abort(error.obligation.clone(), suggest_increasing_limit)
             }
-            FulfillmentErrorCode::SubtypeError(ref expected_found, ref err) => self
+            FulfillmentErrorCode::Subtype(ref expected_found, ref err) => self
                 .report_mismatched_types(
                     &error.obligation.cause,
                     expected_found.expected,
@@ -1528,7 +1527,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     *err,
                 )
                 .emit(),
-            FulfillmentErrorCode::ConstEquateError(ref expected_found, ref err) => {
+            FulfillmentErrorCode::ConstEquate(ref expected_found, ref err) => {
                 let mut diag = self.report_mismatched_consts(
                     &error.obligation.cause,
                     expected_found.expected,
@@ -1536,10 +1535,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     *err,
                 );
                 let code = error.obligation.cause.code().peel_derives().peel_match_impls();
-                if let ObligationCauseCode::BindingObligation(..)
-                | ObligationCauseCode::ItemObligation(..)
-                | ObligationCauseCode::ExprBindingObligation(..)
-                | ObligationCauseCode::ExprItemObligation(..) = code
+                if let ObligationCauseCode::SpannedWhereClause(..)
+                | ObligationCauseCode::WhereClause(..)
+                | ObligationCauseCode::SpannedWhereClauseInExpr(..)
+                | ObligationCauseCode::WhereClauseInExpr(..) = code
                 {
                     self.note_obligation_cause_code(
                         error.obligation.cause.body_id,
@@ -1613,10 +1612,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
 
                 let is_normalized_term_expected = !matches!(
                     obligation.cause.code().peel_derives(),
-                    ObligationCauseCode::ItemObligation(_)
-                        | ObligationCauseCode::BindingObligation(_, _)
-                        | ObligationCauseCode::ExprItemObligation(..)
-                        | ObligationCauseCode::ExprBindingObligation(..)
+                    ObligationCauseCode::WhereClause(_)
+                        | ObligationCauseCode::SpannedWhereClause(_, _)
+                        | ObligationCauseCode::WhereClauseInExpr(..)
+                        | ObligationCauseCode::SpannedWhereClauseInExpr(..)
                         | ObligationCauseCode::Coercion { .. }
                 );
 
@@ -2213,7 +2212,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         code: &ObligationCauseCode<'tcx>,
     ) -> Option<(Ty<'tcx>, Option<Span>)> {
         match code {
-            ObligationCauseCode::BuiltinDerivedObligation(data) => {
+            ObligationCauseCode::BuiltinDerived(data) => {
                 let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred);
                 match self.get_parent_trait_ref(&data.parent_code) {
                     Some(t) => Some(t),
@@ -2225,7 +2224,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     }
                 }
             }
-            ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => {
+            ObligationCauseCode::FunctionArg { parent_code, .. } => {
                 self.get_parent_trait_ref(parent_code)
             }
             _ => None,
@@ -2448,8 +2447,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     }
                 }
 
-                if let ObligationCauseCode::ItemObligation(def_id)
-                | ObligationCauseCode::ExprItemObligation(def_id, ..) = *obligation.cause.code()
+                if let ObligationCauseCode::WhereClause(def_id)
+                | ObligationCauseCode::WhereClauseInExpr(def_id, ..) = *obligation.cause.code()
                 {
                     self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
                 }
@@ -2826,9 +2825,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 if let ty::Param(_) = *ty.kind() {
                     let infcx = self.infcx;
-                    *self.var_map.entry(ty).or_insert_with(|| {
-                        infcx.next_ty_var(TypeVariableOrigin { param_def_id: None, span: DUMMY_SP })
-                    })
+                    *self.var_map.entry(ty).or_insert_with(|| infcx.next_ty_var(DUMMY_SP))
                 } else {
                     ty.super_fold_with(self)
                 }
@@ -2886,8 +2883,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         else {
             return;
         };
-        let (ObligationCauseCode::BindingObligation(item_def_id, span)
-        | ObligationCauseCode::ExprBindingObligation(item_def_id, span, ..)) =
+        let (ObligationCauseCode::SpannedWhereClause(item_def_id, span)
+        | ObligationCauseCode::SpannedWhereClauseInExpr(item_def_id, span, ..)) =
             *obligation.cause.code().peel_derives()
         else {
             return;
@@ -3007,7 +3004,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         obligated_types: &mut Vec<Ty<'tcx>>,
         cause_code: &ObligationCauseCode<'tcx>,
     ) -> bool {
-        if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = cause_code {
+        if let ObligationCauseCode::BuiltinDerived(ref data) = cause_code {
             let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred);
             let self_ty = parent_trait_ref.skip_binder().self_ty();
             if obligated_types.iter().any(|ot| ot == &self_ty) {
@@ -3184,8 +3181,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             ObligationCauseCode::RustCall => {
                 err.primary_message("functions with the \"rust-call\" ABI must take a single non-self tuple argument");
             }
-            ObligationCauseCode::BindingObligation(def_id, _)
-            | ObligationCauseCode::ItemObligation(def_id)
+            ObligationCauseCode::SpannedWhereClause(def_id, _)
+            | ObligationCauseCode::WhereClause(def_id)
                 if self.tcx.is_fn_trait(*def_id) =>
             {
                 err.code(E0059);
@@ -3443,8 +3440,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         self.dcx().try_steal_replace_and_emit_err(self.tcx.def_span(def_id), StashKey::Cycle, err)
     }
 
-    // FIXME(@lcnr): This function could be changed to trait `TraitRef` directly
-    // instead of using a `Binder`.
     fn report_signature_mismatch_error(
         &self,
         obligation: &PredicateObligation<'tcx>,
@@ -3576,7 +3571,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     match self.tcx.sess.source_map().span_to_snippet(const_span) {
                         Ok(snippet) => {
                             let code = format!("[(); {snippet}{cast}]:");
-                            let def_id = if let ObligationCauseCode::CompareImplItemObligation {
+                            let def_id = if let ObligationCauseCode::CompareImplItem {
                                 trait_item_def_id,
                                 ..
                             } = obligation.cause.code()
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 1f10cb71543..e3497c646db 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -411,7 +411,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
 
                 ty::PredicateKind::ObjectSafe(trait_def_id) => {
                     if !self.selcx.tcx().check_is_object_safe(trait_def_id) {
-                        ProcessResult::Error(FulfillmentErrorCode::SelectionError(Unimplemented))
+                        ProcessResult::Error(FulfillmentErrorCode::Select(Unimplemented))
                     } else {
                         ProcessResult::Changed(vec![])
                     }
@@ -435,7 +435,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                         ty,
                     ) {
                         Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())),
-                        Err(_) => ProcessResult::Error(FulfillmentErrorCode::SelectionError(
+                        Err(_) => ProcessResult::Error(FulfillmentErrorCode::Select(
                             SelectionError::Unimplemented,
                         )),
                     }
@@ -493,10 +493,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                         Ok(Err(err)) => {
                             let expected_found =
                                 ExpectedFound::new(subtype.a_is_expected, subtype.a, subtype.b);
-                            ProcessResult::Error(FulfillmentErrorCode::SubtypeError(
-                                expected_found,
-                                err,
-                            ))
+                            ProcessResult::Error(FulfillmentErrorCode::Subtype(expected_found, err))
                         }
                     }
                 }
@@ -516,10 +513,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                         Ok(Ok(ok)) => ProcessResult::Changed(mk_pending(ok.obligations)),
                         Ok(Err(err)) => {
                             let expected_found = ExpectedFound::new(false, coerce.a, coerce.b);
-                            ProcessResult::Error(FulfillmentErrorCode::SubtypeError(
-                                expected_found,
-                                err,
-                            ))
+                            ProcessResult::Error(FulfillmentErrorCode::Subtype(expected_found, err))
                         }
                     }
                 }
@@ -542,7 +536,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                         Err(
                             e @ NotConstEvaluatable::MentionsParam
                             | e @ NotConstEvaluatable::Error(_),
-                        ) => ProcessResult::Error(FulfillmentErrorCode::SelectionError(
+                        ) => ProcessResult::Error(FulfillmentErrorCode::Select(
                             SelectionError::NotConstEvaluatable(e),
                         )),
                     }
@@ -638,7 +632,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                                     ProcessResult::Changed(mk_pending(inf_ok.into_obligations()))
                                 }
                                 Err(err) => {
-                                    ProcessResult::Error(FulfillmentErrorCode::ConstEquateError(
+                                    ProcessResult::Error(FulfillmentErrorCode::ConstEquate(
                                         ExpectedFound::new(true, c1, c2),
                                         err,
                                     ))
@@ -646,13 +640,11 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                             }
                         }
                         (Err(ErrorHandled::Reported(reported, _)), _)
-                        | (_, Err(ErrorHandled::Reported(reported, _))) => {
-                            ProcessResult::Error(FulfillmentErrorCode::SelectionError(
-                                SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(
-                                    reported.into(),
-                                )),
-                            ))
-                        }
+                        | (_, Err(ErrorHandled::Reported(reported, _))) => ProcessResult::Error(
+                            FulfillmentErrorCode::Select(SelectionError::NotConstEvaluatable(
+                                NotConstEvaluatable::Error(reported.into()),
+                            )),
+                        ),
                         (Err(ErrorHandled::TooGeneric(_)), _)
                         | (_, Err(ErrorHandled::TooGeneric(_))) => {
                             if c1.has_non_region_infer() || c2.has_non_region_infer() {
@@ -660,7 +652,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                             } else {
                                 // Two different constants using generic parameters ~> error.
                                 let expected_found = ExpectedFound::new(true, c1, c2);
-                                ProcessResult::Error(FulfillmentErrorCode::ConstEquateError(
+                                ProcessResult::Error(FulfillmentErrorCode::ConstEquate(
                                     expected_found,
                                     TypeError::ConstMismatch(expected_found),
                                 ))
@@ -741,7 +733,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
             Err(selection_err) => {
                 debug!("selecting trait at depth {} yielded Err", obligation.recursion_depth);
 
-                ProcessResult::Error(FulfillmentErrorCode::SelectionError(selection_err))
+                ProcessResult::Error(FulfillmentErrorCode::Select(selection_err))
             }
         }
     }
@@ -793,7 +785,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
                 project_obligation.with(tcx, project_obligation.predicate),
             ])),
             ProjectAndUnifyResult::MismatchedProjectionTypes(e) => {
-                ProcessResult::Error(FulfillmentErrorCode::ProjectionError(e))
+                ProcessResult::Error(FulfillmentErrorCode::Project(e))
             }
         }
     }
diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs
index 93f9c2333f0..da2b004761f 100644
--- a/compiler/rustc_trait_selection/src/traits/misc.rs
+++ b/compiler/rustc_trait_selection/src/traits/misc.rs
@@ -10,7 +10,7 @@ use rustc_infer::infer::canonical::Canonical;
 use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
 use rustc_infer::traits::query::NoSolution;
 use rustc_infer::{infer::outlives::env::OutlivesEnvironment, traits::FulfillmentError};
-use rustc_middle::ty::{self, AdtDef, GenericArg, List, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeVisitableExt};
 use rustc_span::DUMMY_SP;
 
 use super::outlives_bounds::InferCtxtExt;
@@ -129,7 +129,7 @@ pub fn all_fields_implement_trait<'tcx>(
     param_env: ty::ParamEnv<'tcx>,
     self_type: Ty<'tcx>,
     adt: AdtDef<'tcx>,
-    args: &'tcx List<GenericArg<'tcx>>,
+    args: ty::GenericArgsRef<'tcx>,
     parent_cause: ObligationCause<'tcx>,
     lang_item: LangItem,
 ) -> Result<(), Vec<(&'tcx ty::FieldDef, Ty<'tcx>, InfringingFieldsReason<'tcx>)>> {
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index 0e15dd27537..5cb61dff831 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -397,7 +397,7 @@ pub fn object_safety_violations_for_assoc_item(
         // Associated types can only be object safe if they have `Self: Sized` bounds.
         ty::AssocKind::Type => {
             if !tcx.features().generic_associated_types_extended
-                && !tcx.generics_of(item.def_id).params.is_empty()
+                && !tcx.generics_of(item.def_id).own_params.is_empty()
                 && !item.is_impl_trait_in_trait()
             {
                 vec![ObjectSafetyViolation::GAT(item.name, item.ident(tcx).span)]
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 116e17c7e43..1e78484f305 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -13,12 +13,12 @@ use super::Selection;
 use super::SelectionContext;
 use super::SelectionError;
 use super::{Normalized, NormalizedTy, ProjectionCacheEntry, ProjectionCacheKey};
+use rustc_infer::traits::ObligationCauseCode;
 use rustc_middle::traits::BuiltinImplSource;
 use rustc_middle::traits::ImplSource;
 use rustc_middle::traits::ImplSourceUserDefinedData;
 
 use crate::errors::InherentProjectionNormalizationOverflow;
-use crate::infer::type_variable::TypeVariableOrigin;
 use crate::infer::{BoundRegionConversionTime, InferOk};
 use crate::traits::normalize::normalize_with_depth;
 use crate::traits::normalize::normalize_with_depth_to;
@@ -521,10 +521,7 @@ fn normalize_to_error<'a, 'tcx>(
         predicate: trait_ref.to_predicate(selcx.tcx()),
     };
     let tcx = selcx.infcx.tcx;
-    let new_value = selcx.infcx.next_ty_var(TypeVariableOrigin {
-        param_def_id: None,
-        span: tcx.def_span(projection_ty.def_id),
-    });
+    let new_value = selcx.infcx.next_ty_var(tcx.def_span(projection_ty.def_id));
     Normalized { value: new_value, obligations: vec![trait_obligation] }
 }
 
@@ -577,9 +574,9 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>(
             // diagnostics which is not ideal.
             // Consider creating separate cause codes for this specific situation.
             if span.is_dummy() {
-                super::ItemObligation(alias_ty.def_id)
+                ObligationCauseCode::WhereClause(alias_ty.def_id)
             } else {
-                super::BindingObligation(alias_ty.def_id, span)
+                ObligationCauseCode::SpannedWhereClause(alias_ty.def_id, span)
             },
         );
 
@@ -977,9 +974,12 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                 //
                 // NOTE: This should be kept in sync with the similar code in
                 // `rustc_ty_utils::instance::resolve_associated_item()`.
-                let node_item =
-                    specialization_graph::assoc_def(selcx.tcx(), impl_data.impl_def_id, obligation.predicate.def_id)
-                        .map_err(|ErrorGuaranteed { .. }| ())?;
+                let node_item = specialization_graph::assoc_def(
+                    selcx.tcx(),
+                    impl_data.impl_def_id,
+                    obligation.predicate.def_id,
+                )
+                .map_err(|ErrorGuaranteed { .. }| ())?;
 
                 if node_item.is_final() {
                     // Non-specializable items are always projectable.
@@ -1022,7 +1022,8 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                     lang_items.async_fn_trait(),
                     lang_items.async_fn_mut_trait(),
                     lang_items.async_fn_once_trait(),
-                ].contains(&Some(trait_ref.def_id))
+                ]
+                .contains(&Some(trait_ref.def_id))
                 {
                     true
                 } else if lang_items.async_fn_kind_helper() == Some(trait_ref.def_id) {
@@ -1035,7 +1036,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                         true
                     } else {
                         obligation.predicate.args.type_at(0).to_opt_closure_kind().is_some()
-                        && obligation.predicate.args.type_at(1).to_opt_closure_kind().is_some()
+                            && obligation.predicate.args.type_at(1).to_opt_closure_kind().is_some()
                     }
                 } else if lang_items.discriminant_kind_trait() == Some(trait_ref.def_id) {
                     match self_ty.kind() {
@@ -1162,12 +1163,20 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                         // Otherwise, type parameters, opaques, and unnormalized projections have
                         // unit metadata if they're known (e.g. by the param_env) to be sized.
                         ty::Param(_) | ty::Alias(..)
-                            if self_ty != tail || selcx.infcx.predicate_must_hold_modulo_regions(
-                                &obligation.with(
-                                    selcx.tcx(),
-                                    ty::TraitRef::from_lang_item(selcx.tcx(), LangItem::Sized, obligation.cause.span(),[self_ty]),
-                                ),
-                            ) =>
+                            if self_ty != tail
+                                || selcx.infcx.predicate_must_hold_modulo_regions(
+                                    &obligation.with(
+                                        selcx.tcx(),
+                                        ty::TraitRef::new(
+                                            selcx.tcx(),
+                                            selcx.tcx().require_lang_item(
+                                                LangItem::Sized,
+                                                Some(obligation.cause.span()),
+                                            ),
+                                            [self_ty],
+                                        ),
+                                    ),
+                                ) =>
                         {
                             true
                         }
@@ -1230,7 +1239,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                     obligation.cause.span,
                     format!("Cannot project an associated type from `{impl_source:?}`"),
                 );
-                return Err(())
+                return Err(());
             }
         };
 
@@ -1559,10 +1568,9 @@ fn confirm_builtin_candidate<'cx, 'tcx>(
                 // and opaque types: If the `self_ty` is `Sized`, then the metadata is `()`.
                 // FIXME(ptr_metadata): This impl overlaps with the other impls and shouldn't
                 // exist. Instead, `Pointee<Metadata = ()>` should be a supertrait of `Sized`.
-                let sized_predicate = ty::TraitRef::from_lang_item(
+                let sized_predicate = ty::TraitRef::new(
                     tcx,
-                    LangItem::Sized,
-                    obligation.cause.span(),
+                    tcx.require_lang_item(LangItem::Sized, Some(obligation.cause.span())),
                     [self_ty],
                 );
                 obligations.push(obligation.with(tcx, sized_predicate));
@@ -2117,22 +2125,22 @@ fn assoc_ty_own_obligations<'cx, 'tcx>(
 
         let nested_cause = if matches!(
             obligation.cause.code(),
-            super::CompareImplItemObligation { .. }
-                | super::CheckAssociatedTypeBounds { .. }
-                | super::AscribeUserTypeProvePredicate(..)
+            ObligationCauseCode::CompareImplItem { .. }
+                | ObligationCauseCode::CheckAssociatedTypeBounds { .. }
+                | ObligationCauseCode::AscribeUserTypeProvePredicate(..)
         ) {
             obligation.cause.clone()
         } else if span.is_dummy() {
             ObligationCause::new(
                 obligation.cause.span,
                 obligation.cause.body_id,
-                super::ItemObligation(obligation.predicate.def_id),
+                ObligationCauseCode::WhereClause(obligation.predicate.def_id),
             )
         } else {
             ObligationCause::new(
                 obligation.cause.span,
                 obligation.cause.body_id,
-                super::BindingObligation(obligation.predicate.def_id, span),
+                ObligationCauseCode::SpannedWhereClause(obligation.predicate.def_id, span),
             )
         };
         nested.push(Obligation::with_depth(
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs
index 279d96dec72..e9948bf1f71 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs
@@ -34,7 +34,9 @@ where
     }
 }
 
-pub trait Normalizable<'tcx>: fmt::Debug + TypeFoldable<TyCtxt<'tcx>> + Lift<'tcx> + Copy {
+pub trait Normalizable<'tcx>:
+    fmt::Debug + TypeFoldable<TyCtxt<'tcx>> + Lift<TyCtxt<'tcx>> + Copy
+{
     fn type_op_method(
         tcx: TyCtxt<'tcx>,
         canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 4fa2455c42d..69d11b45e60 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -11,6 +11,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir::lang_items::LangItem;
 use rustc_infer::infer::HigherRankedType;
 use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
+use rustc_infer::traits::ObligationCauseCode;
 use rustc_middle::traits::{BuiltinImplSource, SignatureMismatchData};
 use rustc_middle::ty::{
     self, GenericArgs, GenericArgsRef, GenericParamDefKind, ToPolyTraitRef, ToPredicate,
@@ -25,10 +26,9 @@ use crate::traits::vtable::{
     VtblSegment,
 };
 use crate::traits::{
-    BuiltinDerivedObligation, ImplDerivedObligation, ImplDerivedObligationCause, ImplSource,
-    ImplSourceUserDefinedData, Normalized, Obligation, ObligationCause, PolyTraitObligation,
-    PredicateObligation, Selection, SelectionError, SignatureMismatch, TraitNotObjectSafe,
-    TraitObligation, Unimplemented,
+    ImplDerivedCause, ImplSource, ImplSourceUserDefinedData, Normalized, Obligation,
+    ObligationCause, PolyTraitObligation, PredicateObligation, Selection, SelectionError,
+    SignatureMismatch, TraitNotObjectSafe, TraitObligation, Unimplemented,
 };
 
 use super::BuiltinImplConditions;
@@ -275,7 +275,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 bug!("obligation {:?} had matched a builtin impl but now doesn't", obligation);
             };
 
-            let cause = obligation.derived_cause(BuiltinDerivedObligation);
+            let cause = obligation.derived_cause(ObligationCauseCode::BuiltinDerived);
             self.collect_predicates_for_types(
                 obligation.param_env,
                 cause,
@@ -435,7 +435,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     ) -> Vec<PredicateObligation<'tcx>> {
         debug!(?nested, "vtable_auto_impl");
         ensure_sufficient_stack(|| {
-            let cause = obligation.derived_cause(BuiltinDerivedObligation);
+            let cause = obligation.derived_cause(ObligationCauseCode::BuiltinDerived);
 
             let poly_trait_ref = obligation.predicate.to_poly_trait_ref();
             let trait_ref = self.infcx.enter_forall_and_leak_universe(poly_trait_ref);
@@ -606,7 +606,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         for assoc_type in assoc_types {
             let defs: &ty::Generics = tcx.generics_of(assoc_type);
 
-            if !defs.params.is_empty() && !tcx.features().generic_associated_types_extended {
+            if !defs.own_params.is_empty() && !tcx.features().generic_associated_types_extended {
                 tcx.dcx().span_delayed_bug(
                     obligation.cause.span,
                     "GATs in trait object shouldn't have been considered",
@@ -693,7 +693,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         let vtable_base = vtable_trait_first_method_offset(
             tcx,
-            (unnormalized_upcast_trait_ref, ty::Binder::dummy(object_trait_ref)),
+            unnormalized_upcast_trait_ref,
+            ty::Binder::dummy(object_trait_ref),
         );
 
         Ok(ImplSource::Builtin(BuiltinImplSource::Object { vtable_base: vtable_base }, nested))
@@ -722,7 +723,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         let mut nested =
             self.equate_trait_refs(obligation.with(tcx, placeholder_predicate), trait_ref)?;
-        let cause = obligation.derived_cause(BuiltinDerivedObligation);
+        let cause = obligation.derived_cause(ObligationCauseCode::BuiltinDerived);
 
         // Confirm the `type Output: Sized;` bound that is present on `FnOnce`
         let output_ty = self.infcx.enter_forall_and_leak_universe(sig.output());
@@ -734,7 +735,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             output_ty,
             &mut nested,
         );
-        let tr = ty::TraitRef::from_lang_item(self.tcx(), LangItem::Sized, cause.span, [output_ty]);
+        let tr = ty::TraitRef::new(
+            self.tcx(),
+            self.tcx().require_lang_item(LangItem::Sized, Some(cause.span)),
+            [output_ty],
+        );
         nested.push(Obligation::new(self.infcx.tcx, cause, obligation.param_env, tr));
 
         Ok(nested)
@@ -1008,10 +1013,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         } else {
             nested.push(obligation.with(
                 self.tcx(),
-                ty::TraitRef::from_lang_item(
+                ty::TraitRef::new(
                     self.tcx(),
-                    LangItem::AsyncFnKindHelper,
-                    obligation.cause.span,
+                    self.tcx().require_lang_item(
+                        LangItem::AsyncFnKindHelper,
+                        Some(obligation.cause.span),
+                    ),
                     [kind_ty, Ty::from_closure_kind(self.tcx(), goal_kind)],
                 ),
             ));
@@ -1240,10 +1247,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     .collect();
 
                 // We can only make objects from sized types.
-                let tr = ty::TraitRef::from_lang_item(
+                let tr = ty::TraitRef::new(
                     tcx,
-                    LangItem::Sized,
-                    obligation.cause.span,
+                    tcx.require_lang_item(LangItem::Sized, Some(obligation.cause.span)),
                     [source],
                 );
                 nested.push(predicate_to_obligation(tr.to_predicate(tcx)));
@@ -1380,7 +1386,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let self_ty = obligation.self_ty().map_bound(|ty| self.infcx.shallow_resolve(ty));
 
         let mut nested = vec![];
-        let cause = obligation.derived_cause(BuiltinDerivedObligation);
+        let cause = obligation.derived_cause(ObligationCauseCode::BuiltinDerived);
 
         // If we have a custom `impl const Drop`, then
         // first check it like a regular impl candidate.
@@ -1395,7 +1401,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             debug!(?args, "impl args");
 
             let cause = obligation.derived_cause(|derived| {
-                ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
+                ObligationCauseCode::ImplDerived(Box::new(ImplDerivedCause {
                     derived,
                     impl_or_alias_def_id: impl_def_id,
                     impl_def_predicate_index: None,
@@ -1473,10 +1479,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                         cause.clone(),
                         obligation.recursion_depth + 1,
                         self_ty.rebind(ty::TraitPredicate {
-                            trait_ref: ty::TraitRef::from_lang_item(
+                            trait_ref: ty::TraitRef::new(
                                 self.tcx(),
-                                LangItem::Destruct,
-                                cause.span,
+                                self.tcx().require_lang_item(LangItem::Destruct, Some(cause.span)),
                                 [nested_ty.into(), host_effect_param],
                             ),
                             polarity: ty::PredicatePolarity::Positive,
@@ -1506,10 +1511,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 | ty::Infer(_)
                 | ty::Placeholder(_) => {
                     let predicate = self_ty.rebind(ty::TraitPredicate {
-                        trait_ref: ty::TraitRef::from_lang_item(
+                        trait_ref: ty::TraitRef::new(
                             self.tcx(),
-                            LangItem::Destruct,
-                            cause.span,
+                            self.tcx().require_lang_item(LangItem::Destruct, Some(cause.span)),
                             [nested_ty.into(), host_effect_param],
                         ),
                         polarity: ty::PredicatePolarity::Positive,
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 18cb3184fe1..7aa2aabed7f 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -13,9 +13,9 @@ use super::util;
 use super::util::closure_trait_ref_and_return_type;
 use super::wf;
 use super::{
-    ImplDerivedObligation, ImplDerivedObligationCause, Normalized, Obligation, ObligationCause,
-    ObligationCauseCode, Overflow, PolyTraitObligation, PredicateObligation, Selection,
-    SelectionError, SelectionResult, TraitQueryMode,
+    ImplDerivedCause, Normalized, Obligation, ObligationCause, ObligationCauseCode, Overflow,
+    PolyTraitObligation, PredicateObligation, Selection, SelectionError, SelectionResult,
+    TraitQueryMode,
 };
 
 use crate::infer::{InferCtxt, InferOk, TypeFreshener};
@@ -41,6 +41,7 @@ use rustc_middle::dep_graph::DepNodeIndex;
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::ty::_match::MatchAgainstFreshVars;
 use rustc_middle::ty::abstract_const::NotConstEvaluatable;
+use rustc_middle::ty::print::PrintTraitRefExt as _;
 use rustc_middle::ty::relate::TypeRelation;
 use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, PolyProjectionPredicate, ToPredicate};
@@ -1777,7 +1778,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             // If this type is a GAT, and of the GAT args resolve to something new,
             // that means that we must have newly inferred something about the GAT.
             // We should give up in that case.
-            if !generics.params.is_empty()
+            if !generics.own_params.is_empty()
                 && obligation.predicate.args[generics.parent_count..].iter().any(|&p| {
                     p.has_non_region_infer() && self.infcx.resolve_vars_if_possible(p) != p
                 })
@@ -2441,7 +2442,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                     });
 
                 let tcx = self.tcx();
-                let trait_ref = if tcx.generics_of(trait_def_id).params.len() == 1 {
+                let trait_ref = if tcx.generics_of(trait_def_id).own_params.len() == 1 {
                     ty::TraitRef::new(tcx, trait_def_id, [normalized_ty])
                 } else {
                     // If this is an ill-formed auto/built-in trait, then synthesize
@@ -2771,7 +2772,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                     cause.clone()
                 } else {
                     cause.clone().derived_cause(parent_trait_pred, |derived| {
-                        ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
+                        ObligationCauseCode::ImplDerived(Box::new(ImplDerivedCause {
                             derived,
                             impl_or_alias_def_id: def_id,
                             impl_def_predicate_index: Some(index),
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index 390e711a18d..fe3f66f3a3f 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -11,6 +11,7 @@
 
 pub mod specialization_graph;
 use rustc_infer::infer::DefineOpaqueTypes;
+use rustc_middle::ty::print::PrintTraitRefExt as _;
 use specialization_graph::GraphExt;
 
 use crate::errors::NegativePositiveConflict;
diff --git a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
index 64ab8378abb..96a06e0c169 100644
--- a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
@@ -1,5 +1,4 @@
 use rustc_infer::infer::at::At;
-use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::traits::{FulfillmentError, TraitEngine};
 use rustc_macros::extension;
 use rustc_middle::ty::{self, Ty};
@@ -20,9 +19,7 @@ impl<'tcx> At<'_, 'tcx> {
                 return Ok(ty);
             };
 
-            let new_infer_ty = self
-                .infcx
-                .next_ty_var(TypeVariableOrigin { param_def_id: None, span: self.cause.span });
+            let new_infer_ty = self.infcx.next_ty_var(self.cause.span);
 
             // We simply emit an `alias-eq` goal here, since that will take care of
             // normalizing the LHS of the projection until it is a rigid projection
diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs
index 178f3c63ef7..3f1ba80acd3 100644
--- a/compiler/rustc_trait_selection/src/traits/vtable.rs
+++ b/compiler/rustc_trait_selection/src/traits/vtable.rs
@@ -320,16 +320,11 @@ fn vtable_entries<'tcx>(
 }
 
 /// Find slot base for trait methods within vtable entries of another trait
-// FIXME(@lcnr): This isn't a query, so why does it take a tuple as its argument.
 pub(super) fn vtable_trait_first_method_offset<'tcx>(
     tcx: TyCtxt<'tcx>,
-    key: (
-        ty::PolyTraitRef<'tcx>, // trait_to_be_found
-        ty::PolyTraitRef<'tcx>, // trait_owning_vtable
-    ),
+    trait_to_be_found: ty::PolyTraitRef<'tcx>,
+    trait_owning_vtable: ty::PolyTraitRef<'tcx>,
 ) -> usize {
-    let (trait_to_be_found, trait_owning_vtable) = key;
-
     // #90177
     let trait_to_be_found_erased = tcx.erase_regions(trait_to_be_found);
 
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 28ee76f7145..2c2b84d4a87 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -2,6 +2,7 @@ use crate::infer::InferCtxt;
 use crate::traits;
 use rustc_hir as hir;
 use rustc_hir::lang_items::LangItem;
+use rustc_infer::traits::ObligationCauseCode;
 use rustc_middle::ty::{
     self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
 };
@@ -333,7 +334,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
             return self.out;
         }
 
-        let cause = self.cause(traits::WellFormed(None));
+        let cause = self.cause(ObligationCauseCode::WellFormed(None));
         let param_env = self.param_env;
         let mut obligations = Vec::with_capacity(self.out.len());
         for mut obligation in self.out {
@@ -381,7 +382,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
             if let Some(parent_trait_pred) = predicate.to_opt_poly_trait_pred() {
                 cause = cause.derived_cause(
                     parent_trait_pred,
-                    traits::ObligationCauseCode::WellFormedDerivedObligation,
+                    traits::ObligationCauseCode::WellFormedDerived,
                 );
             }
             extend_cause_with_original_assoc_item_obligation(tcx, item, &mut cause, predicate);
@@ -485,7 +486,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
                 &mut traits::SelectionContext::new(self.infcx),
                 self.param_env,
                 data,
-                self.cause(traits::WellFormed(None)),
+                self.cause(ObligationCauseCode::WellFormed(None)),
                 self.recursion_depth,
                 &mut self.out,
             );
@@ -498,7 +499,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
 
     fn compute_projection_args(&mut self, args: GenericArgsRef<'tcx>) {
         let tcx = self.tcx();
-        let cause = self.cause(traits::WellFormed(None));
+        let cause = self.cause(ObligationCauseCode::WellFormed(None));
         let param_env = self.param_env;
         let depth = self.recursion_depth;
 
@@ -525,8 +526,11 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
     fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>) {
         if !subty.has_escaping_bound_vars() {
             let cause = self.cause(cause);
-            let trait_ref =
-                ty::TraitRef::from_lang_item(self.tcx(), LangItem::Sized, cause.span, [subty]);
+            let trait_ref = ty::TraitRef::new(
+                self.tcx(),
+                self.tcx().require_lang_item(LangItem::Sized, Some(cause.span)),
+                [subty],
+            );
             self.out.push(traits::Obligation::with_depth(
                 self.tcx(),
                 cause,
@@ -565,9 +569,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
         iter::zip(predicates, origins.into_iter().rev())
             .map(|((pred, span), origin_def_id)| {
                 let code = if span.is_dummy() {
-                    traits::ItemObligation(origin_def_id)
+                    ObligationCauseCode::WhereClause(origin_def_id)
                 } else {
-                    traits::BindingObligation(origin_def_id, span)
+                    ObligationCauseCode::SpannedWhereClause(origin_def_id, span)
                 };
                 let cause = self.cause(code);
                 traits::Obligation::with_depth(
@@ -626,7 +630,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
 
             self.out.reserve(implicit_bounds.len());
             for implicit_bound in implicit_bounds {
-                let cause = self.cause(traits::ObjectTypeBound(ty, explicit_bound));
+                let cause = self.cause(ObligationCauseCode::ObjectTypeBound(ty, explicit_bound));
                 let outlives =
                     ty::Binder::dummy(ty::OutlivesPredicate(explicit_bound, implicit_bound));
                 self.out.push(traits::Obligation::with_depth(
@@ -644,7 +648,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
 impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
     type Result = ();
 
-    fn visit_ty(&mut self, t: <TyCtxt<'tcx> as ty::Interner>::Ty) -> Self::Result {
+    fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
         debug!("wf bounds for t={:?} t.kind={:#?}", t, t.kind());
 
         let tcx = self.tcx();
@@ -673,22 +677,22 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
             ty::Infer(ty::FloatVar(_)) => {}
 
             ty::Slice(subty) => {
-                self.require_sized(subty, traits::SliceOrArrayElem);
+                self.require_sized(subty, ObligationCauseCode::SliceOrArrayElem);
             }
 
             ty::Array(subty, _) => {
-                self.require_sized(subty, traits::SliceOrArrayElem);
+                self.require_sized(subty, ObligationCauseCode::SliceOrArrayElem);
                 // Note that we handle the len is implicitly checked while walking `arg`.
             }
 
             ty::Pat(subty, _) => {
-                self.require_sized(subty, traits::MiscObligation);
+                self.require_sized(subty, ObligationCauseCode::Misc);
             }
 
             ty::Tuple(tys) => {
                 if let Some((_last, rest)) = tys.split_last() {
                     for &elem in rest {
-                        self.require_sized(elem, traits::TupleElem);
+                        self.require_sized(elem, ObligationCauseCode::TupleElem);
                     }
                 }
             }
@@ -728,7 +732,7 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
             ty::Ref(r, rty, _) => {
                 // WfReference
                 if !r.has_escaping_bound_vars() && !rty.has_escaping_bound_vars() {
-                    let cause = self.cause(traits::ReferenceOutlivesReferent(t));
+                    let cause = self.cause(ObligationCauseCode::ReferenceOutlivesReferent(t));
                     self.out.push(traits::Obligation::with_depth(
                         tcx,
                         cause,
@@ -825,7 +829,7 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
                     if let Some(principal) = data.principal_def_id() {
                         self.out.push(traits::Obligation::with_depth(
                             tcx,
-                            self.cause(traits::WellFormed(None)),
+                            self.cause(ObligationCauseCode::WellFormed(None)),
                             self.recursion_depth,
                             self.param_env,
                             ty::Binder::dummy(ty::PredicateKind::ObjectSafe(principal)),
@@ -847,7 +851,7 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
             // See also the comment on `fn obligations`, describing "livelock"
             // prevention, which happens before this can be reached.
             ty::Infer(_) => {
-                let cause = self.cause(traits::WellFormed(None));
+                let cause = self.cause(ObligationCauseCode::WellFormed(None));
                 self.out.push(traits::Obligation::with_depth(
                     tcx,
                     cause,
@@ -863,7 +867,7 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
         t.super_visit_with(self)
     }
 
-    fn visit_const(&mut self, c: <TyCtxt<'tcx> as ty::Interner>::Const) -> Self::Result {
+    fn visit_const(&mut self, c: ty::Const<'tcx>) -> Self::Result {
         let tcx = self.tcx();
 
         match c.kind() {
@@ -875,7 +879,7 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
                     let predicate = ty::Binder::dummy(ty::PredicateKind::Clause(
                         ty::ClauseKind::ConstEvaluatable(c),
                     ));
-                    let cause = self.cause(traits::WellFormed(None));
+                    let cause = self.cause(ObligationCauseCode::WellFormed(None));
                     self.out.push(traits::Obligation::with_depth(
                         tcx,
                         cause,
@@ -886,7 +890,7 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
                 }
             }
             ty::ConstKind::Infer(_) => {
-                let cause = self.cause(traits::WellFormed(None));
+                let cause = self.cause(ObligationCauseCode::WellFormed(None));
 
                 self.out.push(traits::Obligation::with_depth(
                     tcx,
@@ -909,7 +913,7 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
                 let predicate = ty::Binder::dummy(ty::PredicateKind::Clause(
                     ty::ClauseKind::ConstEvaluatable(c),
                 ));
-                let cause = self.cause(traits::WellFormed(None));
+                let cause = self.cause(ObligationCauseCode::WellFormed(None));
                 self.out.push(traits::Obligation::with_depth(
                     tcx,
                     cause,
@@ -933,7 +937,7 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
         c.super_visit_with(self)
     }
 
-    fn visit_predicate(&mut self, _p: <TyCtxt<'tcx> as ty::Interner>::Predicate) -> Self::Result {
+    fn visit_predicate(&mut self, _p: ty::Predicate<'tcx>) -> Self::Result {
         bug!("predicate should not be checked for well-formedness");
     }
 }
diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs
index 01b9a5640b8..b6a59a4ad3a 100644
--- a/compiler/rustc_traits/src/type_op.rs
+++ b/compiler/rustc_traits/src/type_op.rs
@@ -3,7 +3,7 @@ use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::query::Providers;
 use rustc_middle::traits::query::NoSolution;
 use rustc_middle::ty::{Clause, ParamEnvAnd};
-use rustc_middle::ty::{FnSig, Lift, PolyFnSig, Ty, TyCtxt, TypeFoldable};
+use rustc_middle::ty::{FnSig, PolyFnSig, Ty, TyCtxt, TypeFoldable};
 use rustc_trait_selection::infer::InferCtxtBuilderExt;
 use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
 use rustc_trait_selection::traits::query::type_op::ascribe_user_type::{
@@ -54,7 +54,7 @@ fn type_op_normalize<'tcx, T>(
     key: ParamEnvAnd<'tcx, Normalize<T>>,
 ) -> Result<T, NoSolution>
 where
-    T: fmt::Debug + TypeFoldable<TyCtxt<'tcx>> + Lift<'tcx>,
+    T: fmt::Debug + TypeFoldable<TyCtxt<'tcx>>,
 {
     let (param_env, Normalize { value }) = key.into_parts();
     let Normalized { value, obligations } =
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index ba75424ec0c..d3fe8291e03 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -340,22 +340,22 @@ fn associated_type_for_impl_trait_in_impl(
     impl_assoc_ty.generics_of({
         let trait_assoc_generics = tcx.generics_of(trait_assoc_def_id);
         let trait_assoc_parent_count = trait_assoc_generics.parent_count;
-        let mut params = trait_assoc_generics.params.clone();
+        let mut own_params = trait_assoc_generics.own_params.clone();
 
         let parent_generics = tcx.generics_of(impl_local_def_id.to_def_id());
-        let parent_count = parent_generics.parent_count + parent_generics.params.len();
+        let parent_count = parent_generics.parent_count + parent_generics.own_params.len();
 
-        for param in &mut params {
+        for param in &mut own_params {
             param.index = param.index + parent_count as u32 - trait_assoc_parent_count as u32;
         }
 
         let param_def_id_to_index =
-            params.iter().map(|param| (param.def_id, param.index)).collect();
+            own_params.iter().map(|param| (param.def_id, param.index)).collect();
 
         ty::Generics {
             parent: Some(impl_local_def_id.to_def_id()),
             parent_count,
-            params,
+            own_params,
             param_def_id_to_index,
             has_self: false,
             has_late_bound_regions: trait_assoc_generics.has_late_bound_regions,
diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs
index e1534af4987..862fb2e1663 100644
--- a/compiler/rustc_ty_utils/src/implied_bounds.rs
+++ b/compiler/rustc_ty_utils/src/implied_bounds.rs
@@ -69,7 +69,8 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'
                     // case, since it has been liberated), map it back to the early-bound lifetime of
                     // the GAT. Since RPITITs also have all of the fn's generics, we slice only
                     // the end of the list corresponding to the opaque's generics.
-                    for param in &generics.params[tcx.generics_of(fn_def_id).params.len()..] {
+                    for param in &generics.own_params[tcx.generics_of(fn_def_id).own_params.len()..]
+                    {
                         let orig_lt =
                             tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local());
                         if matches!(*orig_lt, ty::ReLateParam(..)) {
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 902b76e8c1e..f78a28d16fd 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -5,7 +5,7 @@ use rustc_index::{IndexSlice, IndexVec};
 use rustc_middle::mir::{CoroutineLayout, CoroutineSavedLocal};
 use rustc_middle::query::Providers;
 use rustc_middle::ty::layout::{
-    IntegerExt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, MAX_SIMD_LANES,
+    FloatExt, IntegerExt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, MAX_SIMD_LANES,
 };
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{
@@ -180,12 +180,7 @@ fn layout_of_uncached<'tcx>(
         )),
         ty::Int(ity) => scalar(Int(Integer::from_int_ty(dl, ity), true)),
         ty::Uint(ity) => scalar(Int(Integer::from_uint_ty(dl, ity), false)),
-        ty::Float(fty) => scalar(match fty {
-            ty::FloatTy::F16 => F16,
-            ty::FloatTy::F32 => F32,
-            ty::FloatTy::F64 => F64,
-            ty::FloatTy::F128 => F128,
-        }),
+        ty::Float(fty) => scalar(Float(Float::from_float_ty(fty))),
         ty::FnPtr(_) => {
             let mut ptr = scalar_unit(Pointer(dl.instruction_address_space));
             ptr.valid_range_mut().start = 1;
diff --git a/compiler/rustc_ty_utils/src/representability.rs b/compiler/rustc_ty_utils/src/representability.rs
index a5ffa553c2a..446f16b4125 100644
--- a/compiler/rustc_ty_utils/src/representability.rs
+++ b/compiler/rustc_ty_utils/src/representability.rs
@@ -85,7 +85,7 @@ fn representability_adt_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Representab
 fn params_in_repr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> BitSet<u32> {
     let adt_def = tcx.adt_def(def_id);
     let generics = tcx.generics_of(def_id);
-    let mut params_in_repr = BitSet::new_empty(generics.params.len());
+    let mut params_in_repr = BitSet::new_empty(generics.own_params.len());
     for variant in adt_def.variants() {
         for field in variant.fields.iter() {
             params_in_repr_ty(
diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs
deleted file mode 100644
index 57f961ac97e..00000000000
--- a/compiler/rustc_type_ir/src/binder.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-use crate::Interner;
-
-pub trait BoundVars<I: Interner> {
-    fn bound_vars(&self) -> I::BoundVars;
-
-    fn has_no_bound_vars(&self) -> bool;
-}
diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs
index f041c5831fc..f7c7ec242c1 100644
--- a/compiler/rustc_type_ir/src/canonical.rs
+++ b/compiler/rustc_type_ir/src/canonical.rs
@@ -6,8 +6,9 @@ use std::fmt;
 use std::hash::Hash;
 
 use crate::fold::{FallibleTypeFolder, TypeFoldable};
+use crate::inherent::*;
 use crate::visit::{TypeVisitable, TypeVisitor};
-use crate::{Interner, PlaceholderLike, UniverseIndex};
+use crate::{Interner, UniverseIndex};
 
 /// A "canonicalized" type `V` is one where all free inference
 /// variables have been rewritten to "canonical vars". These are
diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs
new file mode 100644
index 00000000000..0fd34e0a65f
--- /dev/null
+++ b/compiler/rustc_type_ir/src/inherent.rs
@@ -0,0 +1,85 @@
+use std::fmt::Debug;
+use std::hash::Hash;
+
+use crate::fold::TypeSuperFoldable;
+use crate::visit::{Flags, TypeSuperVisitable};
+use crate::{
+    BoundVar, ConstKind, DebruijnIndex, DebugWithInfcx, Interner, RegionKind, TyKind, UniverseIndex,
+};
+
+pub trait Ty<I: Interner<Ty = Self>>:
+    Copy
+    + DebugWithInfcx<I>
+    + Hash
+    + Eq
+    + Into<I::GenericArg>
+    + IntoKind<Kind = TyKind<I>>
+    + TypeSuperVisitable<I>
+    + TypeSuperFoldable<I>
+    + Flags
+{
+    fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar) -> Self;
+}
+
+pub trait Region<I: Interner<Region = Self>>:
+    Copy + DebugWithInfcx<I> + Hash + Eq + Into<I::GenericArg> + IntoKind<Kind = RegionKind<I>> + Flags
+{
+    fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar) -> Self;
+
+    fn new_static(interner: I) -> Self;
+}
+
+pub trait Const<I: Interner<Const = Self>>:
+    Copy
+    + DebugWithInfcx<I>
+    + Hash
+    + Eq
+    + Into<I::GenericArg>
+    + IntoKind<Kind = ConstKind<I>>
+    + TypeSuperVisitable<I>
+    + TypeSuperFoldable<I>
+    + Flags
+{
+    fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar, ty: I::Ty) -> Self;
+
+    fn ty(self) -> I::Ty;
+}
+
+pub trait GenericsOf<I: Interner<GenericsOf = Self>> {
+    fn count(&self) -> usize;
+}
+
+pub trait GenericArgs<I: Interner<GenericArgs = Self>>:
+    Copy + DebugWithInfcx<I> + Hash + Eq + IntoIterator<Item = I::GenericArg>
+{
+    fn type_at(self, i: usize) -> I::Ty;
+
+    fn identity_for_item(interner: I, def_id: I::DefId) -> I::GenericArgs;
+}
+
+pub trait Predicate<I: Interner<Predicate = Self>>:
+    Copy + Debug + Hash + Eq + TypeSuperVisitable<I> + TypeSuperFoldable<I> + Flags
+{
+}
+
+/// Common capabilities of placeholder kinds
+pub trait PlaceholderLike: Copy + Debug + Hash + Eq {
+    fn universe(self) -> UniverseIndex;
+    fn var(self) -> BoundVar;
+
+    fn with_updated_universe(self, ui: UniverseIndex) -> Self;
+
+    fn new(ui: UniverseIndex, var: BoundVar) -> Self;
+}
+
+pub trait IntoKind {
+    type Kind;
+
+    fn kind(self) -> Self::Kind;
+}
+
+pub trait BoundVars<I: Interner> {
+    fn bound_vars(&self) -> I::BoundVars;
+
+    fn has_no_bound_vars(&self) -> bool;
+}
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index 70f7e58be19..c8bd7fea11b 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -2,23 +2,17 @@ use smallvec::SmallVec;
 use std::fmt::Debug;
 use std::hash::Hash;
 
-use crate::fold::TypeSuperFoldable;
+use crate::inherent::*;
+use crate::ir_print::IrPrint;
 use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
-use crate::{
-    new, BoundVar, BoundVars, CanonicalVarInfo, ConstKind, DebugWithInfcx, RegionKind, TyKind,
-    UniverseIndex,
-};
+use crate::{CanonicalVarInfo, DebugWithInfcx, TraitRef};
 
-pub trait Interner: Sized + Copy {
+pub trait Interner: Sized + Copy + IrPrint<TraitRef<Self>> {
     type DefId: Copy + Debug + Hash + Eq;
     type DefiningOpaqueTypes: Copy + Debug + Hash + Default + Eq + TypeVisitable<Self>;
     type AdtDef: Copy + Debug + Hash + Eq;
 
-    type GenericArgs: Copy
-        + DebugWithInfcx<Self>
-        + Hash
-        + Eq
-        + IntoIterator<Item = Self::GenericArg>;
+    type GenericArgs: GenericArgs<Self>;
     type GenericArg: Copy + DebugWithInfcx<Self> + Hash + Eq;
     type Term: Copy + Debug + Hash + Eq;
 
@@ -29,21 +23,12 @@ pub trait Interner: Sized + Copy {
     type CanonicalVars: Copy + Debug + Hash + Eq + IntoIterator<Item = CanonicalVarInfo<Self>>;
 
     // Kinds of tys
-    type Ty: Copy
-        + DebugWithInfcx<Self>
-        + Hash
-        + Eq
-        + Into<Self::GenericArg>
-        + IntoKind<Kind = TyKind<Self>>
-        + TypeSuperVisitable<Self>
-        + TypeSuperFoldable<Self>
-        + Flags
-        + new::Ty<Self>;
+    type Ty: Ty<Self>;
     type Tys: Copy + Debug + Hash + Eq + IntoIterator<Item = Self::Ty>;
     type AliasTy: Copy + DebugWithInfcx<Self> + Hash + Eq;
     type ParamTy: Copy + Debug + Hash + Eq;
     type BoundTy: Copy + Debug + Hash + Eq;
-    type PlaceholderTy: Copy + Debug + Hash + Eq + PlaceholderLike;
+    type PlaceholderTy: PlaceholderLike;
 
     // Things stored inside of tys
     type ErrorGuaranteed: Copy + Debug + Hash + Eq;
@@ -53,47 +38,24 @@ pub trait Interner: Sized + Copy {
     type Pat: Copy + Debug + Hash + Eq + DebugWithInfcx<Self>;
 
     // Kinds of consts
-    type Const: Copy
-        + DebugWithInfcx<Self>
-        + Hash
-        + Eq
-        + Into<Self::GenericArg>
-        + IntoKind<Kind = ConstKind<Self>>
-        + ConstTy<Self>
-        + TypeSuperVisitable<Self>
-        + TypeSuperFoldable<Self>
-        + Flags
-        + new::Const<Self>;
+    type Const: Const<Self>;
     type AliasConst: Copy + DebugWithInfcx<Self> + Hash + Eq;
-    type PlaceholderConst: Copy + Debug + Hash + Eq + PlaceholderLike;
+    type PlaceholderConst: PlaceholderLike;
     type ParamConst: Copy + Debug + Hash + Eq;
     type BoundConst: Copy + Debug + Hash + Eq;
     type ValueConst: Copy + Debug + Hash + Eq;
     type ExprConst: Copy + DebugWithInfcx<Self> + Hash + Eq;
 
     // Kinds of regions
-    type Region: Copy
-        + DebugWithInfcx<Self>
-        + Hash
-        + Eq
-        + Into<Self::GenericArg>
-        + IntoKind<Kind = RegionKind<Self>>
-        + Flags
-        + new::Region<Self>;
+    type Region: Region<Self>;
     type EarlyParamRegion: Copy + Debug + Hash + Eq;
     type LateParamRegion: Copy + Debug + Hash + Eq;
     type BoundRegion: Copy + Debug + Hash + Eq;
     type InferRegion: Copy + DebugWithInfcx<Self> + Hash + Eq;
-    type PlaceholderRegion: Copy + Debug + Hash + Eq + PlaceholderLike;
+    type PlaceholderRegion: PlaceholderLike;
 
     // Predicates
-    type Predicate: Copy
-        + Debug
-        + Hash
-        + Eq
-        + TypeSuperVisitable<Self>
-        + TypeSuperFoldable<Self>
-        + Flags;
+    type Predicate: Predicate<Self>;
     type TraitPredicate: Copy + Debug + Hash + Eq;
     type RegionOutlivesPredicate: Copy + Debug + Hash + Eq;
     type TypeOutlivesPredicate: Copy + Debug + Hash + Eq;
@@ -105,26 +67,15 @@ pub trait Interner: Sized + Copy {
     type Clauses: Copy + Debug + Hash + Eq + TypeSuperVisitable<Self> + Flags;
 
     fn mk_canonical_var_infos(self, infos: &[CanonicalVarInfo<Self>]) -> Self::CanonicalVars;
-}
-
-/// Common capabilities of placeholder kinds
-pub trait PlaceholderLike {
-    fn universe(self) -> UniverseIndex;
-    fn var(self) -> BoundVar;
 
-    fn with_updated_universe(self, ui: UniverseIndex) -> Self;
-
-    fn new(ui: UniverseIndex, var: BoundVar) -> Self;
-}
-
-pub trait IntoKind {
-    type Kind;
-
-    fn kind(self) -> Self::Kind;
-}
+    type GenericsOf: GenericsOf<Self>;
+    fn generics_of(self, def_id: Self::DefId) -> Self::GenericsOf;
 
-pub trait ConstTy<I: Interner> {
-    fn ty(self) -> I::Ty;
+    fn check_and_mk_args(
+        self,
+        def_id: Self::DefId,
+        args: impl IntoIterator<Item: Into<Self::GenericArg>>,
+    ) -> Self::GenericArgs;
 }
 
 /// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter`
diff --git a/compiler/rustc_type_ir/src/ir_print.rs b/compiler/rustc_type_ir/src/ir_print.rs
new file mode 100644
index 00000000000..84e889b486a
--- /dev/null
+++ b/compiler/rustc_type_ir/src/ir_print.rs
@@ -0,0 +1,28 @@
+use std::fmt;
+
+use crate::{Interner, TraitRef};
+
+pub trait IrPrint<T> {
+    fn print(t: &T, fmt: &mut fmt::Formatter<'_>) -> fmt::Result;
+    fn print_debug(t: &T, fmt: &mut fmt::Formatter<'_>) -> fmt::Result;
+}
+
+macro_rules! define_display_via_print {
+    ($($ty:ident),+ $(,)?) => {
+        $(
+            impl<I: Interner> fmt::Display for $ty<I> {
+                fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+                    <I as IrPrint<$ty<I>>>::print(self, fmt)
+                }
+            }
+
+            impl<I: Interner> fmt::Debug for $ty<I> {
+                fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+                    <I as IrPrint<$ty<I>>>::print_debug(self, fmt)
+                }
+            }
+        )*
+    }
+}
+
+define_display_via_print!(TraitRef,);
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index ef7437c2542..62efa32c9f2 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -23,13 +23,14 @@ pub mod visit;
 #[cfg(feature = "nightly")]
 pub mod codec;
 pub mod fold;
-pub mod new;
+pub mod inherent;
+pub mod ir_print;
+pub mod lift;
 pub mod ty_info;
 pub mod ty_kind;
 
 #[macro_use]
 mod macros;
-mod binder;
 mod canonical;
 mod const_kind;
 mod debug;
@@ -38,8 +39,8 @@ mod infcx;
 mod interner;
 mod predicate_kind;
 mod region_kind;
+mod trait_ref;
 
-pub use binder::*;
 pub use canonical::*;
 #[cfg(feature = "nightly")]
 pub use codec::*;
@@ -50,6 +51,7 @@ pub use infcx::InferCtxtLike;
 pub use interner::*;
 pub use predicate_kind::*;
 pub use region_kind::*;
+pub use trait_ref::*;
 pub use ty_info::*;
 pub use ty_kind::*;
 pub use AliasKind::*;
diff --git a/compiler/rustc_type_ir/src/lift.rs b/compiler/rustc_type_ir/src/lift.rs
new file mode 100644
index 00000000000..839da10db5e
--- /dev/null
+++ b/compiler/rustc_type_ir/src/lift.rs
@@ -0,0 +1,21 @@
+/// A trait implemented for all `X<'a>` types that can be safely and
+/// efficiently converted to `X<'tcx>` as long as they are part of the
+/// provided `TyCtxt<'tcx>`.
+/// This can be done, for example, for `Ty<'tcx>` or `GenericArgsRef<'tcx>`
+/// by looking them up in their respective interners.
+///
+/// However, this is still not the best implementation as it does
+/// need to compare the components, even for interned values.
+/// It would be more efficient if `TypedArena` provided a way to
+/// determine whether the address is in the allocated range.
+///
+/// `None` is returned if the value or one of the components is not part
+/// of the provided context.
+/// For `Ty`, `None` can be returned if either the type interner doesn't
+/// contain the `TyKind` key or if the address of the interned
+/// pointer differs. The latter case is possible if a primitive type,
+/// e.g., `()` or `u8`, was interned in a different context.
+pub trait Lift<I>: std::fmt::Debug {
+    type Lifted: std::fmt::Debug;
+    fn lift_to_tcx(self, tcx: I) -> Option<Self::Lifted>;
+}
diff --git a/compiler/rustc_type_ir/src/new.rs b/compiler/rustc_type_ir/src/new.rs
deleted file mode 100644
index 1572a641d06..00000000000
--- a/compiler/rustc_type_ir/src/new.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-use crate::{BoundVar, DebruijnIndex, Interner};
-
-pub trait Ty<I: Interner<Ty = Self>> {
-    fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar) -> Self;
-}
-
-pub trait Region<I: Interner<Region = Self>> {
-    fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar) -> Self;
-
-    fn new_static(interner: I) -> Self;
-}
-
-pub trait Const<I: Interner<Const = Self>> {
-    fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar, ty: I::Ty) -> Self;
-}
diff --git a/compiler/rustc_type_ir/src/trait_ref.rs b/compiler/rustc_type_ir/src/trait_ref.rs
new file mode 100644
index 00000000000..4bd513ab7e1
--- /dev/null
+++ b/compiler/rustc_type_ir/src/trait_ref.rs
@@ -0,0 +1,109 @@
+use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
+
+use crate::fold::{FallibleTypeFolder, TypeFoldable};
+use crate::inherent::*;
+use crate::lift::Lift;
+use crate::visit::{TypeVisitable, TypeVisitor};
+use crate::Interner;
+
+/// A complete reference to a trait. These take numerous guises in syntax,
+/// but perhaps the most recognizable form is in a where-clause:
+/// ```ignore (illustrative)
+/// T: Foo<U>
+/// ```
+/// This would be represented by a trait-reference where the `DefId` is the
+/// `DefId` for the trait `Foo` and the args define `T` as parameter 0,
+/// and `U` as parameter 1.
+///
+/// Trait references also appear in object types like `Foo<U>`, but in
+/// that case the `Self` parameter is absent from the generic parameters.
+#[derive(derivative::Derivative)]
+#[derivative(
+    Clone(bound = ""),
+    Copy(bound = ""),
+    Hash(bound = ""),
+    PartialEq(bound = ""),
+    Eq(bound = "")
+)]
+#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
+pub struct TraitRef<I: Interner> {
+    pub def_id: I::DefId,
+    pub args: I::GenericArgs,
+    /// This field exists to prevent the creation of `TraitRef` without
+    /// calling [`TraitRef::new`].
+    _use_trait_ref_new_instead: (),
+}
+
+impl<I: Interner> TraitRef<I> {
+    pub fn new(
+        interner: I,
+        trait_def_id: I::DefId,
+        args: impl IntoIterator<Item: Into<I::GenericArg>>,
+    ) -> Self {
+        let args = interner.check_and_mk_args(trait_def_id, args);
+        Self { def_id: trait_def_id, args, _use_trait_ref_new_instead: () }
+    }
+
+    pub fn from_method(interner: I, trait_id: I::DefId, args: I::GenericArgs) -> TraitRef<I> {
+        let generics = interner.generics_of(trait_id);
+        TraitRef::new(interner, trait_id, args.into_iter().take(generics.count()))
+    }
+
+    /// Returns a `TraitRef` of the form `P0: Foo<P1..Pn>` where `Pi`
+    /// are the parameters defined on trait.
+    pub fn identity(interner: I, def_id: I::DefId) -> TraitRef<I> {
+        TraitRef::new(interner, def_id, I::GenericArgs::identity_for_item(interner, def_id))
+    }
+
+    pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
+        TraitRef::new(
+            interner,
+            self.def_id,
+            [self_ty.into()].into_iter().chain(self.args.into_iter().skip(1)),
+        )
+    }
+
+    #[inline]
+    pub fn self_ty(&self) -> I::Ty {
+        self.args.type_at(0)
+    }
+}
+
+// FIXME(compiler-errors): Make this into a `Lift_Generic` impl.
+impl<I: Interner, U: Interner> Lift<U> for TraitRef<I>
+where
+    I::DefId: Lift<U, Lifted = U::DefId>,
+    I::GenericArgs: Lift<U, Lifted = U::GenericArgs>,
+{
+    type Lifted = TraitRef<U>;
+
+    fn lift_to_tcx(self, tcx: U) -> Option<Self::Lifted> {
+        Some(TraitRef {
+            def_id: self.def_id.lift_to_tcx(tcx)?,
+            args: self.args.lift_to_tcx(tcx)?,
+            _use_trait_ref_new_instead: (),
+        })
+    }
+}
+
+impl<I: Interner> TypeVisitable<I> for TraitRef<I>
+where
+    I::GenericArgs: TypeVisitable<I>,
+{
+    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
+        self.args.visit_with(visitor)
+    }
+}
+
+impl<I: Interner> TypeFoldable<I> for TraitRef<I>
+where
+    I::GenericArgs: TypeFoldable<I>,
+{
+    fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
+        Ok(TraitRef {
+            def_id: self.def_id,
+            args: self.args.try_fold_with(folder)?,
+            _use_trait_ref_new_instead: (),
+        })
+    }
+}
diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs
index 2f588c67f56..3d4125f600e 100644
--- a/compiler/rustc_type_ir/src/visit.rs
+++ b/compiler/rustc_type_ir/src/visit.rs
@@ -47,7 +47,8 @@ use rustc_index::{Idx, IndexVec};
 use std::fmt;
 use std::ops::ControlFlow;
 
-use crate::{self as ty, BoundVars, Interner, IntoKind, Lrc, TypeFlags};
+use crate::inherent::*;
+use crate::{self as ty, Interner, Lrc, TypeFlags};
 
 /// This trait is implemented for every type that can be visited,
 /// providing the skeleton of the traversal.
diff --git a/compiler/stable_mir/src/abi.rs b/compiler/stable_mir/src/abi.rs
index 92bc2e34561..e1c14fe0b38 100644
--- a/compiler/stable_mir/src/abi.rs
+++ b/compiler/stable_mir/src/abi.rs
@@ -6,7 +6,7 @@ use crate::ty::{Align, IndexedVal, Ty, VariantIdx};
 use crate::Error;
 use crate::Opaque;
 use std::fmt::{self, Debug};
-use std::num::NonZeroUsize;
+use std::num::NonZero;
 use std::ops::RangeInclusive;
 
 /// A function ABI definition.
@@ -133,7 +133,7 @@ pub enum FieldsShape {
     Primitive,
 
     /// All fields start at no offset. The `usize` is the field count.
-    Union(NonZeroUsize),
+    Union(NonZero<usize>),
 
     /// Array/vector-like placement, with all fields of identical types.
     Array { stride: Size, count: u64 },
diff --git a/config.example.toml b/config.example.toml
index 5c1fac7672a..3b76952504f 100644
--- a/config.example.toml
+++ b/config.example.toml
@@ -254,6 +254,10 @@
 # executing the debuginfo test suite.
 #gdb = "gdb"
 
+# The path to (or name of) the LLDB executable to use. This is only used for
+# executing the debuginfo test suite.
+#lldb = "lldb"
+
 # The node.js executable to use. Note that this is only used for the emscripten
 # target when running tests, otherwise this can be omitted.
 #nodejs = "node"
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index b93936869b3..91b83cfe011 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -165,6 +165,7 @@
 //
 // Language features:
 // tidy-alphabetical-start
+#![cfg_attr(bootstrap, feature(exclusive_range_pattern))]
 #![cfg_attr(not(test), feature(coroutine_trait))]
 #![cfg_attr(test, feature(panic_update_hook))]
 #![cfg_attr(test, feature(test))]
@@ -179,7 +180,6 @@
 #![feature(const_try)]
 #![feature(decl_macro)]
 #![feature(dropck_eyepatch)]
-#![feature(exclusive_range_pattern)]
 #![feature(fundamental)]
 #![feature(hashmap_internals)]
 #![feature(lang_items)]
diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs
index c0d292cd208..3e23612d0c1 100644
--- a/library/alloc/src/str.rs
+++ b/library/alloc/src/str.rs
@@ -375,14 +375,16 @@ impl str {
         // Safety: We have written only valid ASCII to our vec
         let mut s = unsafe { String::from_utf8_unchecked(out) };
 
-        for (i, c) in rest[..].char_indices() {
+        for (i, c) in rest.char_indices() {
             if c == 'Σ' {
                 // Σ maps to σ, except at the end of a word where it maps to ς.
                 // This is the only conditional (contextual) but language-independent mapping
                 // in `SpecialCasing.txt`,
                 // so hard-code it rather than have a generic "condition" mechanism.
                 // See https://github.com/rust-lang/rust/issues/26035
-                map_uppercase_sigma(rest, i, &mut s)
+                let out_len = self.len() - rest.len();
+                let sigma_lowercase = map_uppercase_sigma(&self, i + out_len);
+                s.push(sigma_lowercase);
             } else {
                 match conversions::to_lower(c) {
                     [a, '\0', _] => s.push(a),
@@ -400,13 +402,13 @@ impl str {
         }
         return s;
 
-        fn map_uppercase_sigma(from: &str, i: usize, to: &mut String) {
+        fn map_uppercase_sigma(from: &str, i: usize) -> char {
             // See https://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G33992
             // for the definition of `Final_Sigma`.
             debug_assert!('Σ'.len_utf8() == 2);
             let is_word_final = case_ignorable_then_cased(from[..i].chars().rev())
                 && !case_ignorable_then_cased(from[i + 2..].chars());
-            to.push_str(if is_word_final { "ς" } else { "σ" });
+            if is_word_final { 'ς' } else { 'σ' }
         }
 
         fn case_ignorable_then_cased<I: Iterator<Item = char>>(iter: I) -> bool {
diff --git a/library/alloc/tests/str.rs b/library/alloc/tests/str.rs
index df8a260624a..0078f5eaa3d 100644
--- a/library/alloc/tests/str.rs
+++ b/library/alloc/tests/str.rs
@@ -1848,6 +1848,9 @@ fn to_lowercase() {
     assert_eq!("ΑΣ'Α".to_lowercase(), "ασ'α");
     assert_eq!("ΑΣ''Α".to_lowercase(), "ασ''α");
 
+    // https://github.com/rust-lang/rust/issues/124714
+    assert_eq!("abcdefghijklmnopΣ".to_lowercase(), "abcdefghijklmnopς");
+
     // a really long string that has it's lowercase form
     // even longer. this tests that implementations don't assume
     // an incorrect upper bound on allocations
diff --git a/library/core/benches/str.rs b/library/core/benches/str.rs
index 7d36eff3d6c..0f14809444b 100644
--- a/library/core/benches/str.rs
+++ b/library/core/benches/str.rs
@@ -3,6 +3,7 @@ use test::{black_box, Bencher};
 
 mod char_count;
 mod corpora;
+mod debug;
 mod iter;
 
 #[bench]
diff --git a/library/core/benches/str/debug.rs b/library/core/benches/str/debug.rs
new file mode 100644
index 00000000000..7c72228f0fb
--- /dev/null
+++ b/library/core/benches/str/debug.rs
@@ -0,0 +1,79 @@
+//! This primarily benchmarks `impl Debug for str`,
+//! and it also explicitly tests that we minimizes calls to the underlying `Write`r.
+//! While that is an implementation detail and there are no guarantees about it,
+//! we should still try to minimize those calls over time rather than regress them.
+
+use std::fmt::{self, Write};
+use test::{black_box, Bencher};
+
+#[derive(Default)]
+struct CountingWriter {
+    buf: String,
+    write_calls: usize,
+}
+
+impl Write for CountingWriter {
+    fn write_str(&mut self, s: &str) -> fmt::Result {
+        self.buf.push_str(s);
+        self.write_calls += 1;
+        Ok(())
+    }
+}
+
+fn assert_fmt(s: &str, expected: &str, expected_write_calls: usize) {
+    let mut w = CountingWriter::default();
+
+    write!(&mut w, "{s:?}").unwrap();
+    assert_eq!(s.len(), 64);
+    assert_eq!(w.buf, expected);
+    assert_eq!(w.write_calls, expected_write_calls);
+}
+
+#[bench]
+fn ascii_only(b: &mut Bencher) {
+    let s = "just a bit of ascii text that has no escapes. 64 bytes exactly!!";
+    assert_fmt(s, r#""just a bit of ascii text that has no escapes. 64 bytes exactly!!""#, 3);
+    b.iter(|| {
+        black_box(format!("{:?}", black_box(s)));
+    });
+}
+
+#[bench]
+fn ascii_escapes(b: &mut Bencher) {
+    let s = "some\tmore\tascii\ttext\nthis time with some \"escapes\", also 64 byte";
+    assert_fmt(
+        s,
+        r#""some\tmore\tascii\ttext\nthis time with some \"escapes\", also 64 byte""#,
+        21,
+    );
+    b.iter(|| {
+        black_box(format!("{:?}", black_box(s)));
+    });
+}
+
+#[bench]
+fn some_unicode(b: &mut Bencher) {
+    let s = "egy kis szöveg néhány unicode betűvel. legyen ez is 64 byte.";
+    assert_fmt(s, r#""egy kis szöveg néhány unicode betűvel. legyen ez is 64 byte.""#, 3);
+    b.iter(|| {
+        black_box(format!("{:?}", black_box(s)));
+    });
+}
+
+#[bench]
+fn mostly_unicode(b: &mut Bencher) {
+    let s = "предложение из кириллических букв.";
+    assert_fmt(s, r#""предложение из кириллических букв.""#, 3);
+    b.iter(|| {
+        black_box(format!("{:?}", black_box(s)));
+    });
+}
+
+#[bench]
+fn mixed(b: &mut Bencher) {
+    let s = "\"❤️\"\n\"hűha ez betű\"\n\"кириллических букв\".";
+    assert_fmt(s, r#""\"❤\u{fe0f}\"\n\"hűha ez betű\"\n\"кириллических букв\".""#, 36);
+    b.iter(|| {
+        black_box(format!("{:?}", black_box(s)));
+    });
+}
diff --git a/library/core/src/iter/adapters/step_by.rs b/library/core/src/iter/adapters/step_by.rs
index a5cf069d407..abdf2f415fe 100644
--- a/library/core/src/iter/adapters/step_by.rs
+++ b/library/core/src/iter/adapters/step_by.rs
@@ -1,7 +1,7 @@
 use crate::{
     intrinsics,
     iter::{from_fn, TrustedLen, TrustedRandomAccess},
-    num::NonZeroUsize,
+    num::NonZero,
     ops::{Range, Try},
 };
 
@@ -42,10 +42,10 @@ impl<I> StepBy<I> {
     /// The `step` that was originally passed to `Iterator::step_by(step)`,
     /// aka `self.step_minus_one + 1`.
     #[inline]
-    fn original_step(&self) -> NonZeroUsize {
+    fn original_step(&self) -> NonZero<usize> {
         // SAFETY: By type invariant, `step_minus_one` cannot be `MAX`, which
         // means the addition cannot overflow and the result cannot be zero.
-        unsafe { NonZeroUsize::new_unchecked(intrinsics::unchecked_add(self.step_minus_one, 1)) }
+        unsafe { NonZero::new_unchecked(intrinsics::unchecked_add(self.step_minus_one, 1)) }
     }
 }
 
@@ -231,12 +231,12 @@ unsafe impl<I: Iterator> StepByImpl<I> for StepBy<I> {
     #[inline]
     default fn spec_size_hint(&self) -> (usize, Option<usize>) {
         #[inline]
-        fn first_size(step: NonZeroUsize) -> impl Fn(usize) -> usize {
+        fn first_size(step: NonZero<usize>) -> impl Fn(usize) -> usize {
             move |n| if n == 0 { 0 } else { 1 + (n - 1) / step }
         }
 
         #[inline]
-        fn other_size(step: NonZeroUsize) -> impl Fn(usize) -> usize {
+        fn other_size(step: NonZero<usize>) -> impl Fn(usize) -> usize {
             move |n| n / step
         }
 
diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs
index 8a94964c8c5..8fe81a9f528 100644
--- a/library/core/src/num/f128.rs
+++ b/library/core/src/num/f128.rs
@@ -15,13 +15,204 @@ use crate::mem;
 
 /// Basic mathematical constants.
 #[unstable(feature = "f128", issue = "116909")]
-pub mod consts {}
+pub mod consts {
+    // FIXME: replace with mathematical constants from cmath.
+
+    /// Archimedes' constant (π)
+    #[unstable(feature = "f128", issue = "116909")]
+    pub const PI: f128 = 3.14159265358979323846264338327950288419716939937510582097494_f128;
+
+    /// The full circle constant (τ)
+    ///
+    /// Equal to 2π.
+    #[unstable(feature = "f128", issue = "116909")]
+    pub const TAU: f128 = 6.28318530717958647692528676655900576839433879875021164194989_f128;
+
+    /// The golden ratio (φ)
+    #[unstable(feature = "f128", issue = "116909")]
+    // Also, #[unstable(feature = "more_float_constants", issue = "103883")]
+    pub const PHI: f128 = 1.61803398874989484820458683436563811772030917980576286213545_f128;
+
+    /// The Euler-Mascheroni constant (γ)
+    #[unstable(feature = "f128", issue = "116909")]
+    // Also, #[unstable(feature = "more_float_constants", issue = "103883")]
+    pub const EGAMMA: f128 = 0.577215664901532860606512090082402431042159335939923598805767_f128;
+
+    /// π/2
+    #[unstable(feature = "f128", issue = "116909")]
+    pub const FRAC_PI_2: f128 = 1.57079632679489661923132169163975144209858469968755291048747_f128;
+
+    /// π/3
+    #[unstable(feature = "f128", issue = "116909")]
+    pub const FRAC_PI_3: f128 = 1.04719755119659774615421446109316762806572313312503527365831_f128;
+
+    /// π/4
+    #[unstable(feature = "f128", issue = "116909")]
+    pub const FRAC_PI_4: f128 = 0.785398163397448309615660845819875721049292349843776455243736_f128;
+
+    /// π/6
+    #[unstable(feature = "f128", issue = "116909")]
+    pub const FRAC_PI_6: f128 = 0.523598775598298873077107230546583814032861566562517636829157_f128;
+
+    /// π/8
+    #[unstable(feature = "f128", issue = "116909")]
+    pub const FRAC_PI_8: f128 = 0.392699081698724154807830422909937860524646174921888227621868_f128;
+
+    /// 1/π
+    #[unstable(feature = "f128", issue = "116909")]
+    pub const FRAC_1_PI: f128 = 0.318309886183790671537767526745028724068919291480912897495335_f128;
+
+    /// 1/sqrt(π)
+    #[unstable(feature = "f128", issue = "116909")]
+    // Also, #[unstable(feature = "more_float_constants", issue = "103883")]
+    pub const FRAC_1_SQRT_PI: f128 =
+        0.564189583547756286948079451560772585844050629328998856844086_f128;
+
+    /// 2/π
+    #[unstable(feature = "f128", issue = "116909")]
+    pub const FRAC_2_PI: f128 = 0.636619772367581343075535053490057448137838582961825794990669_f128;
+
+    /// 2/sqrt(π)
+    #[unstable(feature = "f128", issue = "116909")]
+    pub const FRAC_2_SQRT_PI: f128 =
+        1.12837916709551257389615890312154517168810125865799771368817_f128;
+
+    /// sqrt(2)
+    #[unstable(feature = "f128", issue = "116909")]
+    pub const SQRT_2: f128 = 1.41421356237309504880168872420969807856967187537694807317668_f128;
+
+    /// 1/sqrt(2)
+    #[unstable(feature = "f128", issue = "116909")]
+    pub const FRAC_1_SQRT_2: f128 =
+        0.707106781186547524400844362104849039284835937688474036588340_f128;
+
+    /// sqrt(3)
+    #[unstable(feature = "f128", issue = "116909")]
+    // Also, #[unstable(feature = "more_float_constants", issue = "103883")]
+    pub const SQRT_3: f128 = 1.73205080756887729352744634150587236694280525381038062805581_f128;
+
+    /// 1/sqrt(3)
+    #[unstable(feature = "f128", issue = "116909")]
+    // Also, #[unstable(feature = "more_float_constants", issue = "103883")]
+    pub const FRAC_1_SQRT_3: f128 =
+        0.577350269189625764509148780501957455647601751270126876018602_f128;
+
+    /// Euler's number (e)
+    #[unstable(feature = "f128", issue = "116909")]
+    pub const E: f128 = 2.71828182845904523536028747135266249775724709369995957496697_f128;
+
+    /// log<sub>2</sub>(10)
+    #[unstable(feature = "f128", issue = "116909")]
+    pub const LOG2_10: f128 = 3.32192809488736234787031942948939017586483139302458061205476_f128;
+
+    /// log<sub>2</sub>(e)
+    #[unstable(feature = "f128", issue = "116909")]
+    pub const LOG2_E: f128 = 1.44269504088896340735992468100189213742664595415298593413545_f128;
+
+    /// log<sub>10</sub>(2)
+    #[unstable(feature = "f128", issue = "116909")]
+    pub const LOG10_2: f128 = 0.301029995663981195213738894724493026768189881462108541310427_f128;
+
+    /// log<sub>10</sub>(e)
+    #[unstable(feature = "f128", issue = "116909")]
+    pub const LOG10_E: f128 = 0.434294481903251827651128918916605082294397005803666566114454_f128;
+
+    /// ln(2)
+    #[unstable(feature = "f128", issue = "116909")]
+    pub const LN_2: f128 = 0.693147180559945309417232121458176568075500134360255254120680_f128;
+
+    /// ln(10)
+    #[unstable(feature = "f128", issue = "116909")]
+    pub const LN_10: f128 = 2.30258509299404568401799145468436420760110148862877297603333_f128;
+}
 
 #[cfg(not(test))]
 impl f128 {
-    // FIXME(f16_f128): almost everything in this `impl` is missing examples and a const
+    // FIXME(f16_f128): almost all methods in this `impl` are missing examples and a const
     // implementation. Add these once we can run code on all platforms and have f16/f128 in CTFE.
 
+    /// The radix or base of the internal representation of `f128`.
+    #[unstable(feature = "f128", issue = "116909")]
+    pub const RADIX: u32 = 2;
+
+    /// Number of significant digits in base 2.
+    #[unstable(feature = "f128", issue = "116909")]
+    pub const MANTISSA_DIGITS: u32 = 113;
+
+    /// Approximate number of significant digits in base 10.
+    ///
+    /// This is the maximum <i>x</i> such that any decimal number with <i>x</i>
+    /// significant digits can be converted to `f128` and back without loss.
+    ///
+    /// Equal to floor(log<sub>10</sub>&nbsp;2<sup>[`MANTISSA_DIGITS`]&nbsp;&minus;&nbsp;1</sup>).
+    ///
+    /// [`MANTISSA_DIGITS`]: f128::MANTISSA_DIGITS
+    #[unstable(feature = "f128", issue = "116909")]
+    pub const DIGITS: u32 = 33;
+
+    /// [Machine epsilon] value for `f128`.
+    ///
+    /// This is the difference between `1.0` and the next larger representable number.
+    ///
+    /// Equal to 2<sup>1&nbsp;&minus;&nbsp;[`MANTISSA_DIGITS`]</sup>.
+    ///
+    /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon
+    /// [`MANTISSA_DIGITS`]: f128::MANTISSA_DIGITS
+    #[unstable(feature = "f128", issue = "116909")]
+    pub const EPSILON: f128 = 1.92592994438723585305597794258492731e-34_f128;
+
+    /// Smallest finite `f128` value.
+    ///
+    /// Equal to &minus;[`MAX`].
+    ///
+    /// [`MAX`]: f128::MAX
+    #[unstable(feature = "f128", issue = "116909")]
+    pub const MIN: f128 = -1.18973149535723176508575932662800701e+4932_f128;
+    /// Smallest positive normal `f128` value.
+    ///
+    /// Equal to 2<sup>[`MIN_EXP`]&nbsp;&minus;&nbsp;1</sup>.
+    ///
+    /// [`MIN_EXP`]: f128::MIN_EXP
+    #[unstable(feature = "f128", issue = "116909")]
+    pub const MIN_POSITIVE: f128 = 3.36210314311209350626267781732175260e-4932_f128;
+    /// Largest finite `f128` value.
+    ///
+    /// Equal to
+    /// (1&nbsp;&minus;&nbsp;2<sup>&minus;[`MANTISSA_DIGITS`]</sup>)&nbsp;2<sup>[`MAX_EXP`]</sup>.
+    ///
+    /// [`MANTISSA_DIGITS`]: f128::MANTISSA_DIGITS
+    /// [`MAX_EXP`]: f128::MAX_EXP
+    #[unstable(feature = "f128", issue = "116909")]
+    pub const MAX: f128 = 1.18973149535723176508575932662800701e+4932_f128;
+
+    /// One greater than the minimum possible normal power of 2 exponent.
+    ///
+    /// If <i>x</i>&nbsp;=&nbsp;`MIN_EXP`, then normal numbers
+    /// ≥&nbsp;0.5&nbsp;×&nbsp;2<sup><i>x</i></sup>.
+    #[unstable(feature = "f128", issue = "116909")]
+    pub const MIN_EXP: i32 = -16_381;
+    /// Maximum possible power of 2 exponent.
+    ///
+    /// If <i>x</i>&nbsp;=&nbsp;`MAX_EXP`, then normal numbers
+    /// &lt;&nbsp;1&nbsp;×&nbsp;2<sup><i>x</i></sup>.
+    #[unstable(feature = "f128", issue = "116909")]
+    pub const MAX_EXP: i32 = 16_384;
+
+    /// Minimum <i>x</i> for which 10<sup><i>x</i></sup> is normal.
+    ///
+    /// Equal to ceil(log<sub>10</sub>&nbsp;[`MIN_POSITIVE`]).
+    ///
+    /// [`MIN_POSITIVE`]: f128::MIN_POSITIVE
+    #[unstable(feature = "f128", issue = "116909")]
+    pub const MIN_10_EXP: i32 = -4_931;
+    /// Maximum <i>x</i> for which 10<sup><i>x</i></sup> is normal.
+    ///
+    /// Equal to floor(log<sub>10</sub>&nbsp;[`MAX`]).
+    ///
+    /// [`MAX`]: f128::MAX
+    #[unstable(feature = "f128", issue = "116909")]
+    pub const MAX_10_EXP: i32 = 4_932;
+
     /// Returns `true` if this value is NaN.
     #[inline]
     #[must_use]
diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs
index 039f5188ba4..4290245ab29 100644
--- a/library/core/src/num/f16.rs
+++ b/library/core/src/num/f16.rs
@@ -15,13 +15,200 @@ use crate::mem;
 
 /// Basic mathematical constants.
 #[unstable(feature = "f16", issue = "116909")]
-pub mod consts {}
+pub mod consts {
+    // FIXME: replace with mathematical constants from cmath.
+
+    /// Archimedes' constant (π)
+    #[unstable(feature = "f16", issue = "116909")]
+    pub const PI: f16 = 3.14159265358979323846264338327950288_f16;
+
+    /// The full circle constant (τ)
+    ///
+    /// Equal to 2π.
+    #[unstable(feature = "f16", issue = "116909")]
+    pub const TAU: f16 = 6.28318530717958647692528676655900577_f16;
+
+    /// The golden ratio (φ)
+    #[unstable(feature = "f16", issue = "116909")]
+    // Also, #[unstable(feature = "more_float_constants", issue = "103883")]
+    pub const PHI: f16 = 1.618033988749894848204586834365638118_f16;
+
+    /// The Euler-Mascheroni constant (γ)
+    #[unstable(feature = "f16", issue = "116909")]
+    // Also, #[unstable(feature = "more_float_constants", issue = "103883")]
+    pub const EGAMMA: f16 = 0.577215664901532860606512090082402431_f16;
+
+    /// π/2
+    #[unstable(feature = "f16", issue = "116909")]
+    pub const FRAC_PI_2: f16 = 1.57079632679489661923132169163975144_f16;
+
+    /// π/3
+    #[unstable(feature = "f16", issue = "116909")]
+    pub const FRAC_PI_3: f16 = 1.04719755119659774615421446109316763_f16;
+
+    /// π/4
+    #[unstable(feature = "f16", issue = "116909")]
+    pub const FRAC_PI_4: f16 = 0.785398163397448309615660845819875721_f16;
+
+    /// π/6
+    #[unstable(feature = "f16", issue = "116909")]
+    pub const FRAC_PI_6: f16 = 0.52359877559829887307710723054658381_f16;
+
+    /// π/8
+    #[unstable(feature = "f16", issue = "116909")]
+    pub const FRAC_PI_8: f16 = 0.39269908169872415480783042290993786_f16;
+
+    /// 1/π
+    #[unstable(feature = "f16", issue = "116909")]
+    pub const FRAC_1_PI: f16 = 0.318309886183790671537767526745028724_f16;
+
+    /// 1/sqrt(π)
+    #[unstable(feature = "f16", issue = "116909")]
+    // Also, #[unstable(feature = "more_float_constants", issue = "103883")]
+    pub const FRAC_1_SQRT_PI: f16 = 0.564189583547756286948079451560772586_f16;
+
+    /// 2/π
+    #[unstable(feature = "f16", issue = "116909")]
+    pub const FRAC_2_PI: f16 = 0.636619772367581343075535053490057448_f16;
+
+    /// 2/sqrt(π)
+    #[unstable(feature = "f16", issue = "116909")]
+    pub const FRAC_2_SQRT_PI: f16 = 1.12837916709551257389615890312154517_f16;
+
+    /// sqrt(2)
+    #[unstable(feature = "f16", issue = "116909")]
+    pub const SQRT_2: f16 = 1.41421356237309504880168872420969808_f16;
+
+    /// 1/sqrt(2)
+    #[unstable(feature = "f16", issue = "116909")]
+    pub const FRAC_1_SQRT_2: f16 = 0.707106781186547524400844362104849039_f16;
+
+    /// sqrt(3)
+    #[unstable(feature = "f16", issue = "116909")]
+    // Also, #[unstable(feature = "more_float_constants", issue = "103883")]
+    pub const SQRT_3: f16 = 1.732050807568877293527446341505872367_f16;
+
+    /// 1/sqrt(3)
+    #[unstable(feature = "f16", issue = "116909")]
+    // Also, #[unstable(feature = "more_float_constants", issue = "103883")]
+    pub const FRAC_1_SQRT_3: f16 = 0.577350269189625764509148780501957456_f16;
+
+    /// Euler's number (e)
+    #[unstable(feature = "f16", issue = "116909")]
+    pub const E: f16 = 2.71828182845904523536028747135266250_f16;
+
+    /// log<sub>2</sub>(10)
+    #[unstable(feature = "f16", issue = "116909")]
+    pub const LOG2_10: f16 = 3.32192809488736234787031942948939018_f16;
+
+    /// log<sub>2</sub>(e)
+    #[unstable(feature = "f16", issue = "116909")]
+    pub const LOG2_E: f16 = 1.44269504088896340735992468100189214_f16;
+
+    /// log<sub>10</sub>(2)
+    #[unstable(feature = "f16", issue = "116909")]
+    pub const LOG10_2: f16 = 0.301029995663981195213738894724493027_f16;
+
+    /// log<sub>10</sub>(e)
+    #[unstable(feature = "f16", issue = "116909")]
+    pub const LOG10_E: f16 = 0.434294481903251827651128918916605082_f16;
+
+    /// ln(2)
+    #[unstable(feature = "f16", issue = "116909")]
+    pub const LN_2: f16 = 0.693147180559945309417232121458176568_f16;
+
+    /// ln(10)
+    #[unstable(feature = "f16", issue = "116909")]
+    pub const LN_10: f16 = 2.30258509299404568401799145468436421_f16;
+}
 
 #[cfg(not(test))]
 impl f16 {
-    // FIXME(f16_f128): almost everything in this `impl` is missing examples and a const
+    // FIXME(f16_f128): almost all methods in this `impl` are missing examples and a const
     // implementation. Add these once we can run code on all platforms and have f16/f128 in CTFE.
 
+    /// The radix or base of the internal representation of `f16`.
+    #[unstable(feature = "f16", issue = "116909")]
+    pub const RADIX: u32 = 2;
+
+    /// Number of significant digits in base 2.
+    #[unstable(feature = "f16", issue = "116909")]
+    pub const MANTISSA_DIGITS: u32 = 11;
+
+    /// Approximate number of significant digits in base 10.
+    ///
+    /// This is the maximum <i>x</i> such that any decimal number with <i>x</i>
+    /// significant digits can be converted to `f16` and back without loss.
+    ///
+    /// Equal to floor(log<sub>10</sub>&nbsp;2<sup>[`MANTISSA_DIGITS`]&nbsp;&minus;&nbsp;1</sup>).
+    ///
+    /// [`MANTISSA_DIGITS`]: f16::MANTISSA_DIGITS
+    #[unstable(feature = "f16", issue = "116909")]
+    pub const DIGITS: u32 = 3;
+
+    /// [Machine epsilon] value for `f16`.
+    ///
+    /// This is the difference between `1.0` and the next larger representable number.
+    ///
+    /// Equal to 2<sup>1&nbsp;&minus;&nbsp;[`MANTISSA_DIGITS`]</sup>.
+    ///
+    /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon
+    /// [`MANTISSA_DIGITS`]: f16::MANTISSA_DIGITS
+    #[unstable(feature = "f16", issue = "116909")]
+    pub const EPSILON: f16 = 9.7656e-4_f16;
+
+    /// Smallest finite `f16` value.
+    ///
+    /// Equal to &minus;[`MAX`].
+    ///
+    /// [`MAX`]: f16::MAX
+    #[unstable(feature = "f16", issue = "116909")]
+    pub const MIN: f16 = -6.5504e+4_f16;
+    /// Smallest positive normal `f16` value.
+    ///
+    /// Equal to 2<sup>[`MIN_EXP`]&nbsp;&minus;&nbsp;1</sup>.
+    ///
+    /// [`MIN_EXP`]: f16::MIN_EXP
+    #[unstable(feature = "f16", issue = "116909")]
+    pub const MIN_POSITIVE: f16 = 6.1035e-5_f16;
+    /// Largest finite `f16` value.
+    ///
+    /// Equal to
+    /// (1&nbsp;&minus;&nbsp;2<sup>&minus;[`MANTISSA_DIGITS`]</sup>)&nbsp;2<sup>[`MAX_EXP`]</sup>.
+    ///
+    /// [`MANTISSA_DIGITS`]: f16::MANTISSA_DIGITS
+    /// [`MAX_EXP`]: f16::MAX_EXP
+    #[unstable(feature = "f16", issue = "116909")]
+    pub const MAX: f16 = 6.5504e+4_f16;
+
+    /// One greater than the minimum possible normal power of 2 exponent.
+    ///
+    /// If <i>x</i>&nbsp;=&nbsp;`MIN_EXP`, then normal numbers
+    /// ≥&nbsp;0.5&nbsp;×&nbsp;2<sup><i>x</i></sup>.
+    #[unstable(feature = "f16", issue = "116909")]
+    pub const MIN_EXP: i32 = -13;
+    /// Maximum possible power of 2 exponent.
+    ///
+    /// If <i>x</i>&nbsp;=&nbsp;`MAX_EXP`, then normal numbers
+    /// &lt;&nbsp;1&nbsp;×&nbsp;2<sup><i>x</i></sup>.
+    #[unstable(feature = "f16", issue = "116909")]
+    pub const MAX_EXP: i32 = 16;
+
+    /// Minimum <i>x</i> for which 10<sup><i>x</i></sup> is normal.
+    ///
+    /// Equal to ceil(log<sub>10</sub>&nbsp;[`MIN_POSITIVE`]).
+    ///
+    /// [`MIN_POSITIVE`]: f16::MIN_POSITIVE
+    #[unstable(feature = "f16", issue = "116909")]
+    pub const MIN_10_EXP: i32 = -4;
+    /// Maximum <i>x</i> for which 10<sup><i>x</i></sup> is normal.
+    ///
+    /// Equal to floor(log<sub>10</sub>&nbsp;[`MAX`]).
+    ///
+    /// [`MAX`]: f16::MAX
+    #[unstable(feature = "f16", issue = "116909")]
+    pub const MAX_10_EXP: i32 = 4;
+
     /// Returns `true` if this value is NaN.
     #[inline]
     #[must_use]
@@ -39,7 +226,7 @@ impl f16 {
     /// See [explanation of NaN as a special value](f32) for more info.
     #[inline]
     #[must_use]
-    #[unstable(feature = "f128", issue = "116909")]
+    #[unstable(feature = "f16", issue = "116909")]
     pub fn is_sign_positive(self) -> bool {
         !self.is_sign_negative()
     }
@@ -52,7 +239,7 @@ impl f16 {
     /// See [explanation of NaN as a special value](f32) for more info.
     #[inline]
     #[must_use]
-    #[unstable(feature = "f128", issue = "116909")]
+    #[unstable(feature = "f16", issue = "116909")]
     pub fn is_sign_negative(self) -> bool {
         // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
         // applies to zeros and NaNs as well.
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index c02f73fdf03..09a341e4d80 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -1412,11 +1412,9 @@ fn from_str_radix_panic_rt(radix: u32) -> ! {
 #[cfg_attr(feature = "panic_immediate_abort", inline)]
 #[cold]
 #[track_caller]
-const fn from_str_radix_assert(radix: u32) {
-    if 2 > radix || radix > 36 {
-        // The only difference between these two functions is their panic message.
-        intrinsics::const_eval_select((radix,), from_str_radix_panic_ct, from_str_radix_panic_rt);
-    }
+const fn from_str_radix_panic(radix: u32) {
+    // The only difference between these two functions is their panic message.
+    intrinsics::const_eval_select((radix,), from_str_radix_panic_ct, from_str_radix_panic_rt);
 }
 
 macro_rules! from_str_radix {
@@ -1450,7 +1448,9 @@ macro_rules! from_str_radix {
                 use self::IntErrorKind::*;
                 use self::ParseIntError as PIE;
 
-                from_str_radix_assert(radix);
+                if 2 > radix || radix > 36 {
+                    from_str_radix_panic(radix);
+                }
 
                 if src.is_empty() {
                     return Err(PIE { kind: Empty });
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index 5d3ae7316b1..fcdd983343d 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -453,8 +453,7 @@ macro_rules! nonzero_integer {
         #[$stability:meta]
         Self = $Ty:ident,
         Primitive = $signedness:ident $Int:ident,
-        $(UnsignedNonZero = $UnsignedNonZero:ident,)?
-        UnsignedPrimitive = $UnsignedPrimitive:ty,
+        UnsignedPrimitive = $Uint:ty,
 
         // Used in doc comments.
         leading_zeros_test = $leading_zeros_test:expr,
@@ -492,7 +491,7 @@ macro_rules! nonzero_integer {
         #[$stability]
         pub type $Ty = NonZero<$Int>;
 
-        impl $Ty {
+        impl NonZero<$Int> {
             /// The size of this non-zero integer type in bits.
             ///
             #[doc = concat!("This value is equal to [`", stringify!($Int), "::BITS`].")]
@@ -500,9 +499,9 @@ macro_rules! nonzero_integer {
             /// # Examples
             ///
             /// ```
-            #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-            ///
-            #[doc = concat!("assert_eq!(", stringify!($Ty), "::BITS, ", stringify!($Int), "::BITS);")]
+            /// # use std::num::NonZero;
+            /// #
+            #[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::BITS, ", stringify!($Int), "::BITS);")]
             /// ```
             #[stable(feature = "nonzero_bits", since = "1.67.0")]
             pub const BITS: u32 = <$Int>::BITS;
@@ -516,7 +515,9 @@ macro_rules! nonzero_integer {
             /// Basic usage:
             ///
             /// ```
-            #[doc = concat!("let n = std::num::", stringify!($Ty), "::new(", $leading_zeros_test, ").unwrap();")]
+            /// # use std::num::NonZero;
+            /// #
+            #[doc = concat!("let n = NonZero::<", stringify!($Int), ">::new(", $leading_zeros_test, ").unwrap();")]
             ///
             /// assert_eq!(n.leading_zeros(), 0);
             /// ```
@@ -528,7 +529,7 @@ macro_rules! nonzero_integer {
             pub const fn leading_zeros(self) -> u32 {
                 // SAFETY: since `self` cannot be zero, it is safe to call `ctlz_nonzero`.
                 unsafe {
-                    intrinsics::ctlz_nonzero(self.get() as $UnsignedPrimitive)
+                    intrinsics::ctlz_nonzero(self.get() as $Uint)
                 }
             }
 
@@ -542,7 +543,9 @@ macro_rules! nonzero_integer {
             /// Basic usage:
             ///
             /// ```
-            #[doc = concat!("let n = std::num::", stringify!($Ty), "::new(0b0101000).unwrap();")]
+            /// # use std::num::NonZero;
+            /// #
+            #[doc = concat!("let n = NonZero::<", stringify!($Int), ">::new(0b0101000).unwrap();")]
             ///
             /// assert_eq!(n.trailing_zeros(), 3);
             /// ```
@@ -554,7 +557,7 @@ macro_rules! nonzero_integer {
             pub const fn trailing_zeros(self) -> u32 {
                 // SAFETY: since `self` cannot be zero, it is safe to call `cttz_nonzero`.
                 unsafe {
-                    intrinsics::cttz_nonzero(self.get() as $UnsignedPrimitive)
+                    intrinsics::cttz_nonzero(self.get() as $Uint)
                 }
             }
 
@@ -567,10 +570,10 @@ macro_rules! nonzero_integer {
             /// ```
             /// #![feature(non_zero_count_ones)]
             ///
+            /// # use std::num::NonZero;
+            /// #
             /// # fn main() { test().unwrap(); }
             /// # fn test() -> Option<()> {
-            /// # use std::num::*;
-            /// #
             #[doc = concat!("let a = NonZero::<", stringify!($Int), ">::new(0b100_0000)?;")]
             #[doc = concat!("let b = NonZero::<", stringify!($Int), ">::new(0b100_0011)?;")]
             ///
@@ -597,8 +600,7 @@ macro_rules! nonzero_integer {
             nonzero_integer_signedness_dependent_methods! {
                 Self = $Ty,
                 Primitive = $signedness $Int,
-                $(UnsignedNonZero = $UnsignedNonZero,)?
-                UnsignedPrimitive = $UnsignedPrimitive,
+                UnsignedPrimitive = $Uint,
             }
 
             /// Multiplies two non-zero integers together.
@@ -608,13 +610,13 @@ macro_rules! nonzero_integer {
             /// # Examples
             ///
             /// ```
-            #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+            /// # use std::num::NonZero;
+            /// #
             /// # fn main() { test().unwrap(); }
             /// # fn test() -> Option<()> {
-            #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")]
-            #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")]
-            #[doc = concat!("let max = ", stringify!($Ty), "::new(",
-                            stringify!($Int), "::MAX)?;")]
+            #[doc = concat!("let two = NonZero::new(2", stringify!($Int), ")?;")]
+            #[doc = concat!("let four = NonZero::new(4", stringify!($Int), ")?;")]
+            #[doc = concat!("let max = NonZero::new(", stringify!($Int), "::MAX)?;")]
             ///
             /// assert_eq!(Some(four), two.checked_mul(two));
             /// assert_eq!(None, max.checked_mul(two));
@@ -642,18 +644,18 @@ macro_rules! nonzero_integer {
             }
 
             /// Multiplies two non-zero integers together.
-            #[doc = concat!("Return [`", stringify!($Ty), "::MAX`] on overflow.")]
+            #[doc = concat!("Return [`NonZero::<", stringify!($Int), ">::MAX`] on overflow.")]
             ///
             /// # Examples
             ///
             /// ```
-            #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+            /// # use std::num::NonZero;
+            /// #
             /// # fn main() { test().unwrap(); }
             /// # fn test() -> Option<()> {
-            #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")]
-            #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")]
-            #[doc = concat!("let max = ", stringify!($Ty), "::new(",
-                            stringify!($Int), "::MAX)?;")]
+            #[doc = concat!("let two = NonZero::new(2", stringify!($Int), ")?;")]
+            #[doc = concat!("let four = NonZero::new(4", stringify!($Int), ")?;")]
+            #[doc = concat!("let max = NonZero::new(", stringify!($Int), "::MAX)?;")]
             ///
             /// assert_eq!(four, two.saturating_mul(two));
             /// assert_eq!(max, four.saturating_mul(max));
@@ -698,11 +700,12 @@ macro_rules! nonzero_integer {
             /// ```
             /// #![feature(nonzero_ops)]
             ///
-            #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+            /// # use std::num::NonZero;
+            /// #
             /// # fn main() { test().unwrap(); }
             /// # fn test() -> Option<()> {
-            #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")]
-            #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")]
+            #[doc = concat!("let two = NonZero::new(2", stringify!($Int), ")?;")]
+            #[doc = concat!("let four = NonZero::new(4", stringify!($Int), ")?;")]
             ///
             /// assert_eq!(four, unsafe { two.unchecked_mul(two) });
             /// # Some(())
@@ -724,13 +727,13 @@ macro_rules! nonzero_integer {
             /// # Examples
             ///
             /// ```
-            #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+            /// # use std::num::NonZero;
+            /// #
             /// # fn main() { test().unwrap(); }
             /// # fn test() -> Option<()> {
-            #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")]
-            #[doc = concat!("let twenty_seven = ", stringify!($Ty), "::new(27)?;")]
-            #[doc = concat!("let half_max = ", stringify!($Ty), "::new(",
-                            stringify!($Int), "::MAX / 2)?;")]
+            #[doc = concat!("let three = NonZero::new(3", stringify!($Int), ")?;")]
+            #[doc = concat!("let twenty_seven = NonZero::new(27", stringify!($Int), ")?;")]
+            #[doc = concat!("let half_max = NonZero::new(", stringify!($Int), "::MAX / 2)?;")]
             ///
             /// assert_eq!(Some(twenty_seven), three.checked_pow(3));
             /// assert_eq!(None, half_max.checked_pow(3));
@@ -761,24 +764,24 @@ macro_rules! nonzero_integer {
             #[doc = sign_dependent_expr!{
                 $signedness ?
                 if signed {
-                    concat!("Return [`", stringify!($Ty), "::MIN`] ",
-                                "or [`", stringify!($Ty), "::MAX`] on overflow.")
+                    concat!("Return [`NonZero::<", stringify!($Int), ">::MIN`] ",
+                                "or [`NonZero::<", stringify!($Int), ">::MAX`] on overflow.")
                 }
                 if unsigned {
-                    concat!("Return [`", stringify!($Ty), "::MAX`] on overflow.")
+                    concat!("Return [`NonZero::<", stringify!($Int), ">::MAX`] on overflow.")
                 }
             }]
             ///
             /// # Examples
             ///
             /// ```
-            #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+            /// # use std::num::NonZero;
+            /// #
             /// # fn main() { test().unwrap(); }
             /// # fn test() -> Option<()> {
-            #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")]
-            #[doc = concat!("let twenty_seven = ", stringify!($Ty), "::new(27)?;")]
-            #[doc = concat!("let max = ", stringify!($Ty), "::new(",
-                            stringify!($Int), "::MAX)?;")]
+            #[doc = concat!("let three = NonZero::new(3", stringify!($Int), ")?;")]
+            #[doc = concat!("let twenty_seven = NonZero::new(27", stringify!($Int), ")?;")]
+            #[doc = concat!("let max = NonZero::new(", stringify!($Int), "::MAX)?;")]
             ///
             /// assert_eq!(twenty_seven, three.saturating_pow(3));
             /// assert_eq!(max, max.saturating_pow(3));
@@ -804,7 +807,7 @@ macro_rules! nonzero_integer {
         }
 
         #[stable(feature = "nonzero_parse", since = "1.35.0")]
-        impl FromStr for $Ty {
+        impl FromStr for NonZero<$Int> {
             type Err = ParseIntError;
             fn from_str(src: &str) -> Result<Self, Self::Err> {
                 Self::new(<$Int>::from_str_radix(src, 10)?)
@@ -842,56 +845,55 @@ macro_rules! nonzero_integer_signedness_dependent_impls {
     // Impls for unsigned nonzero types only.
     ($Ty:ident unsigned $Int:ty) => {
         #[stable(feature = "nonzero_div", since = "1.51.0")]
-        impl Div<$Ty> for $Int {
+        impl Div<NonZero<$Int>> for $Int {
             type Output = $Int;
 
-            /// This operation rounds towards zero,
-            /// truncating any fractional part of the exact result, and cannot panic.
+            /// This operation rounds towards zero, truncating any fractional
+            /// part of the exact result, and cannot panic.
             #[inline]
-            fn div(self, other: $Ty) -> $Int {
-                // SAFETY: div by zero is checked because `other` is a nonzero,
+            fn div(self, other: NonZero<$Int>) -> $Int {
+                // SAFETY: Division by zero is checked because `other` is non-zero,
                 // and MIN/-1 is checked because `self` is an unsigned int.
                 unsafe { intrinsics::unchecked_div(self, other.get()) }
             }
         }
 
         #[stable(feature = "nonzero_div_assign", since = "1.79.0")]
-        impl DivAssign<$Ty> for $Int {
-            /// This operation rounds towards zero,
-            /// truncating any fractional part of the exact result, and cannot panic.
+        impl DivAssign<NonZero<$Int>> for $Int {
+            /// This operation rounds towards zero, truncating any fractional
+            /// part of the exact result, and cannot panic.
             #[inline]
-            fn div_assign(&mut self, other: $Ty) {
+            fn div_assign(&mut self, other: NonZero<$Int>) {
                 *self = *self / other;
             }
         }
 
         #[stable(feature = "nonzero_div", since = "1.51.0")]
-        impl Rem<$Ty> for $Int {
+        impl Rem<NonZero<$Int>> for $Int {
             type Output = $Int;
 
             /// This operation satisfies `n % d == n - (n / d) * d`, and cannot panic.
             #[inline]
-            fn rem(self, other: $Ty) -> $Int {
-                // SAFETY: rem by zero is checked because `other` is a nonzero,
+            fn rem(self, other: NonZero<$Int>) -> $Int {
+                // SAFETY: Remainder by zero is checked because `other` is non-zero,
                 // and MIN/-1 is checked because `self` is an unsigned int.
                 unsafe { intrinsics::unchecked_rem(self, other.get()) }
             }
         }
 
         #[stable(feature = "nonzero_div_assign", since = "1.79.0")]
-        impl RemAssign<$Ty> for $Int {
+        impl RemAssign<NonZero<$Int>> for $Int {
             /// This operation satisfies `n % d == n - (n / d) * d`, and cannot panic.
             #[inline]
-            fn rem_assign(&mut self, other: $Ty) {
+            fn rem_assign(&mut self, other: NonZero<$Int>) {
                 *self = *self % other;
             }
         }
     };
-
     // Impls for signed nonzero types only.
     ($Ty:ident signed $Int:ty) => {
         #[stable(feature = "signed_nonzero_neg", since = "1.71.0")]
-        impl Neg for $Ty {
+        impl Neg for NonZero<$Int> {
             type Output = Self;
 
             #[inline]
@@ -901,7 +903,7 @@ macro_rules! nonzero_integer_signedness_dependent_impls {
             }
         }
 
-        forward_ref_unop! { impl Neg, neg for $Ty,
+        forward_ref_unop! { impl Neg, neg for NonZero<$Int>,
         #[stable(feature = "signed_nonzero_neg", since = "1.71.0")] }
     };
 }
@@ -920,8 +922,9 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
         /// # Examples
         ///
         /// ```
-        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-        #[doc = concat!("assert_eq!(", stringify!($Ty), "::MIN.get(), 1", stringify!($Int), ");")]
+        /// # use std::num::NonZero;
+        /// #
+        #[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::MIN.get(), 1", stringify!($Int), ");")]
         /// ```
         #[stable(feature = "nonzero_min_max", since = "1.70.0")]
         pub const MIN: Self = Self::new(1).unwrap();
@@ -933,8 +936,9 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
         /// # Examples
         ///
         /// ```
-        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-        #[doc = concat!("assert_eq!(", stringify!($Ty), "::MAX.get(), ", stringify!($Int), "::MAX);")]
+        /// # use std::num::NonZero;
+        /// #
+        #[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::MAX.get(), ", stringify!($Int), "::MAX);")]
         /// ```
         #[stable(feature = "nonzero_min_max", since = "1.70.0")]
         pub const MAX: Self = Self::new(<$Int>::MAX).unwrap();
@@ -947,13 +951,13 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
         /// # Examples
         ///
         /// ```
-        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        /// # use std::num::NonZero;
+        /// #
         /// # fn main() { test().unwrap(); }
         /// # fn test() -> Option<()> {
-        #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")]
-        #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")]
-        #[doc = concat!("let max = ", stringify!($Ty), "::new(",
-                        stringify!($Int), "::MAX)?;")]
+        #[doc = concat!("let one = NonZero::new(1", stringify!($Int), ")?;")]
+        #[doc = concat!("let two = NonZero::new(2", stringify!($Int), ")?;")]
+        #[doc = concat!("let max = NonZero::new(", stringify!($Int), "::MAX)?;")]
         ///
         /// assert_eq!(Some(two), one.checked_add(1));
         /// assert_eq!(None, max.checked_add(1));
@@ -981,18 +985,18 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
         }
 
         /// Adds an unsigned integer to a non-zero value.
-        #[doc = concat!("Return [`", stringify!($Ty), "::MAX`] on overflow.")]
+        #[doc = concat!("Return [`NonZero::<", stringify!($Int), ">::MAX`] on overflow.")]
         ///
         /// # Examples
         ///
         /// ```
-        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        /// # use std::num::NonZero;
+        /// #
         /// # fn main() { test().unwrap(); }
         /// # fn test() -> Option<()> {
-        #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")]
-        #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")]
-        #[doc = concat!("let max = ", stringify!($Ty), "::new(",
-                        stringify!($Int), "::MAX)?;")]
+        #[doc = concat!("let one = NonZero::new(1", stringify!($Int), ")?;")]
+        #[doc = concat!("let two = NonZero::new(2", stringify!($Int), ")?;")]
+        #[doc = concat!("let max = NonZero::new(", stringify!($Int), "::MAX)?;")]
         ///
         /// assert_eq!(two, one.saturating_add(1));
         /// assert_eq!(max, max.saturating_add(1));
@@ -1027,11 +1031,12 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
         /// ```
         /// #![feature(nonzero_ops)]
         ///
-        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        /// # use std::num::NonZero;
+        /// #
         /// # fn main() { test().unwrap(); }
         /// # fn test() -> Option<()> {
-        #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")]
-        #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")]
+        #[doc = concat!("let one = NonZero::new(1", stringify!($Int), ")?;")]
+        #[doc = concat!("let two = NonZero::new(2", stringify!($Int), ")?;")]
         ///
         /// assert_eq!(two, unsafe { one.unchecked_add(1) });
         /// # Some(())
@@ -1054,14 +1059,14 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
         /// # Examples
         ///
         /// ```
-        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        /// # use std::num::NonZero;
+        /// #
         /// # fn main() { test().unwrap(); }
         /// # fn test() -> Option<()> {
-        #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")]
-        #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")]
-        #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")]
-        #[doc = concat!("let max = ", stringify!($Ty), "::new(",
-                        stringify!($Int), "::MAX)?;")]
+        #[doc = concat!("let two = NonZero::new(2", stringify!($Int), ")?;")]
+        #[doc = concat!("let three = NonZero::new(3", stringify!($Int), ")?;")]
+        #[doc = concat!("let four = NonZero::new(4", stringify!($Int), ")?;")]
+        #[doc = concat!("let max = NonZero::new(", stringify!($Int), "::MAX)?;")]
         ///
         /// assert_eq!(Some(two), two.checked_next_power_of_two() );
         /// assert_eq!(Some(four), three.checked_next_power_of_two() );
@@ -1094,10 +1099,11 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
         /// # Examples
         ///
         /// ```
-        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-        #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(7).unwrap().ilog2(), 2);")]
-        #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(8).unwrap().ilog2(), 3);")]
-        #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(9).unwrap().ilog2(), 3);")]
+        /// # use std::num::NonZero;
+        /// #
+        #[doc = concat!("assert_eq!(NonZero::new(7", stringify!($Int), ").unwrap().ilog2(), 2);")]
+        #[doc = concat!("assert_eq!(NonZero::new(8", stringify!($Int), ").unwrap().ilog2(), 3);")]
+        #[doc = concat!("assert_eq!(NonZero::new(9", stringify!($Int), ").unwrap().ilog2(), 3);")]
         /// ```
         #[stable(feature = "int_log", since = "1.67.0")]
         #[rustc_const_stable(feature = "int_log", since = "1.67.0")]
@@ -1118,10 +1124,11 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
         /// # Examples
         ///
         /// ```
-        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-        #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(99).unwrap().ilog10(), 1);")]
-        #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(100).unwrap().ilog10(), 2);")]
-        #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(101).unwrap().ilog10(), 2);")]
+        /// # use std::num::NonZero;
+        /// #
+        #[doc = concat!("assert_eq!(NonZero::new(99", stringify!($Int), ").unwrap().ilog10(), 1);")]
+        #[doc = concat!("assert_eq!(NonZero::new(100", stringify!($Int), ").unwrap().ilog10(), 2);")]
+        #[doc = concat!("assert_eq!(NonZero::new(101", stringify!($Int), ").unwrap().ilog10(), 2);")]
         /// ```
         #[stable(feature = "int_log", since = "1.67.0")]
         #[rustc_const_stable(feature = "int_log", since = "1.67.0")]
@@ -1142,13 +1149,14 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
         ///
         /// ```
         /// #![feature(num_midpoint)]
-        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
         ///
+        /// # use std::num::NonZero;
+        /// #
         /// # fn main() { test().unwrap(); }
         /// # fn test() -> Option<()> {
-        #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")]
-        #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")]
-        #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")]
+        #[doc = concat!("let one = NonZero::new(1", stringify!($Int), ")?;")]
+        #[doc = concat!("let two = NonZero::new(2", stringify!($Int), ")?;")]
+        #[doc = concat!("let four = NonZero::new(4", stringify!($Int), ")?;")]
         ///
         /// assert_eq!(one.midpoint(four), two);
         /// assert_eq!(four.midpoint(one), two);
@@ -1179,9 +1187,9 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
         /// Basic usage:
         ///
         /// ```
-        #[doc = concat!("let eight = std::num::", stringify!($Ty), "::new(8).unwrap();")]
+        #[doc = concat!("let eight = std::num::NonZero::new(8", stringify!($Int), ").unwrap();")]
         /// assert!(eight.is_power_of_two());
-        #[doc = concat!("let ten = std::num::", stringify!($Ty), "::new(10).unwrap();")]
+        #[doc = concat!("let ten = std::num::NonZero::new(10", stringify!($Int), ").unwrap();")]
         /// assert!(!ten.is_power_of_two());
         /// ```
         #[must_use]
@@ -1202,7 +1210,6 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
     (
         Self = $Ty:ident,
         Primitive = signed $Int:ident,
-        UnsignedNonZero = $Uty:ident,
         UnsignedPrimitive = $Uint:ty,
     ) => {
         /// The smallest value that can be represented by this non-zero
@@ -1216,8 +1223,9 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
         /// # Examples
         ///
         /// ```
-        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-        #[doc = concat!("assert_eq!(", stringify!($Ty), "::MIN.get(), ", stringify!($Int), "::MIN);")]
+        /// # use std::num::NonZero;
+        /// #
+        #[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::MIN.get(), ", stringify!($Int), "::MIN);")]
         /// ```
         #[stable(feature = "nonzero_min_max", since = "1.70.0")]
         pub const MIN: Self = Self::new(<$Int>::MIN).unwrap();
@@ -1233,8 +1241,9 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
         /// # Examples
         ///
         /// ```
-        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-        #[doc = concat!("assert_eq!(", stringify!($Ty), "::MAX.get(), ", stringify!($Int), "::MAX);")]
+        /// # use std::num::NonZero;
+        /// #
+        #[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::MAX.get(), ", stringify!($Int), "::MAX);")]
         /// ```
         #[stable(feature = "nonzero_min_max", since = "1.70.0")]
         pub const MAX: Self = Self::new(<$Int>::MAX).unwrap();
@@ -1246,11 +1255,12 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
         /// # Example
         ///
         /// ```
-        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        /// # use std::num::NonZero;
+        /// #
         /// # fn main() { test().unwrap(); }
         /// # fn test() -> Option<()> {
-        #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")]
-        #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")]
+        #[doc = concat!("let pos = NonZero::new(1", stringify!($Int), ")?;")]
+        #[doc = concat!("let neg = NonZero::new(-1", stringify!($Int), ")?;")]
         ///
         /// assert_eq!(pos, pos.abs());
         /// assert_eq!(pos, neg.abs());
@@ -1269,19 +1279,19 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
 
         /// Checked absolute value.
         /// Checks for overflow and returns [`None`] if
-        #[doc = concat!("`self == ", stringify!($Ty), "::MIN`.")]
+        #[doc = concat!("`self == NonZero::<", stringify!($Int), ">::MIN`.")]
         /// The result cannot be zero.
         ///
         /// # Example
         ///
         /// ```
-        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        /// # use std::num::NonZero;
+        /// #
         /// # fn main() { test().unwrap(); }
         /// # fn test() -> Option<()> {
-        #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")]
-        #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")]
-        #[doc = concat!("let min = ", stringify!($Ty), "::new(",
-                        stringify!($Int), "::MIN)?;")]
+        #[doc = concat!("let pos = NonZero::new(1", stringify!($Int), ")?;")]
+        #[doc = concat!("let neg = NonZero::new(-1", stringify!($Int), ")?;")]
+        #[doc = concat!("let min = NonZero::new(", stringify!($Int), "::MIN)?;")]
         ///
         /// assert_eq!(Some(pos), neg.checked_abs());
         /// assert_eq!(None, min.checked_abs());
@@ -1309,13 +1319,13 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
         /// # Example
         ///
         /// ```
-        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        /// # use std::num::NonZero;
+        /// #
         /// # fn main() { test().unwrap(); }
         /// # fn test() -> Option<()> {
-        #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")]
-        #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")]
-        #[doc = concat!("let min = ", stringify!($Ty), "::new(",
-                        stringify!($Int), "::MIN)?;")]
+        #[doc = concat!("let pos = NonZero::new(1", stringify!($Int), ")?;")]
+        #[doc = concat!("let neg = NonZero::new(-1", stringify!($Int), ")?;")]
+        #[doc = concat!("let min = NonZero::new(", stringify!($Int), "::MIN)?;")]
         ///
         /// assert_eq!((pos, false), pos.overflowing_abs());
         /// assert_eq!((pos, false), neg.overflowing_abs());
@@ -1343,17 +1353,15 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
         /// # Example
         ///
         /// ```
-        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        /// # use std::num::NonZero;
+        /// #
         /// # fn main() { test().unwrap(); }
         /// # fn test() -> Option<()> {
-        #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")]
-        #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")]
-        #[doc = concat!("let min = ", stringify!($Ty), "::new(",
-                        stringify!($Int), "::MIN)?;")]
-        #[doc = concat!("let min_plus = ", stringify!($Ty), "::new(",
-                        stringify!($Int), "::MIN + 1)?;")]
-        #[doc = concat!("let max = ", stringify!($Ty), "::new(",
-                        stringify!($Int), "::MAX)?;")]
+        #[doc = concat!("let pos = NonZero::new(1", stringify!($Int), ")?;")]
+        #[doc = concat!("let neg = NonZero::new(-1", stringify!($Int), ")?;")]
+        #[doc = concat!("let min = NonZero::new(", stringify!($Int), "::MIN)?;")]
+        #[doc = concat!("let min_plus = NonZero::new(", stringify!($Int), "::MIN + 1)?;")]
+        #[doc = concat!("let max = NonZero::new(", stringify!($Int), "::MAX)?;")]
         ///
         /// assert_eq!(pos, pos.saturating_abs());
         /// assert_eq!(pos, neg.saturating_abs());
@@ -1378,15 +1386,14 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
         /// # Example
         ///
         /// ```
-        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        /// # use std::num::NonZero;
+        /// #
         /// # fn main() { test().unwrap(); }
         /// # fn test() -> Option<()> {
-        #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")]
-        #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")]
-        #[doc = concat!("let min = ", stringify!($Ty), "::new(",
-                        stringify!($Int), "::MIN)?;")]
-        #[doc = concat!("# let max = ", stringify!($Ty), "::new(",
-                        stringify!($Int), "::MAX)?;")]
+        #[doc = concat!("let pos = NonZero::new(1", stringify!($Int), ")?;")]
+        #[doc = concat!("let neg = NonZero::new(-1", stringify!($Int), ")?;")]
+        #[doc = concat!("let min = NonZero::new(", stringify!($Int), "::MIN)?;")]
+        #[doc = concat!("# let max = NonZero::new(", stringify!($Int), "::MAX)?;")]
         ///
         /// assert_eq!(pos, pos.wrapping_abs());
         /// assert_eq!(pos, neg.wrapping_abs());
@@ -1411,18 +1418,15 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
         /// # Example
         ///
         /// ```
-        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-        #[doc = concat!("# use std::num::", stringify!($Uty), ";")]
-        ///
+        /// # use std::num::NonZero;
+        /// #
         /// # fn main() { test().unwrap(); }
         /// # fn test() -> Option<()> {
-        #[doc = concat!("let u_pos = ", stringify!($Uty), "::new(1)?;")]
-        #[doc = concat!("let i_pos = ", stringify!($Ty), "::new(1)?;")]
-        #[doc = concat!("let i_neg = ", stringify!($Ty), "::new(-1)?;")]
-        #[doc = concat!("let i_min = ", stringify!($Ty), "::new(",
-                        stringify!($Int), "::MIN)?;")]
-        #[doc = concat!("let u_max = ", stringify!($Uty), "::new(",
-                        stringify!($Uint), "::MAX / 2 + 1)?;")]
+        #[doc = concat!("let u_pos = NonZero::new(1", stringify!($Uint), ")?;")]
+        #[doc = concat!("let i_pos = NonZero::new(1", stringify!($Int), ")?;")]
+        #[doc = concat!("let i_neg = NonZero::new(-1", stringify!($Int), ")?;")]
+        #[doc = concat!("let i_min = NonZero::new(", stringify!($Int), "::MIN)?;")]
+        #[doc = concat!("let u_max = NonZero::new(", stringify!($Uint), "::MAX / 2 + 1)?;")]
         ///
         /// assert_eq!(u_pos, i_pos.unsigned_abs());
         /// assert_eq!(u_pos, i_neg.unsigned_abs());
@@ -1435,9 +1439,9 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline]
-        pub const fn unsigned_abs(self) -> $Uty {
+        pub const fn unsigned_abs(self) -> NonZero<$Uint> {
             // SAFETY: absolute value of nonzero cannot yield zero values.
-            unsafe { $Uty::new_unchecked(self.get().unsigned_abs()) }
+            unsafe { NonZero::new_unchecked(self.get().unsigned_abs()) }
         }
 
         /// Returns `true` if `self` is positive and `false` if the
@@ -1446,11 +1450,12 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
         /// # Example
         ///
         /// ```
-        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        /// # use std::num::NonZero;
+        /// #
         /// # fn main() { test().unwrap(); }
         /// # fn test() -> Option<()> {
-        #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
-        #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
+        #[doc = concat!("let pos_five = NonZero::new(5", stringify!($Int), ")?;")]
+        #[doc = concat!("let neg_five = NonZero::new(-5", stringify!($Int), ")?;")]
         ///
         /// assert!(pos_five.is_positive());
         /// assert!(!neg_five.is_positive());
@@ -1471,11 +1476,12 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
         /// # Example
         ///
         /// ```
-        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        /// # use std::num::NonZero;
+        /// #
         /// # fn main() { test().unwrap(); }
         /// # fn test() -> Option<()> {
-        #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
-        #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
+        #[doc = concat!("let pos_five = NonZero::new(5", stringify!($Int), ")?;")]
+        #[doc = concat!("let neg_five = NonZero::new(-5", stringify!($Int), ")?;")]
         ///
         /// assert!(neg_five.is_negative());
         /// assert!(!pos_five.is_negative());
@@ -1491,18 +1497,18 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
         }
 
         /// Checked negation. Computes `-self`,
-        #[doc = concat!("returning `None` if `self == ", stringify!($Ty), "::MIN`.")]
+        #[doc = concat!("returning `None` if `self == NonZero::<", stringify!($Int), ">::MIN`.")]
         ///
         /// # Example
         ///
         /// ```
-        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        /// # use std::num::NonZero;
+        /// #
         /// # fn main() { test().unwrap(); }
         /// # fn test() -> Option<()> {
-        #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
-        #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
-        #[doc = concat!("let min = ", stringify!($Ty), "::new(",
-                        stringify!($Int), "::MIN)?;")]
+        #[doc = concat!("let pos_five = NonZero::new(5", stringify!($Int), ")?;")]
+        #[doc = concat!("let neg_five = NonZero::new(-5", stringify!($Int), ")?;")]
+        #[doc = concat!("let min = NonZero::new(", stringify!($Int), "::MIN)?;")]
         ///
         /// assert_eq!(pos_five.checked_neg(), Some(neg_five));
         /// assert_eq!(min.checked_neg(), None);
@@ -1528,13 +1534,13 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
         /// # Example
         ///
         /// ```
-        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        /// # use std::num::NonZero;
+        /// #
         /// # fn main() { test().unwrap(); }
         /// # fn test() -> Option<()> {
-        #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
-        #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
-        #[doc = concat!("let min = ", stringify!($Ty), "::new(",
-                        stringify!($Int), "::MIN)?;")]
+        #[doc = concat!("let pos_five = NonZero::new(5", stringify!($Int), ")?;")]
+        #[doc = concat!("let neg_five = NonZero::new(-5", stringify!($Int), ")?;")]
+        #[doc = concat!("let min = NonZero::new(", stringify!($Int), "::MIN)?;")]
         ///
         /// assert_eq!(pos_five.overflowing_neg(), (neg_five, false));
         /// assert_eq!(min.overflowing_neg(), (min, true));
@@ -1551,24 +1557,22 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
         }
 
         /// Saturating negation. Computes `-self`,
-        #[doc = concat!("returning [`", stringify!($Ty), "::MAX`]")]
-        #[doc = concat!("if `self == ", stringify!($Ty), "::MIN`")]
+        #[doc = concat!("returning [`NonZero::<", stringify!($Int), ">::MAX`]")]
+        #[doc = concat!("if `self == NonZero::<", stringify!($Int), ">::MIN`")]
         /// instead of overflowing.
         ///
         /// # Example
         ///
         /// ```
-        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        /// # use std::num::NonZero;
+        /// #
         /// # fn main() { test().unwrap(); }
         /// # fn test() -> Option<()> {
-        #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
-        #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
-        #[doc = concat!("let min = ", stringify!($Ty), "::new(",
-                        stringify!($Int), "::MIN)?;")]
-        #[doc = concat!("let min_plus_one = ", stringify!($Ty), "::new(",
-                        stringify!($Int), "::MIN + 1)?;")]
-        #[doc = concat!("let max = ", stringify!($Ty), "::new(",
-                        stringify!($Int), "::MAX)?;")]
+        #[doc = concat!("let pos_five = NonZero::new(5", stringify!($Int), ")?;")]
+        #[doc = concat!("let neg_five = NonZero::new(-5", stringify!($Int), ")?;")]
+        #[doc = concat!("let min = NonZero::new(", stringify!($Int), "::MIN)?;")]
+        #[doc = concat!("let min_plus_one = NonZero::new(", stringify!($Int), "::MIN + 1)?;")]
+        #[doc = concat!("let max = NonZero::new(", stringify!($Int), "::MAX)?;")]
         ///
         /// assert_eq!(pos_five.saturating_neg(), neg_five);
         /// assert_eq!(min.saturating_neg(), max);
@@ -1595,13 +1599,13 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
         /// # Example
         ///
         /// ```
-        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        /// # use std::num::NonZero;
+        /// #
         /// # fn main() { test().unwrap(); }
         /// # fn test() -> Option<()> {
-        #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
-        #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
-        #[doc = concat!("let min = ", stringify!($Ty), "::new(",
-                        stringify!($Int), "::MIN)?;")]
+        #[doc = concat!("let pos_five = NonZero::new(5", stringify!($Int), ")?;")]
+        #[doc = concat!("let neg_five = NonZero::new(-5", stringify!($Int), ")?;")]
+        #[doc = concat!("let min = NonZero::new(", stringify!($Int), "::MIN)?;")]
         ///
         /// assert_eq!(pos_five.wrapping_neg(), neg_five);
         /// assert_eq!(min.wrapping_neg(), min);
@@ -1662,41 +1666,35 @@ nonzero_integer! {
 nonzero_integer! {
     Self = NonZeroI8,
     Primitive = signed i8,
-    UnsignedNonZero = NonZeroU8,
     UnsignedPrimitive = u8,
 }
 
 nonzero_integer! {
     Self = NonZeroI16,
     Primitive = signed i16,
-    UnsignedNonZero = NonZeroU16,
     UnsignedPrimitive = u16,
 }
 
 nonzero_integer! {
     Self = NonZeroI32,
     Primitive = signed i32,
-    UnsignedNonZero = NonZeroU32,
     UnsignedPrimitive = u32,
 }
 
 nonzero_integer! {
     Self = NonZeroI64,
     Primitive = signed i64,
-    UnsignedNonZero = NonZeroU64,
     UnsignedPrimitive = u64,
 }
 
 nonzero_integer! {
     Self = NonZeroI128,
     Primitive = signed i128,
-    UnsignedNonZero = NonZeroU128,
     UnsignedPrimitive = u128,
 }
 
 nonzero_integer! {
     Self = NonZeroIsize,
     Primitive = signed isize,
-    UnsignedNonZero = NonZeroUsize,
     UnsignedPrimitive = usize,
 }
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index 673144cb328..48a96c5792c 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -2764,6 +2764,7 @@ macro_rules! uint_impl {
         /// ```
         #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".next_power_of_two(), 2);")]
         #[doc = concat!("assert_eq!(3", stringify!($SelfT), ".next_power_of_two(), 4);")]
+        #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".next_power_of_two(), 1);")]
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index 18a9503cfd2..d8597369b9b 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -1133,6 +1133,12 @@ impl<T> (T,) {}
 /// bits. Please see [the documentation for [`prim@f32`] or [Wikipedia on
 /// half-precision values][wikipedia] for more information.
 ///
+/// Note that most common platforms will not support `f16` in hardware without enabling extra target
+/// features, with the notable exception of Apple Silicon (also known as M1, M2, etc.) processors.
+/// Hardware support on x86-64 requires the avx512fp16 feature, while RISC-V requires Zhf.
+/// Usually the fallback implementation will be to use `f32` hardware if it exists, and convert
+/// between `f16` and `f32` when performing math.
+///
 /// *[See also the `std::f16::consts` module](crate::f16::consts).*
 ///
 /// [wikipedia]: https://en.wikipedia.org/wiki/Half-precision_floating-point_format
@@ -1232,6 +1238,12 @@ mod prim_f64 {}
 /// as many bits as `f64`. Please see [the documentation for [`prim@f32`] or [Wikipedia on
 /// quad-precision values][wikipedia] for more information.
 ///
+/// Note that no platforms have hardware support for `f128` without enabling target specific features,
+/// as for all instruction set architectures `f128` is considered an optional feature.
+/// Only Power ISA ("PowerPC") and RISCV specify it, and only certain microarchitectures
+/// actually implement it. For x86-64 and AArch64, ISA support is not even specified,
+/// so it will always be a software implementation significantly slower than `f64`.
+///
 /// *[See also the `std::f128::consts` module](crate::f128::consts).*
 ///
 /// [wikipedia]: https://en.wikipedia.org/wiki/Quadruple-precision_floating-point_format
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 5f3815859c8..8d7192c1b0f 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -812,7 +812,7 @@ pub const fn from_mut<T: ?Sized>(r: &mut T) -> *mut T {
 #[rustc_allow_const_fn_unstable(ptr_metadata)]
 #[rustc_diagnostic_item = "ptr_slice_from_raw_parts"]
 pub const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
-    from_raw_parts(data.cast(), len)
+    intrinsics::aggregate_raw_ptr(data, len)
 }
 
 /// Forms a raw mutable slice from a pointer and a length.
@@ -858,7 +858,7 @@ pub const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
 #[rustc_const_unstable(feature = "const_slice_from_raw_parts_mut", issue = "67456")]
 #[rustc_diagnostic_item = "ptr_slice_from_raw_parts_mut"]
 pub const fn slice_from_raw_parts_mut<T>(data: *mut T, len: usize) -> *mut [T] {
-    from_raw_parts_mut(data.cast(), len)
+    intrinsics::aggregate_raw_ptr(data, len)
 }
 
 /// Swaps the values at two mutable locations of the same type, without
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index ed7bcec89b9..9bee50424b3 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -544,7 +544,7 @@ impl<T> [T] {
     /// ```
     #[inline]
     #[stable(feature = "slice_first_last_chunk", since = "1.77.0")]
-    #[rustc_const_unstable(feature = "const_slice_first_last_chunk", issue = "111774")]
+    #[rustc_const_stable(feature = "slice_first_last_chunk", since = "1.77.0")]
     pub const fn last_chunk<const N: usize>(&self) -> Option<&[T; N]> {
         if self.len() < N {
             None
@@ -1337,8 +1337,10 @@ impl<T> [T] {
     #[must_use]
     pub const fn as_chunks<const N: usize>(&self) -> (&[[T; N]], &[T]) {
         assert!(N != 0, "chunk size must be non-zero");
-        let len = self.len() / N;
-        let (multiple_of_n, remainder) = self.split_at(len * N);
+        let len_rounded_down = self.len() / N * N;
+        // SAFETY: The rounded-down value is always the same or smaller than the
+        // original length, and thus must be in-bounds of the slice.
+        let (multiple_of_n, remainder) = unsafe { self.split_at_unchecked(len_rounded_down) };
         // SAFETY: We already panicked for zero, and ensured by construction
         // that the length of the subslice is a multiple of N.
         let array_slice = unsafe { multiple_of_n.as_chunks_unchecked() };
@@ -1487,8 +1489,10 @@ impl<T> [T] {
     #[must_use]
     pub const fn as_chunks_mut<const N: usize>(&mut self) -> (&mut [[T; N]], &mut [T]) {
         assert!(N != 0, "chunk size must be non-zero");
-        let len = self.len() / N;
-        let (multiple_of_n, remainder) = self.split_at_mut(len * N);
+        let len_rounded_down = self.len() / N * N;
+        // SAFETY: The rounded-down value is always the same or smaller than the
+        // original length, and thus must be in-bounds of the slice.
+        let (multiple_of_n, remainder) = unsafe { self.split_at_mut_unchecked(len_rounded_down) };
         // SAFETY: We already panicked for zero, and ensured by construction
         // that the length of the subslice is a multiple of N.
         let array_slice = unsafe { multiple_of_n.as_chunks_unchecked_mut() };
diff --git a/library/profiler_builtins/Cargo.toml b/library/profiler_builtins/Cargo.toml
index 937149f8e86..5b10fb5a2bd 100644
--- a/library/profiler_builtins/Cargo.toml
+++ b/library/profiler_builtins/Cargo.toml
@@ -13,4 +13,4 @@ core = { path = "../core" }
 compiler_builtins = { version = "0.1.0", features = ['rustc-dep-of-std'] }
 
 [build-dependencies]
-cc = "1.0.90"
+cc = "1.0.97"
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 409ead0e284..77e94365b08 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -408,6 +408,9 @@ impl File {
     ///
     /// This function will create a file if it does not exist, or return an error if it does. This
     /// way, if the call succeeds, the file returned is guaranteed to be new.
+    /// If a file exists at the target location, creating a new file will fail with [`AlreadyExists`]
+    /// or another error based on the situation. See [`OpenOptions::open`] for a
+    /// non-exhaustive list of likely errors.
     ///
     /// This option is useful because it is atomic. Otherwise between checking whether a file
     /// exists and creating a new one, the file may have been created by another process (a TOCTOU
@@ -416,6 +419,8 @@ impl File {
     /// This can also be written using
     /// `File::options().read(true).write(true).create_new(true).open(...)`.
     ///
+    /// [`AlreadyExists`]: crate::io::ErrorKind::AlreadyExists
+    ///
     /// # Examples
     ///
     /// ```no_run
@@ -1071,6 +1076,9 @@ impl OpenOptions {
     ///
     /// No file is allowed to exist at the target location, also no (dangling) symlink. In this
     /// way, if the call succeeds, the file returned is guaranteed to be new.
+    /// If a file exists at the target location, creating a new file will fail with [`AlreadyExists`]
+    /// or another error based on the situation. See [`OpenOptions::open`] for a
+    /// non-exhaustive list of likely errors.
     ///
     /// This option is useful because it is atomic. Otherwise between checking
     /// whether a file exists and creating a new one, the file may have been
@@ -1084,6 +1092,7 @@ impl OpenOptions {
     ///
     /// [`.create()`]: OpenOptions::create
     /// [`.truncate()`]: OpenOptions::truncate
+    /// [`AlreadyExists`]: io::ErrorKind::AlreadyExists
     ///
     /// # Examples
     ///
@@ -2258,7 +2267,7 @@ pub fn canonicalize<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
 /// # Platform-specific behavior
 ///
 /// This function currently corresponds to the `mkdir` function on Unix
-/// and the `CreateDirectory` function on Windows.
+/// and the `CreateDirectoryW` function on Windows.
 /// Note that, this [may change in the future][changes].
 ///
 /// [changes]: io#platform-specific-behavior
@@ -2298,10 +2307,14 @@ pub fn create_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
 /// Recursively create a directory and all of its parent components if they
 /// are missing.
 ///
+/// If this function returns an error, some of the parent components might have
+/// been created already.
+///
 /// # Platform-specific behavior
 ///
-/// This function currently corresponds to the `mkdir` function on Unix
-/// and the `CreateDirectory` function on Windows.
+/// This function currently corresponds to multiple calls to the `mkdir`
+/// function on Unix and the `CreateDirectoryW` function on Windows.
+///
 /// Note that, this [may change in the future][changes].
 ///
 /// [changes]: io#platform-specific-behavior
diff --git a/library/std/src/os/unix/net/listener.rs b/library/std/src/os/unix/net/listener.rs
index 7e53acbc387..a55199c82fc 100644
--- a/library/std/src/os/unix/net/listener.rs
+++ b/library/std/src/os/unix/net/listener.rs
@@ -81,21 +81,25 @@ impl UnixListener {
             ))]
             const backlog: core::ffi::c_int = 128;
             #[cfg(any(
+                // Silently capped to `/proc/sys/net/core/somaxconn`.
                 target_os = "linux",
+                // Silently capped to `kern.ipc.soacceptqueue`.
                 target_os = "freebsd",
+                // Silently capped to `kern.somaxconn sysctl`.
                 target_os = "openbsd",
-                target_os = "macos"
+                // Silently capped to the default 128.
+                target_vendor = "apple",
             ))]
             const backlog: core::ffi::c_int = -1;
             #[cfg(not(any(
                 target_os = "windows",
                 target_os = "redox",
+                target_os = "espidf",
+                target_os = "horizon",
                 target_os = "linux",
                 target_os = "freebsd",
                 target_os = "openbsd",
-                target_os = "macos",
-                target_os = "espidf",
-                target_os = "horizon"
+                target_vendor = "apple",
             )))]
             const backlog: libc::c_int = libc::SOMAXCONN;
 
diff --git a/library/std/src/sys/pal/unix/alloc.rs b/library/std/src/sys/pal/unix/alloc.rs
index af0089978ec..9938c0bac25 100644
--- a/library/std/src/sys/pal/unix/alloc.rs
+++ b/library/std/src/sys/pal/unix/alloc.rs
@@ -13,7 +13,13 @@ unsafe impl GlobalAlloc for System {
         if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
             libc::malloc(layout.size()) as *mut u8
         } else {
-            #[cfg(target_os = "macos")]
+            // `posix_memalign` returns a non-aligned value if supplied a very
+            // large alignment on older versions of Apple's platforms (unknown
+            // exactly which version range, but the issue is definitely
+            // present in macOS 10.14 and iOS 13.3).
+            //
+            // <https://github.com/rust-lang/rust/issues/30170>
+            #[cfg(target_vendor = "apple")]
             {
                 if layout.align() > (1 << 31) {
                     return ptr::null_mut();
diff --git a/library/std/src/sys/pal/unix/fd.rs b/library/std/src/sys/pal/unix/fd.rs
index 203c7180001..1701717db59 100644
--- a/library/std/src/sys/pal/unix/fd.rs
+++ b/library/std/src/sys/pal/unix/fd.rs
@@ -33,14 +33,15 @@ pub struct FileDesc(OwnedFd);
 // with the man page quoting that if the count of bytes to read is
 // greater than `SSIZE_MAX` the result is "unspecified".
 //
-// On macOS, however, apparently the 64-bit libc is either buggy or
+// On Apple targets however, apparently the 64-bit libc is either buggy or
 // intentionally showing odd behavior by rejecting any read with a size
 // larger than or equal to INT_MAX. To handle both of these the read
 // size is capped on both platforms.
-#[cfg(target_os = "macos")]
-const READ_LIMIT: usize = libc::c_int::MAX as usize - 1;
-#[cfg(not(target_os = "macos"))]
-const READ_LIMIT: usize = libc::ssize_t::MAX as usize;
+const READ_LIMIT: usize = if cfg!(target_vendor = "apple") {
+    libc::c_int::MAX as usize - 1
+} else {
+    libc::ssize_t::MAX as usize
+};
 
 #[cfg(any(
     target_os = "dragonfly",
diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs
index 32cdd13fbeb..fbbd40bfb79 100644
--- a/library/std/src/sys/pal/unix/fs.rs
+++ b/library/std/src/sys/pal/unix/fs.rs
@@ -1493,11 +1493,11 @@ impl fmt::Debug for File {
             readlink(&p).ok()
         }
 
-        #[cfg(target_os = "macos")]
+        #[cfg(target_vendor = "apple")]
         fn get_path(fd: c_int) -> Option<PathBuf> {
             // FIXME: The use of PATH_MAX is generally not encouraged, but it
-            // is inevitable in this case because macOS defines `fcntl` with
-            // `F_GETPATH` in terms of `MAXPATHLEN`, and there are no
+            // is inevitable in this case because Apple targets define `fcntl`
+            // with `F_GETPATH` in terms of `MAXPATHLEN`, and there are no
             // alternatives. If a better method is invented, it should be used
             // instead.
             let mut buf = vec![0; libc::PATH_MAX as usize];
@@ -1538,12 +1538,12 @@ impl fmt::Debug for File {
 
         #[cfg(not(any(
             target_os = "linux",
-            target_os = "macos",
             target_os = "vxworks",
             all(target_os = "freebsd", target_arch = "x86_64"),
             target_os = "netbsd",
             target_os = "illumos",
-            target_os = "solaris"
+            target_os = "solaris",
+            target_vendor = "apple",
         )))]
         fn get_path(_fd: c_int) -> Option<PathBuf> {
             // FIXME(#24570): implement this for other Unix platforms
@@ -1552,12 +1552,12 @@ impl fmt::Debug for File {
 
         #[cfg(any(
             target_os = "linux",
-            target_os = "macos",
             target_os = "freebsd",
             target_os = "hurd",
             target_os = "netbsd",
             target_os = "openbsd",
-            target_os = "vxworks"
+            target_os = "vxworks",
+            target_vendor = "apple",
         ))]
         fn get_mode(fd: c_int) -> Option<(bool, bool)> {
             let mode = unsafe { libc::fcntl(fd, libc::F_GETFL) };
@@ -1574,12 +1574,12 @@ impl fmt::Debug for File {
 
         #[cfg(not(any(
             target_os = "linux",
-            target_os = "macos",
             target_os = "freebsd",
             target_os = "hurd",
             target_os = "netbsd",
             target_os = "openbsd",
-            target_os = "vxworks"
+            target_os = "vxworks",
+            target_vendor = "apple",
         )))]
         fn get_mode(_fd: c_int) -> Option<(bool, bool)> {
             // FIXME(#24570): implement this for other Unix platforms
diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs
index 1ac5729c02f..21f233e2262 100644
--- a/library/std/src/sys/pal/unix/mod.rs
+++ b/library/std/src/sys/pal/unix/mod.rs
@@ -63,11 +63,11 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
     args::init(argc, argv);
 
     // Normally, `thread::spawn` will call `Thread::set_name` but since this thread
-    // already exists, we have to call it ourselves. We only do this on macos
+    // already exists, we have to call it ourselves. We only do this on Apple targets
     // because some unix-like operating systems such as Linux share process-id and
     // thread-id for the main thread and so renaming the main thread will rename the
     // process and we only want to enable this on platforms we've tested.
-    if cfg!(target_os = "macos") {
+    if cfg!(target_vendor = "apple") {
         thread::Thread::set_name(&c"main");
     }
 
diff --git a/library/std/src/sys/pal/unix/net.rs b/library/std/src/sys/pal/unix/net.rs
index 7237989c905..b8dc1538a63 100644
--- a/library/std/src/sys/pal/unix/net.rs
+++ b/library/std/src/sys/pal/unix/net.rs
@@ -86,7 +86,14 @@ impl Socket {
                     // flag to atomically create the socket and set it as
                     // CLOEXEC. On Linux this was added in 2.6.27.
                     let fd = cvt(libc::socket(fam, ty | libc::SOCK_CLOEXEC, 0))?;
-                    Ok(Socket(FileDesc::from_raw_fd(fd)))
+                    let socket = Socket(FileDesc::from_raw_fd(fd));
+
+                    // DragonFlyBSD, FreeBSD and NetBSD use `SO_NOSIGPIPE` as a `setsockopt`
+                    // flag to disable `SIGPIPE` emission on socket.
+                    #[cfg(any(target_os = "freebsd", target_os = "netbsd", target_os = "dragonfly"))]
+                    setsockopt(&socket, libc::SOL_SOCKET, libc::SO_NOSIGPIPE, 1)?;
+
+                    Ok(socket)
                 } else {
                     let fd = cvt(libc::socket(fam, ty, 0))?;
                     let fd = FileDesc::from_raw_fd(fd);
diff --git a/library/std/src/sys/pal/unix/thread_parking.rs b/library/std/src/sys/pal/unix/thread_parking.rs
index 66ffc006057..1366410b71e 100644
--- a/library/std/src/sys/pal/unix/thread_parking.rs
+++ b/library/std/src/sys/pal/unix/thread_parking.rs
@@ -5,7 +5,7 @@
 use crate::ffi::{c_int, c_void};
 use crate::ptr;
 use crate::time::Duration;
-use libc::{_lwp_self, clockid_t, lwpid_t, time_t, timespec, CLOCK_MONOTONIC};
+use libc::{_lwp_self, c_long, clockid_t, lwpid_t, time_t, timespec, CLOCK_MONOTONIC};
 
 extern "C" {
     fn ___lwp_park60(
@@ -38,7 +38,7 @@ pub fn park_timeout(dur: Duration, hint: usize) {
         // Saturate so that the operation will definitely time out
         // (even if it is after the heat death of the universe).
         tv_sec: dur.as_secs().try_into().ok().unwrap_or(time_t::MAX),
-        tv_nsec: dur.subsec_nanos().into(),
+        tv_nsec: dur.subsec_nanos() as c_long,
     };
 
     // Timeout needs to be mutable since it is modified on NetBSD 9.0 and
diff --git a/library/std/src/sys/personality/dwarf/eh.rs b/library/std/src/sys/personality/dwarf/eh.rs
index 3f3615ea3e0..ff88ef4e0e1 100644
--- a/library/std/src/sys/personality/dwarf/eh.rs
+++ b/library/std/src/sys/personality/dwarf/eh.rs
@@ -54,7 +54,14 @@ pub enum EHAction {
     Terminate,
 }
 
-pub const USING_SJLJ_EXCEPTIONS: bool = cfg!(all(target_os = "ios", target_arch = "arm"));
+/// 32-bit Apple ARM uses SjLj exceptions, except for watchOS.
+///
+/// I.e. iOS and tvOS, as those are the only Apple OSes that used 32-bit ARM
+/// devices.
+///
+/// <https://github.com/llvm/llvm-project/blob/llvmorg-18.1.4/clang/lib/Driver/ToolChains/Darwin.cpp#L3107-L3119>
+pub const USING_SJLJ_EXCEPTIONS: bool =
+    cfg!(all(target_vendor = "apple", not(target_os = "watchos"), target_arch = "arm"));
 
 pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result<EHAction, ()> {
     if lsda.is_null() {
diff --git a/library/std/src/sys/personality/gcc.rs b/library/std/src/sys/personality/gcc.rs
index b0f744dd966..0dc53550ca9 100644
--- a/library/std/src/sys/personality/gcc.rs
+++ b/library/std/src/sys/personality/gcc.rs
@@ -92,11 +92,12 @@ const UNWIND_DATA_REG: (i32, i32) = (4, 5); // a0, a1
 // https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c
 
 cfg_if::cfg_if! {
-    if #[cfg(all(target_arch = "arm", not(target_os = "ios"), not(target_os = "tvos"), not(target_os = "watchos"), not(target_os = "visionos"), not(target_os = "netbsd")))] {
+    if #[cfg(all(not(all(target_vendor = "apple", not(target_os = "watchos"))), target_arch = "arm", not(target_os = "netbsd")))] {
         // ARM EHABI personality routine.
         // https://web.archive.org/web/20190728160938/https://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf
         //
-        // iOS uses the default routine instead since it uses SjLj unwinding.
+        // Apple 32-bit ARM (but not watchOS) uses the default routine instead
+        // since it uses SjLj unwinding.
         #[lang = "eh_personality"]
         unsafe extern "C" fn rust_eh_personality(
             state: uw::_Unwind_State,
diff --git a/tests/ui/stdlib-unit-tests/builtin-clone.rs b/library/std/tests/builtin-clone.rs
index 47c00ede0e9..66b57130c95 100644
--- a/tests/ui/stdlib-unit-tests/builtin-clone.rs
+++ b/library/std/tests/builtin-clone.rs
@@ -1,4 +1,3 @@
-//@ run-pass
 // Test that `Clone` is correctly implemented for builtin types.
 // Also test that cloning an array or a tuple is done right, i.e.
 // each component is cloned.
@@ -7,7 +6,7 @@ fn test_clone<T: Clone>(arg: T) {
     let _ = arg.clone();
 }
 
-fn foo() { }
+fn foo() {}
 
 #[derive(Debug, PartialEq, Eq)]
 struct S(i32);
@@ -18,7 +17,8 @@ impl Clone for S {
     }
 }
 
-fn main() {
+#[test]
+fn builtin_clone() {
     test_clone(foo);
     test_clone([1; 56]);
     test_clone((1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1));
@@ -27,19 +27,7 @@ fn main() {
     let b = [S(1), S(2), S(3)];
     assert_eq!(b, a.clone());
 
-    let a = (
-        (S(1), S(0)),
-        (
-            (S(0), S(0), S(1)),
-            S(0)
-        )
-    );
-    let b = (
-        (S(2), S(1)),
-        (
-            (S(1), S(1), S(2)),
-            S(1)
-        )
-    );
+    let a = ((S(1), S(0)), ((S(0), S(0), S(1)), S(0)));
+    let b = ((S(2), S(1)), ((S(1), S(1), S(2)), S(1)));
     assert_eq!(b, a.clone());
 }
diff --git a/library/std/tests/eq-multidispatch.rs b/library/std/tests/eq-multidispatch.rs
new file mode 100644
index 00000000000..96e440f85e0
--- /dev/null
+++ b/library/std/tests/eq-multidispatch.rs
@@ -0,0 +1,51 @@
+#[derive(PartialEq, Debug)]
+struct Bar;
+#[derive(Debug)]
+struct Baz;
+#[derive(Debug)]
+struct Foo;
+#[derive(Debug)]
+struct Fu;
+
+impl PartialEq for Baz {
+    fn eq(&self, _: &Baz) -> bool {
+        true
+    }
+}
+
+impl PartialEq<Fu> for Foo {
+    fn eq(&self, _: &Fu) -> bool {
+        true
+    }
+}
+
+impl PartialEq<Foo> for Fu {
+    fn eq(&self, _: &Foo) -> bool {
+        true
+    }
+}
+
+impl PartialEq<Bar> for Foo {
+    fn eq(&self, _: &Bar) -> bool {
+        false
+    }
+}
+
+impl PartialEq<Foo> for Bar {
+    fn eq(&self, _: &Foo) -> bool {
+        false
+    }
+}
+
+#[test]
+fn eq_multidispatch() {
+    assert!(Bar != Foo);
+    assert!(Foo != Bar);
+
+    assert_eq!(Bar, Bar);
+
+    assert_eq!(Baz, Baz);
+
+    assert_eq!(Foo, Fu);
+    assert_eq!(Fu, Foo);
+}
diff --git a/tests/ui/stdlib-unit-tests/istr.rs b/library/std/tests/istr.rs
index f6298919425..9a127ae803e 100644
--- a/tests/ui/stdlib-unit-tests/istr.rs
+++ b/library/std/tests/istr.rs
@@ -1,5 +1,4 @@
-//@ run-pass
-
+#[test]
 fn test_stack_assign() {
     let s: String = "a".to_string();
     println!("{}", s.clone());
@@ -9,8 +8,12 @@ fn test_stack_assign() {
     assert!((s != u));
 }
 
-fn test_heap_lit() { "a big string".to_string(); }
+#[test]
+fn test_heap_lit() {
+    "a big string".to_string();
+}
 
+#[test]
 fn test_heap_assign() {
     let s: String = "a big ol' string".to_string();
     let t: String = "a big ol' string".to_string();
@@ -19,11 +22,13 @@ fn test_heap_assign() {
     assert!((s != u));
 }
 
+#[test]
 fn test_heap_log() {
     let s = "a big ol' string".to_string();
     println!("{}", s);
 }
 
+#[test]
 fn test_append() {
     let mut s = String::new();
     s.push_str("a");
@@ -41,11 +46,3 @@ fn test_append() {
     s.push_str("&tea");
     assert_eq!(s, "coffee&tea");
 }
-
-pub fn main() {
-    test_stack_assign();
-    test_heap_lit();
-    test_heap_assign();
-    test_heap_log();
-    test_append();
-}
diff --git a/tests/ui/stdlib-unit-tests/log-knows-the-names-of-variants-in-std.rs b/library/std/tests/log-knows-the-names-of-variants-in-std.rs
index 8f351b2b40b..118bee62018 100644
--- a/tests/ui/stdlib-unit-tests/log-knows-the-names-of-variants-in-std.rs
+++ b/library/std/tests/log-knows-the-names-of-variants-in-std.rs
@@ -1,18 +1,18 @@
-//@ run-pass
-
 #![allow(non_camel_case_types)]
 #![allow(dead_code)]
+
 #[derive(Clone, Debug)]
 enum foo {
-  a(usize),
-  b(String),
+    a(usize),
+    b(String),
 }
 
 fn check_log<T: std::fmt::Debug>(exp: String, v: T) {
     assert_eq!(exp, format!("{:?}", v));
 }
 
-pub fn main() {
+#[test]
+fn log_knows_the_names_of_variants_in_std() {
     let mut x = Some(foo::a(22));
     let exp = "Some(a(22))".to_string();
     let act = format!("{:?}", x);
diff --git a/tests/ui/stdlib-unit-tests/minmax-stability-issue-23687.rs b/library/std/tests/minmax-stability-issue-23687.rs
index bf42347df0b..119c520de8f 100644
--- a/tests/ui/stdlib-unit-tests/minmax-stability-issue-23687.rs
+++ b/library/std/tests/minmax-stability-issue-23687.rs
@@ -1,12 +1,10 @@
-//@ run-pass
-
-use std::fmt::Debug;
 use std::cmp::{self, Ordering};
+use std::fmt::Debug;
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
 struct Foo {
     n: u8,
-    name: &'static str
+    name: &'static str,
 }
 
 impl PartialOrd for Foo {
@@ -21,7 +19,8 @@ impl Ord for Foo {
     }
 }
 
-fn main() {
+#[test]
+fn minmax_stability() {
     let a = Foo { n: 4, name: "a" };
     let b = Foo { n: 4, name: "b" };
     let c = Foo { n: 8, name: "c" };
diff --git a/tests/ui/stdlib-unit-tests/seq-compare.rs b/library/std/tests/seq-compare.rs
index 1be0569e17c..221f1c7cabd 100644
--- a/tests/ui/stdlib-unit-tests/seq-compare.rs
+++ b/library/std/tests/seq-compare.rs
@@ -1,6 +1,5 @@
-//@ run-pass
-
-pub fn main() {
+#[test]
+fn seq_compare() {
     assert!(("hello".to_string() < "hellr".to_string()));
     assert!(("hello ".to_string() > "hello".to_string()));
     assert!(("hello".to_string() != "there".to_string()));
diff --git a/tests/ui/std/slice-from-array-issue-113238.rs b/library/std/tests/slice-from-array-issue-113238.rs
index 44f2d7a9478..97aba4fec01 100644
--- a/tests/ui/std/slice-from-array-issue-113238.rs
+++ b/library/std/tests/slice-from-array-issue-113238.rs
@@ -1,9 +1,8 @@
-//@ check-pass
-
 // This intends to use the unsizing coercion from array to slice, but it only
 // works if we resolve `<&[u8]>::from` as the reflexive `From<T> for T`. In
 // #113238, we found that gimli had added its own `From<EndianSlice> for &[u8]`
 // that affected all `std/backtrace` users.
-fn main() {
+#[test]
+fn slice_from_array() {
     let _ = <&[u8]>::from(&[]);
 }
diff --git a/tests/ui/stdlib-unit-tests/issue-21058.rs b/library/std/tests/type-name-unsized.rs
index 0e04f1e21b8..2974668b2ce 100644
--- a/tests/ui/stdlib-unit-tests/issue-21058.rs
+++ b/library/std/tests/type-name-unsized.rs
@@ -1,10 +1,13 @@
-//@ run-pass
 #![allow(dead_code)]
 
 use std::fmt::Debug;
 
 struct NT(str);
-struct DST { a: u32, b: str }
+
+struct DST {
+    a: u32,
+    b: str,
+}
 
 macro_rules! check {
     (val: $ty_of:expr, $expected:expr) => {
@@ -15,23 +18,24 @@ macro_rules! check {
     };
 }
 
-fn main() {
-    // type_name should support unsized types
+/// Tests that [`std::any::type_name`] supports unsized types.
+#[test]
+fn type_name_unsized() {
     check!([u8], "[u8]");
     check!(str, "str");
     check!(dyn Send, "dyn core::marker::Send");
-    check!(NT, "issue_21058::NT");
-    check!(DST, "issue_21058::DST");
+    check!(NT, "type_name_unsized::NT");
+    check!(DST, "type_name_unsized::DST");
     check!(&i32, "&i32");
     check!(&'static i32, "&i32");
     check!((i32, u32), "(i32, u32)");
-    check!(val: foo(), "issue_21058::Foo");
-    check!(val: Foo::new, "issue_21058::Foo::new");
+    check!(val: foo(), "type_name_unsized::Foo");
+    check!(val: Foo::new, "type_name_unsized::Foo::new");
     check!(val:
         <Foo as Debug>::fmt,
-        "<issue_21058::Foo as core::fmt::Debug>::fmt"
+        "<type_name_unsized::Foo as core::fmt::Debug>::fmt"
     );
-    check!(val: || {}, "issue_21058::main::{{closure}}");
+    check!(val: || {}, "type_name_unsized::type_name_unsized::{{closure}}");
     bar::<i32>();
 }
 
@@ -56,7 +60,9 @@ fn type_name_of_val<T>(_: T) -> &'static str {
 struct Foo;
 
 impl Foo {
-    fn new() -> Self { Foo }
+    fn new() -> Self {
+        Foo
+    }
 }
 
 fn foo() -> impl Debug {
diff --git a/tests/ui/stdlib-unit-tests/volatile-fat-ptr.rs b/library/std/tests/volatile-fat-ptr.rs
index ef227a9134d..b005c12c618 100644
--- a/tests/ui/stdlib-unit-tests/volatile-fat-ptr.rs
+++ b/library/std/tests/volatile-fat-ptr.rs
@@ -1,10 +1,10 @@
-//@ run-pass
-
 #![allow(stable_features)]
 #![feature(volatile)]
+
 use std::ptr::{read_volatile, write_volatile};
 
-fn main() {
+#[test]
+fn volatile_fat_ptr() {
     let mut x: &'static str = "test";
     unsafe {
         let a = read_volatile(&x);
diff --git a/library/test/src/bench.rs b/library/test/src/bench.rs
index 23925e6ea72..9a5dc351f6d 100644
--- a/library/test/src/bench.rs
+++ b/library/test/src/bench.rs
@@ -68,12 +68,12 @@ pub fn fmt_bench_samples(bs: &BenchSamples) -> String {
     use std::fmt::Write;
     let mut output = String::new();
 
-    let median = bs.ns_iter_summ.median as usize;
-    let deviation = (bs.ns_iter_summ.max - bs.ns_iter_summ.min) as usize;
+    let median = bs.ns_iter_summ.median;
+    let deviation = bs.ns_iter_summ.max - bs.ns_iter_summ.min;
 
     write!(
         output,
-        "{:>11} ns/iter (+/- {})",
+        "{:>14} ns/iter (+/- {})",
         fmt_thousands_sep(median, ','),
         fmt_thousands_sep(deviation, ',')
     )
@@ -85,24 +85,27 @@ pub fn fmt_bench_samples(bs: &BenchSamples) -> String {
 }
 
 // Format a number with thousands separators
-fn fmt_thousands_sep(mut n: usize, sep: char) -> String {
+fn fmt_thousands_sep(mut n: f64, sep: char) -> String {
     use std::fmt::Write;
     let mut output = String::new();
     let mut trailing = false;
     for &pow in &[9, 6, 3, 0] {
         let base = 10_usize.pow(pow);
-        if pow == 0 || trailing || n / base != 0 {
-            if !trailing {
-                write!(output, "{}", n / base).unwrap();
-            } else {
-                write!(output, "{:03}", n / base).unwrap();
+        if pow == 0 || trailing || n / base as f64 >= 1.0 {
+            match (pow, trailing) {
+                // modern CPUs can execute multiple instructions per nanosecond
+                // e.g. benching an ADD takes about 0.25ns.
+                (0, true) => write!(output, "{:06.2}", n / base as f64).unwrap(),
+                (0, false) => write!(output, "{:.2}", n / base as f64).unwrap(),
+                (_, true) => write!(output, "{:03}", n as usize / base).unwrap(),
+                _ => write!(output,  "{}", n as usize / base).unwrap()
             }
             if pow != 0 {
                 output.push(sep);
             }
             trailing = true;
         }
-        n %= base;
+        n %= base as f64;
     }
 
     output
diff --git a/library/test/src/formatters/json.rs b/library/test/src/formatters/json.rs
index 47c4e7757e4..6245aae17c4 100644
--- a/library/test/src/formatters/json.rs
+++ b/library/test/src/formatters/json.rs
@@ -167,8 +167,8 @@ impl<T: Write> OutputFormatter for JsonFormatter<T> {
             ),
 
             TestResult::TrBench(ref bs) => {
-                let median = bs.ns_iter_summ.median as usize;
-                let deviation = (bs.ns_iter_summ.max - bs.ns_iter_summ.min) as usize;
+                let median = bs.ns_iter_summ.median;
+                let deviation = bs.ns_iter_summ.max - bs.ns_iter_summ.min;
 
                 let mbps = if bs.mb_s == 0 {
                     String::new()
diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs
index e34e73a3516..e5e28f32e4d 100644
--- a/library/unwind/src/libunwind.rs
+++ b/library/unwind/src/libunwind.rs
@@ -33,10 +33,10 @@ pub const unwinder_private_data_size: usize = 2;
 #[cfg(all(target_arch = "x86_64", target_os = "windows"))]
 pub const unwinder_private_data_size: usize = 6;
 
-#[cfg(all(target_arch = "arm", not(any(target_os = "ios", target_os = "watchos"))))]
+#[cfg(all(target_arch = "arm", not(all(target_vendor = "apple", not(target_os = "watchos")))))]
 pub const unwinder_private_data_size: usize = 20;
 
-#[cfg(all(target_arch = "arm", any(target_os = "ios", target_os = "watchos")))]
+#[cfg(all(target_arch = "arm", all(target_vendor = "apple", not(target_os = "watchos"))))]
 pub const unwinder_private_data_size: usize = 5;
 
 #[cfg(all(target_arch = "aarch64", target_pointer_width = "64", not(target_os = "windows")))]
@@ -123,7 +123,7 @@ extern "C" {
 }
 
 cfg_if::cfg_if! {
-if #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos", target_os = "netbsd", not(target_arch = "arm")))] {
+if #[cfg(any(all(target_vendor = "apple", not(target_os = "watchos")), target_os = "netbsd", not(target_arch = "arm")))] {
     // Not ARM EHABI
     #[repr(C)]
     #[derive(Copy, Clone, PartialEq)]
@@ -258,8 +258,15 @@ if #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos", targe
 } // cfg_if!
 
 cfg_if::cfg_if! {
-if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] {
-    // Not 32-bit iOS
+if #[cfg(all(target_vendor = "apple", not(target_os = "watchos"), target_arch = "arm"))] {
+    // 32-bit ARM Apple (except for watchOS) uses SjLj and does not provide
+    // _Unwind_Backtrace()
+    extern "C-unwind" {
+        pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
+    }
+
+    pub use _Unwind_SjLj_RaiseException as _Unwind_RaiseException;
+} else {
     #[cfg_attr(
         all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")),
         link(name = "unwind", kind = "static", modifiers = "-bundle")
@@ -276,13 +283,6 @@ if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] {
                                  trace_argument: *mut c_void)
                                  -> _Unwind_Reason_Code;
     }
-} else {
-    // 32-bit iOS uses SjLj and does not provide _Unwind_Backtrace()
-    extern "C-unwind" {
-        pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
-    }
-
-    pub use _Unwind_SjLj_RaiseException as _Unwind_RaiseException;
 }
 } // cfg_if!
 
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
index 9c2b7500a20..4a5d768961f 100644
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
@@ -98,9 +98,9 @@ dependencies = [
 
 [[package]]
 name = "cc"
-version = "1.0.73"
+version = "1.0.97"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
+checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4"
 
 [[package]]
 name = "cfg-if"
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index c7a513d0890..ca0d1fa5bd0 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -33,10 +33,10 @@ path = "src/bin/sccache-plus-cl.rs"
 test = false
 
 [dependencies]
-# Most of the time updating these dependencies requires modifications
-# to the bootstrap codebase; otherwise, some targets will fail. That's
-# why these dependencies are explicitly pinned.
-cc = "=1.0.73"
+# Most of the time updating these dependencies requires modifications to the
+# bootstrap codebase(e.g., https://github.com/rust-lang/rust/issues/124565);
+# otherwise, some targets will fail. That's why these dependencies are explicitly pinned.
+cc = "=1.0.97"
 cmake = "=0.1.48"
 
 build_helper = { path = "../tools/build_helper" }
diff --git a/src/bootstrap/src/bin/rustc.rs b/src/bootstrap/src/bin/rustc.rs
index 4b182a7a693..d2274199177 100644
--- a/src/bootstrap/src/bin/rustc.rs
+++ b/src/bootstrap/src/bin/rustc.rs
@@ -91,12 +91,13 @@ fn main() {
         rustc_real
     };
 
-    let mut cmd = if let Some(wrapper) = env::var_os("RUSTC_WRAPPER_REAL") {
-        let mut cmd = Command::new(wrapper);
-        cmd.arg(rustc_driver);
-        cmd
-    } else {
-        Command::new(rustc_driver)
+    let mut cmd = match env::var_os("RUSTC_WRAPPER_REAL") {
+        Some(wrapper) if !wrapper.is_empty() => {
+            let mut cmd = Command::new(wrapper);
+            cmd.arg(rustc_driver);
+            cmd
+        }
+        _ => Command::new(rustc_driver),
     };
     cmd.args(&args).env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
 
diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs
index d4473e24039..3af1a05caa8 100644
--- a/src/bootstrap/src/core/build_steps/llvm.rs
+++ b/src/bootstrap/src/core/build_steps/llvm.rs
@@ -20,7 +20,9 @@ use std::sync::OnceLock;
 use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
 use crate::core::config::{Config, TargetSelection};
 use crate::utils::channel;
-use crate::utils::helpers::{self, exe, get_clang_cl_resource_dir, output, t, up_to_date};
+use crate::utils::helpers::{
+    self, exe, get_clang_cl_resource_dir, output, t, unhashed_basename, up_to_date,
+};
 use crate::{generate_smart_stamp_hash, CLang, GitRepo, Kind};
 
 use build_helper::ci::CiEnv;
@@ -506,7 +508,7 @@ impl Step for Llvm {
             cfg.define("LLVM_VERSION_SUFFIX", suffix);
         }
 
-        configure_cmake(builder, target, &mut cfg, true, ldflags, &[]);
+        configure_cmake(builder, target, &mut cfg, true, ldflags, &[], &[]);
         configure_llvm(builder, target, &mut cfg);
 
         for (key, val) in &builder.config.llvm_build_config {
@@ -596,6 +598,7 @@ fn configure_cmake(
     use_compiler_launcher: bool,
     mut ldflags: LdFlags,
     extra_compiler_flags: &[&str],
+    suppressed_compiler_flag_prefixes: &[&str],
 ) {
     // Do not print installation messages for up-to-date files.
     // LLVM and LLD builds can produce a lot of those and hit CI limits on log size.
@@ -729,7 +732,17 @@ fn configure_cmake(
     }
 
     cfg.build_arg("-j").build_arg(builder.jobs().to_string());
-    let mut cflags: OsString = builder.cflags(target, GitRepo::Llvm, CLang::C).join(" ").into();
+    let mut cflags: OsString = builder
+        .cflags(target, GitRepo::Llvm, CLang::C)
+        .into_iter()
+        .filter(|flag| {
+            !suppressed_compiler_flag_prefixes
+                .iter()
+                .any(|suppressed_prefix| flag.starts_with(suppressed_prefix))
+        })
+        .collect::<Vec<String>>()
+        .join(" ")
+        .into();
     if let Some(ref s) = builder.config.llvm_cflags {
         cflags.push(" ");
         cflags.push(s);
@@ -742,7 +755,17 @@ fn configure_cmake(
         cflags.push(&format!(" {flag}"));
     }
     cfg.define("CMAKE_C_FLAGS", cflags);
-    let mut cxxflags: OsString = builder.cflags(target, GitRepo::Llvm, CLang::Cxx).join(" ").into();
+    let mut cxxflags: OsString = builder
+        .cflags(target, GitRepo::Llvm, CLang::Cxx)
+        .into_iter()
+        .filter(|flag| {
+            !suppressed_compiler_flag_prefixes
+                .iter()
+                .any(|suppressed_prefix| flag.starts_with(suppressed_prefix))
+        })
+        .collect::<Vec<String>>()
+        .join(" ")
+        .into();
     if let Some(ref s) = builder.config.llvm_cxxflags {
         cxxflags.push(" ");
         cxxflags.push(s);
@@ -921,7 +944,7 @@ impl Step for Lld {
             ldflags.push_all("-Wl,-rpath,'$ORIGIN/../../../'");
         }
 
-        configure_cmake(builder, target, &mut cfg, true, ldflags, &[]);
+        configure_cmake(builder, target, &mut cfg, true, ldflags, &[], &[]);
         configure_llvm(builder, target, &mut cfg);
 
         // Re-use the same flags as llvm to control the level of debug information
@@ -1022,6 +1045,12 @@ impl Step for Sanitizers {
         let use_compiler_launcher = !self.target.contains("apple-darwin");
         let extra_compiler_flags: &[&str] =
             if self.target.contains("apple") { &["-fembed-bitcode=off"] } else { &[] };
+        // Since v1.0.86, the cc crate adds -mmacosx-version-min to the default
+        // flags on MacOS. A long-standing bug in the CMake rules for compiler-rt
+        // causes architecture detection to be skipped when this flag is present,
+        // and compilation fails. https://github.com/llvm/llvm-project/issues/88780
+        let suppressed_compiler_flag_prefixes: &[&str] =
+            if self.target.contains("apple-darwin") { &["-mmacosx-version-min="] } else { &[] };
         configure_cmake(
             builder,
             self.target,
@@ -1029,6 +1058,7 @@ impl Step for Sanitizers {
             use_compiler_launcher,
             LdFlags::default(),
             extra_compiler_flags,
+            suppressed_compiler_flag_prefixes,
         );
 
         t!(fs::create_dir_all(&out_dir));
@@ -1190,7 +1220,7 @@ impl Step for CrtBeginEnd {
 
         let crtbegin_src = builder.src.join("src/llvm-project/compiler-rt/lib/builtins/crtbegin.c");
         let crtend_src = builder.src.join("src/llvm-project/compiler-rt/lib/builtins/crtend.c");
-        if up_to_date(&crtbegin_src, &out_dir.join("crtbegin.o"))
+        if up_to_date(&crtbegin_src, &out_dir.join("crtbeginS.o"))
             && up_to_date(&crtend_src, &out_dir.join("crtendS.o"))
         {
             return out_dir;
@@ -1222,10 +1252,15 @@ impl Step for CrtBeginEnd {
             .define("CRT_HAS_INITFINI_ARRAY", None)
             .define("EH_USE_FRAME_REGISTRY", None);
 
-        cfg.compile("crt");
+        let objs = cfg.compile_intermediates();
+        assert_eq!(objs.len(), 2);
+        for obj in objs {
+            let base_name = unhashed_basename(&obj);
+            assert!(base_name == "crtbegin" || base_name == "crtend");
+            t!(fs::copy(&obj, out_dir.join(format!("{}S.o", base_name))));
+            t!(fs::rename(&obj, out_dir.join(format!("{}.o", base_name))));
+        }
 
-        t!(fs::copy(out_dir.join("crtbegin.o"), out_dir.join("crtbeginS.o")));
-        t!(fs::copy(out_dir.join("crtend.o"), out_dir.join("crtendS.o")));
         out_dir
     }
 }
@@ -1372,9 +1407,9 @@ impl Step for Libunwind {
         for entry in fs::read_dir(&out_dir).unwrap() {
             let file = entry.unwrap().path().canonicalize().unwrap();
             if file.is_file() && file.extension() == Some(OsStr::new("o")) {
-                // file name starts with "Unwind-EHABI", "Unwind-seh" or "libunwind"
-                let file_name = file.file_name().unwrap().to_str().expect("UTF-8 file name");
-                if cpp_sources.iter().any(|f| file_name.starts_with(&f[..f.len() - 4])) {
+                // Object file name without the hash prefix is "Unwind-EHABI", "Unwind-seh" or "libunwind".
+                let base_name = unhashed_basename(&file);
+                if cpp_sources.iter().any(|f| *base_name == f[..f.len() - 4]) {
                     cc_cfg.object(&file);
                     count += 1;
                 }
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index 9a585a39e1e..360bd3840d4 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -1892,15 +1892,16 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
                     .to_string()
             })
         };
-        let lldb_exe = "lldb";
-        let lldb_version = Command::new(lldb_exe)
+
+        let lldb_exe = builder.config.lldb.clone().unwrap_or_else(|| PathBuf::from("lldb"));
+        let lldb_version = Command::new(&lldb_exe)
             .arg("--version")
             .output()
             .map(|output| String::from_utf8_lossy(&output.stdout).to_string())
             .ok();
         if let Some(ref vers) = lldb_version {
             cmd.arg("--lldb-version").arg(vers);
-            let lldb_python_dir = run(Command::new(lldb_exe).arg("-P")).ok();
+            let lldb_python_dir = run(Command::new(&lldb_exe).arg("-P")).ok();
             if let Some(ref dir) = lldb_python_dir {
                 cmd.arg("--lldb-python-dir").arg(dir);
             }
diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs
index 0ad6c959309..77fa46da0c9 100644
--- a/src/bootstrap/src/core/builder.rs
+++ b/src/bootstrap/src/core/builder.rs
@@ -88,6 +88,9 @@ pub trait Step: 'static + Clone + Debug + PartialEq + Eq + Hash {
 
     /// Primary function to execute this rule. Can call `builder.ensure()`
     /// with other steps to run those.
+    ///
+    /// This gets called twice during a normal `./x.py` execution: first
+    /// with `dry_run() == true`, and then for real.
     fn run(self, builder: &Builder<'_>) -> Self::Output;
 
     /// When bootstrap is passed a set of paths, this controls whether this rule
@@ -2221,13 +2224,8 @@ impl<'a> Builder<'a> {
         out
     }
 
-    /// Return paths of all submodules managed by git.
-    /// If the current checkout is not managed by git, returns an empty slice.
+    /// Return paths of all submodules.
     pub fn get_all_submodules(&self) -> &[String] {
-        if !self.rust_info().is_managed_git_subrepository() {
-            return &[];
-        }
-
         static SUBMODULES_PATHS: OnceLock<Vec<String>> = OnceLock::new();
 
         let init_submodules_paths = |src: &PathBuf| {
@@ -2554,7 +2552,12 @@ impl Cargo {
         // FIXME: the guard against msvc shouldn't need to be here
         if target.is_msvc() {
             if let Some(ref cl) = builder.config.llvm_clang_cl {
-                self.command.env("CC", cl).env("CXX", cl);
+                // FIXME: There is a bug in Clang 18 when building for ARM64:
+                // https://github.com/llvm/llvm-project/pull/81849. This is
+                // fixed in LLVM 19, but can't be backported.
+                if !target.starts_with("aarch64") && !target.starts_with("arm64ec") {
+                    self.command.env("CC", cl).env("CXX", cl);
+                }
             }
         } else {
             let ccache = builder.config.ccache.as_ref();
diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs
index caec46366dd..9898d495c02 100644
--- a/src/bootstrap/src/core/builder/tests.rs
+++ b/src/bootstrap/src/core/builder/tests.rs
@@ -32,7 +32,7 @@ fn configure_with_args(cmd: &[String], host: &[&str], target: &[&str]) -> Config
         .join(&thread::current().name().unwrap_or("unknown").replace(":", "-"));
     t!(fs::create_dir_all(&dir));
     config.out = dir;
-    config.build = TargetSelection::from_user("A");
+    config.build = TargetSelection::from_user("A-A");
     config.hosts = host.iter().map(|s| TargetSelection::from_user(s)).collect();
     config.targets = target.iter().map(|s| TargetSelection::from_user(s)).collect();
     config
@@ -53,27 +53,27 @@ fn run_build(paths: &[PathBuf], config: Config) -> Cache {
 fn check_cli<const N: usize>(paths: [&str; N]) {
     run_build(
         &paths.map(PathBuf::from),
-        configure_with_args(&paths.map(String::from), &["A"], &["A"]),
+        configure_with_args(&paths.map(String::from), &["A-A"], &["A-A"]),
     );
 }
 
 macro_rules! std {
     ($host:ident => $target:ident, stage = $stage:literal) => {
         compile::Std::new(
-            Compiler { host: TargetSelection::from_user(stringify!($host)), stage: $stage },
-            TargetSelection::from_user(stringify!($target)),
+            Compiler { host: TargetSelection::from_user(concat!(stringify!($host), "-", stringify!($host))), stage: $stage },
+            TargetSelection::from_user(concat!(stringify!($target), "-", stringify!($target))),
         )
     };
 }
 
 macro_rules! doc_std {
     ($host:ident => $target:ident, stage = $stage:literal) => {{
-        let config = configure("doc", &["A"], &["A"]);
+        let config = configure("doc", &["A-A"], &["A-A"]);
         let build = Build::new(config);
         let builder = Builder::new(&build);
         doc::Std::new(
             $stage,
-            TargetSelection::from_user(stringify!($target)),
+            TargetSelection::from_user(concat!(stringify!($target), "-", stringify!($target))),
             &builder,
             DocumentationFormat::Html,
         )
@@ -83,8 +83,8 @@ macro_rules! doc_std {
 macro_rules! rustc {
     ($host:ident => $target:ident, stage = $stage:literal) => {
         compile::Rustc::new(
-            Compiler { host: TargetSelection::from_user(stringify!($host)), stage: $stage },
-            TargetSelection::from_user(stringify!($target)),
+            Compiler { host: TargetSelection::from_user(concat!(stringify!($host), "-", stringify!($host))), stage: $stage },
+            TargetSelection::from_user(concat!(stringify!($target), "-", stringify!($target))),
         )
     };
 }
@@ -117,7 +117,7 @@ fn test_intersection() {
 
 #[test]
 fn validate_path_remap() {
-    let build = Build::new(configure("test", &["A"], &["A"]));
+    let build = Build::new(configure("test", &["A-A"], &["A-A"]));
 
     PATH_REMAP
         .iter()
@@ -130,7 +130,7 @@ fn validate_path_remap() {
 
 #[test]
 fn test_exclude() {
-    let mut config = configure("test", &["A"], &["A"]);
+    let mut config = configure("test", &["A-A"], &["A-A"]);
     config.skip = vec!["src/tools/tidy".into()];
     let cache = run_build(&[], config);
 
@@ -145,7 +145,7 @@ fn test_exclude() {
 fn test_exclude_kind() {
     let path = PathBuf::from("compiler/rustc_data_structures");
 
-    let mut config = configure("test", &["A"], &["A"]);
+    let mut config = configure("test", &["A-A"], &["A-A"]);
     // Ensure our test is valid, and `test::Rustc` would be run without the exclude.
     assert!(run_build(&[], config.clone()).contains::<test::CrateLibrustc>());
     // Ensure tests for rustc are not skipped.
@@ -159,13 +159,13 @@ fn test_exclude_kind() {
 #[test]
 fn alias_and_path_for_library() {
     let mut cache =
-        run_build(&["library".into(), "core".into()], configure("build", &["A"], &["A"]));
+        run_build(&["library".into(), "core".into()], configure("build", &["A-A"], &["A-A"]));
     assert_eq!(
         first(cache.all::<compile::Std>()),
         &[std!(A => A, stage = 0), std!(A => A, stage = 1)]
     );
 
-    let mut cache = run_build(&["library".into(), "core".into()], configure("doc", &["A"], &["A"]));
+    let mut cache = run_build(&["library".into(), "core".into()], configure("doc", &["A-A"], &["A-A"]));
     assert_eq!(first(cache.all::<doc::Std>()), &[doc_std!(A => A, stage = 0)]);
 }
 
@@ -177,9 +177,9 @@ mod defaults {
 
     #[test]
     fn build_default() {
-        let mut cache = run_build(&[], configure("build", &["A"], &["A"]));
+        let mut cache = run_build(&[], configure("build", &["A-A"], &["A-A"]));
 
-        let a = TargetSelection::from_user("A");
+        let a = TargetSelection::from_user("A-A");
         assert_eq!(
             first(cache.all::<compile::Std>()),
             &[std!(A => A, stage = 0), std!(A => A, stage = 1),]
@@ -197,10 +197,10 @@ mod defaults {
 
     #[test]
     fn build_stage_0() {
-        let config = Config { stage: 0, ..configure("build", &["A"], &["A"]) };
+        let config = Config { stage: 0, ..configure("build", &["A-A"], &["A-A"]) };
         let mut cache = run_build(&[], config);
 
-        let a = TargetSelection::from_user("A");
+        let a = TargetSelection::from_user("A-A");
         assert_eq!(first(cache.all::<compile::Std>()), &[std!(A => A, stage = 0)]);
         assert!(!cache.all::<compile::Assemble>().is_empty());
         assert_eq!(
@@ -214,11 +214,11 @@ mod defaults {
 
     #[test]
     fn build_cross_compile() {
-        let config = Config { stage: 1, ..configure("build", &["A", "B"], &["A", "B"]) };
+        let config = Config { stage: 1, ..configure("build", &["A-A", "B-B"], &["A-A", "B-B"]) };
         let mut cache = run_build(&[], config);
 
-        let a = TargetSelection::from_user("A");
-        let b = TargetSelection::from_user("B");
+        let a = TargetSelection::from_user("A-A");
+        let b = TargetSelection::from_user("B-B");
 
         // Ideally, this build wouldn't actually have `target: a`
         // rustdoc/rustcc/std here (the user only requested a host=B build, so
@@ -257,11 +257,11 @@ mod defaults {
 
     #[test]
     fn doc_default() {
-        let mut config = configure("doc", &["A"], &["A"]);
+        let mut config = configure("doc", &["A-A"], &["A-A"]);
         config.compiler_docs = true;
         config.cmd = Subcommand::Doc { open: false, json: false };
         let mut cache = run_build(&[], config);
-        let a = TargetSelection::from_user("A");
+        let a = TargetSelection::from_user("A-A");
 
         // error_index_generator uses stage 0 to share rustdoc artifacts with the
         // rustdoc tool.
@@ -291,9 +291,9 @@ mod dist {
 
     #[test]
     fn dist_baseline() {
-        let mut cache = run_build(&[], configure(&["A"], &["A"]));
+        let mut cache = run_build(&[], configure(&["A-A"], &["A-A"]));
 
-        let a = TargetSelection::from_user("A");
+        let a = TargetSelection::from_user("A-A");
 
         assert_eq!(first(cache.all::<dist::Docs>()), &[dist::Docs { host: a },]);
         assert_eq!(first(cache.all::<dist::Mingw>()), &[dist::Mingw { host: a },]);
@@ -315,10 +315,10 @@ mod dist {
 
     #[test]
     fn dist_with_targets() {
-        let mut cache = run_build(&[], configure(&["A"], &["A", "B"]));
+        let mut cache = run_build(&[], configure(&["A-A"], &["A-A", "B-B"]));
 
-        let a = TargetSelection::from_user("A");
-        let b = TargetSelection::from_user("B");
+        let a = TargetSelection::from_user("A-A");
+        let b = TargetSelection::from_user("B-B");
 
         assert_eq!(
             first(cache.all::<dist::Docs>()),
@@ -344,10 +344,10 @@ mod dist {
 
     #[test]
     fn dist_with_hosts() {
-        let mut cache = run_build(&[], configure(&["A", "B"], &["A", "B"]));
+        let mut cache = run_build(&[], configure(&["A-A", "B-B"], &["A-A", "B-B"]));
 
-        let a = TargetSelection::from_user("A");
-        let b = TargetSelection::from_user("B");
+        let a = TargetSelection::from_user("A-A");
+        let b = TargetSelection::from_user("B-B");
 
         assert_eq!(
             first(cache.all::<dist::Docs>()),
@@ -386,8 +386,8 @@ mod dist {
 
     #[test]
     fn dist_only_cross_host() {
-        let b = TargetSelection::from_user("B");
-        let mut config = configure(&["A", "B"], &["A", "B"]);
+        let b = TargetSelection::from_user("B-B");
+        let mut config = configure(&["A-A", "B-B"], &["A-A", "B-B"]);
         config.docs = false;
         config.extended = true;
         config.hosts = vec![b];
@@ -405,11 +405,11 @@ mod dist {
 
     #[test]
     fn dist_with_targets_and_hosts() {
-        let mut cache = run_build(&[], configure(&["A", "B"], &["A", "B", "C"]));
+        let mut cache = run_build(&[], configure(&["A-A", "B-B"], &["A-A", "B-B", "C-C"]));
 
-        let a = TargetSelection::from_user("A");
-        let b = TargetSelection::from_user("B");
-        let c = TargetSelection::from_user("C");
+        let a = TargetSelection::from_user("A-A");
+        let b = TargetSelection::from_user("B-B");
+        let c = TargetSelection::from_user("C-C");
 
         assert_eq!(
             first(cache.all::<dist::Docs>()),
@@ -439,11 +439,11 @@ mod dist {
 
     #[test]
     fn dist_with_empty_host() {
-        let config = configure(&[], &["C"]);
+        let config = configure(&[], &["C-C"]);
         let mut cache = run_build(&[], config);
 
-        let a = TargetSelection::from_user("A");
-        let c = TargetSelection::from_user("C");
+        let a = TargetSelection::from_user("A-A");
+        let c = TargetSelection::from_user("C-C");
 
         assert_eq!(first(cache.all::<dist::Docs>()), &[dist::Docs { host: c },]);
         assert_eq!(first(cache.all::<dist::Mingw>()), &[dist::Mingw { host: c },]);
@@ -455,10 +455,10 @@ mod dist {
 
     #[test]
     fn dist_with_same_targets_and_hosts() {
-        let mut cache = run_build(&[], configure(&["A", "B"], &["A", "B"]));
+        let mut cache = run_build(&[], configure(&["A-A", "B-B"], &["A-A", "B-B"]));
 
-        let a = TargetSelection::from_user("A");
-        let b = TargetSelection::from_user("B");
+        let a = TargetSelection::from_user("A-A");
+        let b = TargetSelection::from_user("B-B");
 
         assert_eq!(
             first(cache.all::<dist::Docs>()),
@@ -506,7 +506,7 @@ mod dist {
 
     #[test]
     fn build_all() {
-        let build = Build::new(configure(&["A", "B"], &["A", "B", "C"]));
+        let build = Build::new(configure(&["A-A", "B-B"], &["A-A", "B-B", "C-C"]));
         let mut builder = Builder::new(&build);
         builder.run_step_descriptions(
             &Builder::get_step_descriptions(Kind::Build),
@@ -539,29 +539,29 @@ mod dist {
 
     #[test]
     fn llvm_out_behaviour() {
-        let mut config = configure(&["A"], &["B"]);
+        let mut config = configure(&["A-A"], &["B-B"]);
         config.llvm_from_ci = true;
         let build = Build::new(config.clone());
 
-        let target = TargetSelection::from_user("A");
+        let target = TargetSelection::from_user("A-A");
         assert!(build.llvm_out(target).ends_with("ci-llvm"));
-        let target = TargetSelection::from_user("B");
+        let target = TargetSelection::from_user("B-B");
         assert!(build.llvm_out(target).ends_with("llvm"));
 
         config.llvm_from_ci = false;
         let build = Build::new(config.clone());
-        let target = TargetSelection::from_user("A");
+        let target = TargetSelection::from_user("A-A");
         assert!(build.llvm_out(target).ends_with("llvm"));
     }
 
     #[test]
     fn build_with_empty_host() {
-        let config = configure(&[], &["C"]);
+        let config = configure(&[], &["C-C"]);
         let build = Build::new(config);
         let mut builder = Builder::new(&build);
         builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]);
 
-        let a = TargetSelection::from_user("A");
+        let a = TargetSelection::from_user("A-A");
 
         assert_eq!(
             first(builder.cache.all::<compile::Std>()),
@@ -583,7 +583,7 @@ mod dist {
 
     #[test]
     fn test_with_no_doc_stage0() {
-        let mut config = configure(&["A"], &["A"]);
+        let mut config = configure(&["A-A"], &["A-A"]);
         config.stage = 0;
         config.paths = vec!["library/std".into()];
         config.cmd = Subcommand::Test {
@@ -605,7 +605,7 @@ mod dist {
         let build = Build::new(config);
         let mut builder = Builder::new(&build);
 
-        let host = TargetSelection::from_user("A");
+        let host = TargetSelection::from_user("A-A");
 
         builder.run_step_descriptions(
             &[StepDescription::from::<test::Crate>(Kind::Test)],
@@ -627,13 +627,13 @@ mod dist {
 
     #[test]
     fn doc_ci() {
-        let mut config = configure(&["A"], &["A"]);
+        let mut config = configure(&["A-A"], &["A-A"]);
         config.compiler_docs = true;
         config.cmd = Subcommand::Doc { open: false, json: false };
         let build = Build::new(config);
         let mut builder = Builder::new(&build);
         builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), &[]);
-        let a = TargetSelection::from_user("A");
+        let a = TargetSelection::from_user("A-A");
 
         // error_index_generator uses stage 1 to share rustdoc artifacts with the
         // rustdoc tool.
@@ -656,7 +656,7 @@ mod dist {
     #[test]
     fn test_docs() {
         // Behavior of `x.py test` doing various documentation tests.
-        let mut config = configure(&["A"], &["A"]);
+        let mut config = configure(&["A-A"], &["A-A"]);
         config.cmd = Subcommand::Test {
             test_args: vec![],
             rustc_args: vec![],
@@ -678,7 +678,7 @@ mod dist {
         let mut builder = Builder::new(&build);
 
         builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Test), &[]);
-        let a = TargetSelection::from_user("A");
+        let a = TargetSelection::from_user("A-A");
 
         // error_index_generator uses stage 1 to share rustdoc artifacts with the
         // rustdoc tool.
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index ed45bc30362..0167c51fc7e 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -329,6 +329,7 @@ pub struct Config {
     pub nodejs: Option<PathBuf>,
     pub npm: Option<PathBuf>,
     pub gdb: Option<PathBuf>,
+    pub lldb: Option<PathBuf>,
     pub python: Option<PathBuf>,
     pub reuse: Option<PathBuf>,
     pub cargo_native_static: bool,
@@ -834,6 +835,7 @@ define_config! {
         docs_minification: Option<bool> = "docs-minification",
         submodules: Option<bool> = "submodules",
         gdb: Option<String> = "gdb",
+        lldb: Option<String> = "lldb",
         nodejs: Option<String> = "nodejs",
         npm: Option<String> = "npm",
         python: Option<String> = "python",
@@ -1410,6 +1412,7 @@ impl Config {
             docs_minification,
             submodules,
             gdb,
+            lldb,
             nodejs,
             npm,
             python,
@@ -1502,6 +1505,7 @@ impl Config {
         config.nodejs = nodejs.map(PathBuf::from);
         config.npm = npm.map(PathBuf::from);
         config.gdb = gdb.map(PathBuf::from);
+        config.lldb = lldb.map(PathBuf::from);
         config.python = python.map(PathBuf::from);
         config.reuse = reuse.map(PathBuf::from);
         config.submodules = submodules;
diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs
index 0c069a54069..493ad99cc70 100644
--- a/src/bootstrap/src/core/sanity.rs
+++ b/src/bootstrap/src/core/sanity.rs
@@ -192,7 +192,7 @@ than building it.
         let target_str = target.to_string();
 
         // Ignore fake targets that are only used for unit tests in bootstrap.
-        if !["A", "B", "C"].contains(&target_str.as_str()) {
+        if !["A-A", "B-B", "C-C"].contains(&target_str.as_str()) {
             let mut has_target = false;
 
             let supported_target_list =
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index c599709a322..698a576effa 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -683,6 +683,8 @@ impl Build {
 
         if !self.config.dry_run() {
             {
+                // We first do a dry-run. This is a sanity-check to ensure that
+                // steps don't do anything expensive in the dry-run.
                 self.config.dry_run = DryRun::SelfCheck;
                 let builder = builder::Builder::new(self);
                 builder.execute_cli();
@@ -1723,7 +1725,7 @@ impl Build {
             return;
         }
         let _ = fs::remove_file(dst);
-        let metadata = t!(src.symlink_metadata());
+        let metadata = t!(src.symlink_metadata(), format!("src = {}", src.display()));
         let mut src = src.to_path_buf();
         if metadata.file_type().is_symlink() {
             if dereference_symlinks {
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs
index db3df598a0c..c3a03693f71 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -175,4 +175,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
         severity: ChangeSeverity::Warning,
         summary: "The deprecated field `changelog-seen` has been removed. Using that field in `config.toml` from now on will result in breakage.",
     },
+    ChangeInfo {
+        change_id: 124501,
+        severity: ChangeSeverity::Info,
+        summary: "New option `build.lldb` that will override the default lldb binary path used in debuginfo tests",
+    },
 ];
diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs
index 928c9aa4dff..0d2ff4f951b 100644
--- a/src/bootstrap/src/utils/helpers.rs
+++ b/src/bootstrap/src/utils/helpers.rs
@@ -296,6 +296,15 @@ pub fn up_to_date(src: &Path, dst: &Path) -> bool {
     }
 }
 
+/// Returns the filename without the hash prefix added by the cc crate.
+///
+/// Since v1.0.78 of the cc crate, object files are prefixed with a 16-character hash
+/// to avoid filename collisions.
+pub fn unhashed_basename(obj: &Path) -> &str {
+    let basename = obj.file_stem().unwrap().to_str().expect("UTF-8 file name");
+    basename.split_once('-').unwrap().1
+}
+
 fn dir_up_to_date(src: &Path, threshold: SystemTime) -> bool {
     t!(fs::read_dir(src)).map(|e| t!(e)).all(|e| {
         let meta = t!(e.metadata());
diff --git a/src/bootstrap/src/utils/render_tests.rs b/src/bootstrap/src/utils/render_tests.rs
index 462b76d03bd..5c9918bce32 100644
--- a/src/bootstrap/src/utils/render_tests.rs
+++ b/src/bootstrap/src/utils/render_tests.rs
@@ -215,8 +215,8 @@ impl<'a> Renderer<'a> {
             for bench in &self.benches {
                 rows.push((
                     &bench.name,
-                    format!("{:.2?}/iter", Duration::from_nanos(bench.median)),
-                    format!("+/- {:.2?}", Duration::from_nanos(bench.deviation)),
+                    format!("{:.2?}/iter", bench.median),
+                    format!("+/- {:.2?}", bench.deviation),
                 ));
             }
 
@@ -394,8 +394,8 @@ enum TestMessage {
 #[derive(serde_derive::Deserialize)]
 struct BenchOutcome {
     name: String,
-    median: u64,
-    deviation: u64,
+    median: f64,
+    deviation: f64,
 }
 
 #[derive(serde_derive::Deserialize)]
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh
index 005f4537c84..f3591a69bee 100755
--- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh
+++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh
@@ -4,6 +4,7 @@ set -ex
 
 source shared.sh
 
+# Try to keep the LLVM version here in sync with src/ci/scripts/install-clang.sh
 LLVM=llvmorg-18.1.0
 
 mkdir llvm-project
diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh
index fcc507b572c..22dcb808c74 100755
--- a/src/ci/docker/run.sh
+++ b/src/ci/docker/run.sh
@@ -50,39 +50,35 @@ fi
 CACHE_DOMAIN="${CACHE_DOMAIN:-ci-caches.rust-lang.org}"
 
 if [ -f "$docker_dir/$image/Dockerfile" ]; then
-    if isCI; then
-      hash_key=/tmp/.docker-hash-key.txt
-      rm -f "${hash_key}"
-      echo $image >> $hash_key
-
-      cat "$docker_dir/$image/Dockerfile" >> $hash_key
-      # Look for all source files involves in the COPY command
-      copied_files=/tmp/.docker-copied-files.txt
-      rm -f "$copied_files"
-      for i in $(sed -n -e '/^COPY --from=/! s/^COPY \(.*\) .*$/\1/p' \
-          "$docker_dir/$image/Dockerfile"); do
-        # List the file names
-        find "$script_dir/$i" -type f >> $copied_files
-      done
-      # Sort the file names and cat the content into the hash key
-      sort $copied_files | xargs cat >> $hash_key
-
-      # Include the architecture in the hash key, since our Linux CI does not
-      # only run in x86_64 machines.
-      uname -m >> $hash_key
-
-      docker --version >> $hash_key
-
-      # Include cache version. Can be used to manually bust the Docker cache.
-      echo "2" >> $hash_key
-
-      echo "Image input"
-      cat $hash_key
-
-      cksum=$(sha512sum $hash_key | \
-        awk '{print $1}')
-      echo "Image input checksum ${cksum}"
-    fi
+    hash_key=/tmp/.docker-hash-key.txt
+    rm -f "${hash_key}"
+    echo $image >> $hash_key
+
+    cat "$docker_dir/$image/Dockerfile" >> $hash_key
+    # Look for all source files involves in the COPY command
+    copied_files=/tmp/.docker-copied-files.txt
+    rm -f "$copied_files"
+    for i in $(sed -n -e '/^COPY --from=/! s/^COPY \(.*\) .*$/\1/p' \
+      "$docker_dir/$image/Dockerfile"); do
+    # List the file names
+    find "$script_dir/$i" -type f >> $copied_files
+    done
+    # Sort the file names and cat the content into the hash key
+    sort $copied_files | xargs cat >> $hash_key
+
+    # Include the architecture in the hash key, since our Linux CI does not
+    # only run in x86_64 machines.
+    uname -m >> $hash_key
+
+    # Include cache version. Can be used to manually bust the Docker cache.
+    echo "2" >> $hash_key
+
+    echo "Image input"
+    cat $hash_key
+
+    cksum=$(sha512sum $hash_key | \
+    awk '{print $1}')
+    echo "Image input checksum ${cksum}"
 
     dockerfile="$docker_dir/$image/Dockerfile"
     if [ -x /usr/bin/cygpath ]; then
@@ -105,10 +101,18 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then
     # It seems that it cannot be the same as $IMAGE_TAG, otherwise it overwrites the cache
     CACHE_IMAGE_TAG=${REGISTRY}/${REGISTRY_USERNAME}/rust-ci-cache:${cksum}
 
-    # On non-CI jobs, we don't do any caching.
+    # On non-CI jobs, we try to download a pre-built image from the rust-lang-ci
+    # ghcr.io registry. If it is not possible, we fall back to building the image
+    # locally.
     if ! isCI;
     then
-        retry docker build --rm -t rust-ci -f "$dockerfile" "$context"
+        if docker pull "${IMAGE_TAG}"; then
+            echo "Downloaded Docker image from CI"
+            docker tag "${IMAGE_TAG}" rust-ci
+        else
+            echo "Building local Docker image"
+            retry docker build --rm -t rust-ci -f "$dockerfile" "$context"
+        fi
     # On PR CI jobs, we don't have permissions to write to the registry cache,
     # but we can still read from it.
     elif [[ "$PR_CI_JOB" == "1" ]];
diff --git a/src/ci/docker/scripts/fuchsia-test-runner.py b/src/ci/docker/scripts/fuchsia-test-runner.py
index 8ac00a8863f..4f504341d52 100755
--- a/src/ci/docker/scripts/fuchsia-test-runner.py
+++ b/src/ci/docker/scripts/fuchsia-test-runner.py
@@ -9,10 +9,8 @@ https://doc.rust-lang.org/stable/rustc/platform-support/fuchsia.html#aarch64-unk
 
 import argparse
 from dataclasses import dataclass
-import fcntl
 import glob
 import hashlib
-import io
 import json
 import os
 import platform
@@ -143,6 +141,14 @@ class TestEnvironment:
             return sys.stdout
         return subprocess.DEVNULL
 
+    def check_call(self, args, **kwargs):
+        self.log_info(f"Running: {' '.join(args)}")
+        return subprocess.check_call(args, **kwargs)
+
+    def check_output(self, args, **kwargs):
+        self.log_info(f"Running: {' '.join(args)}")
+        return subprocess.check_output(args, **kwargs)
+
     def ffx_daemon_log_path(self):
         return os.path.join(self.tmp_dir(), "ffx_daemon_log")
 
@@ -178,7 +184,7 @@ class TestEnvironment:
             )
 
         # Disable analytics
-        subprocess.check_call(
+        self.check_call(
             [
                 ffx_path,
                 "config",
@@ -197,7 +203,7 @@ class TestEnvironment:
             "test.experimental_structured_output": "true",
         }
         for key, value in configs.items():
-            subprocess.check_call(
+            self.check_call(
                 [
                     ffx_path,
                     "config",
@@ -222,7 +228,7 @@ class TestEnvironment:
         }
 
     def stop_ffx_isolation(self):
-        subprocess.check_call(
+        self.check_call(
             [
                 self.tool_path("ffx"),
                 "daemon",
@@ -265,7 +271,7 @@ class TestEnvironment:
         self.start_ffx_isolation()
 
         # Stop any running emulators (there shouldn't be any)
-        subprocess.check_call(
+        self.check_call(
             [
                 ffx_path,
                 "emu",
@@ -282,11 +288,11 @@ class TestEnvironment:
         product_name = "minimal." + self.triple_to_arch(self.target)
         fuchsia_version = "20.20240412.3.1"
 
-        # FIXME: We should be able to replace this with the machine parsable
-        # `ffx --machine json product lookup ...` once F15 is released.
-        out = subprocess.check_output(
+        out = self.check_output(
             [
                 ffx_path,
+                "--machine",
+                "json",
                 "product",
                 "lookup",
                 product_name,
@@ -300,16 +306,15 @@ class TestEnvironment:
 
         self.log_debug(out)
 
-        for line in io.BytesIO(out):
-            if line.startswith(b"gs://"):
-                transfer_manifest_url = line.rstrip()
-                break
-        else:
-            raise Exception("Unable to parse transfer manifest")
+        try:
+            transfer_manifest_url = json.loads(out)["transfer_manifest_url"]
+        except Exception as e:
+            print(e)
+            raise Exception("Unable to parse transfer manifest") from e
 
         # Download the product bundle.
         product_bundle_dir = os.path.join(self.tmp_dir(), 'product-bundle')
-        subprocess.check_call(
+        self.check_call(
             [
                 ffx_path,
                 "product",
@@ -325,7 +330,7 @@ class TestEnvironment:
 
         # Start emulator
         # FIXME: condition --accel hyper on target arch matching host arch
-        subprocess.check_call(
+        self.check_call(
             [
                 ffx_path,
                 "emu",
@@ -346,42 +351,52 @@ class TestEnvironment:
 
         # Create new package repo
         self.log_info("Creating package repo...")
-        subprocess.check_call(
+        self.check_call(
             [
-                self.tool_path("pm"),
-                "newrepo",
-                "-repo",
+                ffx_path,
+                "repository",
+                "create",
                 self.repo_dir(),
             ],
+            env=ffx_env,
             stdout=self.subprocess_output(),
             stderr=self.subprocess_output(),
         )
 
-        # Add repo
-        subprocess.check_call(
+        self.check_call(
             [
                 ffx_path,
                 "repository",
                 "add-from-pm",
-                self.repo_dir(),
                 "--repository",
                 self.TEST_REPO_NAME,
+                self.repo_dir(),
             ],
             env=ffx_env,
             stdout=self.subprocess_output(),
             stderr=self.subprocess_output(),
         )
 
+        # Write to file
+        self.write_to_file()
+
         # Start repository server
-        subprocess.check_call(
-            [ffx_path, "repository", "server", "start", "--address", "[::]:0"],
+        self.check_call(
+            [
+                ffx_path,
+                "repository",
+                "server",
+                "start",
+                "--address",
+                "[::]:0",
+            ],
             env=ffx_env,
             stdout=self.subprocess_output(),
             stderr=self.subprocess_output(),
         )
 
         # Register with newly-started emulator
-        subprocess.check_call(
+        self.check_call(
             [
                 ffx_path,
                 "target",
@@ -395,12 +410,6 @@ class TestEnvironment:
             stderr=self.subprocess_output(),
         )
 
-        # Create lockfiles
-        open(self.pm_lockfile_path(), "a").close()
-
-        # Write to file
-        self.write_to_file()
-
         self.log_info("Success! Your environment is ready to run tests.")
 
     # FIXME: shardify this
@@ -445,7 +454,6 @@ class TestEnvironment:
     meta/{package_name}.cm={package_dir}/meta/{package_name}.cm
     bin/{exe_name}={bin_path}
     lib/{libstd_name}={libstd_path}
-    lib/{libtest_name}={libtest_path}
     lib/ld.so.1={sdk_dir}/arch/{target_arch}/sysroot/dist/lib/ld.so.1
     lib/libfdio.so={sdk_dir}/arch/{target_arch}/dist/libfdio.so
     """
@@ -482,9 +490,6 @@ class TestEnvironment:
         if not libstd_paths:
             raise Exception(f"Failed to locate libstd (in {self.rustlibs_dir()})")
 
-        if not libtest_paths:
-            raise Exception(f"Failed to locate libtest (in {self.rustlibs_dir()})")
-
         # Build a unique, deterministic name for the test using the name of the
         # binary and the last 6 hex digits of the hash of the full path
         def path_checksum(path):
@@ -500,6 +505,7 @@ class TestEnvironment:
         cml_path = os.path.join(package_dir, "meta", f"{package_name}.cml")
         cm_path = os.path.join(package_dir, "meta", f"{package_name}.cm")
         manifest_path = os.path.join(package_dir, f"{package_name}.manifest")
+        manifest_json_path = os.path.join(package_dir, "package_manifest.json")
         far_path = os.path.join(package_dir, f"{package_name}-0.far")
 
         shared_libs = args.shared_libs[: args.n]
@@ -523,22 +529,6 @@ class TestEnvironment:
 
             log(f"Bin path: {bin_path}")
 
-            log("Setting up package...")
-
-            # Set up package
-            subprocess.check_call(
-                [
-                    self.tool_path("pm"),
-                    "-o",
-                    package_dir,
-                    "-n",
-                    package_name,
-                    "init",
-                ],
-                stdout=log_file,
-                stderr=log_file,
-            )
-
             log("Writing CML...")
 
             # Write and compile CML
@@ -563,7 +553,7 @@ class TestEnvironment:
 
             log("Compiling CML...")
 
-            subprocess.check_call(
+            self.check_call(
                 [
                     self.tool_path("cmc"),
                     "compile",
@@ -590,38 +580,61 @@ class TestEnvironment:
                         target=self.target,
                         sdk_dir=self.sdk_dir,
                         libstd_name=os.path.basename(libstd_paths[0]),
-                        libtest_name=os.path.basename(libtest_paths[0]),
                         libstd_path=libstd_paths[0],
-                        libtest_path=libtest_paths[0],
                         target_arch=self.triple_to_arch(self.target),
                     )
                 )
+                # `libtest`` was historically a shared library, but now seems to be (sometimes?)
+                # statically linked. If we find it as a shared library, include it in the manifest.
+                if libtest_paths:
+                    manifest.write(
+                        f"lib/{os.path.basename(libtest_paths[0])}={libtest_paths[0]}\n"
+                    )
                 for shared_lib in shared_libs:
                     manifest.write(f"lib/{os.path.basename(shared_lib)}={shared_lib}\n")
 
+            log("Determining API level...")
+            out = self.check_output(
+                [
+                    self.tool_path("ffx"),
+                    "--machine",
+                    "json",
+                    "version",
+                ],
+                env=self.ffx_cmd_env(),
+                stderr=log_file,
+            )
+            api_level = json.loads(out)["tool_version"]["api_level"]
+
             log("Compiling and archiving manifest...")
 
-            subprocess.check_call(
+            self.check_call(
                 [
-                    self.tool_path("pm"),
+                    self.tool_path("ffx"),
+                    "package",
+                    "build",
+                    manifest_path,
                     "-o",
                     package_dir,
-                    "-m",
-                    manifest_path,
-                    "build",
+                    "--api-level",
+                    str(api_level),
                 ],
+                env=self.ffx_cmd_env(),
                 stdout=log_file,
                 stderr=log_file,
             )
-            subprocess.check_call(
+
+            self.check_call(
                 [
-                    self.tool_path("pm"),
-                    "-o",
-                    package_dir,
-                    "-m",
-                    manifest_path,
+                    self.tool_path("ffx"),
+                    "package",
                     "archive",
+                    "create",
+                    "-o",
+                    far_path,
+                    manifest_json_path,
                 ],
+                env=self.ffx_cmd_env(),
                 stdout=log_file,
                 stderr=log_file,
             )
@@ -629,25 +642,18 @@ class TestEnvironment:
             log("Publishing package to repo...")
 
             # Publish package to repo
-            with open(self.pm_lockfile_path(), "w") as pm_lockfile:
-                fcntl.lockf(pm_lockfile.fileno(), fcntl.LOCK_EX)
-                subprocess.check_call(
-                    [
-                        self.tool_path("pm"),
-                        "publish",
-                        "-a",
-                        "-repo",
-                        self.repo_dir(),
-                        "-f",
-                        far_path,
-                    ],
-                    stdout=log_file,
-                    stderr=log_file,
-                )
-                # This lock should be released automatically when the pm
-                # lockfile is closed, but we'll be polite and unlock it now
-                # since the spec leaves some wiggle room.
-                fcntl.lockf(pm_lockfile.fileno(), fcntl.LOCK_UN)
+            self.check_call(
+                [
+                    self.tool_path("ffx"),
+                    "repository",
+                    "publish",
+                    "--package",
+                    os.path.join(package_dir, "package_manifest.json"),
+                    self.repo_dir(),
+                ],
+                stdout=log_file,
+                stderr=log_file,
+            )
 
             log("Running ffx test...")
 
@@ -765,7 +771,7 @@ class TestEnvironment:
 
         # Shut down the emulator
         self.log_info("Stopping emulator...")
-        subprocess.check_call(
+        self.check_call(
             [
                 self.tool_path("ffx"),
                 "emu",
diff --git a/src/ci/github-actions/calculate-job-matrix.py b/src/ci/github-actions/calculate-job-matrix.py
index 68565f489c9..4f9bc39a628 100755
--- a/src/ci/github-actions/calculate-job-matrix.py
+++ b/src/ci/github-actions/calculate-job-matrix.py
@@ -8,10 +8,11 @@ It reads job definitions from `src/ci/github-actions/jobs.yml`
 and filters them based on the event that happened on CI.
 """
 import dataclasses
-import enum
 import json
 import logging
 import os
+import re
+import typing
 from pathlib import Path
 from typing import List, Dict, Any, Optional
 
@@ -44,10 +45,22 @@ def add_base_env(jobs: List[Job], environment: Dict[str, str]) -> List[Job]:
     return jobs
 
 
-class WorkflowRunType(enum.Enum):
-    PR = enum.auto()
-    Try = enum.auto()
-    Auto = enum.auto()
+@dataclasses.dataclass
+class PRRunType:
+    pass
+
+
+@dataclasses.dataclass
+class TryRunType:
+    custom_jobs: List[str]
+
+
+@dataclasses.dataclass
+class AutoRunType:
+    pass
+
+
+WorkflowRunType = typing.Union[PRRunType, TryRunType, AutoRunType]
 
 
 @dataclasses.dataclass
@@ -55,11 +68,28 @@ class GitHubCtx:
     event_name: str
     ref: str
     repository: str
+    commit_message: Optional[str]
+
+
+def get_custom_jobs(ctx: GitHubCtx) -> List[str]:
+    """
+    Tries to parse names of specific CI jobs that should be executed in the form of
+    try-job: <job-name>
+    from the commit message of the passed GitHub context.
+    """
+    if ctx.commit_message is None:
+        return []
+
+    regex = re.compile(r"^try-job: (.*)", re.MULTILINE)
+    jobs = []
+    for match in regex.finditer(ctx.commit_message):
+        jobs.append(match.group(1))
+    return jobs
 
 
 def find_run_type(ctx: GitHubCtx) -> Optional[WorkflowRunType]:
     if ctx.event_name == "pull_request":
-        return WorkflowRunType.PR
+        return PRRunType()
     elif ctx.event_name == "push":
         old_bors_try_build = (
             ctx.ref in ("refs/heads/try", "refs/heads/try-perf") and
@@ -72,20 +102,41 @@ def find_run_type(ctx: GitHubCtx) -> Optional[WorkflowRunType]:
         try_build = old_bors_try_build or new_bors_try_build
 
         if try_build:
-            return WorkflowRunType.Try
+            jobs = get_custom_jobs(ctx)
+            return TryRunType(custom_jobs=jobs)
 
         if ctx.ref == "refs/heads/auto" and ctx.repository == "rust-lang-ci/rust":
-            return WorkflowRunType.Auto
+            return AutoRunType()
 
     return None
 
 
 def calculate_jobs(run_type: WorkflowRunType, job_data: Dict[str, Any]) -> List[Job]:
-    if run_type == WorkflowRunType.PR:
+    if isinstance(run_type, PRRunType):
         return add_base_env(name_jobs(job_data["pr"], "PR"), job_data["envs"]["pr"])
-    elif run_type == WorkflowRunType.Try:
-        return add_base_env(name_jobs(job_data["try"], "try"), job_data["envs"]["try"])
-    elif run_type == WorkflowRunType.Auto:
+    elif isinstance(run_type, TryRunType):
+        jobs = job_data["try"]
+        custom_jobs = run_type.custom_jobs
+        if custom_jobs:
+            if len(custom_jobs) > 10:
+                raise Exception(
+                    f"It is only possible to schedule up to 10 custom jobs, "
+                    f"received {len(custom_jobs)} jobs"
+                )
+
+            jobs = []
+            unknown_jobs = []
+            for custom_job in custom_jobs:
+                job = [j for j in job_data["auto"] if j["image"] == custom_job]
+                if not job:
+                    unknown_jobs.append(custom_job)
+                    continue
+                jobs.append(job[0])
+            if unknown_jobs:
+                raise Exception(f"Custom job(s) `{unknown_jobs}` not found in auto jobs")
+
+        return add_base_env(name_jobs(jobs, "try"), job_data["envs"]["try"])
+    elif isinstance(run_type, AutoRunType):
         return add_base_env(name_jobs(job_data["auto"], "auto"), job_data["envs"]["auto"])
 
     return []
@@ -99,19 +150,25 @@ def skip_jobs(jobs: List[Dict[str, Any]], channel: str) -> List[Job]:
 
 
 def get_github_ctx() -> GitHubCtx:
+    event_name = os.environ["GITHUB_EVENT_NAME"]
+
+    commit_message = None
+    if event_name == "push":
+        commit_message = os.environ["COMMIT_MESSAGE"]
     return GitHubCtx(
-        event_name=os.environ["GITHUB_EVENT_NAME"],
+        event_name=event_name,
         ref=os.environ["GITHUB_REF"],
-        repository=os.environ["GITHUB_REPOSITORY"]
+        repository=os.environ["GITHUB_REPOSITORY"],
+        commit_message=commit_message
     )
 
 
 def format_run_type(run_type: WorkflowRunType) -> str:
-    if run_type == WorkflowRunType.PR:
+    if isinstance(run_type, PRRunType):
         return "pr"
-    elif run_type == WorkflowRunType.Auto:
+    elif isinstance(run_type, AutoRunType):
         return "auto"
-    elif run_type == WorkflowRunType.Try:
+    elif isinstance(run_type, TryRunType):
         return "try"
     else:
         raise AssertionError()
@@ -135,6 +192,10 @@ if __name__ == "__main__":
     if run_type is not None:
         jobs = calculate_jobs(run_type, data)
     jobs = skip_jobs(jobs, channel)
+
+    if not jobs:
+        raise Exception("Scheduled job list is empty, this is an error")
+
     run_type = format_run_type(run_type)
 
     logging.info(f"Output:\n{yaml.dump(dict(jobs=jobs, run_type=run_type), indent=4)}")
diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml
index 20b1a55ffb8..04888dc09b5 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -32,14 +32,6 @@ runners:
     os: windows-2022-16core-64gb
     <<: *base-job
 
-  - &job-windows-2019-8c
-    os: windows-2019-8core-32gb
-    <<: *base-job
-
-  - &job-windows-2019-16c
-    os: windows-2019-16core-64gb
-    <<: *base-job
-
   - &job-aarch64-linux
     os: [ self-hosted, ARM64, linux ]
 
@@ -349,13 +341,13 @@ auto:
     env:
       RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler
       SCRIPT: make ci-msvc
-    <<: *job-windows-2019-8c
+    <<: *job-windows-8c
 
   - image: i686-msvc
     env:
       RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc
       SCRIPT: make ci-msvc
-    <<: *job-windows-2019-8c
+    <<: *job-windows-8c
 
   - image: x86_64-msvc-ext
     env:
@@ -363,7 +355,7 @@ auto:
       HOST_TARGET: x86_64-pc-windows-msvc
       RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-lld --save-toolstates=/tmp/toolstate/toolstates.json
       DEPLOY_TOOLSTATES_JSON: toolstates-windows.json
-    <<: *job-windows-2019-8c
+    <<: *job-windows-8c
 
   # 32/64-bit MinGW builds.
   #
@@ -414,7 +406,7 @@ auto:
         --set rust.codegen-units=1
       SCRIPT: python x.py build --set rust.debug=true opt-dist && PGO_HOST=x86_64-pc-windows-msvc ./build/x86_64-pc-windows-msvc/stage0-tools-bin/opt-dist windows-ci -- python x.py dist bootstrap --include-default-paths
       DIST_REQUIRE_ALL_TOOLS: 1
-    <<: *job-windows-2019-8c
+    <<: *job-windows-8c
 
   - image: dist-i686-msvc
     env:
@@ -426,7 +418,7 @@ auto:
         --enable-profiler
       SCRIPT: python x.py dist bootstrap --include-default-paths
       DIST_REQUIRE_ALL_TOOLS: 1
-    <<: *job-windows-2019-8c
+    <<: *job-windows-8c
 
   - image: dist-aarch64-msvc
     env:
@@ -437,7 +429,7 @@ auto:
         --enable-profiler
       SCRIPT: python x.py dist bootstrap --include-default-paths
       DIST_REQUIRE_ALL_TOOLS: 1
-    <<: *job-windows-2019-8c
+    <<: *job-windows-8c
 
   - image: dist-i686-mingw
     env:
@@ -471,4 +463,4 @@ auto:
     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-2019-8c
+    <<: *job-windows-8c
diff --git a/src/ci/scripts/install-clang.sh b/src/ci/scripts/install-clang.sh
index aa7ff813f51..24b9904d65c 100755
--- a/src/ci/scripts/install-clang.sh
+++ b/src/ci/scripts/install-clang.sh
@@ -10,18 +10,24 @@ IFS=$'\n\t'
 source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"
 
 # Update both macOS's and Windows's tarballs when bumping the version here.
-LLVM_VERSION="14.0.5"
+# Try to keep this in sync with src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh
+LLVM_VERSION="18.1.4"
 
 if isMacOS; then
+    # FIXME: This is the latest pre-built version of LLVM that's available for
+    # x86_64 MacOS. We may want to consider bulding our own LLVM binaries
+    # instead, or set `USE_XCODE_CLANG` like AArch64 does.
+    LLVM_VERSION="15.0.7"
+
     # If the job selects a specific Xcode version, use that instead of
     # downloading our own version.
     if [[ ${USE_XCODE_CLANG-0} -eq 1 ]]; then
         bindir="$(xcode-select --print-path)/Toolchains/XcodeDefault.xctoolchain/usr/bin"
     else
-        file="${MIRRORS_BASE}/clang%2Bllvm-${LLVM_VERSION}-x86_64-apple-darwin.tar.xz"
-        retry curl -f "${file}" -o "clang+llvm-${LLVM_VERSION}-x86_64-apple-darwin.tar.xz"
-        tar xJf "clang+llvm-${LLVM_VERSION}-x86_64-apple-darwin.tar.xz"
-        bindir="$(pwd)/clang+llvm-${LLVM_VERSION}-x86_64-apple-darwin/bin"
+        file="${MIRRORS_BASE}/clang%2Bllvm-${LLVM_VERSION}-x86_64-apple-darwin21.0.tar.xz"
+        retry curl -f "${file}" -o "clang+llvm-${LLVM_VERSION}-x86_64-apple-darwin21.0.tar.xz"
+        tar xJf "clang+llvm-${LLVM_VERSION}-x86_64-apple-darwin21.0.tar.xz"
+        bindir="$(pwd)/clang+llvm-${LLVM_VERSION}-x86_64-apple-darwin21.0/bin"
     fi
 
     ciCommandSetEnv CC "${bindir}/clang"
diff --git a/src/doc/book b/src/doc/book
-Subproject d207d894cc5e1d496ab99beeacd1a420e5d4d23
+Subproject bebcf527e67755a989a1739b7cfaa8f0e6b3004
diff --git a/src/doc/embedded-book b/src/doc/embedded-book
-Subproject aa7d4b0b4653ddb47cb1de2036d090ec2ba9dab
+Subproject 17842ebb050f62e40a4618edeb8e8ee86e75870
diff --git a/src/doc/reference b/src/doc/reference
-Subproject 5854fcc286557ad3ab34d325073d11d8118096b
+Subproject 51817951d0d213a0011f82b62aae02c3b3f2472
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
-Subproject 60d34b5fd33db1346f9aabfc0c9d0bda6c8e42b
+Subproject 229ad13b64d919b12e548d560f06d88963b25cd
diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide
-Subproject 07425fed36b00e60341c5e29e28d37d40cbd445
+Subproject 2d1947ff34d50ca46dfe242ad75531a4c429bb5
diff --git a/src/doc/rustc/src/check-cfg.md b/src/doc/rustc/src/check-cfg.md
index 37708bda1f3..8e39adaa438 100644
--- a/src/doc/rustc/src/check-cfg.md
+++ b/src/doc/rustc/src/check-cfg.md
@@ -1,18 +1,29 @@
 # Checking conditional configurations
 
-`rustc` accepts the `--check-cfg` option, which specifies whether to check conditions and how to
-check them. The `--check-cfg` option takes a value, called the _check cfg specification_.
-This specification has one form:
+`rustc` supports checking that every _reachable_[^reachable] `#[cfg]` matches a list of the
+expected config names and values.
 
-1. `--check-cfg cfg(...)` mark a configuration and it's expected values as expected.
+This can help with verifying that the crate is correctly handling conditional compilation for
+different target platforms or features. It ensures that the cfg settings are consistent between
+what is intended and what is used, helping to catch potential bugs or errors early in the
+development process.
 
-*No implicit expectation is added when using `--cfg`. Users are expected to
-pass all expected names and values using the _check cfg specification_.*
+In order to accomplish that goal, `rustc` accepts the `--check-cfg` flag, which specifies
+whether to check conditions and how to check them.
 
-## The `cfg(...)` form
+> **Note:** No implicit expectation is added when using `--cfg`. Users are expected to
+pass all expected names and values using the _check cfg specification_.
 
-The `cfg(...)` form enables checking the values within list-valued conditions. It has this
-basic form:
+[^reachable]: `rustc` promises to at least check reachable `#[cfg]`, and while non-reachable
+`#[cfg]` are not currently checked, they may well be checked in the future without it being a
+breaking change.
+
+## Specifying expected names and values
+
+To specify expected names and values, the _check cfg specification_ provides the `cfg(...)`
+option which enables specifying for an expected config name and it's expected values.
+
+It has this basic form:
 
 ```bash
 rustc --check-cfg 'cfg(name, values("value1", "value2", ... "valueN"))'
@@ -20,15 +31,20 @@ rustc --check-cfg 'cfg(name, values("value1", "value2", ... "valueN"))'
 
 where `name` is a bare identifier (has no quotes) and each `"value"` term is a quoted literal
 string. `name` specifies the name of the condition, such as `feature` or `my_cfg`.
+`"value"` specify one of the value of that condition name.
+
+When the `cfg(...)` option is specified, `rustc` will check every[^reachable]:
+ - `#[cfg(name = "value")]` attribute
+ - `#[cfg_attr(name = "value")]` attribute
+ - `#[link(name = "a", cfg(name = "value"))]` attribute
+ -  `cfg!(name = "value")` macro call
 
-When the `cfg(...)` option is specified, `rustc` will check every `#[cfg(name = "value")]`
-attribute, `#[cfg_attr(name = "value")]` attribute, `#[link(name = "a", cfg(name = "value"))]`
-attribute and `cfg!(name = "value")` macro call. It will check that the `"value"` specified is
-present in the list of expected values. If `"value"` is not in it, then `rustc` will report an
-`unexpected_cfgs` lint diagnostic. The default diagnostic level for this lint is `Warn`.
+> *The command line `--cfg` arguments are currently NOT checked but may very well be checked
+in the future.*
 
-*The command line `--cfg` arguments are currently *NOT* checked but may very well be checked in
-the future.*
+`rustc` will check that the `"value"` specified is present in the list of expected values.
+If `"value"` is not in it, then `rustc` will report an `unexpected_cfgs` lint diagnostic.
+The default diagnostic level for this lint is `Warn`.
 
 To check for the _none_ value (ie `#[cfg(foo)]`) one can use the `none()` predicate inside
 `values()`: `values(none())`. It can be followed or preceded by any number of `"value"`.
@@ -43,12 +59,12 @@ rustc --check-cfg 'cfg(name, values(none()))'
 
 To enable checking of name but not values, use one of these forms:
 
-  - No expected values (_will lint on every value_):
+  - No expected values (_will lint on every value of `name`_):
     ```bash
     rustc --check-cfg 'cfg(name, values())'
     ```
 
-  - Unknown expected values (_will never lint_):
+  - Unknown expected values (_will never lint on value of `name`_):
     ```bash
     rustc --check-cfg 'cfg(name, values(any()))'
     ```
@@ -59,19 +75,28 @@ To avoid repeating the same set of values, use this form:
 rustc --check-cfg 'cfg(name1, ..., nameN, values("value1", "value2", ... "valueN"))'
 ```
 
+To enable checking without specifying any names or values, use this form:
+
+```bash
+rustc --check-cfg 'cfg()'
+```
+
 The `--check-cfg cfg(...)` option can be repeated, both for the same condition name and for
 different names. If it is repeated for the same condition name, then the sets of values for that
 condition are merged together (precedence is given to `values(any())`).
 
+> To help out an equivalence table between `--cfg` arguments and `--check-cfg` is available
+[down below](#equivalence-table-with---cfg).
+
 ## Well known names and values
 
-`rustc` has a internal list of well known names and their corresponding values.
-Those well known names and values follows the same stability as what they refer to.
+`rustc` maintains a list of well-known names and their corresponding values in order to avoid
+the need to specify them manually.
 
-Well known names and values checking is always enabled as long as at least one
-`--check-cfg` argument is present.
+Well known names and values are implicitly added as long as at least one `--check-cfg` argument
+is present.
 
-As of `2024-04-06T`, the list of known names is as follows:
+As of `2024-05-06T`, the list of known names is as follows:
 
 <!--- See CheckCfg::fill_well_known in compiler/rustc_session/src/config.rs -->
 
@@ -84,6 +109,7 @@ As of `2024-04-06T`, the list of known names is as follows:
  - `panic`
  - `proc_macro`
  - `relocation_model`
+ - `rustfmt`
  - `sanitize`
  - `sanitizer_cfi_generalize_pointers`
  - `sanitizer_cfi_normalize_integers`
@@ -108,11 +134,9 @@ As of `2024-04-06T`, the list of known names is as follows:
 Like with `values(any())`, well known names checking can be disabled by passing `cfg(any())`
 as argument to `--check-cfg`.
 
-## Examples
-
-### Equivalence table
+## Equivalence table with `--cfg`
 
-This table describe the equivalence of a `--cfg` argument to a `--check-cfg` argument.
+This table describe the equivalence between a `--cfg` argument to a `--check-cfg` argument.
 
 | `--cfg`                       | `--check-cfg`                                              |
 |-------------------------------|------------------------------------------------------------|
@@ -124,40 +148,42 @@ This table describe the equivalence of a `--cfg` argument to a `--check-cfg` arg
 | `--cfg foo="1" --cfg bar="2"` | `--check-cfg=cfg(foo, values("1")) --check-cfg=cfg(bar, values("2"))` |
 | `--cfg foo --cfg foo="bar"`   | `--check-cfg=cfg(foo, values(none(), "bar"))`              |
 
+## Examples
+
 ### Example: Cargo-like `feature` example
 
 Consider this command line:
 
 ```bash
 rustc --check-cfg 'cfg(feature, values("lion", "zebra"))' \
-      --cfg 'feature="lion"' -Z unstable-options example.rs
+      --cfg 'feature="lion"' example.rs
 ```
 
-This command line indicates that this crate has two features: `lion` and `zebra`. The `lion`
+> This command line indicates that this crate has two features: `lion` and `zebra`. The `lion`
 feature is enabled, while the `zebra` feature is disabled.
-Given the `--check-cfg` arguments, exhaustive checking of names and
-values are enabled.
 
-`example.rs`:
 ```rust
-#[cfg(feature = "lion")]     // This condition is expected, as "lion" is an expected value of `feature`
+#[cfg(feature = "lion")]     // This condition is expected, as "lion" is an
+                             // expected value of `feature`
 fn tame_lion(lion: Lion) {}
 
-#[cfg(feature = "zebra")]    // This condition is expected, as "zebra" is an expected value of `feature`
-                             // but the condition will still evaluate to false
-                             // since only --cfg feature="lion" was passed
+#[cfg(feature = "zebra")]    // This condition is expected, as "zebra" is an expected
+                             // value of `feature` but the condition will evaluate
+                             // to false since only --cfg feature="lion" was passed
 fn ride_zebra(z: Zebra) {}
 
-#[cfg(feature = "platypus")] // This condition is UNEXPECTED, as "platypus" is NOT an expected value of
-                             // `feature` and will cause a compiler warning (by default).
+#[cfg(feature = "platypus")] // This condition is UNEXPECTED, as "platypus" is NOT
+                             // an expected value of `feature` and will cause a
+                             // the compiler to emit the `unexpected_cfgs` lint
 fn poke_platypus() {}
 
-#[cfg(feechure = "lion")]    // This condition is UNEXPECTED, as 'feechure' is NOT a expected condition
-                             // name, no `cfg(feechure, ...)` was passed in `--check-cfg`
+#[cfg(feechure = "lion")]    // This condition is UNEXPECTED, as 'feechure' is NOT
+                             // a expected condition name, no `cfg(feechure, ...)`
+                             // was passed in `--check-cfg`
 fn tame_lion() {}
 
-#[cfg(windows = "unix")]     // This condition is UNEXPECTED, as while 'windows' is a well known
-                             // condition name, it doesn't expect any values
+#[cfg(windows = "unix")]     // This condition is UNEXPECTED, as the well known
+                             // 'windows' cfg doesn't expect any values
 fn tame_windows() {}
 ```
 
@@ -166,25 +192,28 @@ fn tame_windows() {}
 ```bash
 rustc --check-cfg 'cfg(is_embedded, has_feathers)' \
       --check-cfg 'cfg(feature, values("zapping", "lasers"))' \
-      --cfg has_feathers --cfg 'feature="zapping"' -Z unstable-options
+      --cfg has_feathers --cfg 'feature="zapping"'
 ```
 
 ```rust
-#[cfg(is_embedded)]         // This condition is expected, as 'is_embedded' was provided in --check-cfg
-fn do_embedded() {}         // and doesn't take any value
+#[cfg(is_embedded)]         // This condition is expected, as 'is_embedded' was
+                            // provided in --check-cfg and doesn't take any value
+fn do_embedded() {}
 
-#[cfg(has_feathers)]        // This condition is expected, as 'has_feathers' was provided in --check-cfg
-fn do_features() {}         // and doesn't take any value
+#[cfg(has_feathers)]        // This condition is expected, as 'has_feathers' was
+                            // provided in --check-cfg and doesn't take any value
+fn do_features() {}
 
-#[cfg(has_mumble_frotz)]    // This condition is UNEXPECTED, as 'has_mumble_frotz' was NEVER provided
-                            // in any --check-cfg arguments
+#[cfg(has_mumble_frotz)]    // This condition is UNEXPECTED, as 'has_mumble_frotz'
+                            // was NEVER provided in any --check-cfg arguments
 fn do_mumble_frotz() {}
 
-#[cfg(feature = "lasers")]  // This condition is expected, as "lasers" is an expected value of `feature`
+#[cfg(feature = "lasers")]  // This condition is expected, as "lasers" is an
+                            // expected value of `feature`
 fn shoot_lasers() {}
 
-#[cfg(feature = "monkeys")] // This condition is UNEXPECTED, as "monkeys" is NOT an expected value of
-                            // `feature`
+#[cfg(feature = "monkeys")] // This condition is UNEXPECTED, as "monkeys" is NOT
+                            // an expected value of `feature`
 fn write_shakespeare() {}
 ```
 
@@ -192,24 +221,25 @@ fn write_shakespeare() {}
 
 ```bash
 rustc --check-cfg 'cfg(is_embedded, has_feathers, values(any()))' \
-      --cfg has_feathers -Z unstable-options
+      --cfg has_feathers
 ```
 
 ```rust
-#[cfg(is_embedded)]      // This condition is expected, as 'is_embedded' was provided in --check-cfg
-                         // as condition name
+#[cfg(is_embedded)]      // This condition is expected, as 'is_embedded' was
+                         // provided in --check-cfg as condition name
 fn do_embedded() {}
 
-#[cfg(has_feathers)]     // This condition is expected, as "has_feathers" was provided in --check-cfg
-                         // as condition name
+#[cfg(has_feathers)]     // This condition is expected, as "has_feathers" was
+                         // provided in --check-cfg as condition name
 fn do_features() {}
 
-#[cfg(has_feathers = "zapping")] // This condition is expected, as "has_feathers" was provided in
-                                 // and because *any* values is expected for 'has_feathers' no
+#[cfg(has_feathers = "zapping")] // This condition is expected, as "has_feathers"
+                                 // was provided and because *any* values is
+                                 // expected for 'has_feathers' no
                                  // warning is emitted for the value "zapping"
 fn do_zapping() {}
 
-#[cfg(has_mumble_frotz)] // This condition is UNEXPECTED, as 'has_mumble_frotz' was not provided
-                         // in any --check-cfg arguments
+#[cfg(has_mumble_frotz)] // This condition is UNEXPECTED, as 'has_mumble_frotz'
+                         // was not provided in any --check-cfg arguments
 fn do_mumble_frotz() {}
 ```
diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md
index 7c605333c25..3e1ac2fa8ad 100644
--- a/src/doc/rustc/src/command-line-arguments.md
+++ b/src/doc/rustc/src/command-line-arguments.md
@@ -19,9 +19,15 @@ For examples, `--cfg 'verbose'` or `--cfg 'feature="serde"'`. These correspond
 to `#[cfg(verbose)]` and `#[cfg(feature = "serde")]` respectively.
 
 <a id="option-check-cfg"></a>
-## `--check-cfg`: enables checking conditional configurations
+## `--check-cfg`: configure compile-time checking of conditional compilation
+
+This flag enables checking conditional configurations of the crate at compile-time,
+specifically it helps configure the set of expected cfg names and values, in order
+to check that every _reachable_ `#[cfg]` matches the expected config names and values.
+
+This is different from the `--cfg` flag above which activates some config but do
+not expect them. This is useful to prevent stalled conditions, typos, ...
 
-This flag will enable checking conditional configurations.
 Refer to the [Checking conditional configurations](check-cfg.md) of this book
 for further details and explanation.
 
diff --git a/src/doc/rustc/src/platform-support/fuchsia.md b/src/doc/rustc/src/platform-support/fuchsia.md
index 34ab3cdaf25..9c2e05b57f5 100644
--- a/src/doc/rustc/src/platform-support/fuchsia.md
+++ b/src/doc/rustc/src/platform-support/fuchsia.md
@@ -683,25 +683,37 @@ cd ${RUST_SRC_PATH}
 
 To run the Rust test suite on an emulated Fuchsia device, you'll also need to
 download a copy of the Fuchsia SDK. The current minimum supported SDK version is
-[10.20221207.2.89][minimum_supported_sdk_version].
+[20.20240412.3.1][minimum_supported_sdk_version].
 
-[minimum_supported_sdk_version]: https://chrome-infra-packages.appspot.com/p/fuchsia/sdk/core/linux-amd64/+/version:10.20221207.2.89
+[minimum_supported_sdk_version]: https://chrome-infra-packages.appspot.com/p/fuchsia/sdk/core/linux-amd64/+/version:20.20240412.3.1
 
 Fuchsia's test runner interacts with the Fuchsia emulator and is located at
-`src/ci/docker/scripts/fuchsia-test-runner.py`. We can use it to start our
-test environment with:
+`src/ci/docker/scripts/fuchsia-test-runner.py`. First, add the following
+variables to your existing `config-env.sh`:
+
+```sh
+# TEST_TOOLCHAIN_TMP_DIR can point anywhere, but it:
+#  - must be less than 108 characters, otherwise qemu can't handle the path
+#  - must be consistent across calls to this file (don't use `mktemp -d` here)
+export TEST_TOOLCHAIN_TMP_DIR="/tmp/rust-tmp"
+
+# Keep existing contents of `config-env.sh` from earlier, including SDK_PATH
+```
+
+We can then use the script to start our test environment with:
 
 ```sh
 ( \
+    source config-env.sh &&                                                   \
     src/ci/docker/scripts/fuchsia-test-runner.py start                        \
     --rust-build ${RUST_SRC_PATH}/build                                       \
     --sdk ${SDK_PATH}                                                         \
     --target {x86_64-unknown-fuchsia|aarch64-unknown-fuchsia}                 \
+    --verbose                                                                 \
 )
 ```
 
-Where `${RUST_SRC_PATH}/build` is the `build-dir` set in `config.toml` and
-`${SDK_PATH}` is the path to the downloaded and unzipped SDK.
+Where `${RUST_SRC_PATH}/build` is the `build-dir` set in `config.toml`.
 
 Once our environment is started, we can run our tests using `x.py` as usual. The
 test runner script will run the compiled tests on an emulated Fuchsia device. To
diff --git a/src/doc/rustc/src/platform-support/hermit.md b/src/doc/rustc/src/platform-support/hermit.md
index 146079e36f4..5aa787e53e1 100644
--- a/src/doc/rustc/src/platform-support/hermit.md
+++ b/src/doc/rustc/src/platform-support/hermit.md
@@ -4,7 +4,7 @@
 
 The [Hermit] unikernel target allows compiling your applications into self-contained, specialized unikernel images that can be run in small virtual machines.
 
-[Hermit]: https://github.com/hermitcore
+[Hermit]: https://github.com/hermit-os
 
 Target triplets available so far:
 
@@ -56,9 +56,9 @@ Rust does not yet ship pre-compiled artifacts for these targets.
 To compile for these targets, you will either need to build Rust with the targets enabled
 (see “Building the targets” above), or build your own copy of `core` by using `build-std` or similar.
 
-Building Rust programs can be done by following the tutorial in our starter application [rusty-demo].
+As all Hermit programs are unikernels, building a Rust program also requires including the operating system code. A guide for doing so is provided in our starter [hermit-rs-template].
 
-[rusty-demo]: https://github.com/hermitcore/rusty-demo
+[hermit-rs-template]: https://github.com/hermit-os/hermit-rs-template
 
 ## Testing
 
@@ -67,8 +67,8 @@ These images can be chainloaded by Hermit's [loader] or hypervisor ([Uhyve]).
 QEMU can be used to boot Hermit binaries using the loader on any architecture.
 The targets do not support running the Rust test suite.
 
-[loader]: https://github.com/hermitcore/rusty-loader
-[Uhyve]: https://github.com/hermitcore/uhyve
+[loader]: https://github.com/hermit-os/loader
+[Uhyve]: https://github.com/hermit-os/uhyve
 
 ## Cross-compilation toolchains and C code
 
diff --git a/src/doc/rustdoc/src/read-documentation/search.md b/src/doc/rustdoc/src/read-documentation/search.md
index e2def14b357..e912ca0fe5b 100644
--- a/src/doc/rustdoc/src/read-documentation/search.md
+++ b/src/doc/rustdoc/src/read-documentation/search.md
@@ -146,6 +146,7 @@ and number of matches. For example, a function with the signature
 `fn read_all(&mut self: impl Read) -> Result<Vec<u8>, Error>`
 will match these queries:
 
+* `&mut Read -> Result<Vec<u8>, Error>`
 * `Read -> Result<Vec<u8>, Error>`
 * `Read -> Result<Error, Vec>`
 * `Read -> Result<Vec<u8>>`
@@ -166,6 +167,10 @@ but you need to know which one you want.
 
 | Shorthand        | Explicit names                                    |
 | ---------------- | ------------------------------------------------- |
+| `&`              | `primitive:reference`                             |
+| `&T`             | `primitive:reference<T>`                          |
+| `&mut`           | `primitive:reference<keyword:mut>`                |
+| `&mut T`         | `primitive:reference<keyword:mut, T>`             |
 | `[]`             | `primitive:slice` and/or `primitive:array`        |
 | `[T]`            | `primitive:slice<T>` and/or `primitive:array<T>`  |
 | `()`             | `primitive:unit` and/or `primitive:tuple`         |
@@ -253,7 +258,8 @@ ident = *(ALPHA / DIGIT / "_")
 path = ident *(DOUBLE-COLON ident) [BANG]
 slice-like = OPEN-SQUARE-BRACKET [ nonempty-arg-list ] CLOSE-SQUARE-BRACKET
 tuple-like = OPEN-PAREN [ nonempty-arg-list ] CLOSE-PAREN
-arg = [type-filter *WS COLON *WS] (path [generics] / slice-like / tuple-like)
+borrow-ref = AMP *WS [MUT] *WS [arg]
+arg = [type-filter *WS COLON *WS] (path [generics] / slice-like / tuple-like / borrow-ref)
 type-sep = COMMA/WS *(COMMA/WS)
 nonempty-arg-list = *(type-sep) arg *(type-sep arg) *(type-sep) [ return-args ]
 generic-arg-list = *(type-sep) arg [ EQUAL arg ] *(type-sep arg [ EQUAL arg ]) *(type-sep)
@@ -310,6 +316,8 @@ COMMA = ","
 RETURN-ARROW = "->"
 EQUAL = "="
 BANG = "!"
+AMP = "&"
+MUT = "mut"
 
 ALPHA = %x41-5A / %x61-7A ; A-Z / a-z
 DIGIT = %x30-39
diff --git a/src/doc/unstable-book/src/language-features/exclusive-range-pattern.md b/src/doc/unstable-book/src/language-features/exclusive-range-pattern.md
deleted file mode 100644
index d26512703f4..00000000000
--- a/src/doc/unstable-book/src/language-features/exclusive-range-pattern.md
+++ /dev/null
@@ -1,26 +0,0 @@
-# `exclusive_range_pattern`
-
-The tracking issue for this feature is: [#37854].
-
-
-[#67264]: https://github.com/rust-lang/rust/issues/67264
-[#37854]: https://github.com/rust-lang/rust/issues/37854
------
-
-The `exclusive_range_pattern` feature allows non-inclusive range
-patterns (`0..10`) to be used in appropriate pattern matching
-contexts. It also can be combined with `#![feature(half_open_range_patterns]`
-to be able to use RangeTo patterns (`..10`).
-
-It also enabled RangeFrom patterns but that has since been
-stabilized.
-
-```rust
-#![feature(exclusive_range_pattern)]
-    let x = 5;
-    match x {
-        0..10 => println!("single digit"),
-        10 => println!("ten isn't part of the above range"),
-        _ => println!("nor is everything else.")
-    }
-```
diff --git a/src/doc/unstable-book/src/language-features/half-open-range-patterns-in-slices.md b/src/doc/unstable-book/src/language-features/half-open-range-patterns-in-slices.md
index 56a1a97df16..93e9bc32ff0 100644
--- a/src/doc/unstable-book/src/language-features/half-open-range-patterns-in-slices.md
+++ b/src/doc/unstable-book/src/language-features/half-open-range-patterns-in-slices.md
@@ -1,7 +1,7 @@
 # `half_open_range_patterns_in_slices`
 
 The tracking issue for this feature is: [#67264]
-It is part of the `exclusive_range_pattern` feature,
+It is a future part of the `exclusive_range_pattern` feature,
 tracked at [#37854].
 
 [#67264]: https://github.com/rust-lang/rust/issues/67264
@@ -12,7 +12,6 @@ This feature allow using top-level half-open range patterns in slices.
 
 ```rust
 #![feature(half_open_range_patterns_in_slices)]
-#![feature(exclusive_range_pattern)]
 
 fn main() {
     let xs = [13, 1, 5, 2, 3, 1, 21, 8];
diff --git a/src/doc/unstable-book/src/language-features/result-ffi-guarantees.md b/src/doc/unstable-book/src/language-features/result-ffi-guarantees.md
new file mode 100644
index 00000000000..dc9c196524e
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/result-ffi-guarantees.md
@@ -0,0 +1,14 @@
+# `result_ffi_guarantees`
+
+The tracking issue for this feature is: [#110503]
+
+[#110503]: https://github.com/rust-lang/rust/issues/110503
+
+------------------------
+
+This feature adds the possibility of using `Result<T, E>` in FFI if T's niche
+value can be used to describe E or vise-versa.
+
+See [RFC 3391] for more information.
+
+[RFC 3391]: https://github.com/rust-lang/rfcs/blob/master/text/3391-result_ffi_guarantees.md
diff --git a/src/etc/lldb_lookup.py b/src/etc/lldb_lookup.py
index a93b42e1cc4..db3afb00369 100644
--- a/src/etc/lldb_lookup.py
+++ b/src/etc/lldb_lookup.py
@@ -86,7 +86,8 @@ def synthetic_lookup(valobj, dict):
         return synthetic_lookup(valobj.GetChildAtIndex(discriminant), dict)
     if rust_type == RustType.SINGLETON_ENUM:
         return synthetic_lookup(valobj.GetChildAtIndex(0), dict)
-
+    if rust_type == RustType.ENUM:
+        return ClangEncodedEnumProvider(valobj, dict)
     if rust_type == RustType.STD_VEC:
         return StdVecSyntheticProvider(valobj, dict)
     if rust_type == RustType.STD_VEC_DEQUE:
diff --git a/src/etc/lldb_providers.py b/src/etc/lldb_providers.py
index 1c43977a501..a87fd6078b8 100644
--- a/src/etc/lldb_providers.py
+++ b/src/etc/lldb_providers.py
@@ -247,6 +247,58 @@ class StructSyntheticProvider:
         # type: () -> bool
         return True
 
+class ClangEncodedEnumProvider:
+    """Pretty-printer for 'clang-encoded' enums support implemented in LLDB"""
+    DISCRIMINANT_MEMBER_NAME = "$discr$"
+    VALUE_MEMBER_NAME = "value"
+
+    def __init__(self, valobj, dict):
+        self.valobj = valobj
+        self.update()
+
+    def has_children(self):
+       return True
+
+    def num_children(self):
+        if self.is_default:
+            return 1
+        return 2
+
+    def get_child_index(self, name):
+        if name == ClangEncodedEnumProvider.VALUE_MEMBER_NAME:
+            return 0
+        if name == ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME:
+            return 1
+        return -1
+
+    def get_child_at_index(self, index):
+        if index == 0:
+            return self.variant.GetChildMemberWithName(ClangEncodedEnumProvider.VALUE_MEMBER_NAME)
+        if index == 1:
+            return self.variant.GetChildMemberWithName(
+                ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME)
+
+
+    def update(self):
+        all_variants = self.valobj.GetChildAtIndex(0)
+        index = self._getCurrentVariantIndex(all_variants)
+        self.variant = all_variants.GetChildAtIndex(index)
+        self.is_default = self.variant.GetIndexOfChildWithName(
+            ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME) == -1
+
+    def _getCurrentVariantIndex(self, all_variants):
+        default_index = 0
+        for i in range(all_variants.GetNumChildren()):
+            variant = all_variants.GetChildAtIndex(i)
+            discr = variant.GetChildMemberWithName(
+                ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME)
+            if discr.IsValid():
+                discr_unsigned_value = discr.GetValueAsUnsigned()
+                if variant.GetName() == f"$variant${discr_unsigned_value}":
+                    return i
+            else:
+                default_index = i
+        return default_index
 
 class TupleSyntheticProvider:
     """Pretty-printer for tuples and tuple enum variants"""
diff --git a/src/etc/rust_types.py b/src/etc/rust_types.py
index c0415a3cdcf..190fbc13a17 100644
--- a/src/etc/rust_types.py
+++ b/src/etc/rust_types.py
@@ -60,6 +60,7 @@ TUPLE_ITEM_REGEX = re.compile(r"__\d+$")
 
 ENCODED_ENUM_PREFIX = "RUST$ENCODED$ENUM$"
 ENUM_DISR_FIELD_NAME = "<<variant>>"
+ENUM_LLDB_ENCODED_VARIANTS = "$variants$"
 
 STD_TYPE_TO_REGEX = {
     RustType.STD_STRING: STD_STRING_REGEX,
@@ -96,7 +97,11 @@ def classify_struct(name, fields):
         if regex.match(name):
             return ty
 
-    if fields[0].name == ENUM_DISR_FIELD_NAME:
+    # <<variant>> is emitted by GDB while LLDB(18.1+) emits "$variants$"
+    if (
+        fields[0].name == ENUM_DISR_FIELD_NAME
+        or fields[0].name == ENUM_LLDB_ENCODED_VARIANTS
+    ):
         return RustType.ENUM
 
     if is_tuple_fields(fields):
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index daf63998461..c464820413c 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -150,7 +150,7 @@ fn clean_param_env<'tcx>(
     let generics = tcx.generics_of(item_def_id);
 
     let params: ThinVec<_> = generics
-        .params
+        .own_params
         .iter()
         .inspect(|param| {
             if cfg!(debug_assertions) {
@@ -326,7 +326,7 @@ fn clean_region_outlives_constraints<'tcx>(
     }
 
     let region_params: FxIndexSet<_> = generics
-        .params
+        .own_params
         .iter()
         .filter_map(|param| match param.kind {
             ty::GenericParamDefKind::Lifetime => Some(param.name),
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 4d506edc47b..7d8b6f34cbb 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -14,6 +14,7 @@ use rustc_hir::Mutability;
 use rustc_metadata::creader::{CStore, LoadedMacro};
 use rustc_middle::ty::fast_reject::SimplifiedType;
 use rustc_middle::ty::{self, TyCtxt};
+use rustc_span::def_id::LOCAL_CRATE;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{kw, sym, Symbol};
 
@@ -444,24 +445,24 @@ pub(crate) fn build_impl(
 
     let associated_trait = tcx.impl_trait_ref(did).map(ty::EarlyBinder::skip_binder);
 
+    // Do not inline compiler-internal items unless we're a compiler-internal crate.
+    let is_compiler_internal = |did| {
+        tcx.lookup_stability(did)
+            .is_some_and(|stab| stab.is_unstable() && stab.feature == sym::rustc_private)
+    };
+    let document_compiler_internal = is_compiler_internal(LOCAL_CRATE.as_def_id());
+    let is_directly_public = |cx: &mut DocContext<'_>, did| {
+        cx.cache.effective_visibilities.is_directly_public(tcx, did)
+            && (document_compiler_internal || !is_compiler_internal(did))
+    };
+
     // Only inline impl if the implemented trait is
     // reachable in rustdoc generated documentation
     if !did.is_local()
         && let Some(traitref) = associated_trait
+        && !is_directly_public(cx, traitref.def_id)
     {
-        let did = traitref.def_id;
-        if !cx.cache.effective_visibilities.is_directly_public(tcx, did) {
-            return;
-        }
-
-        if !tcx.features().rustc_private && !cx.render_options.force_unstable_if_unmarked {
-            if let Some(stab) = tcx.lookup_stability(did)
-                && stab.is_unstable()
-                && stab.feature == sym::rustc_private
-            {
-                return;
-            }
-        }
+        return;
     }
 
     let impl_item = match did.as_local() {
@@ -484,21 +485,11 @@ pub(crate) fn build_impl(
 
     // Only inline impl if the implementing type is
     // reachable in rustdoc generated documentation
-    if !did.is_local() {
-        if let Some(did) = for_.def_id(&cx.cache) {
-            if !cx.cache.effective_visibilities.is_directly_public(tcx, did) {
-                return;
-            }
-
-            if !tcx.features().rustc_private && !cx.render_options.force_unstable_if_unmarked {
-                if let Some(stab) = tcx.lookup_stability(did)
-                    && stab.is_unstable()
-                    && stab.feature == sym::rustc_private
-                {
-                    return;
-                }
-            }
-        }
+    if !did.is_local()
+        && let Some(did) = for_.def_id(&cx.cache)
+        && !is_directly_public(cx, did)
+    {
+        return;
     }
 
     let document_hidden = cx.render_options.document_hidden;
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index f437c7d319d..90f2e3d09fe 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -795,7 +795,7 @@ fn clean_ty_generics<'tcx>(
     let mut impl_trait = BTreeMap::<u32, Vec<GenericBound>>::default();
 
     let params: ThinVec<_> = gens
-        .params
+        .own_params
         .iter()
         .filter(|param| match param.kind {
             ty::GenericParamDefKind::Lifetime => !param.is_anonymous_lifetime(),
@@ -1860,9 +1860,9 @@ fn normalize<'tcx>(
         return None;
     }
 
-    use crate::rustc_trait_selection::infer::TyCtxtInferExt;
-    use crate::rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
     use rustc_middle::traits::ObligationCause;
+    use rustc_trait_selection::infer::TyCtxtInferExt;
+    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();
@@ -1988,7 +1988,7 @@ impl<'tcx> ContainerTy<'_, 'tcx> {
                 let generics = tcx.generics_of(container);
                 debug_assert_eq!(generics.parent_count, 0);
 
-                let param = generics.params[index].def_id;
+                let param = generics.own_params[index].def_id;
                 let default = tcx.object_lifetime_default(param);
                 match default {
                     rbv::ObjectLifetimeDefault::Param(lifetime) => {
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 465f969435d..d4468fecba4 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -285,8 +285,6 @@ pub(crate) struct RenderOptions {
     pub(crate) no_emit_shared: bool,
     /// If `true`, HTML source code pages won't be generated.
     pub(crate) html_no_source: bool,
-    /// Whether `-Zforce-unstable-if-unmarked` unstable option is set
-    pub(crate) force_unstable_if_unmarked: bool,
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -353,7 +351,6 @@ impl Options {
 
         let codegen_options = CodegenOptions::build(early_dcx, matches);
         let unstable_opts = UnstableOptions::build(early_dcx, matches);
-        let force_unstable_if_unmarked = unstable_opts.force_unstable_if_unmarked;
 
         let dcx = new_dcx(error_format, None, diagnostic_width, &unstable_opts);
 
@@ -790,7 +787,6 @@ impl Options {
             call_locations,
             no_emit_shared: false,
             html_no_source,
-            force_unstable_if_unmarked,
         };
         Some((options, render_options))
     }
diff --git a/src/librustdoc/externalfiles.rs b/src/librustdoc/externalfiles.rs
index 57e82b877bf..6beca8bdb3a 100644
--- a/src/librustdoc/externalfiles.rs
+++ b/src/librustdoc/externalfiles.rs
@@ -1,5 +1,5 @@
 use crate::html::markdown::{ErrorCodes, HeadingOffset, IdMap, Markdown, Playground};
-use crate::rustc_span::edition::Edition;
+use rustc_span::edition::Edition;
 use std::fs;
 use std::path::Path;
 use std::str;
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index f82b89fdd5f..241dc37ab9c 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -594,9 +594,9 @@ fn generate_item_def_id_path(
     root_path: Option<&str>,
     original_def_kind: DefKind,
 ) -> Result<(String, ItemType, Vec<Symbol>), HrefError> {
-    use crate::rustc_trait_selection::infer::TyCtxtInferExt;
-    use crate::rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
     use rustc_middle::traits::ObligationCause;
+    use rustc_trait_selection::infer::TyCtxtInferExt;
+    use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
 
     let tcx = cx.tcx();
     let crate_name = tcx.crate_name(def_id.krate);
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 09a53affb14..b4e62e39d8d 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -52,6 +52,7 @@ use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir::def_id::{DefId, DefIdSet};
 use rustc_hir::Mutability;
+use rustc_middle::ty::print::PrintTraitRefExt;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::RustcVersion;
 use rustc_span::{
@@ -182,6 +183,7 @@ pub(crate) enum RenderTypeId {
     Primitive(clean::PrimitiveType),
     AssociatedType(Symbol),
     Index(isize),
+    Mut,
 }
 
 impl RenderTypeId {
diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs
index 6d2bb31ee13..e635c1e611d 100644
--- a/src/librustdoc/html/render/search_index.rs
+++ b/src/librustdoc/html/render/search_index.rs
@@ -7,7 +7,7 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
 use rustc_middle::ty::TyCtxt;
 use rustc_span::def_id::DefId;
 use rustc_span::sym;
-use rustc_span::symbol::Symbol;
+use rustc_span::symbol::{kw, Symbol};
 use serde::ser::{Serialize, SerializeSeq, SerializeStruct, Serializer};
 use thin_vec::ThinVec;
 
@@ -163,6 +163,15 @@ pub(crate) fn build_index<'tcx>(
         ) -> Option<RenderTypeId> {
             let Cache { ref paths, ref external_paths, ref exact_paths, .. } = *cache;
             match id {
+                RenderTypeId::Mut => Some(insert_into_map(
+                    primitives,
+                    kw::Mut,
+                    lastpathid,
+                    crate_paths,
+                    ItemType::Keyword,
+                    &[kw::Mut],
+                    None,
+                )),
                 RenderTypeId::DefId(defid) => {
                     if let Some(&(ref fqp, item_type)) =
                         paths.get(&defid).or_else(|| external_paths.get(&defid))
@@ -765,9 +774,8 @@ fn get_index_type_id(
             bounds.get(0).map(|b| RenderTypeId::DefId(b.trait_.def_id()))
         }
         clean::Primitive(p) => Some(RenderTypeId::Primitive(p)),
-        clean::BorrowedRef { ref type_, .. } | clean::RawPointer(_, ref type_) => {
-            get_index_type_id(type_, rgen)
-        }
+        clean::BorrowedRef { .. } => Some(RenderTypeId::Primitive(clean::PrimitiveType::Reference)),
+        clean::RawPointer(_, ref type_) => get_index_type_id(type_, rgen),
         // The type parameters are converted to generics in `simplify_fn_type`
         clean::Slice(_) => Some(RenderTypeId::Primitive(clean::PrimitiveType::Slice)),
         clean::Array(_, _) => Some(RenderTypeId::Primitive(clean::PrimitiveType::Array)),
@@ -833,28 +841,14 @@ fn simplify_fn_type<'tcx, 'a>(
     }
 
     // First, check if it's "Self".
-    let mut is_self = false;
-    let mut arg = if let Some(self_) = self_ {
-        match &*arg {
-            Type::BorrowedRef { type_, .. } if type_.is_self_type() => {
-                is_self = true;
-                self_
-            }
-            type_ if type_.is_self_type() => {
-                is_self = true;
-                self_
-            }
-            arg => arg,
-        }
+    let (is_self, arg) = if let Some(self_) = self_
+        && arg.is_self_type()
+    {
+        (true, self_)
     } else {
-        arg
+        (false, arg)
     };
 
-    // strip references from the argument type
-    while let Type::BorrowedRef { type_, .. } = &*arg {
-        arg = &*type_;
-    }
-
     // If this argument is a type parameter and not a trait bound or a type, we need to look
     // for its bounds.
     if let Type::Generic(arg_s) = *arg {
@@ -1027,6 +1021,27 @@ fn simplify_fn_type<'tcx, 'a>(
             bindings: Some(ty_bindings),
             generics: Some(ty_generics),
         });
+    } else if let Type::BorrowedRef { lifetime: _, mutability, ref type_ } = *arg {
+        let mut ty_generics = Vec::new();
+        if mutability.is_mut() {
+            ty_generics.push(RenderType {
+                id: Some(RenderTypeId::Mut),
+                generics: None,
+                bindings: None,
+            });
+        }
+        simplify_fn_type(
+            self_,
+            generics,
+            &type_,
+            tcx,
+            recurse + 1,
+            &mut ty_generics,
+            rgen,
+            is_return,
+            cache,
+        );
+        res.push(get_index_type(arg, ty_generics, rgen));
     } else {
         // This is not a type parameter. So for example if we have `T, U: Option<T>`, and we're
         // looking at `Option`, we enter this "else" condition, otherwise if it's `T`, we don't.
diff --git a/src/librustdoc/html/static/css/noscript.css b/src/librustdoc/html/static/css/noscript.css
index ccb97d7df4c..6e10cf21537 100644
--- a/src/librustdoc/html/static/css/noscript.css
+++ b/src/librustdoc/html/static/css/noscript.css
@@ -85,6 +85,7 @@ nav.sub {
 	--search-tab-button-not-selected-background: #e6e6e6;
 	--search-tab-button-selected-border-top-color: #0089ff;
 	--search-tab-button-selected-background: #fff;
+	--settings-menu-filter: none;
 	--stab-background-color: #fff5d6;
 	--stab-code-color: #000;
 	--code-highlight-kw-color: #8959a8;
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 80a4ea0424a..4c0ba75d261 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -1625,6 +1625,7 @@ a.tooltip:hover::after {
 	,5.1715698,7.5,6  S6.8284302,7.5,6,7.5z" fill="black"/></svg>');
 	width: 22px;
 	height: 22px;
+	filter: var(--settings-menu-filter);
 }
 
 #sidebar-button > a:before {
@@ -2419,6 +2420,7 @@ by default.
 	--search-tab-button-not-selected-background: #e6e6e6;
 	--search-tab-button-selected-border-top-color: #0089ff;
 	--search-tab-button-selected-background: #fff;
+	--settings-menu-filter: none;
 	--stab-background-color: #fff5d6;
 	--stab-code-color: #000;
 	--code-highlight-kw-color: #8959a8;
@@ -2524,6 +2526,7 @@ by default.
 	--search-tab-button-not-selected-background: #252525;
 	--search-tab-button-selected-border-top-color: #0089ff;
 	--search-tab-button-selected-background: #353535;
+	--settings-menu-filter: none;
 	--stab-background-color: #314559;
 	--stab-code-color: #e6e1cf;
 	--code-highlight-kw-color: #ab8ac1;
@@ -2636,6 +2639,7 @@ Original by Dempfi (https://github.com/dempfi/ayu)
 	--search-tab-button-not-selected-background: transparent !important;
 	--search-tab-button-selected-border-top-color: none;
 	--search-tab-button-selected-background: #141920 !important;
+	--settings-menu-filter: invert(100%);
 	--stab-background-color: #314559;
 	--stab-code-color: #e6e1cf;
 	--code-highlight-kw-color: #ff7733;
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index 41a9897de6d..76a6fc9008e 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -786,6 +786,37 @@ function initSearch(rawSearchIndex) {
                 }
                 elems.push(makePrimitiveElement(name, { bindingName, generics }));
             }
+        } else if (parserState.userQuery[parserState.pos] === "&") {
+            if (parserState.typeFilter !== null && parserState.typeFilter !== "primitive") {
+                throw [
+                    "Invalid search type: primitive ",
+                    "&",
+                    " and ",
+                    parserState.typeFilter,
+                    " both specified",
+                ];
+            }
+            parserState.typeFilter = null;
+            parserState.pos += 1;
+            let c = parserState.userQuery[parserState.pos];
+            while (c === " " && parserState.pos < parserState.length) {
+                parserState.pos += 1;
+                c = parserState.userQuery[parserState.pos];
+            }
+            const generics = [];
+            if (parserState.userQuery.slice(parserState.pos, parserState.pos + 3) === "mut") {
+                generics.push(makePrimitiveElement("mut", { typeFilter: "keyword"}));
+                parserState.pos += 3;
+                c = parserState.userQuery[parserState.pos];
+            }
+            while (c === " " && parserState.pos < parserState.length) {
+                parserState.pos += 1;
+                c = parserState.userQuery[parserState.pos];
+            }
+            if (!isEndCharacter(c) && parserState.pos < parserState.length) {
+                getFilteredNextElem(query, parserState, generics, isInGenerics);
+            }
+            elems.push(makePrimitiveElement("reference", { generics }));
         } else {
             const isStringElem = parserState.userQuery[start] === "\"";
             // We handle the strings on their own mostly to make code easier to follow.
diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js
index 73c543567c0..4a27ca92fff 100644
--- a/src/librustdoc/html/static/js/storage.js
+++ b/src/librustdoc/html/static/js/storage.js
@@ -239,3 +239,46 @@ window.addEventListener("pageshow", ev => {
         setTimeout(updateSidebarWidth, 0);
     }
 });
+
+// Custom elements are used to insert some JS-dependent features into Rustdoc,
+// because the [parser] runs the connected callback
+// synchronously. It needs to be added synchronously so that nothing below it
+// becomes visible until after it's done. Otherwise, you get layout jank.
+//
+// That's also why this is in storage.js and not main.js.
+//
+// [parser]: https://html.spec.whatwg.org/multipage/parsing.html
+class RustdocSearchElement extends HTMLElement {
+    constructor() {
+        super();
+    }
+    connectedCallback() {
+        const rootPath = getVar("root-path");
+        const currentCrate = getVar("current-crate");
+        this.innerHTML = `<nav class="sub">
+            <form class="search-form">
+                <span></span> <!-- This empty span is a hacky fix for Safari - See #93184 -->
+                <div id="sidebar-button" tabindex="-1">
+                    <a href="${rootPath}${currentCrate}/all.html" title="show sidebar"></a>
+                </div>
+                <input
+                    class="search-input"
+                    name="search"
+                    aria-label="Run search in the documentation"
+                    autocomplete="off"
+                    spellcheck="false"
+                    placeholder="Type ‘S’ or ‘/’ to search, ‘?’ for more options…"
+                    type="search">
+                <div id="help-button" tabindex="-1">
+                    <a href="${rootPath}help.html" title="help">?</a>
+                </div>
+                <div id="settings-menu" tabindex="-1">
+                    <a href="${rootPath}settings.html" title="settings">
+                        Settings
+                    </a>
+                </div>
+            </form>
+        </nav>`;
+    }
+}
+window.customElements.define("rustdoc-search", RustdocSearchElement);
diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html
index 1e01cd70b96..cdf01fa7a97 100644
--- a/src/librustdoc/html/templates/page.html
+++ b/src/librustdoc/html/templates/page.html
@@ -117,30 +117,9 @@
     <div class="sidebar-resizer"></div> {# #}
     <main> {# #}
         {% if page.css_class != "src" %}<div class="width-limiter">{% endif %}
-            <nav class="sub"> {# #}
-                <form class="search-form"> {# #}
-                    <span></span> {# This empty span is a hacky fix for Safari - See #93184 #}
-                    <div id="sidebar-button" tabindex="-1"> {# #}
-                        <a href="{{page.root_path|safe}}{{layout.krate|safe}}/all.html" title="show sidebar"></a> {# #}
-                    </div> {# #}
-                    <input {#+ #}
-                        class="search-input" {#+ #}
-                        name="search" {#+ #}
-                        aria-label="Run search in the documentation" {#+ #}
-                        autocomplete="off" {#+ #}
-                        spellcheck="false" {#+ #}
-                        placeholder="Type ‘S’ or ‘/’ to search, ‘?’ for more options…" {#+ #}
-                        type="search"> {# #}
-                    <div id="help-button" tabindex="-1"> {# #}
-                        <a href="{{page.root_path|safe}}help.html" title="help">?</a> {# #}
-                    </div> {# #}
-                    <div id="settings-menu" tabindex="-1"> {# #}
-                        <a href="{{page.root_path|safe}}settings.html" title="settings"> {# #}
-                            Settings {# #}
-                        </a> {# #}
-                    </div> {# #}
-                </form> {# #}
-            </nav> {# #}
+            {# defined in storage.js to avoid duplicating complex UI across every page #}
+            {# and because the search form only works if JS is enabled anyway #}
+            <rustdoc-search></rustdoc-search> {# #}
             <section id="main-content" class="content">{{ content|safe }}</section> {# #}
         {% if page.css_class != "src" %}</div>{% endif %}
     </main> {# #}
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index f3972346bb5..bed76263b45 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -236,7 +236,7 @@ fn main() {
     let num_threads = if let Some(num) = env::var_os("BUILD_MANIFEST_NUM_THREADS") {
         num.to_str().unwrap().parse().expect("invalid number for BUILD_MANIFEST_NUM_THREADS")
     } else {
-        std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get)
+        std::thread::available_parallelism().map_or(1, std::num::NonZero::get)
     };
     rayon::ThreadPoolBuilder::new()
         .num_threads(num_threads)
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 05364cb2f61a2c2b091e061c1f42b207dfb5f81
+Subproject 4de0094ac78743d2c8ff682489e35c8a7cafe8e
diff --git a/src/tools/clippy/clippy_lints/src/default_union_representation.rs b/src/tools/clippy/clippy_lints/src/default_union_representation.rs
index 3f87ed8df2b..b4290b6437f 100644
--- a/src/tools/clippy/clippy_lints/src/default_union_representation.rs
+++ b/src/tools/clippy/clippy_lints/src/default_union_representation.rs
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_help;
 use rustc_hir::{HirId, Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::layout::LayoutOf;
-use rustc_middle::ty::{self, FieldDef, GenericArg, List};
+use rustc_middle::ty::{self, FieldDef};
 use rustc_session::declare_lint_pass;
 use rustc_span::sym;
 
@@ -85,7 +85,7 @@ fn is_union_with_two_non_zst_fields<'tcx>(cx: &LateContext<'tcx>, item: &Item<'t
     }
 }
 
-fn is_zst<'tcx>(cx: &LateContext<'tcx>, field: &FieldDef, args: &'tcx List<GenericArg<'tcx>>) -> bool {
+fn is_zst<'tcx>(cx: &LateContext<'tcx>, field: &FieldDef, args: ty::GenericArgsRef<'tcx>) -> bool {
     let ty = field.ty(cx.tcx, args);
     if let Ok(layout) = cx.layout_of(ty) {
         layout.is_zst()
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index b936b28470b..c6aef9ac2d6 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -382,7 +382,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
                                         cx,
                                         impl_ty,
                                         trait_id,
-                                        &args[..cx.tcx.generics_of(trait_id).params.len() - 1],
+                                        &args[..cx.tcx.generics_of(trait_id).own_params.len() - 1],
                                     )
                                 {
                                     false
diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs
index 42cd19fb8ec..9662c8f4fe2 100644
--- a/src/tools/clippy/clippy_lints/src/derive.rs
+++ b/src/tools/clippy/clippy_lints/src/derive.rs
@@ -480,7 +480,7 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) ->
     // Vec<(param_def, needs_eq)>
     let mut params = tcx
         .generics_of(did)
-        .params
+        .own_params
         .iter()
         .map(|p| (p, matches!(p.kind, GenericParamDefKind::Type { .. })))
         .collect::<Vec<_>>();
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 18f4e51ebd6..2c2daac0234 100644
--- a/src/tools/clippy/clippy_lints/src/future_not_send.rs
+++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs
@@ -5,6 +5,7 @@ use rustc_hir::{Body, FnDecl};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::{self, AliasTy, ClauseKind, PredicateKind};
+use rustc_middle::ty::print::PrintTraitRefExt;
 use rustc_session::declare_lint_pass;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::{sym, Span};
diff --git a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs
index 3bf8d618955..dc935ed3d7f 100644
--- a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs
+++ b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs
@@ -148,7 +148,7 @@ fn try_resolve_type<'tcx>(
     match args.get(index - 1) {
         Some(GenericArg::Type(ty)) => Some(lower_ty(tcx, ty)),
         Some(_) => None,
-        None => Some(tcx.type_of(generics.params[index].def_id).skip_binder()),
+        None => Some(tcx.type_of(generics.own_params[index].def_id).skip_binder()),
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs
index c749a712330..a75dfaf286f 100644
--- a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs
+++ b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs
@@ -225,7 +225,7 @@ impl {self_ty_without_ref} {{
             && let ImplItemKind::Fn(sig, _) = item.kind
             && let FnRetTy::Return(ret) = sig.decl.output
             && is_nameable_in_impl_trait(ret)
-            && cx.tcx.generics_of(item_did).params.is_empty()
+            && cx.tcx.generics_of(item_did).own_params.is_empty()
             && sig.decl.implicit_self == expected_implicit_self
             && sig.decl.inputs.len() == 1
             && let Some(imp) = get_parent_as_impl(cx.tcx, item.hir_id())
diff --git a/src/tools/clippy/clippy_lints/src/manual_assert.rs b/src/tools/clippy/clippy_lints/src/manual_assert.rs
index d76b94eba23..83c16d4466d 100644
--- a/src/tools/clippy/clippy_lints/src/manual_assert.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_assert.rs
@@ -1,10 +1,9 @@
-use crate::rustc_lint::LintContext;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::macros::{is_panic, root_macro_call};
 use clippy_utils::{is_else_clause, is_parent_stmt, peel_blocks_with_stmt, span_extract_comment, sugg};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, UnOp};
-use rustc_lint::{LateContext, LateLintPass};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_session::declare_lint_pass;
 
 declare_clippy_lint! {
diff --git a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
index 10c3203725a..f775ea072e1 100644
--- a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
@@ -6,7 +6,7 @@ use rustc_errors::{Applicability, Diag};
 use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_hir::{Arm, Expr, ExprKind, MatchSource};
 use rustc_lint::{LateContext, LintContext};
-use rustc_middle::ty::{GenericArgKind, Ty, TypeAndMut};
+use rustc_middle::ty::{GenericArgKind, Ty};
 use rustc_span::Span;
 
 use super::SIGNIFICANT_DROP_IN_SCRUTINEE;
@@ -234,9 +234,9 @@ impl<'a, 'tcx> SigDropHelper<'a, 'tcx> {
         }
         let ty = self.sig_drop_checker.get_type(expr);
         if ty.is_ref() {
-            // We checked that the type was ref, so builtin_deref will return Some TypeAndMut,
-            // but let's avoid any chance of an ICE
-            if let Some(TypeAndMut { ty, .. }) = ty.builtin_deref(true) {
+            // We checked that the type was ref, so builtin_deref will return Some,
+            // but let's avoid any chance of an ICE.
+            if let Some(ty) = ty.builtin_deref(true) {
                 if ty.is_trivially_pure_clone_copy() {
                     self.replace_current_sig_drop(expr.span, false, LintSuggestion::MoveAndDerefToCopy);
                 } else if allow_move_and_clone {
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs b/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs
index 03b4680c522..deac159457a 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs
@@ -9,10 +9,10 @@ use rustc_lint::LateContext;
 use rustc_middle::mir::{FakeReadCause, Mutability};
 use rustc_middle::ty::{self, BorrowKind};
 use rustc_span::sym;
+use rustc_trait_selection::infer::TyCtxtInferExt;
 
 use super::ITER_OVEREAGER_CLONED;
 use crate::redundant_clone::REDUNDANT_CLONE;
-use crate::rustc_trait_selection::infer::TyCtxtInferExt;
 
 #[derive(Clone, Copy)]
 pub(super) enum Op<'a> {
diff --git a/src/tools/clippy/clippy_lints/src/mismatching_type_param_order.rs b/src/tools/clippy/clippy_lints/src/mismatching_type_param_order.rs
index 0842a872824..934b9f490ad 100644
--- a/src/tools/clippy/clippy_lints/src/mismatching_type_param_order.rs
+++ b/src/tools/clippy/clippy_lints/src/mismatching_type_param_order.rs
@@ -76,7 +76,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeParamMismatch {
             };
 
             // get the names of the generic parameters in the type
-            let type_params = &cx.tcx.generics_of(defid).params;
+            let type_params = &cx.tcx.generics_of(defid).own_params;
             let type_param_names: Vec<_> = type_params
                 .iter()
                 .filter_map(|p| match p.kind {
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 a24cd4f9c8a..e6c6a15b8d4 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
@@ -13,7 +13,7 @@ use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::mir::{Rvalue, StatementKind};
 use rustc_middle::ty::{
-    self, ClauseKind, EarlyBinder, FnSig, GenericArg, GenericArgKind, List, ParamTy, ProjectionPredicate, Ty,
+    self, ClauseKind, EarlyBinder, FnSig, GenericArg, GenericArgKind, ParamTy, ProjectionPredicate, Ty,
 };
 use rustc_session::impl_lint_pass;
 use rustc_span::symbol::sym;
@@ -161,7 +161,7 @@ fn needless_borrow_count<'tcx>(
     cx: &LateContext<'tcx>,
     possible_borrowers: &mut Vec<(LocalDefId, PossibleBorrowerMap<'tcx, 'tcx>)>,
     fn_id: DefId,
-    callee_args: &'tcx List<GenericArg<'tcx>>,
+    callee_args: ty::GenericArgsRef<'tcx>,
     arg_index: usize,
     param_ty: ParamTy,
     mut expr: &Expr<'tcx>,
diff --git a/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs b/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs
index ea8ed28ba62..208b20a7a06 100644
--- a/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs
@@ -70,7 +70,7 @@ fn check_op(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: bool)
     let without_deref = symmetric_partial_eq(cx, arg_ty, other_ty).unwrap_or_default();
     let with_deref = arg_ty
         .builtin_deref(true)
-        .and_then(|tam| symmetric_partial_eq(cx, tam.ty, other_ty))
+        .and_then(|ty| symmetric_partial_eq(cx, ty, other_ty))
         .unwrap_or_default();
 
     if !with_deref.is_implemented() && !without_deref.is_implemented() {
diff --git a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
index 2863eb190d3..47d3ed08b8e 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
@@ -1,4 +1,3 @@
-use crate::rustc_lint::LintContext;
 use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir};
 use clippy_utils::get_parent_expr;
 use clippy_utils::sugg::Sugg;
@@ -9,7 +8,7 @@ use rustc_hir::intravisit::{Visitor as HirVisitor, Visitor};
 use rustc_hir::{
     intravisit as hir_visit, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, ExprKind, Node,
 };
-use rustc_lint::{LateContext, LateLintPass};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty;
diff --git a/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs b/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs
index 6540626f7d5..63237c655ef 100644
--- a/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs
+++ b/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs
@@ -1,9 +1,8 @@
-use crate::rustc_lint::LintContext;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_context;
 use rustc_errors::Applicability;
 use rustc_hir::{Block, ExprKind};
-use rustc_lint::{LateContext, LateLintPass};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_session::declare_lint_pass;
 use rustc_span::{ExpnKind, MacroKind, Span};
 
diff --git a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
index 18fbbdb4079..acf44a9bb5a 100644
--- a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
+++ b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
@@ -201,8 +201,8 @@ impl SingleComponentPathImports {
 
                 if segments.is_empty() {
                     // keep track of `use {some_module, some_other_module};` usages
-                    if let UseTreeKind::Nested(trees) = &use_tree.kind {
-                        for tree in trees {
+                    if let UseTreeKind::Nested { items, .. } = &use_tree.kind {
+                        for tree in items {
                             let segments = &tree.0.prefix.segments;
                             if segments.len() == 1 {
                                 if let UseTreeKind::Simple(None) = tree.0.kind {
@@ -229,8 +229,8 @@ impl SingleComponentPathImports {
                         }
 
                         // nested case such as `use self::{module1::Struct1, module2::Struct2}`
-                        if let UseTreeKind::Nested(trees) = &use_tree.kind {
-                            for tree in trees {
+                        if let UseTreeKind::Nested { items, .. } = &use_tree.kind {
+                            for tree in items {
                                 let segments = &tree.0.prefix.segments;
                                 if !segments.is_empty() {
                                     imports_reused_with_self.push(segments[0].ident.name);
diff --git a/src/tools/clippy/clippy_lints/src/transmute/eager_transmute.rs b/src/tools/clippy/clippy_lints/src/transmute/eager_transmute.rs
index c44f5150dd1..1dfc9f7091e 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/eager_transmute.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/eager_transmute.rs
@@ -87,7 +87,7 @@ pub(super) fn check<'tcx>(
         && is_normalizable(cx, cx.param_env, from_ty)
         && is_normalizable(cx, cx.param_env, to_ty)
         // we only want to lint if the target type has a niche that is larger than the one of the source type
-        // e.g. `u8` to `NonZeroU8` should lint, but `NonZeroU8` to `u8` should not
+        // e.g. `u8` to `NonZero<u8>` should lint, but `NonZero<u8>` to `u8` should not
         && let Ok(from_layout) = cx.tcx.layout_of(cx.param_env.and(from_ty))
         && let Ok(to_layout) = cx.tcx.layout_of(cx.param_env.and(to_ty))
         && match (from_layout.largest_niche, to_layout.largest_niche) {
diff --git a/src/tools/clippy/clippy_lints/src/transmute/mod.rs b/src/tools/clippy/clippy_lints/src/transmute/mod.rs
index 7fa536a1a29..598032ccdeb 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/mod.rs
@@ -257,7 +257,7 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for transmutes from integers to `NonZero*` types, and suggests their `new_unchecked`
+    /// Checks for transmutes from `T` to `NonZero<T>`, and suggests the `new_unchecked`
     /// method instead.
     ///
     /// ### Why is this bad?
@@ -266,13 +266,13 @@ declare_clippy_lint! {
     ///
     /// ### Example
     /// ```no_run
-    /// # use core::num::NonZeroU32;
-    /// let _non_zero: NonZeroU32 = unsafe { std::mem::transmute(123) };
+    /// # use core::num::NonZero;
+    /// let _: NonZero<u32> = unsafe { std::mem::transmute(123) };
     /// ```
     /// Use instead:
     /// ```no_run
-    /// # use core::num::NonZeroU32;
-    /// let _non_zero = unsafe { NonZeroU32::new_unchecked(123) };
+    /// # use core::num::NonZero;
+    /// let _: NonZero<u32> = unsafe { NonZero::new_unchecked(123) };
     /// ```
     #[clippy::version = "1.69.0"]
     pub TRANSMUTE_INT_TO_NON_ZERO,
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_non_zero.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_non_zero.rs
index 2bea3be3d60..7d824ef2139 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_non_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_non_zero.rs
@@ -26,45 +26,22 @@ pub(super) fn check<'tcx>(
         return false;
     };
 
-    // FIXME: This can be simplified once `NonZero<T>` is stable.
-    let coercible_types = [
-        ("NonZeroU8", tcx.types.u8),
-        ("NonZeroU16", tcx.types.u16),
-        ("NonZeroU32", tcx.types.u32),
-        ("NonZeroU64", tcx.types.u64),
-        ("NonZeroU128", tcx.types.u128),
-        ("NonZeroUsize", tcx.types.usize),
-        ("NonZeroI8", tcx.types.i8),
-        ("NonZeroI16", tcx.types.i16),
-        ("NonZeroI32", tcx.types.i32),
-        ("NonZeroI64", tcx.types.i64),
-        ("NonZeroI128", tcx.types.i128),
-        ("NonZeroIsize", tcx.types.isize),
-    ];
-
-    let int_type = substs.type_at(0);
-
-    let Some(nonzero_alias) = coercible_types.iter().find_map(|(nonzero_alias, t)| {
-        if *t == int_type && *t == from_ty {
-            Some(nonzero_alias)
-        } else {
-            None
-        }
-    }) else {
-        return false;
-    };
+    let int_ty = substs.type_at(0);
+    if from_ty != int_ty {
+      return false;
+    }
 
     span_lint_and_then(
         cx,
         TRANSMUTE_INT_TO_NON_ZERO,
         e.span,
-        format!("transmute from a `{from_ty}` to a `{nonzero_alias}`"),
+        format!("transmute from a `{from_ty}` to a `{}<{int_ty}>`", sym::NonZero),
         |diag| {
             let arg = sugg::Sugg::hir(cx, arg, "..");
             diag.span_suggestion(
                 e.span,
                 "consider using",
-                format!("{nonzero_alias}::{}({arg})", sym::new_unchecked),
+                format!("{}::{}({arg})", sym::NonZero, sym::new_unchecked),
                 Applicability::Unspecified,
             );
         },
diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_self_imports.rs b/src/tools/clippy/clippy_lints/src/unnecessary_self_imports.rs
index ddee06b59ca..528a1dfcfc1 100644
--- a/src/tools/clippy/clippy_lints/src/unnecessary_self_imports.rs
+++ b/src/tools/clippy/clippy_lints/src/unnecessary_self_imports.rs
@@ -36,8 +36,8 @@ declare_lint_pass!(UnnecessarySelfImports => [UNNECESSARY_SELF_IMPORTS]);
 impl EarlyLintPass for UnnecessarySelfImports {
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
         if let ItemKind::Use(use_tree) = &item.kind
-            && let UseTreeKind::Nested(nodes) = &use_tree.kind
-            && let [(self_tree, _)] = &**nodes
+            && let UseTreeKind::Nested { items, .. } = &use_tree.kind
+            && let [(self_tree, _)] = &**items
             && let [self_seg] = &*self_tree.prefix.segments
             && self_seg.ident.name == kw::SelfLower
             && let Some(last_segment) = use_tree.prefix.segments.last()
diff --git a/src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs b/src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs
index 51b3ea93b6d..309eaedac8d 100644
--- a/src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs
+++ b/src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs
@@ -49,8 +49,8 @@ fn check_use_tree(use_tree: &UseTree, cx: &EarlyContext<'_>, span: Span) {
             unsafe_to_safe_check(old_name, new_name, cx, span);
         },
         UseTreeKind::Simple(None) | UseTreeKind::Glob => {},
-        UseTreeKind::Nested(ref nested_use_tree) => {
-            for (use_tree, _) in nested_use_tree {
+        UseTreeKind::Nested { ref items, .. } => {
+            for (use_tree, _) in items {
                 check_use_tree(use_tree, cx, span);
             }
         },
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs
index 529d20126b2..d3bbc66bcae 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs
@@ -648,7 +648,7 @@ pub fn eq_use_tree_kind(l: &UseTreeKind, r: &UseTreeKind) -> bool {
     match (l, r) {
         (Glob, Glob) => true,
         (Simple(l), Simple(r)) => both(l, r, |l, r| eq_id(*l, *r)),
-        (Nested(l), Nested(r)) => over(l, r, |(l, _), (r, _)| eq_use_tree(l, r)),
+        (Nested { items: l, .. }, Nested { items: r, .. }) => over(l, r, |(l, _), (r, _)| eq_use_tree(l, r)),
         _ => false,
     }
 }
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 325c9bee057..95851a2eed8 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
@@ -134,7 +134,7 @@ fn check_rvalue<'tcx>(
         ) => Err((span, "function pointer casts are not allowed in const fn".into())),
         Rvalue::Cast(CastKind::PointerCoercion(PointerCoercion::Unsize), op, cast_ty) => {
             let pointee_ty = if let Some(deref_ty) = cast_ty.builtin_deref(true) {
-                deref_ty.ty
+                deref_ty
             } else {
                 // We cannot allow this for now.
                 return Err((span, "unsizing casts are only allowed for references right now".into()));
@@ -402,7 +402,7 @@ fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx>
             tcx,
             ObligationCause::dummy_with_span(body.span),
             ConstCx::new(tcx, body).param_env,
-            TraitRef::from_lang_item(tcx, LangItem::Destruct, body.span, [ty]),
+            TraitRef::new(tcx, tcx.require_lang_item(LangItem::Destruct, Some(body.span)), [ty]),
         );
 
         let infcx = tcx.infer_ctxt().build();
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index 23750ed4d1b..97bba8648c5 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -10,7 +10,6 @@ use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::{Expr, FnDecl, LangItem, TyKind, Unsafety};
-use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::LateContext;
 use rustc_middle::mir::interpret::Scalar;
@@ -19,7 +18,7 @@ use rustc_middle::traits::EvaluationResult;
 use rustc_middle::ty::layout::ValidityRequirement;
 use rustc_middle::ty::{
     self, AdtDef, AliasTy, AssocKind, Binder, BoundRegion, FnSig, GenericArg, GenericArgKind, GenericArgsRef,
-    GenericParamDefKind, IntTy, List, ParamEnv, Region, RegionKind, ToPredicate, TraitRef, Ty, TyCtxt,
+    GenericParamDefKind, IntTy, ParamEnv, Region, RegionKind, ToPredicate, TraitRef, Ty, TyCtxt,
     TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, UintTy, VariantDef, VariantDiscr,
 };
 use rustc_span::symbol::Ident;
@@ -276,11 +275,7 @@ pub fn implements_trait_with_env_from_iter<'tcx>(
         .into_iter()
         .map(|arg| {
             arg.into().unwrap_or_else(|| {
-                let orig = TypeVariableOrigin {
-                    span: DUMMY_SP,
-                    param_def_id: None,
-                };
-                infcx.next_ty_var(orig).into()
+                infcx.next_ty_var(DUMMY_SP).into()
             })
         })
         .collect::<Vec<_>>();
@@ -961,7 +956,11 @@ pub struct AdtVariantInfo {
 
 impl AdtVariantInfo {
     /// Returns ADT variants ordered by size
-    pub fn new<'tcx>(cx: &LateContext<'tcx>, adt: AdtDef<'tcx>, subst: &'tcx List<GenericArg<'tcx>>) -> Vec<Self> {
+    pub fn new<'tcx>(
+        cx: &LateContext<'tcx>,
+        adt: AdtDef<'tcx>,
+        subst: GenericArgsRef<'tcx>
+    ) -> Vec<Self> {
         let mut variants_size = adt
             .variants()
             .iter()
@@ -1070,11 +1069,11 @@ pub fn approx_ty_size<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> u64 {
 fn assert_generic_args_match<'tcx>(tcx: TyCtxt<'tcx>, did: DefId, args: &[GenericArg<'tcx>]) {
     let g = tcx.generics_of(did);
     let parent = g.parent.map(|did| tcx.generics_of(did));
-    let count = g.parent_count + g.params.len();
+    let count = g.parent_count + g.own_params.len();
     let params = parent
-        .map_or([].as_slice(), |p| p.params.as_slice())
+        .map_or([].as_slice(), |p| p.own_params.as_slice())
         .iter()
-        .chain(&g.params)
+        .chain(&g.own_params)
         .map(|x| &x.kind);
 
     assert!(
diff --git a/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs
index 2241494b484..c2ff19931d5 100644
--- a/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs
@@ -176,7 +176,7 @@ fn qpath_certainty(cx: &LateContext<'_>, qpath: &QPath<'_>, resolves_to_type: bo
             .get(*lang_item)
             .map_or(Certainty::Uncertain, |def_id| {
                 let generics = cx.tcx.generics_of(def_id);
-                if generics.parent_count == 0 && generics.params.is_empty() {
+                if generics.parent_count == 0 && generics.own_params.is_empty() {
                     Certainty::Certain(if resolves_to_type { Some(def_id) } else { None })
                 } else {
                     Certainty::Uncertain
@@ -206,7 +206,7 @@ fn path_segment_certainty(
             // Checking `res_generics_def_id(..)` before calling `generics_of` avoids an ICE.
             if cx.tcx.res_generics_def_id(path_segment.res).is_some() {
                 let generics = cx.tcx.generics_of(def_id);
-                let count = generics.params.len() - usize::from(generics.host_effect_index.is_some());
+                let count = generics.own_params.len() - usize::from(generics.host_effect_index.is_some());
                 let lhs = if (parent_certainty.is_certain() || generics.parent_count == 0) && count == 0 {
                     Certainty::Certain(None)
                 } else {
@@ -299,7 +299,7 @@ fn type_is_inferable_from_arguments(cx: &LateContext<'_>, expr: &Expr<'_>) -> bo
     let fn_sig = cx.tcx.fn_sig(callee_def_id).skip_binder();
 
     // Check that all type parameters appear in the functions input types.
-    (0..(generics.parent_count + generics.params.len()) as u32).all(|index| {
+    (0..(generics.parent_count + generics.own_params.len()) as u32).all(|index| {
         Some(index as usize) == generics.host_effect_index
             || fn_sig
                 .inputs()
diff --git a/src/tools/clippy/lintcheck/src/config.rs b/src/tools/clippy/lintcheck/src/config.rs
index e678d40795e..3f712f453fa 100644
--- a/src/tools/clippy/lintcheck/src/config.rs
+++ b/src/tools/clippy/lintcheck/src/config.rs
@@ -1,5 +1,5 @@
 use clap::Parser;
-use std::num::NonZeroUsize;
+use std::num::NonZero;
 use std::path::PathBuf;
 
 #[derive(Clone, Debug, Parser)]
@@ -61,7 +61,7 @@ impl LintcheckConfig {
             config.max_jobs = if config.fix || config.recursive {
                 1
             } else {
-                std::thread::available_parallelism().map_or(1, NonZeroUsize::get)
+                std::thread::available_parallelism().map_or(1, NonZero::get)
             };
         };
 
diff --git a/src/tools/clippy/tests/ui/almost_complete_range.fixed b/src/tools/clippy/tests/ui/almost_complete_range.fixed
index 21caeb153e7..6c2b2f11743 100644
--- a/src/tools/clippy/tests/ui/almost_complete_range.fixed
+++ b/src/tools/clippy/tests/ui/almost_complete_range.fixed
@@ -1,7 +1,6 @@
 //@edition:2018
 //@aux-build:proc_macros.rs
 
-#![feature(exclusive_range_pattern)]
 #![feature(stmt_expr_attributes)]
 #![warn(clippy::almost_complete_range)]
 #![allow(ellipsis_inclusive_range_patterns)]
diff --git a/src/tools/clippy/tests/ui/almost_complete_range.rs b/src/tools/clippy/tests/ui/almost_complete_range.rs
index 556110a5c8a..813668a5309 100644
--- a/src/tools/clippy/tests/ui/almost_complete_range.rs
+++ b/src/tools/clippy/tests/ui/almost_complete_range.rs
@@ -1,7 +1,6 @@
 //@edition:2018
 //@aux-build:proc_macros.rs
 
-#![feature(exclusive_range_pattern)]
 #![feature(stmt_expr_attributes)]
 #![warn(clippy::almost_complete_range)]
 #![allow(ellipsis_inclusive_range_patterns)]
diff --git a/src/tools/clippy/tests/ui/almost_complete_range.stderr b/src/tools/clippy/tests/ui/almost_complete_range.stderr
index 0195e59226d..bfc2beb07d8 100644
--- a/src/tools/clippy/tests/ui/almost_complete_range.stderr
+++ b/src/tools/clippy/tests/ui/almost_complete_range.stderr
@@ -1,5 +1,5 @@
 error: almost complete ascii range
-  --> tests/ui/almost_complete_range.rs:18:17
+  --> tests/ui/almost_complete_range.rs:17:17
    |
 LL |         let _ = ('a') ..'z';
    |                 ^^^^^^--^^^
@@ -10,7 +10,7 @@ LL |         let _ = ('a') ..'z';
    = help: to override `-D warnings` add `#[allow(clippy::almost_complete_range)]`
 
 error: almost complete ascii range
-  --> tests/ui/almost_complete_range.rs:19:17
+  --> tests/ui/almost_complete_range.rs:18:17
    |
 LL |         let _ = 'A' .. ('Z');
    |                 ^^^^--^^^^^^
@@ -18,7 +18,7 @@ LL |         let _ = 'A' .. ('Z');
    |                     help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> tests/ui/almost_complete_range.rs:20:17
+  --> tests/ui/almost_complete_range.rs:19:17
    |
 LL |         let _ = ((('0'))) .. ('9');
    |                 ^^^^^^^^^^--^^^^^^
@@ -26,7 +26,7 @@ LL |         let _ = ((('0'))) .. ('9');
    |                           help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> tests/ui/almost_complete_range.rs:27:13
+  --> tests/ui/almost_complete_range.rs:26:13
    |
 LL |     let _ = (b'a')..(b'z');
    |             ^^^^^^--^^^^^^
@@ -34,7 +34,7 @@ LL |     let _ = (b'a')..(b'z');
    |                   help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> tests/ui/almost_complete_range.rs:28:13
+  --> tests/ui/almost_complete_range.rs:27:13
    |
 LL |     let _ = b'A'..b'Z';
    |             ^^^^--^^^^
@@ -42,7 +42,7 @@ LL |     let _ = b'A'..b'Z';
    |                 help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> tests/ui/almost_complete_range.rs:29:13
+  --> tests/ui/almost_complete_range.rs:28:13
    |
 LL |     let _ = b'0'..b'9';
    |             ^^^^--^^^^
@@ -50,7 +50,7 @@ LL |     let _ = b'0'..b'9';
    |                 help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> tests/ui/almost_complete_range.rs:35:13
+  --> tests/ui/almost_complete_range.rs:34:13
    |
 LL |     let _ = inline!('a')..'z';
    |             ^^^^^^^^^^^^--^^^
@@ -58,7 +58,7 @@ LL |     let _ = inline!('a')..'z';
    |                         help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> tests/ui/almost_complete_range.rs:36:13
+  --> tests/ui/almost_complete_range.rs:35:13
    |
 LL |     let _ = inline!('A')..'Z';
    |             ^^^^^^^^^^^^--^^^
@@ -66,7 +66,7 @@ LL |     let _ = inline!('A')..'Z';
    |                         help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> tests/ui/almost_complete_range.rs:37:13
+  --> tests/ui/almost_complete_range.rs:36:13
    |
 LL |     let _ = inline!('0')..'9';
    |             ^^^^^^^^^^^^--^^^
@@ -74,7 +74,7 @@ LL |     let _ = inline!('0')..'9';
    |                         help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> tests/ui/almost_complete_range.rs:40:9
+  --> tests/ui/almost_complete_range.rs:39:9
    |
 LL |         b'a'..b'z' if true => 1,
    |         ^^^^--^^^^
@@ -82,7 +82,7 @@ LL |         b'a'..b'z' if true => 1,
    |             help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> tests/ui/almost_complete_range.rs:41:9
+  --> tests/ui/almost_complete_range.rs:40:9
    |
 LL |         b'A'..b'Z' if true => 2,
    |         ^^^^--^^^^
@@ -90,7 +90,7 @@ LL |         b'A'..b'Z' if true => 2,
    |             help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> tests/ui/almost_complete_range.rs:42:9
+  --> tests/ui/almost_complete_range.rs:41:9
    |
 LL |         b'0'..b'9' if true => 3,
    |         ^^^^--^^^^
@@ -98,7 +98,7 @@ LL |         b'0'..b'9' if true => 3,
    |             help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> tests/ui/almost_complete_range.rs:50:9
+  --> tests/ui/almost_complete_range.rs:49:9
    |
 LL |         'a'..'z' if true => 1,
    |         ^^^--^^^
@@ -106,7 +106,7 @@ LL |         'a'..'z' if true => 1,
    |            help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> tests/ui/almost_complete_range.rs:51:9
+  --> tests/ui/almost_complete_range.rs:50:9
    |
 LL |         'A'..'Z' if true => 2,
    |         ^^^--^^^
@@ -114,7 +114,7 @@ LL |         'A'..'Z' if true => 2,
    |            help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> tests/ui/almost_complete_range.rs:52:9
+  --> tests/ui/almost_complete_range.rs:51:9
    |
 LL |         '0'..'9' if true => 3,
    |         ^^^--^^^
@@ -122,7 +122,7 @@ LL |         '0'..'9' if true => 3,
    |            help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> tests/ui/almost_complete_range.rs:65:17
+  --> tests/ui/almost_complete_range.rs:64:17
    |
 LL |         let _ = 'a'..'z';
    |                 ^^^--^^^
@@ -132,7 +132,7 @@ LL |         let _ = 'a'..'z';
    = note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: almost complete ascii range
-  --> tests/ui/almost_complete_range.rs:66:17
+  --> tests/ui/almost_complete_range.rs:65:17
    |
 LL |         let _ = 'A'..'Z';
    |                 ^^^--^^^
@@ -142,7 +142,7 @@ LL |         let _ = 'A'..'Z';
    = note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: almost complete ascii range
-  --> tests/ui/almost_complete_range.rs:67:17
+  --> tests/ui/almost_complete_range.rs:66:17
    |
 LL |         let _ = '0'..'9';
    |                 ^^^--^^^
@@ -152,7 +152,7 @@ LL |         let _ = '0'..'9';
    = note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: almost complete ascii range
-  --> tests/ui/almost_complete_range.rs:74:9
+  --> tests/ui/almost_complete_range.rs:73:9
    |
 LL |         'a'..'z' => 1,
    |         ^^^--^^^
@@ -160,7 +160,7 @@ LL |         'a'..'z' => 1,
    |            help: use an inclusive range: `...`
 
 error: almost complete ascii range
-  --> tests/ui/almost_complete_range.rs:75:9
+  --> tests/ui/almost_complete_range.rs:74:9
    |
 LL |         'A'..'Z' => 2,
    |         ^^^--^^^
@@ -168,7 +168,7 @@ LL |         'A'..'Z' => 2,
    |            help: use an inclusive range: `...`
 
 error: almost complete ascii range
-  --> tests/ui/almost_complete_range.rs:76:9
+  --> tests/ui/almost_complete_range.rs:75:9
    |
 LL |         '0'..'9' => 3,
    |         ^^^--^^^
@@ -176,7 +176,7 @@ LL |         '0'..'9' => 3,
    |            help: use an inclusive range: `...`
 
 error: almost complete ascii range
-  --> tests/ui/almost_complete_range.rs:83:13
+  --> tests/ui/almost_complete_range.rs:82:13
    |
 LL |     let _ = 'a'..'z';
    |             ^^^--^^^
@@ -184,7 +184,7 @@ LL |     let _ = 'a'..'z';
    |                help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> tests/ui/almost_complete_range.rs:84:13
+  --> tests/ui/almost_complete_range.rs:83:13
    |
 LL |     let _ = 'A'..'Z';
    |             ^^^--^^^
@@ -192,7 +192,7 @@ LL |     let _ = 'A'..'Z';
    |                help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> tests/ui/almost_complete_range.rs:85:13
+  --> tests/ui/almost_complete_range.rs:84:13
    |
 LL |     let _ = '0'..'9';
    |             ^^^--^^^
@@ -200,7 +200,7 @@ LL |     let _ = '0'..'9';
    |                help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> tests/ui/almost_complete_range.rs:87:9
+  --> tests/ui/almost_complete_range.rs:86:9
    |
 LL |         'a'..'z' => 1,
    |         ^^^--^^^
@@ -208,7 +208,7 @@ LL |         'a'..'z' => 1,
    |            help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> tests/ui/almost_complete_range.rs:88:9
+  --> tests/ui/almost_complete_range.rs:87:9
    |
 LL |         'A'..'Z' => 1,
    |         ^^^--^^^
@@ -216,7 +216,7 @@ LL |         'A'..'Z' => 1,
    |            help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> tests/ui/almost_complete_range.rs:89:9
+  --> tests/ui/almost_complete_range.rs:88:9
    |
 LL |         '0'..'9' => 3,
    |         ^^^--^^^
diff --git a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
index 66d71f337f2..33a91e8bbbe 100644
--- a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
+++ b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
@@ -15,7 +15,7 @@
 
 extern crate proc_macro_derive;
 
-use core::num::{NonZeroUsize, Saturating, Wrapping};
+use core::num::{NonZero, Saturating, Wrapping};
 
 const ONE: i32 = 1;
 const ZERO: i32 = 0;
@@ -494,15 +494,15 @@ pub fn issue_11262() {
 }
 
 pub fn issue_11392() {
-    fn example_div(unsigned: usize, nonzero_unsigned: NonZeroUsize) -> usize {
+    fn example_div(unsigned: usize, nonzero_unsigned: NonZero<usize>) -> usize {
         unsigned / nonzero_unsigned
     }
 
-    fn example_rem(unsigned: usize, nonzero_unsigned: NonZeroUsize) -> usize {
+    fn example_rem(unsigned: usize, nonzero_unsigned: NonZero<usize>) -> usize {
         unsigned % nonzero_unsigned
     }
 
-    let (unsigned, nonzero_unsigned) = (0, NonZeroUsize::new(1).unwrap());
+    let (unsigned, nonzero_unsigned) = (0, NonZero::new(1).unwrap());
     example_div(unsigned, nonzero_unsigned);
     example_rem(unsigned, nonzero_unsigned);
 }
diff --git a/src/tools/clippy/tests/ui/eager_transmute.fixed b/src/tools/clippy/tests/ui/eager_transmute.fixed
index c29e7dd9ab3..ba4342462dc 100644
--- a/src/tools/clippy/tests/ui/eager_transmute.fixed
+++ b/src/tools/clippy/tests/ui/eager_transmute.fixed
@@ -2,7 +2,7 @@
 #![warn(clippy::eager_transmute)]
 #![allow(clippy::transmute_int_to_non_zero, clippy::missing_transmute_annotations)]
 
-use std::num::NonZeroU8;
+use std::num::NonZero;
 
 #[repr(u8)]
 enum Opcode {
@@ -85,21 +85,21 @@ macro_rules! impls {
 }
 impls!(NonMaxU8, NonZeroNonMaxU8);
 
-fn niche_tests(v1: u8, v2: NonZeroU8, v3: NonZeroNonMaxU8) {
-    // u8 -> NonZeroU8, do lint
-    let _: Option<NonZeroU8> = (v1 > 0).then(|| unsafe { std::mem::transmute(v1) });
+fn niche_tests(v1: u8, v2: NonZero<u8>, v3: NonZeroNonMaxU8) {
+    // u8 -> NonZero<u8>, do lint
+    let _: Option<NonZero<u8>> = (v1 > 0).then(|| unsafe { std::mem::transmute(v1) });
 
-    // NonZeroU8 -> u8, don't lint, target type has no niche and therefore a higher validity range
-    let _: Option<u8> = (v2 > NonZeroU8::new(1).unwrap()).then_some(unsafe { std::mem::transmute(v2) });
+    // NonZero<u8> -> u8, don't lint, target type has no niche and therefore a higher validity range
+    let _: Option<u8> = (v2 > NonZero::new(1u8).unwrap()).then_some(unsafe { std::mem::transmute(v2) });
 
-    // NonZeroU8 -> NonMaxU8, do lint, different niche
-    let _: Option<NonMaxU8> = (v2 < NonZeroU8::new(255).unwrap()).then(|| unsafe { std::mem::transmute(v2) });
+    // NonZero<u8> -> NonMaxU8, do lint, different niche
+    let _: Option<NonMaxU8> = (v2 < NonZero::new(255u8).unwrap()).then(|| unsafe { std::mem::transmute(v2) });
 
     // NonZeroNonMaxU8 -> NonMaxU8, don't lint, target type has more validity
     let _: Option<NonMaxU8> = (v3 < 255).then_some(unsafe { std::mem::transmute(v2) });
 
-    // NonZeroU8 -> NonZeroNonMaxU8, do lint, target type has less validity
-    let _: Option<NonZeroNonMaxU8> = (v2 < NonZeroU8::new(255).unwrap()).then(|| unsafe { std::mem::transmute(v2) });
+    // NonZero<u8> -> NonZeroNonMaxU8, do lint, target type has less validity
+    let _: Option<NonZeroNonMaxU8> = (v2 < NonZero::new(255u8).unwrap()).then(|| unsafe { std::mem::transmute(v2) });
 }
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/eager_transmute.rs b/src/tools/clippy/tests/ui/eager_transmute.rs
index 491a9485c93..9750e87ce57 100644
--- a/src/tools/clippy/tests/ui/eager_transmute.rs
+++ b/src/tools/clippy/tests/ui/eager_transmute.rs
@@ -2,7 +2,7 @@
 #![warn(clippy::eager_transmute)]
 #![allow(clippy::transmute_int_to_non_zero, clippy::missing_transmute_annotations)]
 
-use std::num::NonZeroU8;
+use std::num::NonZero;
 
 #[repr(u8)]
 enum Opcode {
@@ -85,21 +85,21 @@ macro_rules! impls {
 }
 impls!(NonMaxU8, NonZeroNonMaxU8);
 
-fn niche_tests(v1: u8, v2: NonZeroU8, v3: NonZeroNonMaxU8) {
-    // u8 -> NonZeroU8, do lint
-    let _: Option<NonZeroU8> = (v1 > 0).then_some(unsafe { std::mem::transmute(v1) });
+fn niche_tests(v1: u8, v2: NonZero<u8>, v3: NonZeroNonMaxU8) {
+    // u8 -> NonZero<u8>, do lint
+    let _: Option<NonZero<u8>> = (v1 > 0).then_some(unsafe { std::mem::transmute(v1) });
 
-    // NonZeroU8 -> u8, don't lint, target type has no niche and therefore a higher validity range
-    let _: Option<u8> = (v2 > NonZeroU8::new(1).unwrap()).then_some(unsafe { std::mem::transmute(v2) });
+    // NonZero<u8> -> u8, don't lint, target type has no niche and therefore a higher validity range
+    let _: Option<u8> = (v2 > NonZero::new(1u8).unwrap()).then_some(unsafe { std::mem::transmute(v2) });
 
-    // NonZeroU8 -> NonMaxU8, do lint, different niche
-    let _: Option<NonMaxU8> = (v2 < NonZeroU8::new(255).unwrap()).then_some(unsafe { std::mem::transmute(v2) });
+    // NonZero<u8> -> NonMaxU8, do lint, different niche
+    let _: Option<NonMaxU8> = (v2 < NonZero::new(255u8).unwrap()).then_some(unsafe { std::mem::transmute(v2) });
 
     // NonZeroNonMaxU8 -> NonMaxU8, don't lint, target type has more validity
     let _: Option<NonMaxU8> = (v3 < 255).then_some(unsafe { std::mem::transmute(v2) });
 
-    // NonZeroU8 -> NonZeroNonMaxU8, do lint, target type has less validity
-    let _: Option<NonZeroNonMaxU8> = (v2 < NonZeroU8::new(255).unwrap()).then_some(unsafe { std::mem::transmute(v2) });
+    // NonZero<u8> -> NonZeroNonMaxU8, do lint, target type has less validity
+    let _: Option<NonZeroNonMaxU8> = (v2 < NonZero::new(255u8).unwrap()).then_some(unsafe { std::mem::transmute(v2) });
 }
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/eager_transmute.stderr b/src/tools/clippy/tests/ui/eager_transmute.stderr
index b9a4321d99e..5cf7bd49a92 100644
--- a/src/tools/clippy/tests/ui/eager_transmute.stderr
+++ b/src/tools/clippy/tests/ui/eager_transmute.stderr
@@ -155,36 +155,36 @@ LL |     (op < 4).then(|| std::mem::transmute::<_, Opcode>(op));
    |              ~~~~ ++
 
 error: this transmute is always evaluated eagerly, even if the condition is false
-  --> tests/ui/eager_transmute.rs:90:60
+  --> tests/ui/eager_transmute.rs:90:62
    |
-LL |     let _: Option<NonZeroU8> = (v1 > 0).then_some(unsafe { std::mem::transmute(v1) });
-   |                                                            ^^^^^^^^^^^^^^^^^^^^^^^
+LL |     let _: Option<NonZero<u8>> = (v1 > 0).then_some(unsafe { std::mem::transmute(v1) });
+   |                                                              ^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: consider using `bool::then` to only transmute if the condition holds
    |
-LL |     let _: Option<NonZeroU8> = (v1 > 0).then(|| unsafe { std::mem::transmute(v1) });
-   |                                         ~~~~ ++
+LL |     let _: Option<NonZero<u8>> = (v1 > 0).then(|| unsafe { std::mem::transmute(v1) });
+   |                                           ~~~~ ++
 
 error: this transmute is always evaluated eagerly, even if the condition is false
   --> tests/ui/eager_transmute.rs:96:86
    |
-LL |     let _: Option<NonMaxU8> = (v2 < NonZeroU8::new(255).unwrap()).then_some(unsafe { std::mem::transmute(v2) });
+LL |     let _: Option<NonMaxU8> = (v2 < NonZero::new(255u8).unwrap()).then_some(unsafe { std::mem::transmute(v2) });
    |                                                                                      ^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: consider using `bool::then` to only transmute if the condition holds
    |
-LL |     let _: Option<NonMaxU8> = (v2 < NonZeroU8::new(255).unwrap()).then(|| unsafe { std::mem::transmute(v2) });
+LL |     let _: Option<NonMaxU8> = (v2 < NonZero::new(255u8).unwrap()).then(|| unsafe { std::mem::transmute(v2) });
    |                                                                   ~~~~ ++
 
 error: this transmute is always evaluated eagerly, even if the condition is false
   --> tests/ui/eager_transmute.rs:102:93
    |
-LL |     let _: Option<NonZeroNonMaxU8> = (v2 < NonZeroU8::new(255).unwrap()).then_some(unsafe { std::mem::transmute(v2) });
+LL |     let _: Option<NonZeroNonMaxU8> = (v2 < NonZero::new(255u8).unwrap()).then_some(unsafe { std::mem::transmute(v2) });
    |                                                                                             ^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: consider using `bool::then` to only transmute if the condition holds
    |
-LL |     let _: Option<NonZeroNonMaxU8> = (v2 < NonZeroU8::new(255).unwrap()).then(|| unsafe { std::mem::transmute(v2) });
+LL |     let _: Option<NonZeroNonMaxU8> = (v2 < NonZero::new(255u8).unwrap()).then(|| unsafe { std::mem::transmute(v2) });
    |                                                                          ~~~~ ++
 
 error: aborting due to 17 previous errors
diff --git a/src/tools/clippy/tests/ui/manual_range_patterns.fixed b/src/tools/clippy/tests/ui/manual_range_patterns.fixed
index e9f6fbcc3fc..f1b99637afd 100644
--- a/src/tools/clippy/tests/ui/manual_range_patterns.fixed
+++ b/src/tools/clippy/tests/ui/manual_range_patterns.fixed
@@ -1,7 +1,6 @@
 #![allow(unused)]
 #![allow(non_contiguous_range_endpoints)]
 #![warn(clippy::manual_range_patterns)]
-#![feature(exclusive_range_pattern)]
 
 fn main() {
     let f = 6;
diff --git a/src/tools/clippy/tests/ui/manual_range_patterns.rs b/src/tools/clippy/tests/ui/manual_range_patterns.rs
index d525aaa24ad..869ffbe80b9 100644
--- a/src/tools/clippy/tests/ui/manual_range_patterns.rs
+++ b/src/tools/clippy/tests/ui/manual_range_patterns.rs
@@ -1,7 +1,6 @@
 #![allow(unused)]
 #![allow(non_contiguous_range_endpoints)]
 #![warn(clippy::manual_range_patterns)]
-#![feature(exclusive_range_pattern)]
 
 fn main() {
     let f = 6;
diff --git a/src/tools/clippy/tests/ui/manual_range_patterns.stderr b/src/tools/clippy/tests/ui/manual_range_patterns.stderr
index af9256aeea3..7c19fdd475f 100644
--- a/src/tools/clippy/tests/ui/manual_range_patterns.stderr
+++ b/src/tools/clippy/tests/ui/manual_range_patterns.stderr
@@ -1,5 +1,5 @@
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:9:25
+  --> tests/ui/manual_range_patterns.rs:8:25
    |
 LL |     let _ = matches!(f, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10);
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10`
@@ -8,109 +8,109 @@ LL |     let _ = matches!(f, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10);
    = help: to override `-D warnings` add `#[allow(clippy::manual_range_patterns)]`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:10:25
+  --> tests/ui/manual_range_patterns.rs:9:25
    |
 LL |     let _ = matches!(f, 4 | 2 | 3 | 1 | 5 | 6 | 9 | 7 | 8 | 10);
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:17:25
+  --> tests/ui/manual_range_patterns.rs:16:25
    |
 LL |     let _ = matches!(f, 1 | (2..=4));
    |                         ^^^^^^^^^^^ help: try: `1..=4`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:18:25
+  --> tests/ui/manual_range_patterns.rs:17:25
    |
 LL |     let _ = matches!(f, 1 | (2..4));
    |                         ^^^^^^^^^^ help: try: `1..4`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:19:25
+  --> tests/ui/manual_range_patterns.rs:18:25
    |
 LL |     let _ = matches!(f, (1..=10) | (2..=13) | (14..=48324728) | 48324729);
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=48324729`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:20:25
+  --> tests/ui/manual_range_patterns.rs:19:25
    |
 LL |     let _ = matches!(f, 0 | (1..=10) | 48324730 | (2..=13) | (14..=48324728) | 48324729);
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `0..=48324730`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:21:25
+  --> tests/ui/manual_range_patterns.rs:20:25
    |
 LL |     let _ = matches!(f, 0..=1 | 0..=2 | 0..=3);
    |                         ^^^^^^^^^^^^^^^^^^^^^ help: try: `0..=3`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:24:9
+  --> tests/ui/manual_range_patterns.rs:23:9
    |
 LL |         1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 => true,
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:27:25
+  --> tests/ui/manual_range_patterns.rs:26:25
    |
 LL |     let _ = matches!(f, -1 | -5 | 3 | -2 | -4 | -3 | 0 | 1 | 2);
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-5..=3`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:29:25
+  --> tests/ui/manual_range_patterns.rs:28:25
    |
 LL |     let _ = matches!(f, -1_000_000..=1_000_000 | -1_000_001 | 1_000_001);
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-1_000_001..=1_000_001`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:32:17
+  --> tests/ui/manual_range_patterns.rs:31:17
    |
 LL |     matches!(f, 0x00 | 0x01 | 0x02 | 0x03);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `0x00..=0x03`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:33:17
+  --> tests/ui/manual_range_patterns.rs:32:17
    |
 LL |     matches!(f, 0x00..=0x05 | 0x06 | 0x07);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `0x00..=0x07`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:34:17
+  --> tests/ui/manual_range_patterns.rs:33:17
    |
 LL |     matches!(f, -0x09 | -0x08 | -0x07..=0x00);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-0x09..=0x00`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:36:17
+  --> tests/ui/manual_range_patterns.rs:35:17
    |
 LL |     matches!(f, 0..5 | 5);
    |                 ^^^^^^^^ help: try: `0..=5`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:37:17
+  --> tests/ui/manual_range_patterns.rs:36:17
    |
 LL |     matches!(f, 0 | 1..5);
    |                 ^^^^^^^^ help: try: `0..5`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:39:17
+  --> tests/ui/manual_range_patterns.rs:38:17
    |
 LL |     matches!(f, 0..=5 | 6..10);
    |                 ^^^^^^^^^^^^^ help: try: `0..10`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:40:17
+  --> tests/ui/manual_range_patterns.rs:39:17
    |
 LL |     matches!(f, 0..5 | 5..=10);
    |                 ^^^^^^^^^^^^^ help: try: `0..=10`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:41:17
+  --> tests/ui/manual_range_patterns.rs:40:17
    |
 LL |     matches!(f, 5..=10 | 0..5);
    |                 ^^^^^^^^^^^^^ help: try: `0..=10`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:45:26
+  --> tests/ui/manual_range_patterns.rs:44:26
    |
 LL |             matches!($e, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10)
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10`
diff --git a/src/tools/clippy/tests/ui/match_overlapping_arm.rs b/src/tools/clippy/tests/ui/match_overlapping_arm.rs
index c2c2f28392d..4457ae73da2 100644
--- a/src/tools/clippy/tests/ui/match_overlapping_arm.rs
+++ b/src/tools/clippy/tests/ui/match_overlapping_arm.rs
@@ -1,4 +1,3 @@
-#![feature(exclusive_range_pattern)]
 #![warn(clippy::match_overlapping_arm)]
 #![allow(clippy::redundant_pattern_matching)]
 #![allow(clippy::if_same_then_else, clippy::equatable_if_let, clippy::needless_if)]
diff --git a/src/tools/clippy/tests/ui/match_overlapping_arm.stderr b/src/tools/clippy/tests/ui/match_overlapping_arm.stderr
index 1a6c5746c3d..65092ffbb55 100644
--- a/src/tools/clippy/tests/ui/match_overlapping_arm.stderr
+++ b/src/tools/clippy/tests/ui/match_overlapping_arm.stderr
@@ -1,11 +1,11 @@
 error: some ranges overlap
-  --> tests/ui/match_overlapping_arm.rs:12:9
+  --> tests/ui/match_overlapping_arm.rs:11:9
    |
 LL |         0..=10 => println!("0..=10"),
    |         ^^^^^^
    |
 note: overlaps with this
-  --> tests/ui/match_overlapping_arm.rs:14:9
+  --> tests/ui/match_overlapping_arm.rs:13:9
    |
 LL |         0..=11 => println!("0..=11"),
    |         ^^^^^^
@@ -13,85 +13,85 @@ LL |         0..=11 => println!("0..=11"),
    = help: to override `-D warnings` add `#[allow(clippy::match_overlapping_arm)]`
 
 error: some ranges overlap
-  --> tests/ui/match_overlapping_arm.rs:19:9
+  --> tests/ui/match_overlapping_arm.rs:18:9
    |
 LL |         0..=5 => println!("0..=5"),
    |         ^^^^^
    |
 note: overlaps with this
-  --> tests/ui/match_overlapping_arm.rs:22:9
+  --> tests/ui/match_overlapping_arm.rs:21:9
    |
 LL |         FOO..=11 => println!("FOO..=11"),
    |         ^^^^^^^^
 
 error: some ranges overlap
-  --> tests/ui/match_overlapping_arm.rs:57:9
+  --> tests/ui/match_overlapping_arm.rs:56:9
    |
 LL |         0..11 => println!("0..11"),
    |         ^^^^^
    |
 note: overlaps with this
-  --> tests/ui/match_overlapping_arm.rs:59:9
+  --> tests/ui/match_overlapping_arm.rs:58:9
    |
 LL |         0..=11 => println!("0..=11"),
    |         ^^^^^^
 
 error: some ranges overlap
-  --> tests/ui/match_overlapping_arm.rs:83:9
+  --> tests/ui/match_overlapping_arm.rs:82:9
    |
 LL |         0..=10 => println!("0..=10"),
    |         ^^^^^^
    |
 note: overlaps with this
-  --> tests/ui/match_overlapping_arm.rs:82:9
+  --> tests/ui/match_overlapping_arm.rs:81:9
    |
 LL |         5..14 => println!("5..14"),
    |         ^^^^^
 
 error: some ranges overlap
-  --> tests/ui/match_overlapping_arm.rs:89:9
+  --> tests/ui/match_overlapping_arm.rs:88:9
    |
 LL |         0..7 => println!("0..7"),
    |         ^^^^
    |
 note: overlaps with this
-  --> tests/ui/match_overlapping_arm.rs:91:9
+  --> tests/ui/match_overlapping_arm.rs:90:9
    |
 LL |         0..=10 => println!("0..=10"),
    |         ^^^^^^
 
 error: some ranges overlap
-  --> tests/ui/match_overlapping_arm.rs:102:9
+  --> tests/ui/match_overlapping_arm.rs:101:9
    |
 LL |         ..=23 => println!("..=23"),
    |         ^^^^^
    |
 note: overlaps with this
-  --> tests/ui/match_overlapping_arm.rs:104:9
+  --> tests/ui/match_overlapping_arm.rs:103:9
    |
 LL |         ..26 => println!("..26"),
    |         ^^^^
 
 error: some ranges overlap
-  --> tests/ui/match_overlapping_arm.rs:112:9
+  --> tests/ui/match_overlapping_arm.rs:111:9
    |
 LL |         21..=30 => (),
    |         ^^^^^^^
    |
 note: overlaps with this
-  --> tests/ui/match_overlapping_arm.rs:114:9
+  --> tests/ui/match_overlapping_arm.rs:113:9
    |
 LL |         21..=40 => (),
    |         ^^^^^^^
 
 error: some ranges overlap
-  --> tests/ui/match_overlapping_arm.rs:127:9
+  --> tests/ui/match_overlapping_arm.rs:126:9
    |
 LL |         0..=0x0000_0000_0000_00ff => (),
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: overlaps with this
-  --> tests/ui/match_overlapping_arm.rs:129:9
+  --> tests/ui/match_overlapping_arm.rs:128:9
    |
 LL |         0..=0x0000_0000_0000_ffff => (),
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/match_wild_err_arm.rs b/src/tools/clippy/tests/ui/match_wild_err_arm.rs
index 7bdd75d7f46..8e670ce5bda 100644
--- a/src/tools/clippy/tests/ui/match_wild_err_arm.rs
+++ b/src/tools/clippy/tests/ui/match_wild_err_arm.rs
@@ -1,4 +1,3 @@
-#![feature(exclusive_range_pattern)]
 #![allow(clippy::match_same_arms, dead_code)]
 #![warn(clippy::match_wild_err_arm)]
 
diff --git a/src/tools/clippy/tests/ui/match_wild_err_arm.stderr b/src/tools/clippy/tests/ui/match_wild_err_arm.stderr
index 3145665a341..f98065d9a59 100644
--- a/src/tools/clippy/tests/ui/match_wild_err_arm.stderr
+++ b/src/tools/clippy/tests/ui/match_wild_err_arm.stderr
@@ -1,5 +1,5 @@
 error: `Err(_)` matches all errors
-  --> tests/ui/match_wild_err_arm.rs:24:9
+  --> tests/ui/match_wild_err_arm.rs:23:9
    |
 LL |         Err(_) => panic!("err"),
    |         ^^^^^^
@@ -9,7 +9,7 @@ LL |         Err(_) => panic!("err"),
    = help: to override `-D warnings` add `#[allow(clippy::match_wild_err_arm)]`
 
 error: `Err(_)` matches all errors
-  --> tests/ui/match_wild_err_arm.rs:32:9
+  --> tests/ui/match_wild_err_arm.rs:31:9
    |
 LL |         Err(_) => panic!(),
    |         ^^^^^^
@@ -17,7 +17,7 @@ LL |         Err(_) => panic!(),
    = note: match each error separately or use the error output, or use `.expect(msg)` if the error case is unreachable
 
 error: `Err(_)` matches all errors
-  --> tests/ui/match_wild_err_arm.rs:40:9
+  --> tests/ui/match_wild_err_arm.rs:39:9
    |
 LL |         Err(_) => {
    |         ^^^^^^
@@ -25,7 +25,7 @@ LL |         Err(_) => {
    = note: match each error separately or use the error output, or use `.expect(msg)` if the error case is unreachable
 
 error: `Err(_e)` matches all errors
-  --> tests/ui/match_wild_err_arm.rs:50:9
+  --> tests/ui/match_wild_err_arm.rs:49:9
    |
 LL |         Err(_e) => panic!(),
    |         ^^^^^^^
diff --git a/src/tools/clippy/tests/ui/transmute_int_to_non_zero.fixed b/src/tools/clippy/tests/ui/transmute_int_to_non_zero.fixed
index fe8db3dcb0c..1a48051ec8c 100644
--- a/src/tools/clippy/tests/ui/transmute_int_to_non_zero.fixed
+++ b/src/tools/clippy/tests/ui/transmute_int_to_non_zero.fixed
@@ -1,7 +1,7 @@
 #![warn(clippy::transmute_int_to_non_zero)]
 #![allow(clippy::missing_transmute_annotations)]
 
-use core::num::*;
+use core::num::NonZero;
 
 fn main() {
     let int_u8: u8 = 1;
@@ -16,38 +16,38 @@ fn main() {
     let int_i64: i64 = 1;
     let int_i128: i128 = 1;
 
-    let _: NonZeroU8 = unsafe { NonZeroU8::new_unchecked(int_u8) };
-    //~^ ERROR: transmute from a `u8` to a `NonZeroU8`
+    let _: NonZero<u8> = unsafe { NonZero::new_unchecked(int_u8) };
+    //~^ ERROR: transmute from a `u8` to a `NonZero<u8>`
     //~| NOTE: `-D clippy::transmute-int-to-non-zero` implied by `-D warnings`
-    let _: NonZeroU16 = unsafe { NonZeroU16::new_unchecked(int_u16) };
-    //~^ ERROR: transmute from a `u16` to a `NonZeroU16`
-    let _: NonZeroU32 = unsafe { NonZeroU32::new_unchecked(int_u32) };
-    //~^ ERROR: transmute from a `u32` to a `NonZeroU32`
-    let _: NonZeroU64 = unsafe { NonZeroU64::new_unchecked(int_u64) };
-    //~^ ERROR: transmute from a `u64` to a `NonZeroU64`
-    let _: NonZeroU128 = unsafe { NonZeroU128::new_unchecked(int_u128) };
-    //~^ ERROR: transmute from a `u128` to a `NonZeroU128`
+    let _: NonZero<u16> = unsafe { NonZero::new_unchecked(int_u16) };
+    //~^ ERROR: transmute from a `u16` to a `NonZero<u16>`
+    let _: NonZero<u32> = unsafe { NonZero::new_unchecked(int_u32) };
+    //~^ ERROR: transmute from a `u32` to a `NonZero<u32>`
+    let _: NonZero<u64> = unsafe { NonZero::new_unchecked(int_u64) };
+    //~^ ERROR: transmute from a `u64` to a `NonZero<u64>`
+    let _: NonZero<u128> = unsafe { NonZero::new_unchecked(int_u128) };
+    //~^ ERROR: transmute from a `u128` to a `NonZero<u128>`
 
-    let _: NonZeroI8 = unsafe { NonZeroI8::new_unchecked(int_i8) };
-    //~^ ERROR: transmute from a `i8` to a `NonZeroI8`
-    let _: NonZeroI16 = unsafe { NonZeroI16::new_unchecked(int_i16) };
-    //~^ ERROR: transmute from a `i16` to a `NonZeroI16`
-    let _: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(int_i32) };
-    //~^ ERROR: transmute from a `i32` to a `NonZeroI32`
-    let _: NonZeroI64 = unsafe { NonZeroI64::new_unchecked(int_i64) };
-    //~^ ERROR: transmute from a `i64` to a `NonZeroI64`
-    let _: NonZeroI128 = unsafe { NonZeroI128::new_unchecked(int_i128) };
-    //~^ ERROR: transmute from a `i128` to a `NonZeroI128`
+    let _: NonZero<i8> = unsafe { NonZero::new_unchecked(int_i8) };
+    //~^ ERROR: transmute from a `i8` to a `NonZero<i8>`
+    let _: NonZero<i16> = unsafe { NonZero::new_unchecked(int_i16) };
+    //~^ ERROR: transmute from a `i16` to a `NonZero<i16>`
+    let _: NonZero<i32> = unsafe { NonZero::new_unchecked(int_i32) };
+    //~^ ERROR: transmute from a `i32` to a `NonZero<i32>`
+    let _: NonZero<i64> = unsafe { NonZero::new_unchecked(int_i64) };
+    //~^ ERROR: transmute from a `i64` to a `NonZero<i64>`
+    let _: NonZero<i128> = unsafe { NonZero::new_unchecked(int_i128) };
+    //~^ ERROR: transmute from a `i128` to a `NonZero<i128>`
 
-    let _: NonZeroU8 = unsafe { NonZeroU8::new_unchecked(int_u8) };
-    let _: NonZeroU16 = unsafe { NonZeroU16::new_unchecked(int_u16) };
-    let _: NonZeroU32 = unsafe { NonZeroU32::new_unchecked(int_u32) };
-    let _: NonZeroU64 = unsafe { NonZeroU64::new_unchecked(int_u64) };
-    let _: NonZeroU128 = unsafe { NonZeroU128::new_unchecked(int_u128) };
+    let _: NonZero<u8> = unsafe { NonZero::new_unchecked(int_u8) };
+    let _: NonZero<u16> = unsafe { NonZero::new_unchecked(int_u16) };
+    let _: NonZero<u32> = unsafe { NonZero::new_unchecked(int_u32) };
+    let _: NonZero<u64> = unsafe { NonZero::new_unchecked(int_u64) };
+    let _: NonZero<u128> = unsafe { NonZero::new_unchecked(int_u128) };
 
-    let _: NonZeroI8 = unsafe { NonZeroI8::new_unchecked(int_i8) };
-    let _: NonZeroI16 = unsafe { NonZeroI16::new_unchecked(int_i16) };
-    let _: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(int_i32) };
-    let _: NonZeroI64 = unsafe { NonZeroI64::new_unchecked(int_i64) };
-    let _: NonZeroI128 = unsafe { NonZeroI128::new_unchecked(int_i128) };
+    let _: NonZero<i8> = unsafe { NonZero::new_unchecked(int_i8) };
+    let _: NonZero<i16> = unsafe { NonZero::new_unchecked(int_i16) };
+    let _: NonZero<i32> = unsafe { NonZero::new_unchecked(int_i32) };
+    let _: NonZero<i64> = unsafe { NonZero::new_unchecked(int_i64) };
+    let _: NonZero<i128> = unsafe { NonZero::new_unchecked(int_i128) };
 }
diff --git a/src/tools/clippy/tests/ui/transmute_int_to_non_zero.rs b/src/tools/clippy/tests/ui/transmute_int_to_non_zero.rs
index a79ed5279b1..d8e842fb99c 100644
--- a/src/tools/clippy/tests/ui/transmute_int_to_non_zero.rs
+++ b/src/tools/clippy/tests/ui/transmute_int_to_non_zero.rs
@@ -1,7 +1,7 @@
 #![warn(clippy::transmute_int_to_non_zero)]
 #![allow(clippy::missing_transmute_annotations)]
 
-use core::num::*;
+use core::num::NonZero;
 
 fn main() {
     let int_u8: u8 = 1;
@@ -16,38 +16,38 @@ fn main() {
     let int_i64: i64 = 1;
     let int_i128: i128 = 1;
 
-    let _: NonZeroU8 = unsafe { std::mem::transmute(int_u8) };
-    //~^ ERROR: transmute from a `u8` to a `NonZeroU8`
+    let _: NonZero<u8> = unsafe { std::mem::transmute(int_u8) };
+    //~^ ERROR: transmute from a `u8` to a `NonZero<u8>`
     //~| NOTE: `-D clippy::transmute-int-to-non-zero` implied by `-D warnings`
-    let _: NonZeroU16 = unsafe { std::mem::transmute(int_u16) };
-    //~^ ERROR: transmute from a `u16` to a `NonZeroU16`
-    let _: NonZeroU32 = unsafe { std::mem::transmute(int_u32) };
-    //~^ ERROR: transmute from a `u32` to a `NonZeroU32`
-    let _: NonZeroU64 = unsafe { std::mem::transmute(int_u64) };
-    //~^ ERROR: transmute from a `u64` to a `NonZeroU64`
-    let _: NonZeroU128 = unsafe { std::mem::transmute(int_u128) };
-    //~^ ERROR: transmute from a `u128` to a `NonZeroU128`
+    let _: NonZero<u16> = unsafe { std::mem::transmute(int_u16) };
+    //~^ ERROR: transmute from a `u16` to a `NonZero<u16>`
+    let _: NonZero<u32> = unsafe { std::mem::transmute(int_u32) };
+    //~^ ERROR: transmute from a `u32` to a `NonZero<u32>`
+    let _: NonZero<u64> = unsafe { std::mem::transmute(int_u64) };
+    //~^ ERROR: transmute from a `u64` to a `NonZero<u64>`
+    let _: NonZero<u128> = unsafe { std::mem::transmute(int_u128) };
+    //~^ ERROR: transmute from a `u128` to a `NonZero<u128>`
 
-    let _: NonZeroI8 = unsafe { std::mem::transmute(int_i8) };
-    //~^ ERROR: transmute from a `i8` to a `NonZeroI8`
-    let _: NonZeroI16 = unsafe { std::mem::transmute(int_i16) };
-    //~^ ERROR: transmute from a `i16` to a `NonZeroI16`
-    let _: NonZeroI32 = unsafe { std::mem::transmute(int_i32) };
-    //~^ ERROR: transmute from a `i32` to a `NonZeroI32`
-    let _: NonZeroI64 = unsafe { std::mem::transmute(int_i64) };
-    //~^ ERROR: transmute from a `i64` to a `NonZeroI64`
-    let _: NonZeroI128 = unsafe { std::mem::transmute(int_i128) };
-    //~^ ERROR: transmute from a `i128` to a `NonZeroI128`
+    let _: NonZero<i8> = unsafe { std::mem::transmute(int_i8) };
+    //~^ ERROR: transmute from a `i8` to a `NonZero<i8>`
+    let _: NonZero<i16> = unsafe { std::mem::transmute(int_i16) };
+    //~^ ERROR: transmute from a `i16` to a `NonZero<i16>`
+    let _: NonZero<i32> = unsafe { std::mem::transmute(int_i32) };
+    //~^ ERROR: transmute from a `i32` to a `NonZero<i32>`
+    let _: NonZero<i64> = unsafe { std::mem::transmute(int_i64) };
+    //~^ ERROR: transmute from a `i64` to a `NonZero<i64>`
+    let _: NonZero<i128> = unsafe { std::mem::transmute(int_i128) };
+    //~^ ERROR: transmute from a `i128` to a `NonZero<i128>`
 
-    let _: NonZeroU8 = unsafe { NonZeroU8::new_unchecked(int_u8) };
-    let _: NonZeroU16 = unsafe { NonZeroU16::new_unchecked(int_u16) };
-    let _: NonZeroU32 = unsafe { NonZeroU32::new_unchecked(int_u32) };
-    let _: NonZeroU64 = unsafe { NonZeroU64::new_unchecked(int_u64) };
-    let _: NonZeroU128 = unsafe { NonZeroU128::new_unchecked(int_u128) };
+    let _: NonZero<u8> = unsafe { NonZero::new_unchecked(int_u8) };
+    let _: NonZero<u16> = unsafe { NonZero::new_unchecked(int_u16) };
+    let _: NonZero<u32> = unsafe { NonZero::new_unchecked(int_u32) };
+    let _: NonZero<u64> = unsafe { NonZero::new_unchecked(int_u64) };
+    let _: NonZero<u128> = unsafe { NonZero::new_unchecked(int_u128) };
 
-    let _: NonZeroI8 = unsafe { NonZeroI8::new_unchecked(int_i8) };
-    let _: NonZeroI16 = unsafe { NonZeroI16::new_unchecked(int_i16) };
-    let _: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(int_i32) };
-    let _: NonZeroI64 = unsafe { NonZeroI64::new_unchecked(int_i64) };
-    let _: NonZeroI128 = unsafe { NonZeroI128::new_unchecked(int_i128) };
+    let _: NonZero<i8> = unsafe { NonZero::new_unchecked(int_i8) };
+    let _: NonZero<i16> = unsafe { NonZero::new_unchecked(int_i16) };
+    let _: NonZero<i32> = unsafe { NonZero::new_unchecked(int_i32) };
+    let _: NonZero<i64> = unsafe { NonZero::new_unchecked(int_i64) };
+    let _: NonZero<i128> = unsafe { NonZero::new_unchecked(int_i128) };
 }
diff --git a/src/tools/clippy/tests/ui/transmute_int_to_non_zero.stderr b/src/tools/clippy/tests/ui/transmute_int_to_non_zero.stderr
index bb0b0d0ff4f..199b8ec59d0 100644
--- a/src/tools/clippy/tests/ui/transmute_int_to_non_zero.stderr
+++ b/src/tools/clippy/tests/ui/transmute_int_to_non_zero.stderr
@@ -1,65 +1,65 @@
-error: transmute from a `u8` to a `NonZeroU8`
-  --> tests/ui/transmute_int_to_non_zero.rs:19:33
+error: transmute from a `u8` to a `NonZero<u8>`
+  --> tests/ui/transmute_int_to_non_zero.rs:19:35
    |
-LL |     let _: NonZeroU8 = unsafe { std::mem::transmute(int_u8) };
-   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroU8::new_unchecked(int_u8)`
+LL |     let _: NonZero<u8> = unsafe { std::mem::transmute(int_u8) };
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZero::new_unchecked(int_u8)`
    |
    = note: `-D clippy::transmute-int-to-non-zero` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::transmute_int_to_non_zero)]`
 
-error: transmute from a `u16` to a `NonZeroU16`
-  --> tests/ui/transmute_int_to_non_zero.rs:22:34
+error: transmute from a `u16` to a `NonZero<u16>`
+  --> tests/ui/transmute_int_to_non_zero.rs:22:36
    |
-LL |     let _: NonZeroU16 = unsafe { std::mem::transmute(int_u16) };
-   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroU16::new_unchecked(int_u16)`
+LL |     let _: NonZero<u16> = unsafe { std::mem::transmute(int_u16) };
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZero::new_unchecked(int_u16)`
 
-error: transmute from a `u32` to a `NonZeroU32`
-  --> tests/ui/transmute_int_to_non_zero.rs:24:34
+error: transmute from a `u32` to a `NonZero<u32>`
+  --> tests/ui/transmute_int_to_non_zero.rs:24:36
    |
-LL |     let _: NonZeroU32 = unsafe { std::mem::transmute(int_u32) };
-   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroU32::new_unchecked(int_u32)`
+LL |     let _: NonZero<u32> = unsafe { std::mem::transmute(int_u32) };
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZero::new_unchecked(int_u32)`
 
-error: transmute from a `u64` to a `NonZeroU64`
-  --> tests/ui/transmute_int_to_non_zero.rs:26:34
+error: transmute from a `u64` to a `NonZero<u64>`
+  --> tests/ui/transmute_int_to_non_zero.rs:26:36
    |
-LL |     let _: NonZeroU64 = unsafe { std::mem::transmute(int_u64) };
-   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroU64::new_unchecked(int_u64)`
+LL |     let _: NonZero<u64> = unsafe { std::mem::transmute(int_u64) };
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZero::new_unchecked(int_u64)`
 
-error: transmute from a `u128` to a `NonZeroU128`
-  --> tests/ui/transmute_int_to_non_zero.rs:28:35
+error: transmute from a `u128` to a `NonZero<u128>`
+  --> tests/ui/transmute_int_to_non_zero.rs:28:37
    |
-LL |     let _: NonZeroU128 = unsafe { std::mem::transmute(int_u128) };
-   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroU128::new_unchecked(int_u128)`
+LL |     let _: NonZero<u128> = unsafe { std::mem::transmute(int_u128) };
+   |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZero::new_unchecked(int_u128)`
 
-error: transmute from a `i8` to a `NonZeroI8`
-  --> tests/ui/transmute_int_to_non_zero.rs:31:33
+error: transmute from a `i8` to a `NonZero<i8>`
+  --> tests/ui/transmute_int_to_non_zero.rs:31:35
    |
-LL |     let _: NonZeroI8 = unsafe { std::mem::transmute(int_i8) };
-   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroI8::new_unchecked(int_i8)`
+LL |     let _: NonZero<i8> = unsafe { std::mem::transmute(int_i8) };
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZero::new_unchecked(int_i8)`
 
-error: transmute from a `i16` to a `NonZeroI16`
-  --> tests/ui/transmute_int_to_non_zero.rs:33:34
+error: transmute from a `i16` to a `NonZero<i16>`
+  --> tests/ui/transmute_int_to_non_zero.rs:33:36
    |
-LL |     let _: NonZeroI16 = unsafe { std::mem::transmute(int_i16) };
-   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroI16::new_unchecked(int_i16)`
+LL |     let _: NonZero<i16> = unsafe { std::mem::transmute(int_i16) };
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZero::new_unchecked(int_i16)`
 
-error: transmute from a `i32` to a `NonZeroI32`
-  --> tests/ui/transmute_int_to_non_zero.rs:35:34
+error: transmute from a `i32` to a `NonZero<i32>`
+  --> tests/ui/transmute_int_to_non_zero.rs:35:36
    |
-LL |     let _: NonZeroI32 = unsafe { std::mem::transmute(int_i32) };
-   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroI32::new_unchecked(int_i32)`
+LL |     let _: NonZero<i32> = unsafe { std::mem::transmute(int_i32) };
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZero::new_unchecked(int_i32)`
 
-error: transmute from a `i64` to a `NonZeroI64`
-  --> tests/ui/transmute_int_to_non_zero.rs:37:34
+error: transmute from a `i64` to a `NonZero<i64>`
+  --> tests/ui/transmute_int_to_non_zero.rs:37:36
    |
-LL |     let _: NonZeroI64 = unsafe { std::mem::transmute(int_i64) };
-   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroI64::new_unchecked(int_i64)`
+LL |     let _: NonZero<i64> = unsafe { std::mem::transmute(int_i64) };
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZero::new_unchecked(int_i64)`
 
-error: transmute from a `i128` to a `NonZeroI128`
-  --> tests/ui/transmute_int_to_non_zero.rs:39:35
+error: transmute from a `i128` to a `NonZero<i128>`
+  --> tests/ui/transmute_int_to_non_zero.rs:39:37
    |
-LL |     let _: NonZeroI128 = unsafe { std::mem::transmute(int_i128) };
-   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroI128::new_unchecked(int_i128)`
+LL |     let _: NonZero<i128> = unsafe { std::mem::transmute(int_i128) };
+   |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZero::new_unchecked(int_i128)`
 
 error: aborting due to 10 previous errors
 
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 42159b147d5..c7c807d3e68 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -932,6 +932,8 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "test-mir-pass",
     "unset-exec-env",
     "unset-rustc-env",
+    // Used by the tidy check `unknown_revision`.
+    "unused-revision-names",
     // tidy-alphabetical-end
 ];
 
diff --git a/src/tools/html-checker/main.rs b/src/tools/html-checker/main.rs
index 9b4d2c52598..e74f72608ef 100644
--- a/src/tools/html-checker/main.rs
+++ b/src/tools/html-checker/main.rs
@@ -29,6 +29,8 @@ fn check_html_file(file: &Path) -> usize {
         .arg("-quiet")
         .arg("--mute-id") // this option is useful in case we want to mute more warnings
         .arg("yes")
+        .arg("--new-blocklevel-tags")
+        .arg("rustdoc-search") // custom elements
         .arg("--mute")
         .arg(&to_mute_s)
         .arg(file);
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index ca6f4d50917..3636c856d0b 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-d568423a7a4ddb4b49323d96078a22f94df55fbd
+ef15976387ad9c1cdceaabf469e0cf35f5852f6d
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 a6dd1d829cb..3da8744626d 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
@@ -136,7 +136,7 @@ impl NewPermission {
         cx: &crate::MiriInterpCx<'_, 'tcx>,
     ) -> Self {
         // `ty` is not the `Box` but the field of the Box with this pointer (due to allocator handling).
-        let pointee = ty.builtin_deref(true).unwrap().ty;
+        let pointee = ty.builtin_deref(true).unwrap();
         if pointee.is_unpin(*cx.tcx, cx.param_env()) {
             // A regular box. On `FnEntry` this is `noalias`, but not `dereferenceable` (hence only
             // a weak protector).
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 fc5eb942a27..b5bf16d3d36 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
@@ -173,7 +173,7 @@ impl<'tcx> NewPermission {
         cx: &crate::MiriInterpCx<'_, 'tcx>,
         zero_size: bool,
     ) -> Option<Self> {
-        let pointee = ty.builtin_deref(true).unwrap().ty;
+        let pointee = ty.builtin_deref(true).unwrap();
         pointee.is_unpin(*cx.tcx, cx.param_env()).then_some(()).map(|()| {
             // Regular `Unpin` box, give it `noalias` but only a weak protector
             // because it is valid to deallocate it within the function.
diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs
index effd7f6d543..9e7fc7a21fc 100644
--- a/src/tools/miri/src/intrinsics/mod.rs
+++ b/src/tools/miri/src/intrinsics/mod.rs
@@ -117,7 +117,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
             "write_bytes" | "volatile_set_memory" => {
                 let [ptr, val_byte, count] = check_arg_count(args)?;
-                let ty = ptr.layout.ty.builtin_deref(true).unwrap().ty;
+                let ty = ptr.layout.ty.builtin_deref(true).unwrap();
                 let ty_layout = this.layout_of(ty)?;
                 let val_byte = this.read_scalar(val_byte)?.to_u8()?;
                 let ptr = this.read_pointer(ptr)?;
diff --git a/src/tools/miri/src/intrinsics/simd.rs b/src/tools/miri/src/intrinsics/simd.rs
index 3be98d7f5f8..d0a78429ca8 100644
--- a/src/tools/miri/src/intrinsics/simd.rs
+++ b/src/tools/miri/src/intrinsics/simd.rs
@@ -267,7 +267,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                         Op::WrappingOffset => {
                             let ptr = left.to_scalar().to_pointer(this)?;
                             let offset_count = right.to_scalar().to_target_isize(this)?;
-                            let pointee_ty = left.layout.ty.builtin_deref(true).unwrap().ty;
+                            let pointee_ty = left.layout.ty.builtin_deref(true).unwrap();
 
                             let pointee_size = i64::try_from(this.layout_of(pointee_ty)?.size.bytes()).unwrap();
                             let offset_bytes = offset_count.wrapping_mul(pointee_size);
diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs
index 595cf64a4e4..aaf47248af6 100644
--- a/src/tools/miri/src/shims/unix/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/foreign_items.rs
@@ -378,8 +378,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     .builtin_deref(true)
                     .ok_or_else(|| err_ub_format!(
                         "wrong signature used for `pthread_key_create`: first argument must be a raw pointer."
-                    ))?
-                    .ty;
+                    ))?;
                 let key_layout = this.layout_of(key_type)?;
 
                 // Create key and write it into the memory where `key_ptr` wants it.
diff --git a/src/tools/miri/src/shims/x86/avx2.rs b/src/tools/miri/src/shims/x86/avx2.rs
index 783be802bb7..bbde5b49588 100644
--- a/src/tools/miri/src/shims/x86/avx2.rs
+++ b/src/tools/miri/src/shims/x86/avx2.rs
@@ -1,5 +1,5 @@
-use crate::rustc_middle::ty::layout::LayoutOf as _;
 use rustc_middle::mir;
+use rustc_middle::ty::layout::LayoutOf as _;
 use rustc_middle::ty::Ty;
 use rustc_span::Symbol;
 use rustc_target::spec::abi::Abi;
diff --git a/src/tools/miri/tests/fail/enum-set-discriminant-niche-variant-wrong.rs b/src/tools/miri/tests/fail/enum-set-discriminant-niche-variant-wrong.rs
index 428f371ca51..eca6d908b44 100644
--- a/src/tools/miri/tests/fail/enum-set-discriminant-niche-variant-wrong.rs
+++ b/src/tools/miri/tests/fail/enum-set-discriminant-niche-variant-wrong.rs
@@ -2,7 +2,7 @@
 #![feature(custom_mir)]
 
 use std::intrinsics::mir::*;
-use std::num::NonZeroI32;
+use std::num::NonZero;
 
 // We define our own option type so that we can control the variant indices.
 #[allow(unused)]
@@ -13,7 +13,7 @@ enum Option<T> {
 use Option::*;
 
 #[custom_mir(dialect = "runtime", phase = "optimized")]
-fn set_discriminant(ptr: &mut Option<NonZeroI32>) {
+fn set_discriminant(ptr: &mut Option<NonZero<i32>>) {
     mir! {
         {
             // We set the discriminant to `Some`, which is a NOP since this is the niched variant.
diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_repr_C.rs b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_repr_C.rs
index 2cf4e044777..c5900489b4c 100644
--- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_repr_C.rs
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_repr_C.rs
@@ -1,7 +1,7 @@
-use std::num::*;
+use std::num::NonZero;
 
 #[repr(C)]
-struct S1(NonZeroI32);
+struct S1(NonZero<i32>);
 
 #[repr(C)]
 struct S2(i32);
@@ -11,6 +11,6 @@ fn callee(_s: S2) {}
 fn main() {
     let fnptr: fn(S2) = callee;
     let fnptr: fn(S1) = unsafe { std::mem::transmute(fnptr) };
-    fnptr(S1(NonZeroI32::new(1).unwrap()));
+    fnptr(S1(NonZero::new(1).unwrap()));
     //~^ ERROR: calling a function with argument of type S2 passing data of type S1
 }
diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_repr_C.stderr b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_repr_C.stderr
index eaacc32bf68..8ec19db813a 100644
--- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_repr_C.stderr
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_repr_C.stderr
@@ -1,8 +1,8 @@
 error: Undefined Behavior: calling a function with argument of type S2 passing data of type S1
   --> $DIR/abi_mismatch_repr_C.rs:LL:CC
    |
-LL |     fnptr(S1(NonZeroI32::new(1).unwrap()));
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calling a function with argument of type S2 passing data of type S1
+LL |     fnptr(S1(NonZero::new(1).unwrap()));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calling a function with argument of type S2 passing data of type S1
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.rs b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.rs
new file mode 100644
index 00000000000..57b4fd0dedb
--- /dev/null
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.rs
@@ -0,0 +1,21 @@
+#![feature(strict_provenance)]
+use core::ptr;
+
+fn main() {
+    unsafe {
+        let base = ptr::without_provenance::<()>(10);
+        let unit = &*base;
+        let p1 = unit as *const ();
+
+        let base = ptr::without_provenance::<()>(11);
+        let unit = &*base;
+        let p2 = unit as *const ();
+
+        // Seems to work because they are same pointer
+        // even though it's dangling.
+        let _ = p1.byte_offset_from(p1);
+
+        // UB because different pointers.
+        let _ = p1.byte_offset_from(p2); //~ERROR: different pointers without provenance
+    }
+}
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.stderr
new file mode 100644
index 00000000000..6e9e5633fec
--- /dev/null
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: `ptr_offset_from` called on different pointers without provenance (i.e., without an associated allocation)
+  --> $DIR/ptr_offset_from_different_ints.rs:LL:CC
+   |
+LL |         let _ = p1.byte_offset_from(p2);
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called on different pointers without provenance (i.e., without an associated allocation)
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/ptr_offset_from_different_ints.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_ret.rs b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_ret.rs
index 7cdc15c6094..9fabdd8e86b 100644
--- a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_ret.rs
+++ b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_ret.rs
@@ -2,15 +2,15 @@
 #![feature(core_intrinsics, custom_mir)]
 
 use std::intrinsics::mir::*;
-use std::num::NonZeroU32;
+use std::num::NonZero;
 use std::ptr;
 
-// This function supposedly returns a NonZeroU32, but actually returns something invalid in a way that
-// never materializes a bad NonZeroU32 value: we take a pointer to the return place and cast the pointer
+// This function supposedly returns a `NonZero<u32>`, but actually returns something invalid in a way that
+// never materializes a bad `NonZero<u32>` value: we take a pointer to the return place and cast the pointer
 // type. That way we never get an "invalid value constructed" error inside the function, it can
 // only possibly be detected when the return value is passed to the caller.
 #[custom_mir(dialect = "runtime", phase = "optimized")]
-fn f() -> NonZeroU32 {
+fn f() -> NonZero<u32> {
     mir! {
         {
             let tmp = ptr::addr_of_mut!(RET);
@@ -22,7 +22,7 @@ fn f() -> NonZeroU32 {
 }
 
 fn main() {
-    let f: fn() -> u32 = unsafe { std::mem::transmute(f as fn() -> NonZeroU32) };
-    // There's a NonZeroU32-to-u32 transmute happening here
+    let f: fn() -> u32 = unsafe { std::mem::transmute(f as fn() -> NonZero<u32>) };
+    // There's a `NonZero<u32>` to `u32` transmute happening here.
     f(); //~ERROR: expected something greater or equal to 1
 }
diff --git a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs
index 3a87bb78677..7ca26bffc14 100644
--- a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs
+++ b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs
@@ -2,24 +2,24 @@
 #![feature(core_intrinsics, custom_mir)]
 
 use std::intrinsics::mir::*;
-use std::num::NonZeroU32;
+use std::num::NonZero;
 use std::ptr;
 
 fn f(c: u32) {
     println!("{c}");
 }
 
-// Call that function in a bad way, with an invalid NonZeroU32, but without
-// ever materializing this as a NonZeroU32 value outside the call itself.
+// Call that function in a bad way, with an invalid `NonZero<u32>`, but without
+// ever materializing this as a `NonZero<u32>` value outside the call itself.
 #[custom_mir(dialect = "runtime", phase = "optimized")]
-fn call(f: fn(NonZeroU32)) {
+fn call(f: fn(NonZero<u32>)) {
     mir! {
         let _res: ();
         {
             let c = 0;
             let tmp = ptr::addr_of!(c);
-            let ptr = tmp as *const NonZeroU32;
-            // The call site now is a NonZeroU32-to-u32 transmute.
+            let ptr = tmp as *const NonZero<u32>;
+            // The call site now is a `NonZero<u32>` to `u32` transmute.
             Call(_res = f(*ptr), ReturnTo(retblock), UnwindContinue()) //~ERROR: expected something greater or equal to 1
         }
         retblock = {
@@ -29,6 +29,6 @@ fn call(f: fn(NonZeroU32)) {
 }
 
 fn main() {
-    let f: fn(NonZeroU32) = unsafe { std::mem::transmute(f as fn(u32)) };
+    let f: fn(NonZero<u32>) = unsafe { std::mem::transmute(f as fn(u32)) };
     call(f);
 }
diff --git a/src/tools/miri/tests/pass/function_calls/abi_compat.rs b/src/tools/miri/tests/pass/function_calls/abi_compat.rs
index 14fd2d333d4..136660a305a 100644
--- a/src/tools/miri/tests/pass/function_calls/abi_compat.rs
+++ b/src/tools/miri/tests/pass/function_calls/abi_compat.rs
@@ -70,7 +70,7 @@ fn main() {
         test_abi_compat(0usize, 0u64);
         test_abi_compat(0isize, 0i64);
     }
-    test_abi_compat(42u32, num::NonZeroU32::new(1).unwrap());
+    test_abi_compat(42u32, num::NonZero::new(1u32).unwrap());
     // - `char` and `u32`.
     test_abi_compat(42u32, 'x');
     // - Reference/pointer types with the same pointee.
@@ -86,9 +86,9 @@ fn main() {
     // - Guaranteed null-pointer-optimizations (RFC 3391).
     test_abi_compat(&0u32 as *const u32, Some(&0u32));
     test_abi_compat(main as fn(), Some(main as fn()));
-    test_abi_compat(0u32, Some(num::NonZeroU32::new(1).unwrap()));
+    test_abi_compat(0u32, Some(num::NonZero::new(1u32).unwrap()));
     test_abi_compat(&0u32 as *const u32, Some(Wrapper(&0u32)));
-    test_abi_compat(0u32, Some(Wrapper(num::NonZeroU32::new(1).unwrap())));
+    test_abi_compat(0u32, Some(Wrapper(num::NonZero::new(1u32).unwrap())));
 
     // These must work for *any* type, since we guarantee that `repr(transparent)` is ABI-compatible
     // with the wrapped field.
@@ -102,7 +102,7 @@ fn main() {
     test_abi_newtype::<[u32; 2]>();
     test_abi_newtype::<[u32; 32]>();
     test_abi_newtype::<Option<i32>>();
-    test_abi_newtype::<Option<num::NonZeroU32>>();
+    test_abi_newtype::<Option<num::NonZero<u32>>>();
 
     // Extra test for assumptions made by arbitrary-self-dyn-receivers.
     // This is interesting since these types are not `repr(transparent)`. So this is not part of our
diff --git a/src/tools/miri/tests/pass/shims/available-parallelism-miri-num-cpus.rs b/src/tools/miri/tests/pass/shims/available-parallelism-miri-num-cpus.rs
index 137fa510249..0d96bc2f5e7 100644
--- a/src/tools/miri/tests/pass/shims/available-parallelism-miri-num-cpus.rs
+++ b/src/tools/miri/tests/pass/shims/available-parallelism-miri-num-cpus.rs
@@ -1,8 +1,8 @@
 //@compile-flags: -Zmiri-num-cpus=1024
 
-use std::num::NonZeroUsize;
+use std::num::NonZero;
 use std::thread::available_parallelism;
 
 fn main() {
-    assert_eq!(available_parallelism().unwrap(), NonZeroUsize::new(1024).unwrap());
+    assert_eq!(available_parallelism().unwrap(), NonZero::new(1024).unwrap());
 }
diff --git a/src/tools/miri/tests/ui.rs b/src/tools/miri/tests/ui.rs
index 1a7c4724500..3a8b098ccbe 100644
--- a/src/tools/miri/tests/ui.rs
+++ b/src/tools/miri/tests/ui.rs
@@ -1,5 +1,5 @@
 use std::ffi::OsString;
-use std::num::NonZeroUsize;
+use std::num::NonZero;
 use std::path::{Path, PathBuf};
 use std::sync::OnceLock;
 use std::{env, process::Command};
@@ -77,7 +77,7 @@ fn miri_config(target: &str, path: &str, mode: Mode, with_dependencies: bool) ->
         edition: Some("2021".into()), // keep in sync with `./miri run`
         threads: std::env::var("MIRI_TEST_THREADS")
             .ok()
-            .map(|threads| NonZeroUsize::new(threads.parse().unwrap()).unwrap()),
+            .map(|threads| NonZero::new(threads.parse().unwrap()).unwrap()),
         ..Config::rustc(path)
     };
 
diff --git a/src/tools/opt-dist/Cargo.toml b/src/tools/opt-dist/Cargo.toml
index 4cb6acb394c..1ff410e723a 100644
--- a/src/tools/opt-dist/Cargo.toml
+++ b/src/tools/opt-dist/Cargo.toml
@@ -16,7 +16,7 @@ camino = "1"
 reqwest = { version = "0.11", features = ["blocking"] }
 zip = { version = "0.6", default-features = false, features = ["deflate"] }
 tar = "0.4"
-xz = "0.1"
+xz = { version = "0.1", package = "xz2" }
 serde = { version = "1", features = ["derive"] }
 serde_json = "1"
 glob = "0.3"
diff --git a/src/tools/run-make-support/src/cc.rs b/src/tools/run-make-support/src/cc.rs
index 4082639f618..a67f5c8a9ee 100644
--- a/src/tools/run-make-support/src/cc.rs
+++ b/src/tools/run-make-support/src/cc.rs
@@ -73,7 +73,7 @@ impl Cc {
     }
 
     /// Get the [`Output`][::std::process::Output] of the finished process.
-    pub fn output(&mut self) -> ::std::process::Output {
+    pub fn command_output(&mut self) -> ::std::process::Output {
         self.cmd.output().expect("failed to get output of finished process")
     }
 }
diff --git a/src/tools/run-make-support/src/clang.rs b/src/tools/run-make-support/src/clang.rs
index c30ba29ed76..6ccce67b250 100644
--- a/src/tools/run-make-support/src/clang.rs
+++ b/src/tools/run-make-support/src/clang.rs
@@ -72,7 +72,7 @@ impl Clang {
     }
 
     /// Get the [`Output`][::std::process::Output] of the finished process.
-    pub fn output(&mut self) -> ::std::process::Output {
+    pub fn command_output(&mut self) -> ::std::process::Output {
         self.cmd.output().expect("failed to get output of finished process")
     }
 }
diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs
index d040b05f20e..9888ca2d1ed 100644
--- a/src/tools/run-make-support/src/lib.rs
+++ b/src/tools/run-make-support/src/lib.rs
@@ -164,7 +164,7 @@ pub fn set_host_rpath(cmd: &mut Command) {
 ///
 /// impl CommandWrapper {
 ///     /// Get the [`Output`][::std::process::Output] of the finished process.
-///     pub fn output(&mut self) -> Output { /* ... */ } // <- required `output()` method
+///     pub fn command_output(&mut self) -> Output { /* ... */ } // <- required `command_output()` method
 /// }
 ///
 /// crate::impl_common_helpers!(CommandWrapper);
@@ -242,7 +242,7 @@ macro_rules! impl_common_helpers {
                 let caller_location = ::std::panic::Location::caller();
                 let caller_line_number = caller_location.line();
 
-                let output = self.output();
+                let output = self.command_output();
                 if !output.status.success() {
                     handle_failed_output(&self.cmd, output, caller_line_number);
                 }
@@ -255,7 +255,7 @@ macro_rules! impl_common_helpers {
                 let caller_location = ::std::panic::Location::caller();
                 let caller_line_number = caller_location.line();
 
-                let output = self.output();
+                let output = self.command_output();
                 if output.status.success() {
                     handle_failed_output(&self.cmd, output, caller_line_number);
                 }
diff --git a/src/tools/run-make-support/src/llvm_readobj.rs b/src/tools/run-make-support/src/llvm_readobj.rs
index 4e1f2b002f3..f114aacfa3f 100644
--- a/src/tools/run-make-support/src/llvm_readobj.rs
+++ b/src/tools/run-make-support/src/llvm_readobj.rs
@@ -44,7 +44,7 @@ impl LlvmReadobj {
 
     /// Get the [`Output`][::std::process::Output] of the finished process.
     #[track_caller]
-    pub fn output(&mut self) -> ::std::process::Output {
+    pub fn command_output(&mut self) -> ::std::process::Output {
         self.cmd.output().expect("failed to get output of finished process")
     }
 }
diff --git a/src/tools/run-make-support/src/rustc.rs b/src/tools/run-make-support/src/rustc.rs
index 37539528ab3..de773d688ef 100644
--- a/src/tools/run-make-support/src/rustc.rs
+++ b/src/tools/run-make-support/src/rustc.rs
@@ -91,6 +91,13 @@ impl Rustc {
         self
     }
 
+    /// Specify path to the output file.
+    pub fn output<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
+        self.cmd.arg("-o");
+        self.cmd.arg(path.as_ref());
+        self
+    }
+
     /// This flag defers LTO optimizations to the linker.
     pub fn linker_plugin_lto(&mut self, option: &str) -> &mut Self {
         self.cmd.arg(format!("-Clinker-plugin-lto={option}"));
@@ -171,7 +178,7 @@ impl Rustc {
 
     /// Get the [`Output`][::std::process::Output] of the finished process.
     #[track_caller]
-    pub fn output(&mut self) -> ::std::process::Output {
+    pub fn command_output(&mut self) -> ::std::process::Output {
         // let's make sure we piped all the input and outputs
         self.cmd.stdin(Stdio::piped());
         self.cmd.stdout(Stdio::piped());
@@ -196,7 +203,7 @@ impl Rustc {
         let caller_location = std::panic::Location::caller();
         let caller_line_number = caller_location.line();
 
-        let output = self.output();
+        let output = self.command_output();
         if output.status.code().unwrap() != code {
             handle_failed_output(&self.cmd, output, caller_line_number);
         }
diff --git a/src/tools/run-make-support/src/rustdoc.rs b/src/tools/run-make-support/src/rustdoc.rs
index c2c4f2e68e2..aa3c7dcf0e3 100644
--- a/src/tools/run-make-support/src/rustdoc.rs
+++ b/src/tools/run-make-support/src/rustdoc.rs
@@ -51,6 +51,13 @@ impl Rustdoc {
         self
     }
 
+    /// Specify path to the output folder.
+    pub fn output<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
+        self.cmd.arg("-o");
+        self.cmd.arg(path.as_ref());
+        self
+    }
+
     /// Specify output directory.
     pub fn out_dir<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
         self.cmd.arg("--out-dir").arg(path.as_ref());
@@ -73,7 +80,7 @@ impl Rustdoc {
 
     /// Get the [`Output`][::std::process::Output] of the finished process.
     #[track_caller]
-    pub fn output(&mut self) -> ::std::process::Output {
+    pub fn command_output(&mut self) -> ::std::process::Output {
         // let's make sure we piped all the input and outputs
         self.cmd.stdin(Stdio::piped());
         self.cmd.stdout(Stdio::piped());
@@ -93,12 +100,19 @@ impl Rustdoc {
         }
     }
 
+    /// Specify the edition year.
+    pub fn edition(&mut self, edition: &str) -> &mut Self {
+        self.cmd.arg("--edition");
+        self.cmd.arg(edition);
+        self
+    }
+
     #[track_caller]
     pub fn run_fail_assert_exit_code(&mut self, code: i32) -> Output {
         let caller_location = std::panic::Location::caller();
         let caller_line_number = caller_location.line();
 
-        let output = self.output();
+        let output = self.command_output();
         if output.status.code().unwrap() != code {
             handle_failed_output(&self.cmd, output, caller_line_number);
         }
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 dd949e26c2a..d9fd029d378 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,8 @@ use base_db::salsa::Cycle;
 use chalk_ir::{AdtId, FloatTy, IntTy, TyKind, UintTy};
 use hir_def::{
     layout::{
-        Abi, FieldsShape, Integer, LayoutCalculator, LayoutS, Primitive, ReprOptions, Scalar, Size,
-        StructKind, TargetDataLayout, WrappingRange,
+        Abi, FieldsShape, Float, Integer, LayoutCalculator, LayoutS, Primitive, ReprOptions,
+        Scalar, Size, StructKind, TargetDataLayout, WrappingRange,
     },
     LocalFieldId, StructId,
 };
@@ -264,10 +264,10 @@ pub fn layout_of_ty_query(
             ),
             chalk_ir::Scalar::Float(f) => scalar(
                 dl,
-                match f {
-                    FloatTy::F32 => Primitive::F32,
-                    FloatTy::F64 => Primitive::F64,
-                },
+                Primitive::Float(match f {
+                    FloatTy::F32 => Float::F32,
+                    FloatTy::F64 => Float::F64,
+                }),
             ),
         },
         TyKind::Tuple(len, tys) => {
diff --git a/src/tools/rustfmt/src/imports.rs b/src/tools/rustfmt/src/imports.rs
index 09f6e752338..2da746295fc 100644
--- a/src/tools/rustfmt/src/imports.rs
+++ b/src/tools/rustfmt/src/imports.rs
@@ -458,7 +458,9 @@ impl UseTree {
                     version,
                 });
             }
-            UseTreeKind::Nested(ref list) => {
+            UseTreeKind::Nested {
+                items: ref list, ..
+            } => {
                 // Extract comments between nested use items.
                 // This needs to be done before sorting use items.
                 let items = itemize_list(
diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index d4d6c1460ce..e87950b36d9 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -44,7 +44,6 @@ run-make/dep-graph/Makefile
 run-make/dep-info-doesnt-run-much/Makefile
 run-make/dep-info-spaces/Makefile
 run-make/dep-info/Makefile
-run-make/doctests-runtool/Makefile
 run-make/dump-ice-to-disk/Makefile
 run-make/dump-mono-stats/Makefile
 run-make/duplicate-output-flavors/Makefile
@@ -245,10 +244,7 @@ run-make/rlib-format-packed-bundled-libs-3/Makefile
 run-make/rlib-format-packed-bundled-libs/Makefile
 run-make/rmeta-preferred/Makefile
 run-make/rustc-macro-dep-files/Makefile
-run-make/rustdoc-error-lines/Makefile
 run-make/rustdoc-io-error/Makefile
-run-make/rustdoc-map-file/Makefile
-run-make/rustdoc-output-path/Makefile
 run-make/rustdoc-scrape-examples-invalid-expr/Makefile
 run-make/rustdoc-scrape-examples-macros/Makefile
 run-make/rustdoc-scrape-examples-multiple/Makefile
diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt
index 4f02a61f7bc..a931782e8cc 100644
--- a/src/tools/tidy/src/issues.txt
+++ b/src/tools/tidy/src/issues.txt
@@ -3862,7 +3862,6 @@ ui/statics/issue-91050-1.rs
 ui/statics/issue-91050-2.rs
 ui/std/issue-3563-3.rs
 ui/std/issue-81357-unsound-file-methods.rs
-ui/stdlib-unit-tests/issue-21058.rs
 ui/structs-enums/enum-rec/issue-17431-6.rs
 ui/structs-enums/enum-rec/issue-17431-7.rs
 ui/structs-enums/issue-103869.rs
diff --git a/src/tools/tidy/src/iter_header.rs b/src/tools/tidy/src/iter_header.rs
index ae635904607..684c789039f 100644
--- a/src/tools/tidy/src/iter_header.rs
+++ b/src/tools/tidy/src/iter_header.rs
@@ -3,6 +3,7 @@ const COMMENT: &str = "//@";
 /// A header line, like `//@name: value` consists of the prefix `//@` and the directive
 /// `name: value`. It is also possibly revisioned, e.g. `//@[revision] name: value`.
 pub(crate) struct HeaderLine<'ln> {
+    pub(crate) line_number: usize,
     pub(crate) revision: Option<&'ln str>,
     pub(crate) directive: &'ln str,
 }
@@ -11,7 +12,7 @@ pub(crate) struct HeaderLine<'ln> {
 ///
 /// Adjusted from compiletest/src/header.rs.
 pub(crate) fn iter_header<'ln>(contents: &'ln str, it: &mut dyn FnMut(HeaderLine<'ln>)) {
-    for ln in contents.lines() {
+    for (line_number, ln) in (1..).zip(contents.lines()) {
         let ln = ln.trim();
 
         // We're left with potentially `[rev]name: value`.
@@ -24,9 +25,9 @@ pub(crate) fn iter_header<'ln>(contents: &'ln str, it: &mut dyn FnMut(HeaderLine
                 panic!("malformed revision directive: expected `//@[rev]`, found `{ln}`");
             };
             // We trimmed off the `[rev]` portion, left with `name: value`.
-            it(HeaderLine { revision: Some(revision), directive: remainder.trim() });
+            it(HeaderLine { line_number, revision: Some(revision), directive: remainder.trim() });
         } else {
-            it(HeaderLine { revision: None, directive: remainder.trim() });
+            it(HeaderLine { line_number, revision: None, directive: remainder.trim() });
         }
     }
 }
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index c15081a56d1..ae9d2b8b8dc 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -87,6 +87,7 @@ pub mod tests_placement;
 pub mod tests_revision_unpaired_stdout_stderr;
 pub mod ui_tests;
 pub mod unit_tests;
+pub mod unknown_revision;
 pub mod unstable_book;
 pub mod walk;
 pub mod x_version;
diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs
index 77691815830..1d2b2e4d034 100644
--- a/src/tools/tidy/src/main.rs
+++ b/src/tools/tidy/src/main.rs
@@ -110,6 +110,7 @@ fn main() {
         check!(rustdoc_gui_tests, &tests_path);
         check!(rustdoc_css_themes, &librustdoc_path);
         check!(known_bug, &crashes_path);
+        check!(unknown_revision, &tests_path);
 
         // Checks that only make sense for the compiler.
         check!(error_codes, &root_path, &[&compiler_path, &librustdoc_path], verbose);
diff --git a/src/tools/tidy/src/target_specific_tests.rs b/src/tools/tidy/src/target_specific_tests.rs
index cb242bff05d..c876aae494d 100644
--- a/src/tools/tidy/src/target_specific_tests.rs
+++ b/src/tools/tidy/src/target_specific_tests.rs
@@ -20,7 +20,7 @@ pub fn check(path: &Path, bad: &mut bool) {
     crate::walk::walk(path, |path, _is_dir| filter_not_rust(path), &mut |entry, content| {
         let file = entry.path().display();
         let mut header_map = BTreeMap::new();
-        iter_header(content, &mut |HeaderLine { revision, directive }| {
+        iter_header(content, &mut |HeaderLine { revision, directive, .. }| {
             if let Some(value) = directive.strip_prefix(LLVM_COMPONENTS_HEADER) {
                 let info = header_map.entry(revision).or_insert(RevisionInfo::default());
                 let comp_vec = info.llvm_components.get_or_insert(Vec::new());
diff --git a/src/tools/tidy/src/tests_revision_unpaired_stdout_stderr.rs b/src/tools/tidy/src/tests_revision_unpaired_stdout_stderr.rs
index a0773c85bef..00edf99a30d 100644
--- a/src/tools/tidy/src/tests_revision_unpaired_stdout_stderr.rs
+++ b/src/tools/tidy/src/tests_revision_unpaired_stdout_stderr.rs
@@ -61,7 +61,7 @@ pub fn check(tests_path: impl AsRef<Path>, bad: &mut bool) {
             let contents = std::fs::read_to_string(test).unwrap();
 
             // Collect directives.
-            iter_header(&contents, &mut |HeaderLine { revision, directive }| {
+            iter_header(&contents, &mut |HeaderLine { revision, directive, .. }| {
                 // We're trying to *find* `//@ revision: xxx` directives themselves, not revisioned
                 // directives.
                 if revision.is_some() {
diff --git a/src/tools/tidy/src/unknown_revision.rs b/src/tools/tidy/src/unknown_revision.rs
new file mode 100644
index 00000000000..abfff1d632a
--- /dev/null
+++ b/src/tools/tidy/src/unknown_revision.rs
@@ -0,0 +1,114 @@
+//! Checks that test revision names appearing in header directives and error
+//! annotations have actually been declared in `revisions`.
+
+// FIXME(jieyouxu) Ideally these checks would be integrated into compiletest's
+// own directive and revision handling, but for now they've been split out as a
+// separate `tidy` check to avoid making compiletest even messier.
+
+use std::collections::{BTreeSet, HashMap, HashSet};
+use std::path::Path;
+use std::sync::OnceLock;
+
+use ignore::DirEntry;
+use regex::Regex;
+
+use crate::iter_header::{iter_header, HeaderLine};
+use crate::walk::{filter_dirs, filter_not_rust, walk};
+
+pub fn check(tests_path: impl AsRef<Path>, bad: &mut bool) {
+    walk(
+        tests_path.as_ref(),
+        |path, is_dir| {
+            filter_dirs(path) || filter_not_rust(path) || {
+                // Auxiliary source files for incremental tests can refer to revisions
+                // declared by the main file, which this check doesn't handle.
+                is_dir && path.file_name().is_some_and(|name| name == "auxiliary")
+            }
+        },
+        &mut |entry, contents| visit_test_file(entry, contents, bad),
+    );
+}
+
+fn visit_test_file(entry: &DirEntry, contents: &str, bad: &mut bool) {
+    let mut revisions = HashSet::new();
+    let mut unused_revision_names = HashSet::new();
+
+    // Maps each mentioned revision to the first line it was mentioned on.
+    let mut mentioned_revisions = HashMap::<&str, usize>::new();
+    let mut add_mentioned_revision = |line_number: usize, revision| {
+        let first_line = mentioned_revisions.entry(revision).or_insert(line_number);
+        *first_line = (*first_line).min(line_number);
+    };
+
+    // Scan all `//@` headers to find declared revisions and mentioned revisions.
+    iter_header(contents, &mut |HeaderLine { line_number, revision, directive }| {
+        if let Some(revs) = directive.strip_prefix("revisions:") {
+            revisions.extend(revs.split_whitespace());
+        } else if let Some(revs) = directive.strip_prefix("unused-revision-names:") {
+            unused_revision_names.extend(revs.split_whitespace());
+        }
+
+        if let Some(revision) = revision {
+            add_mentioned_revision(line_number, revision);
+        }
+    });
+
+    // If a wildcard appears in `unused-revision-names`, skip all revision name
+    // checking for this file.
+    if unused_revision_names.contains(&"*") {
+        return;
+    }
+
+    // Scan all `//[rev]~` error annotations to find mentioned revisions.
+    for_each_error_annotation_revision(contents, &mut |ErrorAnnRev { line_number, revision }| {
+        add_mentioned_revision(line_number, revision);
+    });
+
+    let path = entry.path().display();
+
+    // Fail if any revision names appear in both places, since that's probably a mistake.
+    for rev in revisions.intersection(&unused_revision_names).copied().collect::<BTreeSet<_>>() {
+        tidy_error!(
+            bad,
+            "revision name [{rev}] appears in both `revisions` and `unused-revision-names` in {path}"
+        );
+    }
+
+    // Compute the set of revisions that were mentioned but not declared,
+    // sorted by the first line number they appear on.
+    let mut bad_revisions = mentioned_revisions
+        .into_iter()
+        .filter(|(rev, _)| !revisions.contains(rev) && !unused_revision_names.contains(rev))
+        .map(|(rev, line_number)| (line_number, rev))
+        .collect::<Vec<_>>();
+    bad_revisions.sort();
+
+    for (line_number, rev) in bad_revisions {
+        tidy_error!(bad, "unknown revision [{rev}] at {path}:{line_number}");
+    }
+}
+
+struct ErrorAnnRev<'a> {
+    line_number: usize,
+    revision: &'a str,
+}
+
+fn for_each_error_annotation_revision<'a>(
+    contents: &'a str,
+    callback: &mut dyn FnMut(ErrorAnnRev<'a>),
+) {
+    let error_regex = {
+        // Simplified from the regex used by `parse_expected` in `src/tools/compiletest/src/errors.rs`,
+        // because we only care about extracting revision names.
+        static RE: OnceLock<Regex> = OnceLock::new();
+        RE.get_or_init(|| Regex::new(r"//\[(?<revs>[^]]*)\]~").unwrap())
+    };
+
+    for (line_number, line) in (1..).zip(contents.lines()) {
+        let Some(captures) = error_regex.captures(line) else { continue };
+
+        for revision in captures.name("revs").unwrap().as_str().split(',') {
+            callback(ErrorAnnRev { line_number, revision });
+        }
+    }
+}
diff --git a/tests/codegen/debug-fndef-size.rs b/tests/codegen/debug-fndef-size.rs
index 5551d2cc39c..27bf00adf0e 100644
--- a/tests/codegen/debug-fndef-size.rs
+++ b/tests/codegen/debug-fndef-size.rs
@@ -13,6 +13,6 @@ pub fn main() {
 }
 
 // CHECK: %compare.dbg.spill = alloca [0 x i8], align 1
-// CHECK: call void @llvm.dbg.declare(metadata ptr %compare.dbg.spill, metadata ![[VAR:.*]], metadata !DIExpression()), !dbg !{{.*}}
+// CHECK: dbg{{.}}declare({{(metadata )?}}ptr %compare.dbg.spill, {{(metadata )?}}![[VAR:.*]], {{(metadata )?}}!DIExpression()
 // CHECK: ![[TYPE:.*]] = !DIDerivedType(tag: DW_TAG_pointer_type, name: "fn(&i32, &i32) -> core::cmp::Ordering", baseType: !{{.*}}, align: 1, dwarfAddressSpace: {{.*}})
 // CHECK: ![[VAR]] = !DILocalVariable(name: "compare", scope: !{{.*}}, file: !{{.*}}, line: {{.*}}, type: ![[TYPE]], align: 1)
diff --git a/tests/codegen/debuginfo-constant-locals.rs b/tests/codegen/debuginfo-constant-locals.rs
index f607e0dd08b..c8f1d964722 100644
--- a/tests/codegen/debuginfo-constant-locals.rs
+++ b/tests/codegen/debuginfo-constant-locals.rs
@@ -18,8 +18,8 @@ fn foo(x: i32) {
 }
 
 // CHECK-LABEL: @check_it
-// CHECK: call void @llvm.dbg.value(metadata i32 1, metadata ![[a_metadata:[0-9]+]], metadata !DIExpression())
-// CHECK: call void @llvm.dbg.value(metadata i32 42, metadata ![[b_metadata:[0-9]+]], metadata !DIExpression())
+// CHECK: dbg{{.}}value({{(metadata )?}}i32 1, {{(metadata )?}}![[a_metadata:[0-9]+]], {{(metadata )?}}!DIExpression()
+// CHECK: dbg{{.}}value({{(metadata )?}}i32 42, {{(metadata )?}}![[b_metadata:[0-9]+]], {{(metadata )?}}!DIExpression()
 
 // CHECK: ![[a_metadata]] = !DILocalVariable(name: "a"
 // CHECK-SAME: line: 9
diff --git a/tests/codegen/inline-debuginfo.rs b/tests/codegen/inline-debuginfo.rs
index b6ea489f99f..f327180560d 100644
--- a/tests/codegen/inline-debuginfo.rs
+++ b/tests/codegen/inline-debuginfo.rs
@@ -9,7 +9,7 @@ pub extern "C" fn callee(x: u32) -> u32 {
 }
 
 // CHECK-LABEL: caller
-// CHECK: call void @llvm.dbg.value(metadata i32 %y, metadata !{{.*}}, metadata !DIExpression(DW_OP_constu, 3, DW_OP_minus, DW_OP_stack_value)), !dbg [[A:!.*]]
+// CHECK: dbg{{.}}value({{(metadata )?}}i32 %y, {{(metadata )?}}!{{.*}}, {{(metadata )?}}!DIExpression(DW_OP_constu, 3, DW_OP_minus, DW_OP_stack_value){{.*}} [[A:![0-9]+]]
 // CHECK: [[A]] = !DILocation(line: {{.*}}, scope: {{.*}}, inlinedAt: {{.*}})
 #[no_mangle]
 pub extern "C" fn caller(y: u32) -> u32 {
diff --git a/tests/codegen/mir-aggregate-no-alloca.rs b/tests/codegen/mir-aggregate-no-alloca.rs
new file mode 100644
index 00000000000..a7752d714fe
--- /dev/null
+++ b/tests/codegen/mir-aggregate-no-alloca.rs
@@ -0,0 +1,123 @@
+//@ compile-flags: -O -C no-prepopulate-passes -Z randomize-layout=no
+
+#![crate_type = "lib"]
+
+#[repr(transparent)]
+pub struct Transparent32(u32);
+
+// CHECK: i32 @make_transparent(i32 noundef %x)
+#[no_mangle]
+pub fn make_transparent(x: u32) -> Transparent32 {
+    // CHECK-NOT: alloca
+    // CHECK: ret i32 %x
+    let a = Transparent32(x);
+    a
+}
+
+// CHECK: i32 @make_closure(i32 noundef %x)
+#[no_mangle]
+pub fn make_closure(x: i32) -> impl Fn(i32) -> i32 {
+    // CHECK-NOT: alloca
+    // CHECK: ret i32 %x
+    move |y| x + y
+}
+
+#[repr(transparent)]
+pub struct TransparentPair((), (u16, u16), ());
+
+// CHECK: { i16, i16 } @make_transparent_pair(i16 noundef %x.0, i16 noundef %x.1)
+#[no_mangle]
+pub fn make_transparent_pair(x: (u16, u16)) -> TransparentPair {
+    // CHECK-NOT: alloca
+    // CHECK: %[[TEMP0:.+]] = insertvalue { i16, i16 } poison, i16 %x.0, 0
+    // CHECK: %[[TEMP1:.+]] = insertvalue { i16, i16 } %[[TEMP0]], i16 %x.1, 1
+    // CHECK: ret { i16, i16 } %[[TEMP1]]
+    let a = TransparentPair((), x, ());
+    a
+}
+
+// CHECK-LABEL: { i32, i32 } @make_2_tuple(i32 noundef %x)
+#[no_mangle]
+pub fn make_2_tuple(x: u32) -> (u32, u32) {
+    // CHECK-NOT: alloca
+    // CHECK: %[[TEMP0:.+]] = insertvalue { i32, i32 } poison, i32 %x, 0
+    // CHECK: %[[TEMP1:.+]] = insertvalue { i32, i32 } %[[TEMP0]], i32 %x, 1
+    // CHECK: ret { i32, i32 } %[[TEMP1]]
+    let pair = (x, x);
+    pair
+}
+
+// CHECK-LABEL: i8 @make_cell_of_bool(i1 noundef zeroext %b)
+#[no_mangle]
+pub fn make_cell_of_bool(b: bool) -> std::cell::Cell<bool> {
+    // CHECK: %[[BYTE:.+]] = zext i1 %b to i8
+    // CHECK: ret i8 %[[BYTE]]
+    std::cell::Cell::new(b)
+}
+
+// CHECK-LABLE: { i8, i16 } @make_cell_of_bool_and_short(i1 noundef zeroext %b, i16 noundef %s)
+#[no_mangle]
+pub fn make_cell_of_bool_and_short(b: bool, s: u16) -> std::cell::Cell<(bool, u16)> {
+    // CHECK-NOT: alloca
+    // CHECK: %[[BYTE:.+]] = zext i1 %b to i8
+    // CHECK: %[[TEMP0:.+]] = insertvalue { i8, i16 } poison, i8 %[[BYTE]], 0
+    // CHECK: %[[TEMP1:.+]] = insertvalue { i8, i16 } %[[TEMP0]], i16 %s, 1
+    // CHECK: ret { i8, i16 } %[[TEMP1]]
+    std::cell::Cell::new((b, s))
+}
+
+// CHECK-LABEL: { i1, i1 } @make_tuple_of_bools(i1 noundef zeroext %a, i1 noundef zeroext %b)
+#[no_mangle]
+pub fn make_tuple_of_bools(a: bool, b: bool) -> (bool, bool) {
+    // CHECK-NOT: alloca
+    // CHECK: %[[TEMP0:.+]] = insertvalue { i1, i1 } poison, i1 %a, 0
+    // CHECK: %[[TEMP1:.+]] = insertvalue { i1, i1 } %[[TEMP0]], i1 %b, 1
+    // CHECK: ret { i1, i1 } %[[TEMP1]]
+    (a, b)
+}
+
+pub struct Struct0();
+
+// CHECK-LABEL: void @make_struct_0()
+#[no_mangle]
+pub fn make_struct_0() -> Struct0 {
+    // CHECK: ret void
+    let s = Struct0();
+    s
+}
+
+pub struct Struct1(i32);
+
+// CHECK-LABEL: i32 @make_struct_1(i32 noundef %a)
+#[no_mangle]
+pub fn make_struct_1(a: i32) -> Struct1 {
+    // CHECK: ret i32 %a
+    let s = Struct1(a);
+    s
+}
+
+pub struct Struct2Asc(i16, i64);
+
+// CHECK-LABEL: { i64, i16 } @make_struct_2_asc(i16 noundef %a, i64 noundef %b)
+#[no_mangle]
+pub fn make_struct_2_asc(a: i16, b: i64) -> Struct2Asc {
+    // CHECK-NOT: alloca
+    // CHECK: %[[TEMP0:.+]] = insertvalue { i64, i16 } poison, i64 %b, 0
+    // CHECK: %[[TEMP1:.+]] = insertvalue { i64, i16 } %[[TEMP0]], i16 %a, 1
+    // CHECK: ret { i64, i16 } %[[TEMP1]]
+    let s = Struct2Asc(a, b);
+    s
+}
+
+pub struct Struct2Desc(i64, i16);
+
+// CHECK-LABEL: { i64, i16 } @make_struct_2_desc(i64 noundef %a, i16 noundef %b)
+#[no_mangle]
+pub fn make_struct_2_desc(a: i64, b: i16) -> Struct2Desc {
+    // CHECK-NOT: alloca
+    // CHECK: %[[TEMP0:.+]] = insertvalue { i64, i16 } poison, i64 %a, 0
+    // CHECK: %[[TEMP1:.+]] = insertvalue { i64, i16 } %[[TEMP0]], i16 %b, 1
+    // CHECK: ret { i64, i16 } %[[TEMP1]]
+    let s = Struct2Desc(a, b);
+    s
+}
diff --git a/tests/codegen/sroa-fragment-debuginfo.rs b/tests/codegen/sroa-fragment-debuginfo.rs
index 32786d2a76a..670ddb56540 100644
--- a/tests/codegen/sroa-fragment-debuginfo.rs
+++ b/tests/codegen/sroa-fragment-debuginfo.rs
@@ -17,9 +17,9 @@ pub fn extra(s: &[u8]) {
 // CHECK: %slice.dbg.spill1 = alloca [4 x i8],
 // CHECK: %slice.dbg.spill = alloca [16 x i8],
 // CHECK: %s.dbg.spill = alloca [16 x i8],
-// CHECK: call void @llvm.dbg.declare(metadata ptr %s.dbg.spill, metadata ![[S_EXTRA:.*]], metadata !DIExpression()),
-// CHECK: call void @llvm.dbg.declare(metadata ptr %slice.dbg.spill, metadata ![[SLICE_EXTRA:.*]], metadata !DIExpression(DW_OP_LLVM_fragment, 0, 128)),
-// CHECK: call void @llvm.dbg.declare(metadata ptr %slice.dbg.spill1, metadata ![[SLICE_EXTRA]], metadata !DIExpression(DW_OP_LLVM_fragment, 128, 32)),
+// CHECK: dbg{{.}}declare({{(metadata )?}}ptr %s.dbg.spill, {{(metadata )?}}![[S_EXTRA:.*]], {{(metadata )?}}!DIExpression()
+// CHECK: dbg{{.}}declare({{(metadata )?}}ptr %slice.dbg.spill, {{(metadata )?}}![[SLICE_EXTRA:.*]], {{(metadata )?}}!DIExpression(DW_OP_LLVM_fragment, 0, 128)
+// CHECK: dbg{{.}}declare({{(metadata )?}}ptr %slice.dbg.spill1, {{(metadata )?}}![[SLICE_EXTRA]], {{(metadata )?}}!DIExpression(DW_OP_LLVM_fragment, 128, 32)
     let slice = ExtraSlice { slice: s, extra: s.len() as u32 };
 }
 
@@ -36,9 +36,9 @@ pub fn zst(s: &[u8]) {
     // variable, so is not a fragment. In that case, the variable must have no fragment.
 
 // CHECK: void @zst(
-// CHECK-NOT: call void @llvm.dbg.declare(metadata ptr %slice.dbg.spill, metadata !{}, metadata !DIExpression(DW_OP_LLVM_fragment,
-// CHECK: call void @llvm.dbg.declare(metadata ptr %{{.*}}, metadata ![[SLICE_ZST:.*]], metadata !DIExpression()),
-// CHECK-NOT: call void @llvm.dbg.declare(metadata ptr %{{.*}}, metadata ![[SLICE_ZST]],
+// CHECK-NOT: dbg{{.}}declare({{(metadata )?}}ptr %slice.dbg.spill, {{(metadata )?}}!{}, {{(metadata )?}}!DIExpression(DW_OP_LLVM_fragment,
+// CHECK: dbg{{.}}declare({{(metadata )?}}ptr %{{.*}}, {{(metadata )?}}![[SLICE_ZST:.*]], {{(metadata )?}}!DIExpression()
+// CHECK-NOT: dbg{{.}}declare({{(metadata )?}}ptr %{{.*}}, {{(metadata )?}}![[SLICE_ZST]],
     let slice = ZstSlice { slice: s, extra: Zst };
 }
 
diff --git a/tests/coverage/branch/if-let.cov-map b/tests/coverage/branch/if-let.cov-map
index c12df8d9801..0c7d986933e 100644
--- a/tests/coverage/branch/if-let.cov-map
+++ b/tests/coverage/branch/if-let.cov-map
@@ -1,13 +1,16 @@
 Function name: if_let::if_let
-Raw bytes (38): 0x[01, 01, 02, 05, 09, 09, 02, 06, 01, 0c, 01, 01, 10, 02, 03, 11, 00, 12, 05, 00, 16, 00, 1b, 02, 00, 1c, 02, 06, 09, 02, 0c, 02, 06, 07, 03, 05, 01, 02]
+Raw bytes (45): 0x[01, 01, 02, 05, 09, 09, 02, 07, 01, 0c, 01, 01, 10, 20, 02, 09, 03, 0c, 00, 13, 02, 00, 11, 00, 12, 05, 00, 16, 00, 1b, 02, 00, 1c, 02, 06, 09, 02, 0c, 02, 06, 07, 03, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 2
 - expression 0 operands: lhs = Counter(1), rhs = Counter(2)
 - expression 1 operands: lhs = Counter(2), rhs = Expression(0, Sub)
-Number of file 0 mappings: 6
+Number of file 0 mappings: 7
 - Code(Counter(0)) at (prev + 12, 1) to (start + 1, 16)
-- Code(Expression(0, Sub)) at (prev + 3, 17) to (start + 0, 18)
+- Branch { true: Expression(0, Sub), false: Counter(2) } at (prev + 3, 12) to (start + 0, 19)
+    true  = (c1 - c2)
+    false = c2
+- Code(Expression(0, Sub)) at (prev + 0, 17) to (start + 0, 18)
     = (c1 - c2)
 - Code(Counter(1)) at (prev + 0, 22) to (start + 0, 27)
 - Code(Expression(0, Sub)) at (prev + 0, 28) to (start + 2, 6)
@@ -17,7 +20,7 @@ Number of file 0 mappings: 6
     = (c2 + (c1 - c2))
 
 Function name: if_let::if_let_chain
-Raw bytes (52): 0x[01, 01, 04, 01, 05, 05, 09, 0f, 0d, 05, 09, 08, 01, 17, 01, 00, 33, 02, 01, 11, 00, 12, 01, 00, 16, 00, 17, 0d, 01, 15, 00, 16, 02, 00, 1a, 00, 1b, 0d, 01, 05, 03, 06, 0f, 03, 0c, 02, 06, 0b, 03, 05, 01, 02]
+Raw bytes (66): 0x[01, 01, 04, 01, 05, 05, 09, 0f, 0d, 05, 09, 0a, 01, 17, 01, 00, 33, 20, 02, 05, 01, 0c, 00, 13, 02, 00, 11, 00, 12, 01, 00, 16, 00, 17, 20, 0d, 09, 01, 10, 00, 17, 0d, 00, 15, 00, 16, 02, 00, 1a, 00, 1b, 0d, 01, 05, 03, 06, 0f, 03, 0c, 02, 06, 0b, 03, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 4
@@ -25,12 +28,18 @@ Number of expressions: 4
 - expression 1 operands: lhs = Counter(1), rhs = Counter(2)
 - expression 2 operands: lhs = Expression(3, Add), rhs = Counter(3)
 - expression 3 operands: lhs = Counter(1), rhs = Counter(2)
-Number of file 0 mappings: 8
+Number of file 0 mappings: 10
 - Code(Counter(0)) at (prev + 23, 1) to (start + 0, 51)
-- Code(Expression(0, Sub)) at (prev + 1, 17) to (start + 0, 18)
+- Branch { true: Expression(0, Sub), false: Counter(1) } at (prev + 1, 12) to (start + 0, 19)
+    true  = (c0 - c1)
+    false = c1
+- Code(Expression(0, Sub)) at (prev + 0, 17) to (start + 0, 18)
     = (c0 - c1)
 - Code(Counter(0)) at (prev + 0, 22) to (start + 0, 23)
-- Code(Counter(3)) at (prev + 1, 21) to (start + 0, 22)
+- Branch { true: Counter(3), false: Counter(2) } at (prev + 1, 16) to (start + 0, 23)
+    true  = c3
+    false = c2
+- Code(Counter(3)) at (prev + 0, 21) to (start + 0, 22)
 - Code(Expression(0, Sub)) at (prev + 0, 26) to (start + 0, 27)
     = (c0 - c1)
 - Code(Counter(3)) at (prev + 1, 5) to (start + 3, 6)
diff --git a/tests/coverage/branch/if-let.coverage b/tests/coverage/branch/if-let.coverage
index f30c5d34eca..9a3f0113f75 100644
--- a/tests/coverage/branch/if-let.coverage
+++ b/tests/coverage/branch/if-let.coverage
@@ -14,6 +14,9 @@
    LL|       |
    LL|      3|    if let Some(x) = input {
                               ^2
+  ------------------
+  |  Branch (LL:12): [True: 2, False: 1]
+  ------------------
    LL|      2|        say(x);
    LL|      2|    } else {
    LL|      1|        say("none");
@@ -24,8 +27,14 @@
    LL|     15|fn if_let_chain(a: Option<&str>, b: Option<&str>) {
    LL|     15|    if let Some(x) = a
                               ^12
+  ------------------
+  |  Branch (LL:12): [True: 12, False: 3]
+  ------------------
    LL|     12|        && let Some(y) = b
                                   ^8
+  ------------------
+  |  Branch (LL:16): [True: 8, False: 4]
+  ------------------
    LL|      8|    {
    LL|      8|        say(x);
    LL|      8|        say(y);
diff --git a/tests/coverage/branch/let-else.cov-map b/tests/coverage/branch/let-else.cov-map
index ad987bd6bb1..c7f7adddbc2 100644
--- a/tests/coverage/branch/let-else.cov-map
+++ b/tests/coverage/branch/let-else.cov-map
@@ -1,13 +1,16 @@
 Function name: let_else::let_else
-Raw bytes (38): 0x[01, 01, 02, 05, 09, 09, 02, 06, 01, 0c, 01, 01, 10, 02, 03, 0e, 00, 0f, 05, 00, 13, 00, 18, 09, 01, 09, 01, 0f, 02, 04, 05, 00, 0b, 07, 01, 01, 00, 02]
+Raw bytes (45): 0x[01, 01, 02, 05, 09, 09, 02, 07, 01, 0c, 01, 01, 10, 20, 02, 09, 03, 09, 00, 10, 02, 00, 0e, 00, 0f, 05, 00, 13, 00, 18, 09, 01, 09, 01, 0f, 02, 04, 05, 00, 0b, 07, 01, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 2
 - expression 0 operands: lhs = Counter(1), rhs = Counter(2)
 - expression 1 operands: lhs = Counter(2), rhs = Expression(0, Sub)
-Number of file 0 mappings: 6
+Number of file 0 mappings: 7
 - Code(Counter(0)) at (prev + 12, 1) to (start + 1, 16)
-- Code(Expression(0, Sub)) at (prev + 3, 14) to (start + 0, 15)
+- Branch { true: Expression(0, Sub), false: Counter(2) } at (prev + 3, 9) to (start + 0, 16)
+    true  = (c1 - c2)
+    false = c2
+- Code(Expression(0, Sub)) at (prev + 0, 14) to (start + 0, 15)
     = (c1 - c2)
 - Code(Counter(1)) at (prev + 0, 19) to (start + 0, 24)
 - Code(Counter(2)) at (prev + 1, 9) to (start + 1, 15)
diff --git a/tests/coverage/branch/let-else.coverage b/tests/coverage/branch/let-else.coverage
index 83730e1dfba..22ad8f2b0e1 100644
--- a/tests/coverage/branch/let-else.coverage
+++ b/tests/coverage/branch/let-else.coverage
@@ -14,6 +14,9 @@
    LL|       |
    LL|      3|    let Some(x) = value else {
                            ^2
+  ------------------
+  |  Branch (LL:9): [True: 2, False: 1]
+  ------------------
    LL|      1|        say("none");
    LL|      1|        return;
    LL|       |    };
diff --git a/tests/crashes/120421.rs b/tests/crashes/120421.rs
deleted file mode 100644
index b6059f3ace4..00000000000
--- a/tests/crashes/120421.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-//@ known-bug: #120421
-//@ compile-flags: -Zlint-mir
-
-#![feature(never_patterns)]
-
-enum Void {}
-
-fn main() {
-    let res_void: Result<bool, Void> = Ok(true);
-
-    for (Ok(mut _x) | Err(!)) in [res_void] {}
-}
diff --git a/tests/crashes/122989.rs b/tests/crashes/122989.rs
deleted file mode 100644
index 70ad7d3b65c..00000000000
--- a/tests/crashes/122989.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-//@ known-bug: #122989
-trait Traitor<const N: N<2> = 1, const N: N<2> = N> {
-    fn N(&N) -> N<2> {
-        M
-    }
-}
-
-trait N<const N: Traitor<2> = 12> {}
diff --git a/tests/crashes/123911.rs b/tests/crashes/123911.rs
deleted file mode 100644
index 1a4d6a79512..00000000000
--- a/tests/crashes/123911.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-//@ known-bug: #123911
-
-macro_rules! m {
-    ($attr_path: path) => {
-        #[$attr_path]
-        fn f() {}
-    }
-}
-
-m!(inline<{
-    let a = CharCharFloat { a: 1 };
-    let b = rustrt::rust_dbg_abi_4(a);
-    println!("a: {}", b.a);
-}>);
-
-fn main() {}
diff --git a/tests/crashes/123912.rs b/tests/crashes/123912.rs
deleted file mode 100644
index 35216caabcd..00000000000
--- a/tests/crashes/123912.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-//@ known-bug: #123912
-
-macro_rules! m {
-    ($attr_path: path) => {
-        #[$attr_path]
-        fn f() {}
-    }
-}
-
-m!(inline<{
-    let a = CharCharFloat { a: 1 };
-    println!("a: {}", a);
-}>);
-
-fn main() {}
diff --git a/tests/crashes/124436.rs b/tests/crashes/124436.rs
new file mode 100644
index 00000000000..aed830e8f0e
--- /dev/null
+++ b/tests/crashes/124436.rs
@@ -0,0 +1,7 @@
+//@ known-bug: rust-lang/rust#124436
+//@ compile-flags: -Zdump-mir=all -Zpolymorphize=on
+
+pub trait TraitCat {}
+pub trait TraitDog {}
+
+pub fn gamma<T: TraitCat + TraitDog>(t: [TraitDog; 32]) {}
diff --git a/tests/crashes/124440.rs b/tests/crashes/124440.rs
new file mode 100644
index 00000000000..431c4e444f1
--- /dev/null
+++ b/tests/crashes/124440.rs
@@ -0,0 +1,23 @@
+//@ known-bug: rust-lang/rust#124440
+
+#![allow(warnings)]
+
+trait Foo {}
+
+impl<F> Foo for F where F: FnMut(&()) {}
+
+struct Bar<F> {
+    f: F,
+}
+
+impl<F> Foo for Bar<F> where F: Foo {}
+
+fn assert_foo<F>(_: F)
+where
+    Bar<F>: Foo,
+{
+}
+
+fn main() {
+    assert_foo(|_| ());
+}
diff --git a/tests/crashes/124464.rs b/tests/crashes/124464.rs
new file mode 100644
index 00000000000..471479f5cf1
--- /dev/null
+++ b/tests/crashes/124464.rs
@@ -0,0 +1,17 @@
+//@ known-bug: rust-lang/rust #124464
+enum TestOption<T> {
+    TestSome(T),
+    TestSome(T),
+}
+
+pub struct Request {
+    bar: TestOption<u64>,
+    bar: u8,
+}
+
+fn default_instance() -> &'static Request {
+    static instance: Request = Request { bar: 17 };
+    &instance
+}
+
+pub fn main() {}
diff --git a/tests/crashes/124490.rs b/tests/crashes/124490.rs
new file mode 100644
index 00000000000..9f605c32cf2
--- /dev/null
+++ b/tests/crashes/124490.rs
@@ -0,0 +1,16 @@
+//@ known-bug: rust-lang/rust#124490
+use io::{self as std};
+use std::collections::{self as io};
+
+mod a {
+    pub mod b {
+        pub mod c {}
+    }
+}
+
+use a::*;
+
+use b::c;
+use c as b;
+
+fn main() {}
diff --git a/tests/crashes/124552.rs b/tests/crashes/124552.rs
new file mode 100644
index 00000000000..5320ce27843
--- /dev/null
+++ b/tests/crashes/124552.rs
@@ -0,0 +1,12 @@
+//@ known-bug: rust-lang/rust#124552
+
+struct B;
+
+struct Foo {
+    b: u32,
+    b: B,
+}
+
+static BAR: Foo = Foo { b: B };
+
+fn main() {}
diff --git a/tests/crashes/124563.rs b/tests/crashes/124563.rs
new file mode 100644
index 00000000000..b082739af53
--- /dev/null
+++ b/tests/crashes/124563.rs
@@ -0,0 +1,46 @@
+//@ known-bug: rust-lang/rust#124563
+
+use std::marker::PhantomData;
+
+pub trait Trait {}
+
+pub trait Foo {
+    type Trait: Trait;
+    type Bar: Bar;
+    fn foo(&mut self);
+}
+
+pub struct FooImpl<'a, 'b, A: Trait>(PhantomData<&'a &'b A>);
+
+impl<'a, 'b, T> Foo for FooImpl<'a, 'b, T>
+where
+    T: Trait,
+{
+    type Trait = T;
+    type Bar = BarImpl<'a, 'b, T>;
+
+    fn foo(&mut self) {
+        self.enter_scope(|ctx| {
+            BarImpl(ctx);
+        });
+    }
+}
+
+impl<'a, 'b, T> FooImpl<'a, 'b, T>
+where
+    T: Trait,
+{
+    fn enter_scope(&mut self, _scope: impl FnOnce(&mut Self)) {}
+}
+pub trait Bar {
+    type Foo: Foo;
+}
+
+pub struct BarImpl<'a, 'b, T: Trait>(&'b mut FooImpl<'a, 'b, T>);
+
+impl<'a, 'b, T> Bar for BarImpl<'a, 'b, T>
+where
+    T: Trait,
+{
+    type Foo = FooImpl<'a, 'b, T>;
+}
diff --git a/tests/crashes/124583.rs b/tests/crashes/124583.rs
new file mode 100644
index 00000000000..ffd9d7521ad
--- /dev/null
+++ b/tests/crashes/124583.rs
@@ -0,0 +1,5 @@
+//@ known-bug: rust-lang/rust#124583
+
+fn main() {
+    let _ = -(-0.0f16);
+}
diff --git a/tests/crashes/124751.rs b/tests/crashes/124751.rs
new file mode 100644
index 00000000000..f15e39965d3
--- /dev/null
+++ b/tests/crashes/124751.rs
@@ -0,0 +1,8 @@
+//@ known-bug: rust-lang/rust#124751
+//@ compile-flags: -Zunstable-options --edition=2024
+
+#![feature(gen_blocks)]
+
+fn main() {
+    let _ = async gen || {};
+}
diff --git a/tests/debuginfo/borrowed-enum.rs b/tests/debuginfo/borrowed-enum.rs
index 39883ffd0b6..fc2ab62a21c 100644
--- a/tests/debuginfo/borrowed-enum.rs
+++ b/tests/debuginfo/borrowed-enum.rs
@@ -1,6 +1,6 @@
 // Require a gdb or lldb that can read DW_TAG_variant_part.
 //@ min-gdb-version: 8.2
-//@ needs-rust-lldb
+//@ min-lldb-version: 1800
 
 //@ compile-flags:-g
 
@@ -23,10 +23,13 @@
 // lldb-command:run
 
 // lldb-command:v *the_a_ref
+// lldbg-check:(borrowed_enum::ABC) *the_a_ref = { value = { x = 0 y = 8970181431921507452 } $discr$ = 0 }
 // lldbr-check:(borrowed_enum::ABC::TheA) *the_a_ref = TheA { TheA: 0, TheB: 8970181431921507452 }
 // lldb-command:v *the_b_ref
+// lldbg-check:(borrowed_enum::ABC) *the_b_ref = { value = { 0 = 0 1 = 286331153 2 = 286331153 } $discr$ = 1 }
 // lldbr-check:(borrowed_enum::ABC::TheB) *the_b_ref = { = 0 = 286331153 = 286331153 }
 // lldb-command:v *univariant_ref
+// lldbg-check:(borrowed_enum::Univariant) *univariant_ref = { value = { 0 = 4820353753753434 } }
 // lldbr-check:(borrowed_enum::Univariant) *univariant_ref = { TheOnlyCase = { = 4820353753753434 } }
 
 #![allow(unused_variables)]
diff --git a/tests/debuginfo/coroutine-objects.rs b/tests/debuginfo/coroutine-objects.rs
index e13f20455a8..746b7e40eda 100644
--- a/tests/debuginfo/coroutine-objects.rs
+++ b/tests/debuginfo/coroutine-objects.rs
@@ -1,8 +1,9 @@
 // Require a gdb that can read DW_TAG_variant_part.
 //@ min-gdb-version: 8.2
+//@ min-lldb-version: 1800
 
-// LLDB without native Rust support cannot read DW_TAG_variant_part,
-// so it prints nothing for coroutines. But those tests are kept to
+// LLDB (18.1+) now supports DW_TAG_variant_part, but there is some bug in either compiler or LLDB
+// with memory layout of discriminant for this particular enum
 // ensure that LLDB won't crash at least (like #57822).
 
 //@ compile-flags:-g
@@ -26,16 +27,7 @@
 
 // lldb-command:run
 // lldb-command:v b
-// lldbg-check:(coroutine_objects::main::{coroutine_env#0}) b =
-// lldb-command:continue
-// lldb-command:v b
-// lldbg-check:(coroutine_objects::main::{coroutine_env#0}) b =
-// lldb-command:continue
-// lldb-command:v b
-// lldbg-check:(coroutine_objects::main::{coroutine_env#0}) b =
-// lldb-command:continue
-// lldb-command:v b
-// lldbg-check:(coroutine_objects::main::{coroutine_env#0}) b =
+// lldb-check:(coroutine_objects::main::{coroutine_env#0}) b = { value = { _ref__a = 0x[...] } $discr$ = [...] }
 
 // === CDB TESTS ===================================================================================
 
diff --git a/tests/debuginfo/enum-thinlto.rs b/tests/debuginfo/enum-thinlto.rs
index f3f17758931..42a0d1e28f8 100644
--- a/tests/debuginfo/enum-thinlto.rs
+++ b/tests/debuginfo/enum-thinlto.rs
@@ -1,6 +1,6 @@
 // Require a gdb that can read DW_TAG_variant_part.
 //@ min-gdb-version: 8.2
-
+//@ min-lldb-version: 1800
 //@ compile-flags:-g -Z thinlto
 
 // === GDB TESTS ===================================================================================
@@ -15,7 +15,7 @@
 // lldb-command:run
 
 // lldb-command:v *abc
-// lldbg-check:(enum_thinlto::ABC) *abc =
+// lldbg-check:(enum_thinlto::ABC) *abc = { value = { x = 0 y = 8970181431921507452 } $discr$ = 0 }
 // lldbr-check:(enum_thinlto::ABC) *abc = (x = 0, y = 8970181431921507452)
 
 #![allow(unused_variables)]
diff --git a/tests/debuginfo/issue-57822.rs b/tests/debuginfo/issue-57822.rs
index 995779a6a9c..cadd9b542e9 100644
--- a/tests/debuginfo/issue-57822.rs
+++ b/tests/debuginfo/issue-57822.rs
@@ -3,7 +3,7 @@
 
 // Require a gdb that can read DW_TAG_variant_part.
 //@ min-gdb-version: 8.2
-
+//@ min-lldb-version: 1800
 //@ compile-flags:-g
 
 // === GDB TESTS ===================================================================================
@@ -24,7 +24,7 @@
 // lldbg-check:(issue_57822::main::{closure_env#1}) g = { f = { x = 1 } }
 
 // lldb-command:v b
-// lldbg-check:(issue_57822::main::{coroutine_env#3}) b =
+// lldbg-check:(issue_57822::main::{coroutine_env#3}) b = { value = { a = { value = { y = 2 } $discr$ = '\x02' } } $discr$ = '\x02' }
 
 #![feature(omit_gdb_pretty_printer_section, coroutines, coroutine_trait, stmt_expr_attributes)]
 #![omit_gdb_pretty_printer_section]
diff --git a/tests/debuginfo/msvc-pretty-enums.rs b/tests/debuginfo/msvc-pretty-enums.rs
index 0293ec0ec39..a6032cc8642 100644
--- a/tests/debuginfo/msvc-pretty-enums.rs
+++ b/tests/debuginfo/msvc-pretty-enums.rs
@@ -1,6 +1,80 @@
-//@ only-cdb
+//@ min-lldb-version: 1800
+//@ ignore-gdb
 //@ compile-flags:-g
-//
+
+// === LLDB TESTS ==================================================================================
+// lldb-command:run
+
+// lldb-command:v a
+// lldbg-check:(core::option::Option<msvc_pretty_enums::CStyleEnum>) a = { value = { 0 = Low } }
+
+// lldb-command:v b
+// lldbg-check:(core::option::Option<msvc_pretty_enums::CStyleEnum>) b = { value = $discr$ = '\x01' }
+
+// lldb-command:v c
+// lldbg-check:(msvc_pretty_enums::NicheLayoutEnum) c = { value = $discr$ = '\x11' }
+
+// lldb-command:v d
+// lldbg-check:(msvc_pretty_enums::NicheLayoutEnum) d = { value = { my_data = High } }
+
+// lldb-command:v e
+// lldbg-check:(msvc_pretty_enums::NicheLayoutEnum) e = { value = $discr$ = '\x13' }
+
+// lldb-command:v h
+// lldbg-check:(core::option::Option<u32>) h = { value = { 0 = 12 } $discr$ = 1 }
+
+// lldb-command:v i
+// lldbg-check:(core::option::Option<u32>) i = { value = $discr$ = 0 }
+
+// lldb-command:v j
+// lldbg-check:(msvc_pretty_enums::CStyleEnum) j = High
+
+// lldb-command:v k
+// lldbg-check:(core::option::Option<alloc::string::String>) k = { value = { 0 = "IAMA optional string!" { vec = size=21 { [0] = 'I' [1] = 'A' [2] = 'M' [3] = 'A' [4] = ' ' [5] = 'o' [6] = 'p' [7] = 't' [8] = 'i' [9] = 'o' [10] = 'n' [11] = 'a' [12] = 'l' [13] = ' ' [14] = 's' [15] = 't' [16] = 'r' [17] = 'i' [18] = 'n' [19] = 'g' [20] = '!' } } } }
+
+// lldb-command:v l
+// lldbg-check:(core::result::Result<u32, msvc_pretty_enums::Empty>) l = { value = { 0 = {} } }
+
+// lldb-command:v niche128_some
+// lldbg-check:(core::option::Option<core::num::nonzero::NonZero<i128>>) niche128_some = { value = $discr$ = 123456 }
+
+// lldb-command:v niche128_none
+// lldbg-check:(core::option::Option<core::num::nonzero::NonZero<i128>>) niche128_none = { value = $discr$ = 0 }
+
+// lldb-command:v wrapping_niche128_untagged
+// lldbg-check:(msvc_pretty_enums::Wrapping128Niche) wrapping_niche128_untagged = { value = { 0 = { 0 = 340282366920938463463374607431768211454 } } }
+
+// lldb-command:v wrapping_niche128_none1
+// lldbg-check:(msvc_pretty_enums::Wrapping128Niche) wrapping_niche128_none1 = { value = { 0 = { 0 = 2 } } }
+
+// lldb-command:v direct_tag_128_a
+// lldbg-check:(msvc_pretty_enums::DirectTag128) direct_tag_128_a = { value = { 0 = 42 } $discr$ = 0 }
+
+// lldb-command:v direct_tag_128_b
+// lldbg-check:(msvc_pretty_enums::DirectTag128) direct_tag_128_b = { value = { 0 = 137 } $discr$ = 1 }
+
+// &u32 is incorrectly formatted and LLDB thinks it's a char* so skipping niche_w_fields_1_some
+
+// lldb-command:v niche_w_fields_1_none
+// lldbg-check:(msvc_pretty_enums::NicheLayoutWithFields1) niche_w_fields_1_none = { value = { 0 = 99 } $discr$ = 1 }
+
+// lldb-command:v niche_w_fields_2_some
+// lldbg-check:(msvc_pretty_enums::NicheLayoutWithFields2) niche_w_fields_2_some = { value = { 0 = 800 { __0 = { 0 = 800 } } 1 = 900 } $discr$ = 0 }
+
+// lldb-command:v niche_w_fields_3_some
+// lldbg-check:(msvc_pretty_enums::NicheLayoutWithFields3) niche_w_fields_3_some = { value = { 0 = '\x89' 1 = true } }
+
+// lldb-command:v niche_w_fields_3_niche3
+// lldbg-check:(msvc_pretty_enums::NicheLayoutWithFields3) niche_w_fields_3_niche3 = { value = { 0 = '"' } $discr$ = '\x04' }
+
+// lldb-command:v arbitrary_discr1
+// lldbg-check:(msvc_pretty_enums::ArbitraryDiscr) arbitrary_discr1 = { value = { 0 = 1234 } $discr$ = 1000 }
+
+// lldb-command:v arbitrary_discr2
+// lldbg-check:(msvc_pretty_enums::ArbitraryDiscr) arbitrary_discr2 = { value = { 0 = 5678 } $discr$ = 5000000 }
+
+// === CDB TESTS ==================================================================================
+
 // cdb-command: g
 //
 // cdb-command: dx a
diff --git a/tests/debuginfo/struct-style-enum.rs b/tests/debuginfo/struct-style-enum.rs
index 517b76c1412..42368017cae 100644
--- a/tests/debuginfo/struct-style-enum.rs
+++ b/tests/debuginfo/struct-style-enum.rs
@@ -1,7 +1,6 @@
 // Require a gdb or lldb that can read DW_TAG_variant_part.
 //@ min-gdb-version: 8.2
-//@ needs-rust-lldb
-
+//@ min-lldb-version: 1800
 //@ compile-flags:-g
 
 // === GDB TESTS ===================================================================================
@@ -27,15 +26,19 @@
 // lldb-command:run
 
 // lldb-command:v case1
+// lldbg-check:(struct_style_enum::Regular) case1 = { value = { a = 0 b = 31868 c = 31868 d = 31868 e = 31868 } $discr$ = 0 }
 // lldbr-check:(struct_style_enum::Regular::Case1) case1 = { a = 0 b = 31868 c = 31868 d = 31868 e = 31868 }
 
 // lldb-command:v case2
+// lldbg-check:(struct_style_enum::Regular) case2 = { value = { a = 0 b = 286331153 c = 286331153 } $discr$ = 1 }
 // lldbr-check:(struct_style_enum::Regular::Case2) case2 = Case2 { Case1: 0, Case2: 286331153, Case3: 286331153 }
 
 // lldb-command:v case3
+// lldbg-check:(struct_style_enum::Regular) case3 = { value = { a = 0 b = 6438275382588823897 } $discr$ = 2 }
 // lldbr-check:(struct_style_enum::Regular::Case3) case3 = Case3 { Case1: 0, Case2: 6438275382588823897 }
 
 // lldb-command:v univariant
+// lldbg-check:(struct_style_enum::Univariant) univariant = { value = { a = -1 } }
 // lldbr-check:(struct_style_enum::Univariant) univariant = Univariant { TheOnlyCase: TheOnlyCase { a: -1 } }
 
 #![allow(unused_variables)]
diff --git a/tests/debuginfo/tuple-style-enum.rs b/tests/debuginfo/tuple-style-enum.rs
index 883aa658eb2..3de4ecb1284 100644
--- a/tests/debuginfo/tuple-style-enum.rs
+++ b/tests/debuginfo/tuple-style-enum.rs
@@ -1,6 +1,6 @@
 // Require a gdb or lldb that can read DW_TAG_variant_part.
 //@ min-gdb-version: 8.2
-//@ needs-rust-lldb
+//@ min-lldb-version: 1800
 
 //@ compile-flags:-g
 
@@ -27,15 +27,19 @@
 // lldb-command:run
 
 // lldb-command:v case1
+// lldbg-check:(tuple_style_enum::Regular) case1 = { value = { 0 = 0 1 = 31868 2 = 31868 3 = 31868 4 = 31868 } $discr$ = 0 }
 // lldbr-check:(tuple_style_enum::Regular::Case1) case1 = { = 0 = 31868 = 31868 = 31868 = 31868 }
 
 // lldb-command:v case2
+// lldbg-check:(tuple_style_enum::Regular) case2 = { value = { 0 = 0 1 = 286331153 2 = 286331153 } $discr$ = 1 }
 // lldbr-check:(tuple_style_enum::Regular::Case2) case2 = Case2 { Case1: 0, Case2: 286331153, Case3: 286331153 }
 
 // lldb-command:v case3
+// lldbg-check:(tuple_style_enum::Regular) case3 = { value = { 0 = 0 1 = 6438275382588823897 } $discr$ = 2 }
 // lldbr-check:(tuple_style_enum::Regular::Case3) case3 = Case3 { Case1: 0, Case2: 6438275382588823897 }
 
 // lldb-command:v univariant
+// lldbg-check:(tuple_style_enum::Univariant) univariant = { value = { 0 = -1 } }
 // lldbr-check:(tuple_style_enum::Univariant) univariant = { TheOnlyCase = { = -1 } }
 
 #![allow(unused_variables)]
diff --git a/tests/debuginfo/unique-enum.rs b/tests/debuginfo/unique-enum.rs
index b3879468e0a..514c7c50812 100644
--- a/tests/debuginfo/unique-enum.rs
+++ b/tests/debuginfo/unique-enum.rs
@@ -1,6 +1,6 @@
 // Require a gdb or lldb that can read DW_TAG_variant_part.
 //@ min-gdb-version: 8.2
-//@ needs-rust-lldb
+//@ min-lldb-version: 1800
 
 //@ compile-flags:-g
 
@@ -23,12 +23,15 @@
 // lldb-command:run
 
 // lldb-command:v *the_a
+// lldbg-check:(unique_enum::ABC) *the_a = { value = { x = 0 y = 8970181431921507452 } $discr$ = 0 }
 // lldbr-check:(unique_enum::ABC::TheA) *the_a = TheA { TheA: 0, TheB: 8970181431921507452 }
 
 // lldb-command:v *the_b
+// lldbg-check:(unique_enum::ABC) *the_b = { value = { 0 = 0 1 = 286331153 2 = 286331153 } $discr$ = 1 }
 // lldbr-check:(unique_enum::ABC::TheB) *the_b = { = 0 = 286331153 = 286331153 }
 
 // lldb-command:v *univariant
+// lldbg-check:(unique_enum::Univariant) *univariant = { value = { 0 = 123234 } }
 // lldbr-check:(unique_enum::Univariant) *univariant = { TheOnlyCase = { = 123234 } }
 
 #![allow(unused_variables)]
diff --git a/tests/mir-opt/building/match/never_patterns.opt1.SimplifyCfg-initial.after.mir b/tests/mir-opt/building/match/never_patterns.opt1.SimplifyCfg-initial.after.mir
new file mode 100644
index 00000000000..78356a90743
--- /dev/null
+++ b/tests/mir-opt/building/match/never_patterns.opt1.SimplifyCfg-initial.after.mir
@@ -0,0 +1,41 @@
+// MIR for `opt1` after SimplifyCfg-initial
+
+fn opt1(_1: &Result<u32, Void>) -> &u32 {
+    debug res => _1;
+    let mut _0: &u32;
+    let mut _2: isize;
+    let _3: &u32;
+    let mut _4: !;
+    let mut _5: ();
+    scope 1 {
+        debug x => _3;
+    }
+
+    bb0: {
+        PlaceMention(_1);
+        _2 = discriminant((*_1));
+        switchInt(move _2) -> [0: bb2, 1: bb3, otherwise: bb1];
+    }
+
+    bb1: {
+        FakeRead(ForMatchedPlace(None), _1);
+        unreachable;
+    }
+
+    bb2: {
+        falseEdge -> [real: bb4, imaginary: bb3];
+    }
+
+    bb3: {
+        FakeRead(ForMatchedPlace(None), (((*_1) as Err).0: Void));
+        unreachable;
+    }
+
+    bb4: {
+        StorageLive(_3);
+        _3 = &(((*_1) as Ok).0: u32);
+        _0 = &(*_3);
+        StorageDead(_3);
+        return;
+    }
+}
diff --git a/tests/mir-opt/building/match/never_patterns.opt2.SimplifyCfg-initial.after.mir b/tests/mir-opt/building/match/never_patterns.opt2.SimplifyCfg-initial.after.mir
new file mode 100644
index 00000000000..979fbb2860d
--- /dev/null
+++ b/tests/mir-opt/building/match/never_patterns.opt2.SimplifyCfg-initial.after.mir
@@ -0,0 +1,35 @@
+// MIR for `opt2` after SimplifyCfg-initial
+
+fn opt2(_1: &Result<u32, Void>) -> &u32 {
+    debug res => _1;
+    let mut _0: &u32;
+    let mut _2: isize;
+    let _3: &u32;
+    scope 1 {
+        debug x => _3;
+    }
+
+    bb0: {
+        PlaceMention(_1);
+        _2 = discriminant((*_1));
+        switchInt(move _2) -> [0: bb2, 1: bb3, otherwise: bb1];
+    }
+
+    bb1: {
+        FakeRead(ForMatchedPlace(None), _1);
+        unreachable;
+    }
+
+    bb2: {
+        StorageLive(_3);
+        _3 = &(((*_1) as Ok).0: u32);
+        _0 = &(*_3);
+        StorageDead(_3);
+        return;
+    }
+
+    bb3: {
+        FakeRead(ForMatchedPlace(None), (((*_1) as Err).0: Void));
+        unreachable;
+    }
+}
diff --git a/tests/mir-opt/building/match/never_patterns.opt3.SimplifyCfg-initial.after.mir b/tests/mir-opt/building/match/never_patterns.opt3.SimplifyCfg-initial.after.mir
new file mode 100644
index 00000000000..93ebe600b3f
--- /dev/null
+++ b/tests/mir-opt/building/match/never_patterns.opt3.SimplifyCfg-initial.after.mir
@@ -0,0 +1,35 @@
+// MIR for `opt3` after SimplifyCfg-initial
+
+fn opt3(_1: &Result<u32, Void>) -> &u32 {
+    debug res => _1;
+    let mut _0: &u32;
+    let mut _2: isize;
+    let _3: &u32;
+    scope 1 {
+        debug x => _3;
+    }
+
+    bb0: {
+        PlaceMention(_1);
+        _2 = discriminant((*_1));
+        switchInt(move _2) -> [0: bb3, 1: bb2, otherwise: bb1];
+    }
+
+    bb1: {
+        FakeRead(ForMatchedPlace(None), _1);
+        unreachable;
+    }
+
+    bb2: {
+        FakeRead(ForMatchedPlace(None), (((*_1) as Err).0: Void));
+        unreachable;
+    }
+
+    bb3: {
+        StorageLive(_3);
+        _3 = &(((*_1) as Ok).0: u32);
+        _0 = &(*_3);
+        StorageDead(_3);
+        return;
+    }
+}
diff --git a/tests/mir-opt/building/match/never_patterns.rs b/tests/mir-opt/building/match/never_patterns.rs
new file mode 100644
index 00000000000..8b52440da4c
--- /dev/null
+++ b/tests/mir-opt/building/match/never_patterns.rs
@@ -0,0 +1,44 @@
+#![feature(never_patterns)]
+#![allow(incomplete_features)]
+
+enum Void {}
+
+// EMIT_MIR never_patterns.opt1.SimplifyCfg-initial.after.mir
+fn opt1(res: &Result<u32, Void>) -> &u32 {
+    // CHECK-LABEL: fn opt1(
+    // CHECK: bb0: {
+    // CHECK-NOT: {{bb.*}}: {
+    // CHECK: return;
+    match res {
+        Ok(x) => x,
+        Err(!),
+    }
+}
+
+// EMIT_MIR never_patterns.opt2.SimplifyCfg-initial.after.mir
+fn opt2(res: &Result<u32, Void>) -> &u32 {
+    // CHECK-LABEL: fn opt2(
+    // CHECK: bb0: {
+    // CHECK-NOT: {{bb.*}}: {
+    // CHECK: return;
+    match res {
+        Ok(x) | Err(!) => x,
+    }
+}
+
+// EMIT_MIR never_patterns.opt3.SimplifyCfg-initial.after.mir
+fn opt3(res: &Result<u32, Void>) -> &u32 {
+    // CHECK-LABEL: fn opt3(
+    // CHECK: bb0: {
+    // CHECK-NOT: {{bb.*}}: {
+    // CHECK: return;
+    match res {
+        Err(!) | Ok(x) => x,
+    }
+}
+
+fn main() {
+    assert_eq!(opt1(&Ok(0)), &0);
+    assert_eq!(opt2(&Ok(0)), &0);
+    assert_eq!(opt3(&Ok(0)), &0);
+}
diff --git a/tests/mir-opt/building/match/sort_candidates.rs b/tests/mir-opt/building/match/sort_candidates.rs
index a2583ff8284..f207f0b3234 100644
--- a/tests/mir-opt/building/match/sort_candidates.rs
+++ b/tests/mir-opt/building/match/sort_candidates.rs
@@ -1,5 +1,4 @@
 // Check specific cases of sorting candidates in match lowering.
-#![feature(exclusive_range_pattern)]
 
 // EMIT_MIR sort_candidates.constant_eq.SimplifyCfg-initial.after.mir
 fn constant_eq(s: &str, b: bool) -> u32 {
diff --git a/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff
index 2a36ccaab11..df873600577 100644
--- a/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff
@@ -11,10 +11,28 @@
 +     scope 1 (inlined std::ptr::drop_in_place::<Vec<A>> - shim(Some(Vec<A>))) {
 +         let mut _6: &mut std::vec::Vec<A>;
 +         let mut _7: ();
++         scope 2 (inlined <Vec<A> as Drop>::drop) {
++             let mut _8: *mut [A];
++             let mut _9: *mut A;
++             let mut _10: usize;
++             scope 3 (inlined Vec::<A>::as_mut_ptr) {
++                 let mut _11: &alloc::raw_vec::RawVec<A>;
++                 scope 4 (inlined alloc::raw_vec::RawVec::<A>::ptr) {
++                     let mut _13: std::ptr::NonNull<A>;
++                     scope 5 (inlined Unique::<A>::as_ptr) {
++                         scope 6 (inlined NonNull::<A>::as_ptr) {
++                             let mut _12: *const A;
++                         }
++                     }
++                 }
++             }
++             scope 7 (inlined slice_from_raw_parts_mut::<A>) {
++             }
++         }
 +     }
-+     scope 2 (inlined std::ptr::drop_in_place::<Option<B>> - shim(Some(Option<B>))) {
-+         let mut _8: isize;
-+         let mut _9: isize;
++     scope 8 (inlined std::ptr::drop_in_place::<Option<B>> - shim(Some(Option<B>))) {
++         let mut _14: isize;
++         let mut _15: isize;
 +     }
   
       bb0: {
@@ -25,7 +43,24 @@
 +         StorageLive(_6);
 +         StorageLive(_7);
 +         _6 = &mut (*_4);
-+         _7 = <Vec<A> as Drop>::drop(move _6) -> [return: bb2, unwind unreachable];
++         StorageLive(_8);
++         StorageLive(_9);
++         StorageLive(_11);
++         _11 = &((*_6).0: alloc::raw_vec::RawVec<A>);
++         StorageLive(_13);
++         _13 = ((((*_6).0: alloc::raw_vec::RawVec<A>).0: std::ptr::Unique<A>).0: std::ptr::NonNull<A>);
++         StorageLive(_12);
++         _12 = (_13.0: *const A);
++         _9 = move _12 as *mut A (PtrToPtr);
++         StorageDead(_12);
++         StorageDead(_13);
++         StorageDead(_11);
++         StorageLive(_10);
++         _10 = ((*_6).1: usize);
++         _8 = *mut [A] from (_9, _10);
++         StorageDead(_10);
++         StorageDead(_9);
++         _7 = std::ptr::drop_in_place::<[A]>(move _8) -> [return: bb2, unwind unreachable];
       }
   
       bb1: {
@@ -36,19 +71,20 @@
           StorageLive(_5);
           _5 = _2;
 -         _0 = std::ptr::drop_in_place::<Option<B>>(move _5) -> [return: bb2, unwind unreachable];
-+         StorageLive(_8);
-+         StorageLive(_9);
-+         _8 = discriminant((*_5));
-+         switchInt(move _8) -> [0: bb3, otherwise: bb4];
++         StorageLive(_14);
++         StorageLive(_15);
++         _14 = discriminant((*_5));
++         switchInt(move _14) -> [0: bb3, otherwise: bb4];
       }
   
       bb2: {
++         StorageDead(_8);
 +         drop(((*_4).0: alloc::raw_vec::RawVec<A>)) -> [return: bb1, unwind unreachable];
 +     }
 + 
 +     bb3: {
-+         StorageDead(_9);
-+         StorageDead(_8);
++         StorageDead(_15);
++         StorageDead(_14);
           StorageDead(_5);
           return;
 +     }
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir
index ef3f4a21720..62fe1a86857 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir
@@ -4,20 +4,47 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range<usize>) ->
     debug slice => _1;
     debug index => _2;
     let mut _0: &mut [u32];
+    let mut _3: usize;
+    let mut _4: usize;
     scope 1 (inlined core::slice::<impl [u32]>::get_unchecked_mut::<std::ops::Range<usize>>) {
-        let mut _3: *mut [u32];
-        let mut _4: *mut [u32];
+        let mut _5: *mut [u32];
+        let mut _9: *mut [u32];
+        scope 2 (inlined <std::ops::Range<usize> as SliceIndex<[u32]>>::get_unchecked_mut) {
+            let _6: usize;
+            let mut _7: *mut u32;
+            let mut _8: *mut u32;
+            scope 3 {
+                scope 6 (inlined std::ptr::mut_ptr::<impl *mut [u32]>::as_mut_ptr) {
+                }
+                scope 7 (inlined std::ptr::mut_ptr::<impl *mut u32>::add) {
+                }
+                scope 8 (inlined slice_from_raw_parts_mut::<u32>) {
+                }
+            }
+            scope 4 (inlined std::ptr::mut_ptr::<impl *mut [u32]>::len) {
+                scope 5 (inlined std::ptr::metadata::<[u32]>) {
+                }
+            }
+        }
     }
 
     bb0: {
-        StorageLive(_3);
-        _3 = &raw mut (*_1);
-        _4 = <std::ops::Range<usize> as SliceIndex<[u32]>>::get_unchecked_mut(move _2, move _3) -> [return: bb1, unwind unreachable];
-    }
-
-    bb1: {
-        StorageDead(_3);
-        _0 = &mut (*_4);
+        _3 = move (_2.0: usize);
+        _4 = move (_2.1: usize);
+        StorageLive(_5);
+        _5 = &raw mut (*_1);
+        StorageLive(_6);
+        _6 = SubUnchecked(_4, _3);
+        StorageLive(_8);
+        StorageLive(_7);
+        _7 = _5 as *mut u32 (PtrToPtr);
+        _8 = Offset(_7, _3);
+        StorageDead(_7);
+        _9 = *mut [u32] from (_8, _6);
+        StorageDead(_8);
+        StorageDead(_6);
+        StorageDead(_5);
+        _0 = &mut (*_9);
         return;
     }
 }
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir
index 9e93a43ac72..62fe1a86857 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir
@@ -4,20 +4,47 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range<usize>) ->
     debug slice => _1;
     debug index => _2;
     let mut _0: &mut [u32];
+    let mut _3: usize;
+    let mut _4: usize;
     scope 1 (inlined core::slice::<impl [u32]>::get_unchecked_mut::<std::ops::Range<usize>>) {
-        let mut _3: *mut [u32];
-        let mut _4: *mut [u32];
+        let mut _5: *mut [u32];
+        let mut _9: *mut [u32];
+        scope 2 (inlined <std::ops::Range<usize> as SliceIndex<[u32]>>::get_unchecked_mut) {
+            let _6: usize;
+            let mut _7: *mut u32;
+            let mut _8: *mut u32;
+            scope 3 {
+                scope 6 (inlined std::ptr::mut_ptr::<impl *mut [u32]>::as_mut_ptr) {
+                }
+                scope 7 (inlined std::ptr::mut_ptr::<impl *mut u32>::add) {
+                }
+                scope 8 (inlined slice_from_raw_parts_mut::<u32>) {
+                }
+            }
+            scope 4 (inlined std::ptr::mut_ptr::<impl *mut [u32]>::len) {
+                scope 5 (inlined std::ptr::metadata::<[u32]>) {
+                }
+            }
+        }
     }
 
     bb0: {
-        StorageLive(_3);
-        _3 = &raw mut (*_1);
-        _4 = <std::ops::Range<usize> as SliceIndex<[u32]>>::get_unchecked_mut(move _2, move _3) -> [return: bb1, unwind continue];
-    }
-
-    bb1: {
-        StorageDead(_3);
-        _0 = &mut (*_4);
+        _3 = move (_2.0: usize);
+        _4 = move (_2.1: usize);
+        StorageLive(_5);
+        _5 = &raw mut (*_1);
+        StorageLive(_6);
+        _6 = SubUnchecked(_4, _3);
+        StorageLive(_8);
+        StorageLive(_7);
+        _7 = _5 as *mut u32 (PtrToPtr);
+        _8 = Offset(_7, _3);
+        StorageDead(_7);
+        _9 = *mut [u32] from (_8, _6);
+        StorageDead(_8);
+        StorageDead(_6);
+        StorageDead(_5);
+        _0 = &mut (*_9);
         return;
     }
 }
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-abort.mir
index 018ff6c357d..000432ccca7 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-abort.mir
@@ -17,11 +17,6 @@ fn slice_ptr_get_unchecked_range(_1: *const [u32], _2: std::ops::Range<usize>) -
                 scope 7 (inlined std::ptr::const_ptr::<impl *const u32>::add) {
                 }
                 scope 8 (inlined slice_from_raw_parts::<u32>) {
-                    let mut _8: *const ();
-                    scope 9 (inlined std::ptr::const_ptr::<impl *const u32>::cast::<()>) {
-                    }
-                    scope 10 (inlined std::ptr::from_raw_parts::<[u32]>) {
-                    }
                 }
             }
             scope 4 (inlined std::ptr::const_ptr::<impl *const [u32]>::len) {
@@ -41,10 +36,7 @@ fn slice_ptr_get_unchecked_range(_1: *const [u32], _2: std::ops::Range<usize>) -
         _6 = _1 as *const u32 (PtrToPtr);
         _7 = Offset(_6, _3);
         StorageDead(_6);
-        StorageLive(_8);
-        _8 = _7 as *const () (PtrToPtr);
-        _0 = *const [u32] from (_8, _5);
-        StorageDead(_8);
+        _0 = *const [u32] from (_7, _5);
         StorageDead(_7);
         StorageDead(_5);
         return;
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-unwind.mir
index 018ff6c357d..000432ccca7 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-unwind.mir
@@ -17,11 +17,6 @@ fn slice_ptr_get_unchecked_range(_1: *const [u32], _2: std::ops::Range<usize>) -
                 scope 7 (inlined std::ptr::const_ptr::<impl *const u32>::add) {
                 }
                 scope 8 (inlined slice_from_raw_parts::<u32>) {
-                    let mut _8: *const ();
-                    scope 9 (inlined std::ptr::const_ptr::<impl *const u32>::cast::<()>) {
-                    }
-                    scope 10 (inlined std::ptr::from_raw_parts::<[u32]>) {
-                    }
                 }
             }
             scope 4 (inlined std::ptr::const_ptr::<impl *const [u32]>::len) {
@@ -41,10 +36,7 @@ fn slice_ptr_get_unchecked_range(_1: *const [u32], _2: std::ops::Range<usize>) -
         _6 = _1 as *const u32 (PtrToPtr);
         _7 = Offset(_6, _3);
         StorageDead(_6);
-        StorageLive(_8);
-        _8 = _7 as *const () (PtrToPtr);
-        _0 = *const [u32] from (_8, _5);
-        StorageDead(_8);
+        _0 = *const [u32] from (_7, _5);
         StorageDead(_7);
         StorageDead(_5);
         return;
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 18728d543ad..eabecaed051 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
@@ -25,7 +25,7 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
         scope 6 (inlined std::slice::from_raw_parts::<'_, u8>) {
             debug data => _4;
             debug len => _5;
-            let _7: *const [u8];
+            let _6: *const [u8];
             scope 7 (inlined core::ub_checks::check_language_ub) {
                 scope 8 (inlined core::ub_checks::check_language_ub::runtime) {
                 }
@@ -37,14 +37,6 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
             scope 11 (inlined slice_from_raw_parts::<u8>) {
                 debug data => _4;
                 debug len => _5;
-                let mut _6: *const ();
-                scope 12 (inlined std::ptr::const_ptr::<impl *const u8>::cast::<()>) {
-                    debug self => _4;
-                }
-                scope 13 (inlined std::ptr::from_raw_parts::<[u8]>) {
-                    debug data_pointer => _6;
-                    debug metadata => _5;
-                }
             }
         }
     }
@@ -60,13 +52,10 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
         StorageDead(_2);
         StorageLive(_5);
         _5 = ((*_1).1: usize);
-        StorageLive(_6);
-        _6 = _4 as *const () (PtrToPtr);
-        _7 = *const [u8] from (_6, _5);
-        StorageDead(_6);
+        _6 = *const [u8] from (_4, _5);
         StorageDead(_5);
         StorageDead(_4);
-        _0 = &(*_7);
+        _0 = &(*_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 18728d543ad..eabecaed051 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
@@ -25,7 +25,7 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
         scope 6 (inlined std::slice::from_raw_parts::<'_, u8>) {
             debug data => _4;
             debug len => _5;
-            let _7: *const [u8];
+            let _6: *const [u8];
             scope 7 (inlined core::ub_checks::check_language_ub) {
                 scope 8 (inlined core::ub_checks::check_language_ub::runtime) {
                 }
@@ -37,14 +37,6 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
             scope 11 (inlined slice_from_raw_parts::<u8>) {
                 debug data => _4;
                 debug len => _5;
-                let mut _6: *const ();
-                scope 12 (inlined std::ptr::const_ptr::<impl *const u8>::cast::<()>) {
-                    debug self => _4;
-                }
-                scope 13 (inlined std::ptr::from_raw_parts::<[u8]>) {
-                    debug data_pointer => _6;
-                    debug metadata => _5;
-                }
             }
         }
     }
@@ -60,13 +52,10 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
         StorageDead(_2);
         StorageLive(_5);
         _5 = ((*_1).1: usize);
-        StorageLive(_6);
-        _6 = _4 as *const () (PtrToPtr);
-        _7 = *const [u8] from (_6, _5);
-        StorageDead(_6);
+        _6 = *const [u8] from (_4, _5);
         StorageDead(_5);
         StorageDead(_4);
-        _0 = &(*_7);
+        _0 = &(*_6);
         return;
     }
 }
diff --git a/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs b/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs
index 4b7ce4e57d5..1bdb6347571 100644
--- a/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs
+++ b/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs
@@ -13,7 +13,8 @@ fn main() {
     let mut stable_path = PathBuf::from(env!("TMPDIR"));
     stable_path.push("libstable.rmeta");
 
-    let output = rustc().input("main.rs").emit("metadata").extern_("stable", &stable_path).output();
+    let output =
+        rustc().input("main.rs").emit("metadata").extern_("stable", &stable_path).command_output();
 
     let stderr = String::from_utf8_lossy(&output.stderr);
     let version = include_str!(concat!(env!("S"), "/src/version"));
diff --git a/tests/run-make/alloc-no-oom-handling/Makefile b/tests/run-make/alloc-no-oom-handling/Makefile
index 87f74c69c79..7c3ae90b58d 100644
--- a/tests/run-make/alloc-no-oom-handling/Makefile
+++ b/tests/run-make/alloc-no-oom-handling/Makefile
@@ -1,3 +1,6 @@
+# This test checks that alloc can still compile correctly when the unstable no_global_oom_handling feature is turned on.
+# See https://github.com/rust-lang/rust/pull/84266
+
 include ../tools.mk
 
 all:
diff --git a/tests/run-make/alloc-no-rc/Makefile b/tests/run-make/alloc-no-rc/Makefile
index 9824b17e6c2..fcfe1603b6c 100644
--- a/tests/run-make/alloc-no-rc/Makefile
+++ b/tests/run-make/alloc-no-rc/Makefile
@@ -1,3 +1,6 @@
+# This test checks that alloc can still compile correctly when the unstable no_rc feature is turned on.
+# See https://github.com/rust-lang/rust/pull/89891
+
 include ../tools.mk
 
 all:
diff --git a/tests/run-make/alloc-no-sync/Makefile b/tests/run-make/alloc-no-sync/Makefile
index 04ec4c7d8bc..997dbcf6603 100644
--- a/tests/run-make/alloc-no-sync/Makefile
+++ b/tests/run-make/alloc-no-sync/Makefile
@@ -1,3 +1,6 @@
+# This test checks that alloc can still compile correctly when the unstable no_sync feature is turned on.
+# See https://github.com/rust-lang/rust/pull/89891
+
 include ../tools.mk
 
 all:
diff --git a/tests/run-make/allocator-shim-circular-deps/Makefile b/tests/run-make/allocator-shim-circular-deps/Makefile
index 4624b846803..f667e2e2ec2 100644
--- a/tests/run-make/allocator-shim-circular-deps/Makefile
+++ b/tests/run-make/allocator-shim-circular-deps/Makefile
@@ -1,3 +1,8 @@
+# This test is designed to intentionally introduce a circular dependency scenario to check that a specific compiler bug doesn't make a resurgence.
+# The bug in question arose when at least one crate required a global allocator, and that crate was placed after the one defining it in the linker order. 
+# The generated symbols.o should not result in any linker errors.
+# See https://github.com/rust-lang/rust/issues/112715
+
 # ignore-cross-compile
 include ../tools.mk
 
diff --git a/tests/run-make/archive-duplicate-names/Makefile b/tests/run-make/archive-duplicate-names/Makefile
index 5433a42d252..207eee39299 100644
--- a/tests/run-make/archive-duplicate-names/Makefile
+++ b/tests/run-make/archive-duplicate-names/Makefile
@@ -1,3 +1,7 @@
+# When two object archives with the same filename are present, an iterator is supposed to inspect each object, recognize the duplication and extract each one to a different directory.
+# This test checks that this duplicate handling behaviour has not been broken.
+# See https://github.com/rust-lang/rust/pull/24439
+
 # ignore-cross-compile
 include ../tools.mk
 
diff --git a/tests/run-make/bare-outfile/Makefile b/tests/run-make/bare-outfile/Makefile
index 23b619ea0ba..ad6fe4bd167 100644
--- a/tests/run-make/bare-outfile/Makefile
+++ b/tests/run-make/bare-outfile/Makefile
@@ -1,3 +1,5 @@
+# This test checks that manually setting the output file as a bare file with no file extension still results in successful compilation.
+
 # ignore-cross-compile
 include ../tools.mk
 
diff --git a/tests/run-make/c-dynamic-dylib/Makefile b/tests/run-make/c-dynamic-dylib/Makefile
index b5bfbc76539..0d409640486 100644
--- a/tests/run-make/c-dynamic-dylib/Makefile
+++ b/tests/run-make/c-dynamic-dylib/Makefile
@@ -1,3 +1,6 @@
+# This test checks that dynamic Rust linking with C does not encounter any errors, with dynamic dependencies given preference over static.
+# See https://github.com/rust-lang/rust/issues/10434
+
 # ignore-cross-compile
 include ../tools.mk
 
diff --git a/tests/run-make/c-dynamic-rlib/Makefile b/tests/run-make/c-dynamic-rlib/Makefile
index 0475bd8acae..a64e89cc0dc 100644
--- a/tests/run-make/c-dynamic-rlib/Makefile
+++ b/tests/run-make/c-dynamic-rlib/Makefile
@@ -1,3 +1,6 @@
+# This test checks that dynamic Rust linking with C does not encounter any errors, with static dependencies given preference over dynamic. (This is the default behaviour.)
+# See https://github.com/rust-lang/rust/issues/10434
+
 # ignore-cross-compile
 include ../tools.mk
 
diff --git a/tests/run-make/c-link-to-rust-dylib/Makefile b/tests/run-make/c-link-to-rust-dylib/Makefile
index 2763cb6ed1d..201f717ece4 100644
--- a/tests/run-make/c-link-to-rust-dylib/Makefile
+++ b/tests/run-make/c-link-to-rust-dylib/Makefile
@@ -1,3 +1,6 @@
+# This test checks that C linking with Rust does not encounter any errors, with dynamic libraries.
+# See https://github.com/rust-lang/rust/issues/10434
+
 # ignore-cross-compile
 include ../tools.mk
 
diff --git a/tests/run-make/c-link-to-rust-staticlib/Makefile b/tests/run-make/c-link-to-rust-staticlib/Makefile
index e14775f5c18..d36cc421c46 100644
--- a/tests/run-make/c-link-to-rust-staticlib/Makefile
+++ b/tests/run-make/c-link-to-rust-staticlib/Makefile
@@ -1,3 +1,6 @@
+# This test checks that C linking with Rust does not encounter any errors, with static libraries.
+# See https://github.com/rust-lang/rust/issues/10434
+
 # ignore-cross-compile
 include ../tools.mk
 
diff --git a/tests/run-make/c-static-dylib/Makefile b/tests/run-make/c-static-dylib/Makefile
index 4e23edb6c57..05da1743c83 100644
--- a/tests/run-make/c-static-dylib/Makefile
+++ b/tests/run-make/c-static-dylib/Makefile
@@ -1,3 +1,6 @@
+# This test checks that static Rust linking with C does not encounter any errors, with dynamic dependencies given preference over static.
+# See https://github.com/rust-lang/rust/issues/10434
+
 # ignore-cross-compile
 include ../tools.mk
 
diff --git a/tests/run-make/c-static-rlib/Makefile b/tests/run-make/c-static-rlib/Makefile
index 4e351127cb6..298e432cdb8 100644
--- a/tests/run-make/c-static-rlib/Makefile
+++ b/tests/run-make/c-static-rlib/Makefile
@@ -1,3 +1,6 @@
+# This test checks that static Rust linking with C does not encounter any errors, with static dependencies given preference over dynamic. (This is the default behaviour.)
+# See https://github.com/rust-lang/rust/issues/10434
+
 # ignore-cross-compile
 include ../tools.mk
 
diff --git a/tests/run-make/c-unwind-abi-catch-lib-panic/Makefile b/tests/run-make/c-unwind-abi-catch-lib-panic/Makefile
index b8e0e9483cd..2bb8d42495d 100644
--- a/tests/run-make/c-unwind-abi-catch-lib-panic/Makefile
+++ b/tests/run-make/c-unwind-abi-catch-lib-panic/Makefile
@@ -1,3 +1,6 @@
+# Exercise unwinding a panic. This catches a panic across an FFI boundary and downcasts it into an integer. The Rust code that panics is in a separate crate.
+# See https://github.com/rust-lang/rust/commit/baf227ea0c1e07fc54395a51e4b3881d701180cb
+
 # ignore-cross-compile
 # needs-unwind
 include ../tools.mk
diff --git a/tests/run-make/c-unwind-abi-catch-panic/Makefile b/tests/run-make/c-unwind-abi-catch-panic/Makefile
index 1760ddb3061..0a38d838e32 100644
--- a/tests/run-make/c-unwind-abi-catch-panic/Makefile
+++ b/tests/run-make/c-unwind-abi-catch-panic/Makefile
@@ -1,3 +1,6 @@
+# Exercise unwinding a panic. This catches a panic across an FFI boundary and downcasts it into an integer. The Rust code that panics is in the same directory.
+# See https://github.com/rust-lang/rust/commit/baf227ea0c1e07fc54395a51e4b3881d701180cb
+
 # ignore-cross-compile
 # needs-unwind
 include ../tools.mk
diff --git a/tests/run-make/cat-and-grep-sanity-check/Makefile b/tests/run-make/cat-and-grep-sanity-check/Makefile
index 82351e22009..8ee69c0a0de 100644
--- a/tests/run-make/cat-and-grep-sanity-check/Makefile
+++ b/tests/run-make/cat-and-grep-sanity-check/Makefile
@@ -1,3 +1,7 @@
+# grep in run-make tests was partially replaced with a custom script, CGREP. This tests that CGREP does its job correctly.
+# See https://github.com/rust-lang/rust/commit/ab788a2ee175c7560f0ca58bbc183ecfd57d2f7a
+# FIXME(Oneirical): Note that this test will likely become useless after the port to rmake.rs tests (see https://github.com/rust-lang/rust/issues/121876)
+
 include ../tools.mk
 
 all:
diff --git a/tests/run-make/cdylib-dylib-linkage/Makefile b/tests/run-make/cdylib-dylib-linkage/Makefile
index 51fbfef2d85..db8393d3c05 100644
--- a/tests/run-make/cdylib-dylib-linkage/Makefile
+++ b/tests/run-make/cdylib-dylib-linkage/Makefile
@@ -1,3 +1,6 @@
+# This test checks that cdylibs can link against dylibs as dependencies, after this restriction was disabled.
+# See https://github.com/rust-lang/rust/commit/72aaa3a414d17aa0c4f19feafa5bab5f84b60e63
+
 # ignore-cross-compile
 include ../tools.mk
 
diff --git a/tests/run-make/cdylib-fewer-symbols/Makefile b/tests/run-make/cdylib-fewer-symbols/Makefile
index 4e08f979c36..d587cece5be 100644
--- a/tests/run-make/cdylib-fewer-symbols/Makefile
+++ b/tests/run-make/cdylib-fewer-symbols/Makefile
@@ -1,6 +1,8 @@
 # ignore-cross-compile
+
 # Test that allocator-related symbols don't show up as exported from a cdylib as
 # they're internal to Rust and not part of the public ABI.
+# See https://github.com/rust-lang/rust/commit/fbf98697021173a30b84d9145df0966a23a2f9d2
 
 include ../tools.mk
 
diff --git a/tests/run-make/cdylib/Makefile b/tests/run-make/cdylib/Makefile
index 3c8b5269554..2c6414c3255 100644
--- a/tests/run-make/cdylib/Makefile
+++ b/tests/run-make/cdylib/Makefile
@@ -1,3 +1,6 @@
+# When the cdylib crate type was added as a variation of dylib, it needed a test to check its function.
+# See https://github.com/rust-lang/rust/pull/33553
+
 # ignore-cross-compile
 include ../tools.mk
 
diff --git a/tests/run-make/codegen-options-parsing/Makefile b/tests/run-make/codegen-options-parsing/Makefile
index 56bb900b7d8..beaf233502b 100644
--- a/tests/run-make/codegen-options-parsing/Makefile
+++ b/tests/run-make/codegen-options-parsing/Makefile
@@ -1,3 +1,5 @@
+# This test intentionally feeds invalid inputs to codegen and checks if the error message outputs contain specific helpful indications.
+
 # ignore-cross-compile
 include ../tools.mk
 
diff --git a/tests/run-make/comment-section/Makefile b/tests/run-make/comment-section/Makefile
index 9f810063cc8..d0b98176ffe 100644
--- a/tests/run-make/comment-section/Makefile
+++ b/tests/run-make/comment-section/Makefile
@@ -1,3 +1,6 @@
+# Both GCC and Clang write by default a `.comment` section with compiler information. Rustc received a similar .comment section, so this tests checks that this section properly appears.
+# See https://github.com/rust-lang/rust/commit/74b8d324eb77a8f337b35dc68ac91b0c2c06debc
+
 include ../tools.mk
 
 # only-linux
diff --git a/tests/run-make/compile-stdin/Makefile b/tests/run-make/compile-stdin/Makefile
index 2a495281c24..b3d7cc777a0 100644
--- a/tests/run-make/compile-stdin/Makefile
+++ b/tests/run-make/compile-stdin/Makefile
@@ -1,3 +1,6 @@
+# When provided standard input piped directly into rustc, this test checks that the compilation completes successfully and that the output can be executed.
+# See https://github.com/rust-lang/rust/pull/28805
+
 # ignore-cross-compile
 include ../tools.mk
 
diff --git a/tests/run-make/compiler-lookup-paths-2/Makefile b/tests/run-make/compiler-lookup-paths-2/Makefile
index d4ff7d8daab..ecc0577384a 100644
--- a/tests/run-make/compiler-lookup-paths-2/Makefile
+++ b/tests/run-make/compiler-lookup-paths-2/Makefile
@@ -1,3 +1,6 @@
+# This test checks that extern crate declarations in Cargo without a corresponding declaration in the manifest of a dependency are NOT allowed.
+# See https://github.com/rust-lang/rust/pull/21113
+
 include ../tools.mk
 
 all:
diff --git a/tests/run-make/compiler-lookup-paths/Makefile b/tests/run-make/compiler-lookup-paths/Makefile
index 310d6772c34..fc0cbde4c35 100644
--- a/tests/run-make/compiler-lookup-paths/Makefile
+++ b/tests/run-make/compiler-lookup-paths/Makefile
@@ -1,3 +1,6 @@
+# rustc supports different types of lookup paths, such as dependency, native or crate. This test checks that these lookup paths are functional and result in functional compilation.
+# See https://github.com/rust-lang/rust/pull/19941
+
 include ../tools.mk
 
 # ignore-wasm32 (need a C compiler)
diff --git a/tests/run-make/doctests-runtool/Makefile b/tests/run-make/doctests-runtool/Makefile
deleted file mode 100644
index 7d5df1e307f..00000000000
--- a/tests/run-make/doctests-runtool/Makefile
+++ /dev/null
@@ -1,20 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-# Tests behavior of rustdoc --runtool
-
-MY_SRC_DIR := ${CURDIR}
-
-all: with_test_run_directory
-
-# Behavior with --runtool with relative paths and --test-run-directory.
-with_test_run_directory:
-	mkdir -p $(TMPDIR)/rundir
-	mkdir -p $(TMPDIR)/runtool
-	$(RUSTC) --crate-type rlib t.rs
-	$(RUSTC) runtool.rs -o $(TMPDIR)/runtool/runtool
-	( cd $(TMPDIR); \
-		$(RUSTDOC) -Zunstable-options --test --test-run-directory rundir \
-			--runtool runtool/runtool --extern t=libt.rlib $(MY_SRC_DIR)/t.rs \
-	)
-	rm -rf $(TMPDIR)/rundir $(TMPDIR)/runtool
diff --git a/tests/run-make/doctests-runtool/rmake.rs b/tests/run-make/doctests-runtool/rmake.rs
new file mode 100644
index 00000000000..6f89bf23b47
--- /dev/null
+++ b/tests/run-make/doctests-runtool/rmake.rs
@@ -0,0 +1,39 @@
+// Tests behavior of rustdoc `--runtool`.
+
+use run_make_support::{rustc, rustdoc, tmp_dir};
+use std::env::current_dir;
+use std::fs::{create_dir, remove_dir_all};
+use std::path::PathBuf;
+
+fn mkdir(name: &str) -> PathBuf {
+    let dir = tmp_dir().join(name);
+    create_dir(&dir).expect("failed to create doctests folder");
+    dir
+}
+
+// Behavior with --runtool with relative paths and --test-run-directory.
+fn main() {
+    let run_dir_name = "rundir";
+    let run_dir = mkdir(run_dir_name);
+    let run_tool = mkdir("runtool");
+    let run_tool_binary = run_tool.join("runtool");
+
+    rustc().input("t.rs").crate_type("rlib").run();
+    rustc().input("runtool.rs").output(&run_tool_binary).run();
+
+    rustdoc()
+        .input(current_dir().unwrap().join("t.rs"))
+        .arg("-Zunstable-options")
+        .arg("--test")
+        .arg("--test-run-directory")
+        .arg(run_dir_name)
+        .arg("--runtool")
+        .arg(&run_tool_binary)
+        .arg("--extern")
+        .arg("t=libt.rlib")
+        .current_dir(tmp_dir())
+        .run();
+
+    remove_dir_all(run_dir);
+    remove_dir_all(run_tool);
+}
diff --git a/tests/run-make/exit-code/rmake.rs b/tests/run-make/exit-code/rmake.rs
index b1143153d0a..76d7777581b 100644
--- a/tests/run-make/exit-code/rmake.rs
+++ b/tests/run-make/exit-code/rmake.rs
@@ -15,7 +15,7 @@ fn main() {
         .arg("compile-error.rs")
         .run_fail_assert_exit_code(101);
 
-    rustdoc().arg("success.rs").arg("-o").arg(tmp_dir().join("exit-code")).run();
+    rustdoc().arg("success.rs").output(tmp_dir().join("exit-code")).run();
 
     rustdoc().arg("--invalid-arg-foo").run_fail_assert_exit_code(1);
 
diff --git a/tests/run-make/libtest-padding/Makefile b/tests/run-make/libtest-padding/Makefile
index 42bc1192925..c8e2fc01f67 100644
--- a/tests/run-make/libtest-padding/Makefile
+++ b/tests/run-make/libtest-padding/Makefile
@@ -2,7 +2,7 @@
 # needs-unwind because #[bench] and -Cpanic=abort requires -Zpanic-abort-tests
 include ../tools.mk
 
-NORMALIZE=sed 's%[0-9,]\{1,\} ns/iter (+/- [0-9,]\{1,\})%?? ns/iter (+/- ??)%' | sed 's%finished in [0-9\.]\{1,\}%finished in ??%'
+NORMALIZE=sed 's%[0-9,\.]\{1,\} ns/iter (+/- [0-9,\.]\{1,\})%?? ns/iter (+/- ??)%' | sed 's%finished in [0-9\.]\{1,\}%finished in ??%'
 
 all:
 	$(RUSTC) --test tests.rs
diff --git a/tests/run-make/repr128-dwarf/rmake.rs b/tests/run-make/repr128-dwarf/rmake.rs
index d734b2add79..fd5dd810444 100644
--- a/tests/run-make/repr128-dwarf/rmake.rs
+++ b/tests/run-make/repr128-dwarf/rmake.rs
@@ -10,7 +10,7 @@ use std::rc::Rc;
 
 fn main() {
     let output = tmp_dir().join("repr128");
-    rustc().input("main.rs").arg("-o").arg(&output).arg("-Cdebuginfo=2").run();
+    rustc().input("main.rs").output(&output).arg("-Cdebuginfo=2").run();
     // Mach-O uses packed debug info
     let dsym_location = output
         .with_extension("dSYM")
diff --git a/tests/run-make/rustdoc-determinism/rmake.rs b/tests/run-make/rustdoc-determinism/rmake.rs
index 38ae75199fd..09097d4507d 100644
--- a/tests/run-make/rustdoc-determinism/rmake.rs
+++ b/tests/run-make/rustdoc-determinism/rmake.rs
@@ -1,18 +1,19 @@
-use run_make_support::{diff, rustc, rustdoc, tmp_dir};
+// Assert that the search index is generated deterministically, regardless of the
+// order that crates are documented in.
+
+use run_make_support::{diff, rustdoc, tmp_dir};
 
-/// Assert that the search index is generated deterministically, regardless of the
-/// order that crates are documented in.
 fn main() {
-    let dir_first = tmp_dir().join("first");
-    rustdoc().out_dir(&dir_first).input("foo.rs").run();
-    rustdoc().out_dir(&dir_first).input("bar.rs").run();
+    let foo_first = tmp_dir().join("foo_first");
+    rustdoc().input("foo.rs").output(&foo_first).run();
+    rustdoc().input("bar.rs").output(&foo_first).run();
 
-    let dir_second = tmp_dir().join("second");
-    rustdoc().out_dir(&dir_second).input("bar.rs").run();
-    rustdoc().out_dir(&dir_second).input("foo.rs").run();
+    let bar_first = tmp_dir().join("bar_first");
+    rustdoc().input("bar.rs").output(&bar_first).run();
+    rustdoc().input("foo.rs").output(&bar_first).run();
 
     diff()
-        .expected_file(dir_first.join("search-index.js"))
-        .actual_file(dir_second.join("search-index.js"))
+        .expected_file(foo_first.join("search-index.js"))
+        .actual_file(bar_first.join("search-index.js"))
         .run();
 }
diff --git a/tests/run-make/rustdoc-error-lines/Makefile b/tests/run-make/rustdoc-error-lines/Makefile
deleted file mode 100644
index 2dc30f56b83..00000000000
--- a/tests/run-make/rustdoc-error-lines/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-include ../tools.mk
-
-# Test that hir-tree output doesn't crash and includes
-# the string constant we would expect to see.
-
-all:
-	$(RUSTDOC) --test input.rs > $(TMPDIR)/output || true
-	$(CGREP) 'input.rs - foo (line 5)' < $(TMPDIR)/output
-	$(CGREP) 'input.rs:7:15' < $(TMPDIR)/output
-	$(CGREP) 'input.rs - bar (line 15)' < $(TMPDIR)/output
-	$(CGREP) 'input.rs:17:15' < $(TMPDIR)/output
-	$(CGREP) 'input.rs - bar (line 24)' < $(TMPDIR)/output
-	$(CGREP) 'input.rs:26:15' < $(TMPDIR)/output
diff --git a/tests/run-make/rustdoc-error-lines/rmake.rs b/tests/run-make/rustdoc-error-lines/rmake.rs
new file mode 100644
index 00000000000..31536c78dd4
--- /dev/null
+++ b/tests/run-make/rustdoc-error-lines/rmake.rs
@@ -0,0 +1,22 @@
+// Assert that the search index is generated deterministically, regardless of the
+// order that crates are documented in.
+
+use run_make_support::rustdoc;
+
+fn main() {
+    let output =
+        String::from_utf8(rustdoc().input("input.rs").arg("--test").command_output().stdout)
+            .unwrap();
+
+    let should_contain = &[
+        "input.rs - foo (line 5)",
+        "input.rs:7:15",
+        "input.rs - bar (line 15)",
+        "input.rs:17:15",
+        "input.rs - bar (line 24)",
+        "input.rs:26:15",
+    ];
+    for text in should_contain {
+        assert!(output.contains(text), "output doesn't contains {:?}", text);
+    }
+}
diff --git a/tests/run-make/rustdoc-map-file/Makefile b/tests/run-make/rustdoc-map-file/Makefile
deleted file mode 100644
index 5cbf7747af6..00000000000
--- a/tests/run-make/rustdoc-map-file/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-include ../tools.mk
-
-all:
-	$(RUSTDOC) -Z unstable-options --generate-redirect-map foo.rs -o "$(TMPDIR)/out"
-	"$(PYTHON)" validate_json.py "$(TMPDIR)/out"
diff --git a/tests/run-make/rustdoc-map-file/rmake.rs b/tests/run-make/rustdoc-map-file/rmake.rs
new file mode 100644
index 00000000000..aaa7fea0b6b
--- /dev/null
+++ b/tests/run-make/rustdoc-map-file/rmake.rs
@@ -0,0 +1,15 @@
+use run_make_support::{rustdoc, tmp_dir};
+use std::process::Command;
+
+fn main() {
+    let out_dir = tmp_dir().join("out");
+    rustdoc()
+        .input("foo.rs")
+        .arg("-Zunstable-options")
+        .arg("--generate-redirect-map")
+        .output(&out_dir)
+        .run();
+    // FIXME (GuillaumeGomez): Port the python script to Rust as well.
+    let python = std::env::var("PYTHON").unwrap_or("python".into());
+    assert!(Command::new(python).arg("validate_json.py").arg(&out_dir).status().unwrap().success());
+}
diff --git a/tests/run-make/rustdoc-output-path/Makefile b/tests/run-make/rustdoc-output-path/Makefile
deleted file mode 100644
index 8f5cda9e56e..00000000000
--- a/tests/run-make/rustdoc-output-path/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-include ../tools.mk
-
-all:
-	$(RUSTDOC) -o "$(TMPDIR)/foo/bar/doc" foo.rs
diff --git a/tests/run-make/rustdoc-output-path/rmake.rs b/tests/run-make/rustdoc-output-path/rmake.rs
new file mode 100644
index 00000000000..74fb0a56ac6
--- /dev/null
+++ b/tests/run-make/rustdoc-output-path/rmake.rs
@@ -0,0 +1,9 @@
+// Checks that if the output folder doesn't exist, rustdoc will create it.
+
+use run_make_support::{rustdoc, tmp_dir};
+
+fn main() {
+    let out_dir = tmp_dir().join("foo/bar/doc");
+    rustdoc().input("foo.rs").output(&out_dir).run();
+    assert!(out_dir.exists());
+}
diff --git a/tests/rustdoc-gui/javascript-disabled.goml b/tests/rustdoc-gui/javascript-disabled.goml
index a7579ef7ec1..c6a7ad94b3f 100644
--- a/tests/rustdoc-gui/javascript-disabled.goml
+++ b/tests/rustdoc-gui/javascript-disabled.goml
@@ -4,7 +4,7 @@ javascript: false
 
 go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
 show-text: true
-assert-css: (".sub", {"display": "none"})
+assert-false: ".sub"
 
 // Even though JS is disabled, we should still have themes applied. Links are never black-colored
 // if styles are applied so we check that they are not.
diff --git a/tests/rustdoc-gui/settings-button.goml b/tests/rustdoc-gui/settings-button.goml
new file mode 100644
index 00000000000..c38a537e047
--- /dev/null
+++ b/tests/rustdoc-gui/settings-button.goml
@@ -0,0 +1,31 @@
+// This test ensures that the icon of the settings button looks as expected on
+// all themes.
+include: "utils.goml"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
+show-text: true
+
+define-function: (
+    "check-image",
+    [theme, filter],
+    block {
+        call-function: ("switch-theme", {"theme": |theme|})
+        assert-css: ("#settings-menu > a::before", {
+            "filter": |filter|,
+            "width": "22px",
+            "height": "22px",
+        })
+    }
+)
+
+call-function: ("check-image", {
+    "theme": "ayu",
+    "filter": "invert(1)",
+})
+call-function: ("check-image", {
+    "theme": "dark",
+    "filter": "none",
+})
+call-function: ("check-image", {
+    "theme": "light",
+    "filter": "none",
+})
diff --git a/tests/rustdoc-gui/settings.goml b/tests/rustdoc-gui/settings.goml
index 0011e44ca59..3f4f2946bf5 100644
--- a/tests/rustdoc-gui/settings.goml
+++ b/tests/rustdoc-gui/settings.goml
@@ -1,6 +1,5 @@
 // This test ensures that the settings menu display is working as expected and that
 // the settings page is also rendered as expected.
-include: "utils.goml"
 go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 show-text: true // needed when we check for colors below.
 // First, we check that the settings page doesn't exist.
diff --git a/tests/rustdoc-gui/sidebar-source-code-display.goml b/tests/rustdoc-gui/sidebar-source-code-display.goml
index 3bfbe820b8d..7ce3be8a5b3 100644
--- a/tests/rustdoc-gui/sidebar-source-code-display.goml
+++ b/tests/rustdoc-gui/sidebar-source-code-display.goml
@@ -4,7 +4,7 @@ javascript: false
 go-to: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
 // Since the javascript is disabled, there shouldn't be a toggle.
 wait-for-css: (".sidebar", {"display": "none"})
-assert-css: ("#sidebar-button", {"display": "none"})
+assert-false: "#sidebar-button"
 
 // Let's retry with javascript enabled.
 javascript: true
diff --git a/tests/rustdoc-gui/src/theme_css/custom-theme.css b/tests/rustdoc-gui/src/theme_css/custom-theme.css
index b7f89d4cf15..a56c31ab9d2 100644
--- a/tests/rustdoc-gui/src/theme_css/custom-theme.css
+++ b/tests/rustdoc-gui/src/theme_css/custom-theme.css
@@ -49,6 +49,7 @@
 	--search-tab-button-not-selected-background: #e6e6e6;
 	--search-tab-button-selected-border-top-color: #0089ff;
 	--search-tab-button-selected-background: #fff;
+	--settings-menu-filter: none;
 	--stab-background-color: #fff5d6;
 	--stab-code-color: #000;
 	--code-highlight-kw-color: #8959a8;
diff --git a/tests/rustdoc-js-std/parser-reference.js b/tests/rustdoc-js-std/parser-reference.js
new file mode 100644
index 00000000000..6b1250146be
--- /dev/null
+++ b/tests/rustdoc-js-std/parser-reference.js
@@ -0,0 +1,527 @@
+const PARSED = [
+    {
+        query: '&[',
+        elems: [],
+        foundElems: 0,
+        original: '&[',
+        returned: [],
+        userQuery: '&[',
+        error: 'Unclosed `[`',
+    },
+    {
+        query: '[&',
+        elems: [],
+        foundElems: 0,
+        original: '[&',
+        returned: [],
+        userQuery: '[&',
+        error: 'Unclosed `[`',
+    },
+    {
+        query: '&&&D, []',
+        elems: [
+            {
+                name: "reference",
+                fullPath: ["reference"],
+                pathWithoutLast: [],
+                pathLast: "reference",
+                generics: [
+                    {
+                        name: "reference",
+                        fullPath: ["reference"],
+                        pathWithoutLast: [],
+                        pathLast: "reference",
+                        generics: [
+                            {
+                                name: "reference",
+                                fullPath: ["reference"],
+                                pathWithoutLast: [],
+                                pathLast: "reference",
+                                generics: [
+                                    {
+                                        name: "d",
+                                        fullPath: ["d"],
+                                        pathWithoutLast: [],
+                                        pathLast: "d",
+                                        generics: [],
+                                        typeFilter: -1,
+                                    },
+                                ],
+                                typeFilter: 1,
+                            },
+                        ],
+                        typeFilter: 1,
+                    },
+                ],
+                typeFilter: 1,
+            },
+            {
+                name: "[]",
+                fullPath: ["[]"],
+                pathWithoutLast: [],
+                pathLast: "[]",
+                generics: [],
+                typeFilter: 1,
+            },
+        ],
+        foundElems: 2,
+        original: '&&&D, []',
+        returned: [],
+        userQuery: '&&&d, []',
+        error: null,
+    },
+    {
+        query: '&&&[D]',
+        elems: [
+            {
+                name: "reference",
+                fullPath: ["reference"],
+                pathWithoutLast: [],
+                pathLast: "reference",
+                generics: [
+                    {
+                        name: "reference",
+                        fullPath: ["reference"],
+                        pathWithoutLast: [],
+                        pathLast: "reference",
+                        generics: [
+                            {
+                                name: "reference",
+                                fullPath: ["reference"],
+                                pathWithoutLast: [],
+                                pathLast: "reference",
+                                generics: [
+                                    {
+                                        name: "[]",
+                                        fullPath: ["[]"],
+                                        pathWithoutLast: [],
+                                        pathLast: "[]",
+                                        generics: [
+                                            {
+                                                name: "d",
+                                                fullPath: ["d"],
+                                                pathWithoutLast: [],
+                                                pathLast: "d",
+                                                generics: [],
+                                                typeFilter: -1,
+                                            },
+                                        ],
+                                        typeFilter: 1,
+                                    },
+                                ],
+                                typeFilter: 1,
+                            },
+                        ],
+                        typeFilter: 1,
+                    },
+                ],
+                typeFilter: 1,
+            },
+        ],
+        foundElems: 1,
+        original: '&&&[D]',
+        returned: [],
+        userQuery: '&&&[d]',
+        error: null,
+    },
+    {
+        query: '&',
+        elems: [
+            {
+                name: "reference",
+                fullPath: ["reference"],
+                pathWithoutLast: [],
+                pathLast: "reference",
+                generics: [],
+                typeFilter: 1,
+            },
+        ],
+        foundElems: 1,
+        original: '&',
+        returned: [],
+        userQuery: '&',
+        error: null,
+    },
+    {
+        query: '&mut',
+        elems: [
+            {
+                name: "reference",
+                fullPath: ["reference"],
+                pathWithoutLast: [],
+                pathLast: "reference",
+                generics: [
+                    {
+                        name: "mut",
+                        fullPath: ["mut"],
+                        pathWithoutLast: [],
+                        pathLast: "mut",
+                        generics: [],
+                        typeFilter: 0,
+                    },
+                ],
+                typeFilter: 1,
+            },
+        ],
+        foundElems: 1,
+        original: '&mut',
+        returned: [],
+        userQuery: '&mut',
+        error: null,
+    },
+    {
+        query: '&,u8',
+        elems: [
+            {
+                name: "reference",
+                fullPath: ["reference"],
+                pathWithoutLast: [],
+                pathLast: "reference",
+                generics: [],
+                typeFilter: 1,
+            },
+            {
+                name: "u8",
+                fullPath: ["u8"],
+                pathWithoutLast: [],
+                pathLast: "u8",
+                generics: [],
+                typeFilter: -1,
+            },
+        ],
+        foundElems: 2,
+        original: "&,u8",
+        returned: [],
+        userQuery: "&,u8",
+        error: null,
+    },
+    {
+        query: '&mut,u8',
+        elems: [
+            {
+                name: "reference",
+                fullPath: ["reference"],
+                pathWithoutLast: [],
+                pathLast: "reference",
+                generics: [
+                    {
+                        name: "mut",
+                        fullPath: ["mut"],
+                        pathWithoutLast: [],
+                        pathLast: "mut",
+                        generics: [],
+                        typeFilter: 0,
+                    },
+                ],
+                typeFilter: 1,
+            },
+            {
+                name: "u8",
+                fullPath: ["u8"],
+                pathWithoutLast: [],
+                pathLast: "u8",
+                generics: [],
+                typeFilter: -1,
+            },
+        ],
+        foundElems: 2,
+        original: "&mut,u8",
+        returned: [],
+        userQuery: "&mut,u8",
+        error: null,
+    },
+    {
+        query: '&u8',
+        elems: [
+            {
+                name: "reference",
+                fullPath: ["reference"],
+                pathWithoutLast: [],
+                pathLast: "reference",
+                generics: [
+                    {
+                        name: "u8",
+                        fullPath: ["u8"],
+                        pathWithoutLast: [],
+                        pathLast: "u8",
+                        generics: [],
+                        typeFilter: -1,
+                    },
+                ],
+                typeFilter: 1,
+            },
+        ],
+        foundElems: 1,
+        original: "&u8",
+        returned: [],
+        userQuery: "&u8",
+        error: null,
+    },
+    {
+        query: '&u8<u8>',
+        elems: [
+            {
+                name: "reference",
+                fullPath: ["reference"],
+                pathWithoutLast: [],
+                pathLast: "reference",
+                generics: [
+                    {
+                        name: "u8",
+                        fullPath: ["u8"],
+                        pathWithoutLast: [],
+                        pathLast: "u8",
+                        generics: [
+                            {
+                                name: "u8",
+                                fullPath: ["u8"],
+                                pathWithoutLast: [],
+                                pathLast: "u8",
+                                generics: [],
+                                typeFilter: -1,
+                            },
+                        ],
+                        typeFilter: -1,
+                    },
+                ],
+                typeFilter: 1,
+            },
+        ],
+        foundElems: 1,
+        original: "&u8<u8>",
+        returned: [],
+        userQuery: "&u8<u8>",
+        error: null,
+    },
+    {
+        query: 'u8<&u8>',
+        elems: [
+            {
+                name: "u8",
+                fullPath: ["u8"],
+                pathWithoutLast: [],
+                pathLast: "u8",
+                generics: [
+                    {
+                        name: "reference",
+                        fullPath: ["reference"],
+                        pathWithoutLast: [],
+                        pathLast: "reference",
+                        generics: [
+                            {
+                                name: "u8",
+                                fullPath: ["u8"],
+                                pathWithoutLast: [],
+                                pathLast: "u8",
+                                generics: [],
+                                typeFilter: -1,
+                            },
+                        ],
+                        typeFilter: 1,
+                    },
+                ],
+                typeFilter: -1,
+            },
+        ],
+        foundElems: 1,
+        original: "u8<&u8>",
+        returned: [],
+        userQuery: "u8<&u8>",
+        error: null,
+    },
+    {
+        query: 'u8<&u8, u8>',
+        elems: [
+            {
+                name: "u8",
+                fullPath: ["u8"],
+                pathWithoutLast: [],
+                pathLast: "u8",
+                generics: [
+                    {
+                        name: "reference",
+                        fullPath: ["reference"],
+                        pathWithoutLast: [],
+                        pathLast: "reference",
+                        generics: [
+                            {
+                                name: "u8",
+                                fullPath: ["u8"],
+                                pathWithoutLast: [],
+                                pathLast: "u8",
+                                generics: [],
+                                typeFilter: -1,
+                            },
+                        ],
+                        typeFilter: 1,
+                    },
+                    {
+                        name: "u8",
+                        fullPath: ["u8"],
+                        pathWithoutLast: [],
+                        pathLast: "u8",
+                        generics: [],
+                        typeFilter: -1,
+                    },
+                ],
+                typeFilter: -1,
+            },
+        ],
+        foundElems: 1,
+        original: "u8<&u8, u8>",
+        returned: [],
+        userQuery: "u8<&u8, u8>",
+        error: null,
+    },
+    {
+        query: 'u8<&u8>',
+        elems: [
+            {
+                name: "u8",
+                fullPath: ["u8"],
+                pathWithoutLast: [],
+                pathLast: "u8",
+                generics: [
+                    {
+                        name: "reference",
+                        fullPath: ["reference"],
+                        pathWithoutLast: [],
+                        pathLast: "reference",
+                        generics: [
+                            {
+                                name: "u8",
+                                fullPath: ["u8"],
+                                pathWithoutLast: [],
+                                pathLast: "u8",
+                                generics: [],
+                                typeFilter: -1,
+                            },
+                        ],
+                        typeFilter: 1,
+                    },
+                ],
+                typeFilter: -1,
+            },
+        ],
+        foundElems: 1,
+        original: "u8<&u8>",
+        returned: [],
+        userQuery: "u8<&u8>",
+        error: null,
+    },
+    {
+        query: 'u8<&mut u8, u8>',
+        elems: [
+            {
+                name: "u8",
+                fullPath: ["u8"],
+                pathWithoutLast: [],
+                pathLast: "u8",
+                generics: [
+                    {
+                        name: "reference",
+                        fullPath: ["reference"],
+                        pathWithoutLast: [],
+                        pathLast: "reference",
+                        generics: [
+                            {
+                                name: "mut",
+                                fullPath: ["mut"],
+                                pathWithoutLast: [],
+                                pathLast: "mut",
+                                generics: [],
+                                typeFilter: 0,
+                            },
+                            {
+                                name: "u8",
+                                fullPath: ["u8"],
+                                pathWithoutLast: [],
+                                pathLast: "u8",
+                                generics: [],
+                                typeFilter: -1,
+                            },
+                        ],
+                        typeFilter: 1,
+                    },
+                    {
+                        name: "u8",
+                        fullPath: ["u8"],
+                        pathWithoutLast: [],
+                        pathLast: "u8",
+                        generics: [],
+                        typeFilter: -1,
+                    },
+                ],
+                typeFilter: -1,
+            },
+        ],
+        foundElems: 1,
+        original: "u8<&mut u8, u8>",
+        returned: [],
+        userQuery: "u8<&mut u8, u8>",
+        error: null,
+    },
+    {
+        query: 'primitive:&u8',
+        elems: [
+            {
+                name: "reference",
+                fullPath: ["reference"],
+                pathWithoutLast: [],
+                pathLast: "reference",
+                generics: [
+                    {
+                        name: "u8",
+                        fullPath: ["u8"],
+                        pathWithoutLast: [],
+                        pathLast: "u8",
+                        generics: [],
+                        typeFilter: -1,
+                    },
+                ],
+                typeFilter: 1,
+            },
+        ],
+        foundElems: 1,
+        original: "primitive:&u8",
+        returned: [],
+        userQuery: "primitive:&u8",
+        error: null,
+    },
+    {
+        query: 'macro:&u8',
+        elems: [],
+        foundElems: 0,
+        original: "macro:&u8",
+        returned: [],
+        userQuery: "macro:&u8",
+        error: "Invalid search type: primitive `&` and `macro` both specified",
+    },
+    {
+        query: '&macro:u8',
+        elems: [
+            {
+                name: "reference",
+                fullPath: ["reference"],
+                pathWithoutLast: [],
+                pathLast: "reference",
+                generics: [
+                    {
+                        name: "u8",
+                        fullPath: ["u8"],
+                        pathWithoutLast: [],
+                        pathLast: "u8",
+                        generics: [],
+                        typeFilter: 16,
+                    },
+                ],
+                typeFilter: 1,
+            },
+        ],
+        foundElems: 1,
+        original: "&macro:u8",
+        returned: [],
+        userQuery: "&macro:u8",
+        error: null,
+    },
+];
diff --git a/tests/rustdoc-js/reference.js b/tests/rustdoc-js/reference.js
new file mode 100644
index 00000000000..b4a1fb15d36
--- /dev/null
+++ b/tests/rustdoc-js/reference.js
@@ -0,0 +1,236 @@
+// exact-check
+
+const EXPECTED = [
+    // pinkie with explicit names
+    {
+        'query': 'usize, usize -> ()',
+        'others': [
+            { 'path': 'reference', 'name': 'pinky' },
+        ],
+    },
+    {
+        'query': 'reference<usize>, usize -> ()',
+        'others': [
+            { 'path': 'reference', 'name': 'pinky' },
+        ],
+    },
+    {
+        'query': 'reference<usize>, reference<usize> -> ()',
+        'others': [],
+    },
+    {
+        'query': 'reference<mut, usize>, usize -> ()',
+        'others': [],
+    },
+    // thumb with explicit names
+    {
+        'query': 'thumb, thumb -> ()',
+        'others': [
+            { 'path': 'reference::Thumb', 'name': 'up' },
+        ],
+    },
+    {
+        'query': 'reference<thumb>, thumb -> ()',
+        'others': [
+            { 'path': 'reference::Thumb', 'name': 'up' },
+        ],
+    },
+    {
+        'query': 'reference<thumb>, reference<thumb> -> ()',
+        'others': [],
+    },
+    {
+        'query': 'reference<mut, thumb>, thumb -> ()',
+        'others': [],
+    },
+    // index with explicit names
+    {
+        'query': 'index, index -> ()',
+        'others': [
+            { 'path': 'reference::Index', 'name': 'point' },
+        ],
+    },
+    {
+        'query': 'reference<index>, index -> ()',
+        'others': [
+            { 'path': 'reference::Index', 'name': 'point' },
+        ],
+    },
+    {
+        'query': 'reference<index>, reference<index> -> ()',
+        'others': [],
+    },
+    {
+        'query': 'reference<mut, index>, index -> ()',
+        'others': [],
+    },
+    // ring with explicit names
+    {
+        'query': 'ring, ring -> ()',
+        'others': [
+            { 'path': 'reference::Ring', 'name': 'wear' },
+        ],
+    },
+    {
+        'query': 'reference<ring>, ring -> ()',
+        'others': [
+            { 'path': 'reference::Ring', 'name': 'wear' },
+        ],
+    },
+    {
+        'query': 'reference<ring>, reference<ring> -> ()',
+        'others': [
+            { 'path': 'reference::Ring', 'name': 'wear' },
+        ],
+    },
+    {
+        'query': 'reference<mut, ring>, reference<ring> -> ()',
+        'others': [
+            { 'path': 'reference::Ring', 'name': 'wear' },
+        ],
+    },
+    {
+        'query': 'reference<mut, ring>, reference<mut, ring> -> ()',
+        'others': [],
+    },
+    // middle with explicit names
+    {
+        'query': 'middle, middle -> ()',
+        'others': [
+            { 'path': 'reference', 'name': 'show' },
+        ],
+    },
+    {
+        'query': 'reference<middle>, reference<middle> -> ()',
+        'others': [
+            { 'path': 'reference', 'name': 'show' },
+        ],
+    },
+    {
+        'query': 'reference<mut, middle>, reference<mut, middle> -> ()',
+        'others': [
+            { 'path': 'reference', 'name': 'show' },
+        ],
+    },
+    {
+        'query': 'reference<reference<mut, middle>>, reference<mut, reference<middle>> -> ()',
+        'others': [
+            { 'path': 'reference', 'name': 'show' },
+        ],
+    },
+    {
+        'query': 'reference<mut, reference<middle>>, reference<reference<mut, middle>> -> ()',
+        'others': [
+            { 'path': 'reference', 'name': 'show' },
+        ],
+    },
+    {
+        'query': 'reference<reference<mut, middle>>, reference<reference<mut, middle>> -> ()',
+        'others': [],
+    },
+    {
+        'query': 'reference<mut, reference<middle>>, reference<mut, reference<middle>> -> ()',
+        'others': [],
+    },
+    // pinkie with shorthand
+    {
+        'query': '&usize, usize -> ()',
+        'others': [
+            { 'path': 'reference', 'name': 'pinky' },
+        ],
+    },
+    {
+        'query': '&usize, &usize -> ()',
+        'others': [],
+    },
+    {
+        'query': '&mut usize, usize -> ()',
+        'others': [],
+    },
+    // thumb with shorthand
+    {
+        'query': '&thumb, thumb -> ()',
+        'others': [
+            { 'path': 'reference::Thumb', 'name': 'up' },
+        ],
+    },
+    {
+        'query': '&thumb, &thumb -> ()',
+        'others': [],
+    },
+    {
+        'query': '&mut thumb, thumb -> ()',
+        'others': [],
+    },
+    // index with explicit names
+    {
+        'query': '&index, index -> ()',
+        'others': [
+            { 'path': 'reference::Index', 'name': 'point' },
+        ],
+    },
+    {
+        'query': '&index, &index -> ()',
+        'others': [],
+    },
+    {
+        'query': '&mut index, index -> ()',
+        'others': [],
+    },
+    // ring with shorthand
+    {
+        'query': '&ring, ring -> ()',
+        'others': [
+            { 'path': 'reference::Ring', 'name': 'wear' },
+        ],
+    },
+    {
+        'query': '&ring, ring -> ()',
+        'others': [
+            { 'path': 'reference::Ring', 'name': 'wear' },
+        ],
+    },
+    {
+        'query': '&mut ring, &ring -> ()',
+        'others': [
+            { 'path': 'reference::Ring', 'name': 'wear' },
+        ],
+    },
+    {
+        'query': '&mut ring, &mut ring -> ()',
+        'others': [],
+    },
+    // middle with shorthand
+    {
+        'query': '&middle, &middle -> ()',
+        'others': [
+            { 'path': 'reference', 'name': 'show' },
+        ],
+    },
+    {
+        'query': '&mut middle, &mut middle -> ()',
+        'others': [
+            { 'path': 'reference', 'name': 'show' },
+        ],
+    },
+    {
+        'query': '&&mut middle, &mut &middle -> ()',
+        'others': [
+            { 'path': 'reference', 'name': 'show' },
+        ],
+    },
+    {
+        'query': '&mut &middle, &&mut middle -> ()',
+        'others': [
+            { 'path': 'reference', 'name': 'show' },
+        ],
+    },
+    {
+        'query': '&&mut middle, &&mut middle -> ()',
+        'others': [],
+    },
+    {
+        'query': '&mut &middle, &mut &middle -> ()',
+        'others': [],
+    },
+];
diff --git a/tests/rustdoc-js/reference.rs b/tests/rustdoc-js/reference.rs
new file mode 100644
index 00000000000..3a0a23c65d5
--- /dev/null
+++ b/tests/rustdoc-js/reference.rs
@@ -0,0 +1,32 @@
+#![feature(extern_types)]
+
+pub fn pinky(input: &usize, manage: usize) {
+    unimplemented!()
+}
+
+pub struct Thumb;
+
+impl Thumb {
+    pub fn up(&self, finger: Thumb) { unimplemented!() }
+}
+
+pub enum Index {}
+
+impl Index {
+    pub fn point(self, data: &Index) { unimplemented!() }
+}
+
+pub union Ring {
+    magic: u32,
+    marriage: f32,
+}
+
+impl Ring {
+    pub fn wear(&mut self, extra: &Ring) { unimplemented!() }
+}
+
+extern "C" {
+    pub type Middle;
+}
+
+pub fn show(left: &&mut Middle, right: &mut &Middle) { unimplemented!() }
diff --git a/tests/rustdoc/inline_cross/issue-76736-2.rs b/tests/rustdoc/inline_cross/issue-76736-2.rs
index 83529dd1887..d4e6a697fc8 100644
--- a/tests/rustdoc/inline_cross/issue-76736-2.rs
+++ b/tests/rustdoc/inline_cross/issue-76736-2.rs
@@ -1,6 +1,8 @@
 //@ aux-build:issue-76736-1.rs
 //@ aux-build:issue-76736-2.rs
 
+// https://github.com/rust-lang/rust/issues/124635
+
 #![crate_name = "foo"]
 #![feature(rustc_private)]
 
@@ -8,9 +10,9 @@ extern crate issue_76736_1;
 extern crate issue_76736_2;
 
 // @has foo/struct.Foo.html
-// @has - '//*[@class="impl"]//h3[@class="code-header"]' 'MaybeResult'
+// @!has - '//*[@class="impl"]//h3[@class="code-header"]' 'MaybeResult'
 pub struct Foo;
 
 // @has foo/struct.Bar.html
-// @has - '//*[@class="impl"]//h3[@class="code-header"]' 'MaybeResult'
+// @!has - '//*[@class="impl"]//h3[@class="code-header"]' 'MaybeResult'
 pub use issue_76736_2::Bar;
diff --git a/tests/rustdoc/inline_cross/issue-76736-4.rs b/tests/rustdoc/inline_cross/issue-76736-4.rs
new file mode 100644
index 00000000000..297657ef9de
--- /dev/null
+++ b/tests/rustdoc/inline_cross/issue-76736-4.rs
@@ -0,0 +1,19 @@
+//@ aux-build:issue-76736-1.rs
+//@ aux-build:issue-76736-2.rs
+
+// https://github.com/rust-lang/rust/issues/124635
+
+#![crate_name = "foo"]
+#![feature(rustc_private, staged_api)]
+#![unstable(feature = "rustc_private", issue = "none")]
+
+extern crate issue_76736_1;
+extern crate issue_76736_2;
+
+// @has foo/struct.Foo.html
+// @has - '//*[@class="impl"]//h3[@class="code-header"]' 'MaybeResult'
+pub struct Foo;
+
+// @has foo/struct.Bar.html
+// @has - '//*[@class="impl"]//h3[@class="code-header"]' 'MaybeResult'
+pub use issue_76736_2::Bar;
diff --git a/tests/ui-fulldeps/pprust-expr-roundtrip.rs b/tests/ui-fulldeps/pprust-expr-roundtrip.rs
index 475a69f4ad0..2b1fec94387 100644
--- a/tests/ui-fulldeps/pprust-expr-roundtrip.rs
+++ b/tests/ui-fulldeps/pprust-expr-roundtrip.rs
@@ -180,7 +180,10 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
             18 => {
                 let pat =
                     P(Pat { id: DUMMY_NODE_ID, kind: PatKind::Wild, span: DUMMY_SP, tokens: None });
-                iter_exprs(depth - 1, &mut |e| g(ExprKind::Let(pat.clone(), e, DUMMY_SP, None)))
+                iter_exprs(
+                    depth - 1,
+                    &mut |e| g(ExprKind::Let(pat.clone(), e, DUMMY_SP, Recovered::No))
+                )
             }
             _ => panic!("bad counter value in iter_exprs"),
         }
diff --git a/tests/ui-fulldeps/stable-mir/check_abi.rs b/tests/ui-fulldeps/stable-mir/check_abi.rs
index 74801e007c4..359dd4146ba 100644
--- a/tests/ui-fulldeps/stable-mir/check_abi.rs
+++ b/tests/ui-fulldeps/stable-mir/check_abi.rs
@@ -99,7 +99,7 @@ fn check_result(abi: &ArgAbi) {
     assert_matches!(layout.variants, VariantsShape::Multiple { .. })
 }
 
-/// Check the niche information about: `NonZeroU8`
+/// Checks the niche information about `NonZero<u8>`.
 fn check_niche(abi: &ArgAbi) {
     assert!(abi.ty.kind().is_struct());
     assert_matches!(abi.mode, PassMode::Direct { .. });
@@ -150,12 +150,12 @@ fn generate_input(path: &str) -> std::io::Result<()> {
         #![feature(c_variadic)]
         #![allow(unused_variables)]
 
-        use std::num::NonZeroU8;
+        use std::num::NonZero;
 
         pub fn fn_abi(
             ignore: [u8; 0],
             primitive: char,
-            niche: NonZeroU8,
+            niche: NonZero<u8>,
         ) -> Result<usize, &'static str> {{
                 // We only care about the signature.
                 todo!()
diff --git a/tests/ui/abi/debug.stderr b/tests/ui/abi/debug.stderr
index 00fc7d1ece1..7365839da89 100644
--- a/tests/ui/abi/debug.stderr
+++ b/tests/ui/abi/debug.stderr
@@ -576,7 +576,9 @@ error: ABIs are not compatible
                            },
                            abi: Scalar(
                                Initialized {
-                                   value: F32,
+                                   value: Float(
+                                       F32,
+                                   ),
                                    valid_range: $FULL,
                                },
                            ),
diff --git a/tests/ui/associated-types/bound-lifetime-constrained.ok.stderr b/tests/ui/associated-types/bound-lifetime-constrained.ok.stderr
new file mode 100644
index 00000000000..9082044fe06
--- /dev/null
+++ b/tests/ui/associated-types/bound-lifetime-constrained.ok.stderr
@@ -0,0 +1,8 @@
+error: fatal error triggered by #[rustc_error]
+  --> $DIR/bound-lifetime-constrained.rs:48:1
+   |
+LL | fn main() { }
+   | ^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/associated-types/bound-lifetime-constrained.rs b/tests/ui/associated-types/bound-lifetime-constrained.rs
index 880d350bdf6..1dc3b2f5c2b 100644
--- a/tests/ui/associated-types/bound-lifetime-constrained.rs
+++ b/tests/ui/associated-types/bound-lifetime-constrained.rs
@@ -1,4 +1,4 @@
-//@ revisions: func object clause
+//@ revisions: func object clause ok
 
 #![allow(dead_code)]
 #![feature(rustc_attrs)]
diff --git a/tests/ui/async-await/async-block-control-flow-static-semantics.rs b/tests/ui/async-await/async-block-control-flow-static-semantics.rs
index 0ef7cb7574a..6e04c535cf1 100644
--- a/tests/ui/async-await/async-block-control-flow-static-semantics.rs
+++ b/tests/ui/async-await/async-block-control-flow-static-semantics.rs
@@ -29,14 +29,14 @@ async fn return_targets_async_block_not_async_fn() -> u8 {
 
 fn no_break_in_async_block() {
     async {
-        break 0u8; //~ ERROR `break` inside of an `async` block
+        break 0u8; //~ ERROR `break` inside `async` block
     };
 }
 
 fn no_break_in_async_block_even_with_outer_loop() {
     loop {
         async {
-            break 0u8; //~ ERROR `break` inside of an `async` block
+            break 0u8; //~ ERROR `break` inside `async` block
         };
     }
 }
diff --git a/tests/ui/async-await/async-block-control-flow-static-semantics.stderr b/tests/ui/async-await/async-block-control-flow-static-semantics.stderr
index c89671cc481..ce0d003f014 100644
--- a/tests/ui/async-await/async-block-control-flow-static-semantics.stderr
+++ b/tests/ui/async-await/async-block-control-flow-static-semantics.stderr
@@ -1,18 +1,18 @@
-error[E0267]: `break` inside of an `async` block
+error[E0267]: `break` inside `async` block
   --> $DIR/async-block-control-flow-static-semantics.rs:32:9
    |
 LL | /     async {
 LL | |         break 0u8;
-   | |         ^^^^^^^^^ cannot `break` inside of an `async` block
+   | |         ^^^^^^^^^ cannot `break` inside `async` block
 LL | |     };
    | |_____- enclosing `async` block
 
-error[E0267]: `break` inside of an `async` block
+error[E0267]: `break` inside `async` block
   --> $DIR/async-block-control-flow-static-semantics.rs:39:13
    |
 LL | /         async {
 LL | |             break 0u8;
-   | |             ^^^^^^^^^ cannot `break` inside of an `async` block
+   | |             ^^^^^^^^^ cannot `break` inside `async` block
 LL | |         };
    | |_________- enclosing `async` block
 
diff --git a/tests/ui/attributes/nonterminal-expansion.rs b/tests/ui/attributes/nonterminal-expansion.rs
index 6db7aea0745..1b2e92a3170 100644
--- a/tests/ui/attributes/nonterminal-expansion.rs
+++ b/tests/ui/attributes/nonterminal-expansion.rs
@@ -5,7 +5,7 @@
 macro_rules! pass_nonterminal {
     ($n:expr) => {
         #[repr(align($n))]
-        //~^ ERROR expected unsuffixed literal or identifier, found `n!()`
+        //~^ ERROR expected unsuffixed literal, found `n!()`
         struct S;
     };
 }
diff --git a/tests/ui/attributes/nonterminal-expansion.stderr b/tests/ui/attributes/nonterminal-expansion.stderr
index 78541495b32..b640575d17d 100644
--- a/tests/ui/attributes/nonterminal-expansion.stderr
+++ b/tests/ui/attributes/nonterminal-expansion.stderr
@@ -1,4 +1,4 @@
-error: expected unsuffixed literal or identifier, found `n!()`
+error: expected unsuffixed literal, found `n!()`
   --> $DIR/nonterminal-expansion.rs:7:22
    |
 LL |         #[repr(align($n))]
diff --git a/tests/ui/binding/match-range.rs b/tests/ui/binding/match-range.rs
index a024e5e585a..097ccb34f87 100644
--- a/tests/ui/binding/match-range.rs
+++ b/tests/ui/binding/match-range.rs
@@ -1,5 +1,4 @@
 //@ run-pass
-#![feature(exclusive_range_pattern)]
 
 pub fn main() {
     match 5_usize {
diff --git a/tests/ui/borrowck/two-phase-activation-sharing-interference.nll_target.stderr b/tests/ui/borrowck/two-phase-activation-sharing-interference.nll_target.stderr
index aacf178932e..6cd64c58cab 100644
--- a/tests/ui/borrowck/two-phase-activation-sharing-interference.nll_target.stderr
+++ b/tests/ui/borrowck/two-phase-activation-sharing-interference.nll_target.stderr
@@ -1,5 +1,5 @@
 error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
-  --> $DIR/two-phase-activation-sharing-interference.rs:28:15
+  --> $DIR/two-phase-activation-sharing-interference.rs:29:15
    |
 LL |     let y = &mut x;
    |             ------ mutable borrow occurs here
@@ -10,7 +10,7 @@ LL |     *y += 1;
    |     ------- mutable borrow later used here
 
 error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
-  --> $DIR/two-phase-activation-sharing-interference.rs:36:13
+  --> $DIR/two-phase-activation-sharing-interference.rs:37:13
    |
 LL |     let y = &mut x;
    |             ------ mutable borrow occurs here
@@ -32,7 +32,7 @@ LL |     *y += 1;
    |     ------- mutable borrow later used here
 
 error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
-  --> $DIR/two-phase-activation-sharing-interference.rs:58:14
+  --> $DIR/two-phase-activation-sharing-interference.rs:56:14
    |
 LL |     let y = &mut x;
    |             ------ mutable borrow occurs here
diff --git a/tests/ui/borrowck/two-phase-activation-sharing-interference.rs b/tests/ui/borrowck/two-phase-activation-sharing-interference.rs
index beee9916fca..1b4526a13a8 100644
--- a/tests/ui/borrowck/two-phase-activation-sharing-interference.rs
+++ b/tests/ui/borrowck/two-phase-activation-sharing-interference.rs
@@ -1,6 +1,7 @@
 //@ revisions: nll_target
 
 // The following revisions are disabled due to missing support from two-phase beyond autorefs
+//@ unused-revision-names: nll_beyond
 //@[nll_beyond] compile-flags: -Z two-phase-beyond-autoref
 
 // This is an important corner case pointed out by Niko: one is
@@ -36,8 +37,7 @@ fn not_ok() {
     let z = &x;
     //[nll_target]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable
     *y += 1;
-    //[lxl_beyond]~^   ERROR cannot borrow `x` as mutable because it is also borrowed as immutable
-    //[nll_beyond]~^^  ERROR cannot borrow `x` as mutable because it is also borrowed as immutable
+    //[nll_beyond]~^   ERROR cannot borrow `x` as mutable because it is also borrowed as immutable
     read(z);
 }
 
@@ -48,8 +48,6 @@ fn should_be_ok_with_nll() {
     //[nll_target]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable
     read(z);
     *y += 1;
-    //[lxl_beyond]~^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable
-    // (okay with (generalized) nll today)
 }
 
 fn should_also_eventually_be_ok_with_nll() {
@@ -58,8 +56,6 @@ fn should_also_eventually_be_ok_with_nll() {
     let _z = &x;
     //[nll_target]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable
     *y += 1;
-    //[lxl_beyond]~^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable
-    // (okay with (generalized) nll today)
 }
 
 fn main() { }
diff --git a/tests/ui/borrowck/two-phase-allow-access-during-reservation.nll_target.stderr b/tests/ui/borrowck/two-phase-allow-access-during-reservation.nll_target.stderr
index 1356c80493c..b7a1de02a4f 100644
--- a/tests/ui/borrowck/two-phase-allow-access-during-reservation.nll_target.stderr
+++ b/tests/ui/borrowck/two-phase-allow-access-during-reservation.nll_target.stderr
@@ -1,5 +1,5 @@
 error[E0503]: cannot use `i` because it was mutably borrowed
-  --> $DIR/two-phase-allow-access-during-reservation.rs:26:19
+  --> $DIR/two-phase-allow-access-during-reservation.rs:27:19
    |
 LL |     /*1*/ let p = &mut i; // (reservation of `i` starts here)
    |                   ------ `i` is borrowed here
@@ -11,7 +11,7 @@ LL |     /*3*/ *p += 1;        // (mutable borrow of `i` starts here, since `p`
    |           ------- borrow later used here
 
 error[E0503]: cannot use `i` because it was mutably borrowed
-  --> $DIR/two-phase-allow-access-during-reservation.rs:31:19
+  --> $DIR/two-phase-allow-access-during-reservation.rs:32:19
    |
 LL |     /*1*/ let p = &mut i; // (reservation of `i` starts here)
    |                   ------ `i` is borrowed here
diff --git a/tests/ui/borrowck/two-phase-allow-access-during-reservation.rs b/tests/ui/borrowck/two-phase-allow-access-during-reservation.rs
index e6b2501c1eb..6b5a2f5e623 100644
--- a/tests/ui/borrowck/two-phase-allow-access-during-reservation.rs
+++ b/tests/ui/borrowck/two-phase-allow-access-during-reservation.rs
@@ -1,6 +1,7 @@
 //@ revisions: nll_target
 
 // The following revisions are disabled due to missing support for two_phase_beyond_autoref
+//@ unused-revision-names: nll_beyond
 //@[nll_beyond] compile-flags: -Z two_phase_beyond_autoref
 
 // This is the second counter-example from Niko's blog post
diff --git a/tests/ui/borrowck/two-phase-nonrecv-autoref.base.stderr b/tests/ui/borrowck/two-phase-nonrecv-autoref.base.stderr
index e122977b9f2..c9d49b8756d 100644
--- a/tests/ui/borrowck/two-phase-nonrecv-autoref.base.stderr
+++ b/tests/ui/borrowck/two-phase-nonrecv-autoref.base.stderr
@@ -1,5 +1,5 @@
 error[E0499]: cannot borrow `*f` as mutable more than once at a time
-  --> $DIR/two-phase-nonrecv-autoref.rs:50:11
+  --> $DIR/two-phase-nonrecv-autoref.rs:51:11
    |
 LL |         f(f(10));
    |         - ^ second mutable borrow occurs here
@@ -8,7 +8,7 @@ LL |         f(f(10));
    |         first borrow later used by call
 
 error[E0382]: use of moved value: `f`
-  --> $DIR/two-phase-nonrecv-autoref.rs:57:11
+  --> $DIR/two-phase-nonrecv-autoref.rs:58:11
    |
 LL |     fn twice_ten_so<F: FnOnce(i32) -> i32>(f: Box<F>) {
    |                                            - move occurs because `f` has type `Box<F>`, which does not implement the `Copy` trait
@@ -18,7 +18,7 @@ LL |         f(f(10));
    |         value moved here
 
 error[E0499]: cannot borrow `*f` as mutable more than once at a time
-  --> $DIR/two-phase-nonrecv-autoref.rs:62:11
+  --> $DIR/two-phase-nonrecv-autoref.rs:63:11
    |
 LL |         f(f(10));
    |         - ^ second mutable borrow occurs here
@@ -27,7 +27,7 @@ LL |         f(f(10));
    |         first borrow later used by call
 
 error[E0382]: use of moved value: `f`
-  --> $DIR/two-phase-nonrecv-autoref.rs:69:11
+  --> $DIR/two-phase-nonrecv-autoref.rs:70:11
    |
 LL |     fn twice_ten_oo(f: Box<dyn FnOnce(i32) -> i32>) {
    |                     - move occurs because `f` has type `Box<dyn FnOnce(i32) -> i32>`, which does not implement the `Copy` trait
@@ -37,7 +37,7 @@ LL |         f(f(10));
    |         value moved here
 
 error[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/two-phase-nonrecv-autoref.rs:107:27
+  --> $DIR/two-phase-nonrecv-autoref.rs:108:27
    |
 LL |     double_access(&mut a, &a);
    |     ------------- ------  ^^ immutable borrow occurs here
@@ -46,7 +46,7 @@ LL |     double_access(&mut a, &a);
    |     mutable borrow later used by call
 
 error[E0502]: cannot borrow `i` as immutable because it is also borrowed as mutable
-  --> $DIR/two-phase-nonrecv-autoref.rs:132:7
+  --> $DIR/two-phase-nonrecv-autoref.rs:133:7
    |
 LL |     i[i[3]] = 4;
    |     --^----
@@ -56,18 +56,18 @@ LL |     i[i[3]] = 4;
    |     mutable borrow occurs here
    |
 help: try adding a local storing this...
-  --> $DIR/two-phase-nonrecv-autoref.rs:132:8
+  --> $DIR/two-phase-nonrecv-autoref.rs:133:8
    |
 LL |     i[i[3]] = 4;
    |        ^^^
 help: ...and then using that local here
-  --> $DIR/two-phase-nonrecv-autoref.rs:132:6
+  --> $DIR/two-phase-nonrecv-autoref.rs:133:6
    |
 LL |     i[i[3]] = 4;
    |      ^^^^^^
 
 error[E0502]: cannot borrow `i` as immutable because it is also borrowed as mutable
-  --> $DIR/two-phase-nonrecv-autoref.rs:138:7
+  --> $DIR/two-phase-nonrecv-autoref.rs:139:7
    |
 LL |     i[i[3]] = i[4];
    |     --^----
@@ -77,12 +77,12 @@ LL |     i[i[3]] = i[4];
    |     mutable borrow occurs here
    |
 help: try adding a local storing this...
-  --> $DIR/two-phase-nonrecv-autoref.rs:138:8
+  --> $DIR/two-phase-nonrecv-autoref.rs:139:8
    |
 LL |     i[i[3]] = i[4];
    |        ^^^
 help: ...and then using that local here
-  --> $DIR/two-phase-nonrecv-autoref.rs:138:6
+  --> $DIR/two-phase-nonrecv-autoref.rs:139:6
    |
 LL |     i[i[3]] = i[4];
    |      ^^^^^^
diff --git a/tests/ui/borrowck/two-phase-nonrecv-autoref.rs b/tests/ui/borrowck/two-phase-nonrecv-autoref.rs
index f52e9c2e3fd..3a8ab4ef3b0 100644
--- a/tests/ui/borrowck/two-phase-nonrecv-autoref.rs
+++ b/tests/ui/borrowck/two-phase-nonrecv-autoref.rs
@@ -1,5 +1,6 @@
 //@ revisions: base
 
+//@ unused-revision-names: g2p
 //@[g2p]compile-flags: -Z two-phase-beyond-autoref
 // the above revision is disabled until two-phase-beyond-autoref support is better
 
diff --git a/tests/ui/borrowck/two-phase-reservation-sharing-interference.nll_target.stderr b/tests/ui/borrowck/two-phase-reservation-sharing-interference.nll_target.stderr
index b1e4392989f..5eda4828012 100644
--- a/tests/ui/borrowck/two-phase-reservation-sharing-interference.nll_target.stderr
+++ b/tests/ui/borrowck/two-phase-reservation-sharing-interference.nll_target.stderr
@@ -1,5 +1,5 @@
 error[E0502]: cannot borrow `vec` as mutable because it is also borrowed as immutable
-  --> $DIR/two-phase-reservation-sharing-interference.rs:32:17
+  --> $DIR/two-phase-reservation-sharing-interference.rs:33:17
    |
 LL |         let shared = &vec;
    |                      ---- immutable borrow occurs here
diff --git a/tests/ui/borrowck/two-phase-reservation-sharing-interference.rs b/tests/ui/borrowck/two-phase-reservation-sharing-interference.rs
index b6bcf7b6617..61446577db2 100644
--- a/tests/ui/borrowck/two-phase-reservation-sharing-interference.rs
+++ b/tests/ui/borrowck/two-phase-reservation-sharing-interference.rs
@@ -1,6 +1,7 @@
 //@ revisions: nll_target
 
 // The nll_beyond revision is disabled due to missing support from two-phase beyond autorefs
+//@ unused-revision-names: nll_beyond
 //@[nll_beyond]compile-flags: -Z two-phase-beyond-autoref
 //@[nll_beyond]should-fail
 
diff --git a/tests/ui/check-cfg/allow-same-level.stderr b/tests/ui/check-cfg/allow-same-level.stderr
index 99e81d3bba6..ae4c1605f01 100644
--- a/tests/ui/check-cfg/allow-same-level.stderr
+++ b/tests/ui/check-cfg/allow-same-level.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `FALSE`
 LL | #[cfg(FALSE)]
    |       ^^^^^
    |
-   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
    = help: to expect this configuration use `--check-cfg=cfg(FALSE)`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/check-cfg/cargo-feature.none.stderr b/tests/ui/check-cfg/cargo-feature.none.stderr
index 09a1c950267..627f03ddf55 100644
--- a/tests/ui/check-cfg/cargo-feature.none.stderr
+++ b/tests/ui/check-cfg/cargo-feature.none.stderr
@@ -6,7 +6,7 @@ LL | #[cfg(feature = "serde")]
    |
    = note: no expected values for `feature`
    = help: consider adding `serde` as a feature in `Cargo.toml`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition value: (none)
@@ -17,7 +17,7 @@ LL | #[cfg(feature)]
    |
    = note: no expected values for `feature`
    = help: consider defining some features in `Cargo.toml`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `tokio_unstable`
   --> $DIR/cargo-feature.rs:22:7
@@ -25,9 +25,9 @@ warning: unexpected `cfg` condition name: `tokio_unstable`
 LL | #[cfg(tokio_unstable)]
    |       ^^^^^^^^^^^^^^
    |
-   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
-   = help: consider using a Cargo feature instead or adding `println!("cargo:rustc-check-cfg=cfg(tokio_unstable)");` to the top of a `build.rs`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
+   = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(tokio_unstable)");` to the top of the `build.rs`
+   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `CONFIG_NVME`
   --> $DIR/cargo-feature.rs:26:7
@@ -35,8 +35,8 @@ warning: unexpected `cfg` condition name: `CONFIG_NVME`
 LL | #[cfg(CONFIG_NVME = "m")]
    |       ^^^^^^^^^^^^^^^^^
    |
-   = help: consider using a Cargo feature instead or adding `println!("cargo:rustc-check-cfg=cfg(CONFIG_NVME, values(\"m\"))");` to the top of a `build.rs`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
+   = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(CONFIG_NVME, values(\"m\"))");` to the top of the `build.rs`
+   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
 
 warning: 4 warnings emitted
 
diff --git a/tests/ui/check-cfg/cargo-feature.some.stderr b/tests/ui/check-cfg/cargo-feature.some.stderr
index 4db9c66fc86..9cc5fb6aca0 100644
--- a/tests/ui/check-cfg/cargo-feature.some.stderr
+++ b/tests/ui/check-cfg/cargo-feature.some.stderr
@@ -6,7 +6,7 @@ LL | #[cfg(feature = "serde")]
    |
    = note: expected values for `feature` are: `bitcode`
    = help: consider adding `serde` as a feature in `Cargo.toml`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition value: (none)
@@ -17,7 +17,7 @@ LL | #[cfg(feature)]
    |
    = note: expected values for `feature` are: `bitcode`
    = help: consider defining some features in `Cargo.toml`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `tokio_unstable`
   --> $DIR/cargo-feature.rs:22:7
@@ -25,9 +25,9 @@ warning: unexpected `cfg` condition name: `tokio_unstable`
 LL | #[cfg(tokio_unstable)]
    |       ^^^^^^^^^^^^^^
    |
-   = help: expected names are: `CONFIG_NVME`, `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
-   = help: consider using a Cargo feature instead or adding `println!("cargo:rustc-check-cfg=cfg(tokio_unstable)");` to the top of a `build.rs`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
+   = help: expected names are: `CONFIG_NVME`, `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
+   = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(tokio_unstable)");` to the top of the `build.rs`
+   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `m`
   --> $DIR/cargo-feature.rs:26:7
@@ -38,8 +38,8 @@ LL | #[cfg(CONFIG_NVME = "m")]
    |                     help: there is a expected value with a similar name: `"y"`
    |
    = note: expected values for `CONFIG_NVME` are: `y`
-   = help: consider using a Cargo feature instead or adding `println!("cargo:rustc-check-cfg=cfg(CONFIG_NVME, values(\"m\"))");` to the top of a `build.rs`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
+   = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(CONFIG_NVME, values(\"m\"))");` to the top of the `build.rs`
+   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
 
 warning: 4 warnings emitted
 
diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr
index f1393c55819..4975129802b 100644
--- a/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr
+++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `value`
 LL | #[cfg(value)]
    |       ^^^^^
    |
-   = help: expected names are: `bar`, `bee`, `clippy`, `cow`, `debug_assertions`, `doc`, `doctest`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
+   = help: expected names are: `bar`, `bee`, `clippy`, `cow`, `debug_assertions`, `doc`, `doctest`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
    = help: to expect this configuration use `--check-cfg=cfg(value)`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr
index 3d4f430c2bb..6404556f46c 100644
--- a/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr
+++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `my_value`
 LL | #[cfg(my_value)]
    |       ^^^^^^^^
    |
-   = help: expected names are: `bar`, `clippy`, `debug_assertions`, `doc`, `doctest`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
+   = help: expected names are: `bar`, `clippy`, `debug_assertions`, `doc`, `doctest`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
    = help: to expect this configuration use `--check-cfg=cfg(my_value)`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr
index 142d10076e9..bda1a601410 100644
--- a/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr
+++ b/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `linux`
 LL | #[cfg(linux)]
    |       ^^^^^ help: found config with similar value: `target_os = "linux"`
    |
-   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
    = help: to expect this configuration use `--check-cfg=cfg(linux)`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/check-cfg/compact-names.stderr b/tests/ui/check-cfg/compact-names.stderr
index dd19f606620..079be8d08c2 100644
--- a/tests/ui/check-cfg/compact-names.stderr
+++ b/tests/ui/check-cfg/compact-names.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `target_architecture`
 LL | #[cfg(target(os = "linux", architecture = "arm"))]
    |                            ^^^^^^^^^^^^^^^^^^^^
    |
-   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
    = help: to expect this configuration use `--check-cfg=cfg(target_architecture, values("arm"))`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/check-cfg/diagnotics.cargo.stderr b/tests/ui/check-cfg/diagnotics.cargo.stderr
index 16417fe0105..1b7505682da 100644
--- a/tests/ui/check-cfg/diagnotics.cargo.stderr
+++ b/tests/ui/check-cfg/diagnotics.cargo.stderr
@@ -5,7 +5,7 @@ LL | #[cfg(featur)]
    |       ^^^^^^ help: there is a config with a similar name: `feature`
    |
    = help: expected values for `feature` are: `foo`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition name: `featur`
@@ -14,7 +14,7 @@ warning: unexpected `cfg` condition name: `featur`
 LL | #[cfg(featur = "foo")]
    |       ^^^^^^^^^^^^^^
    |
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
 help: there is a config with a similar name and value
    |
 LL | #[cfg(feature = "foo")]
@@ -27,7 +27,7 @@ LL | #[cfg(featur = "fo")]
    |       ^^^^^^^^^^^^^
    |
    = help: expected values for `feature` are: `foo`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
 help: there is a config with a similar name and different values
    |
 LL | #[cfg(feature = "foo")]
@@ -39,8 +39,8 @@ warning: unexpected `cfg` condition name: `no_value`
 LL | #[cfg(no_value)]
    |       ^^^^^^^^ help: there is a config with a similar name: `no_values`
    |
-   = help: consider using a Cargo feature instead or adding `println!("cargo:rustc-check-cfg=cfg(no_value)");` to the top of a `build.rs`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
+   = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(no_value)");` to the top of the `build.rs`
+   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `no_value`
   --> $DIR/diagnotics.rs:27:7
@@ -48,8 +48,8 @@ warning: unexpected `cfg` condition name: `no_value`
 LL | #[cfg(no_value = "foo")]
    |       ^^^^^^^^^^^^^^^^
    |
-   = help: consider using a Cargo feature instead or adding `println!("cargo:rustc-check-cfg=cfg(no_value, values(\"foo\"))");` to the top of a `build.rs`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
+   = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(no_value, values(\"foo\"))");` to the top of the `build.rs`
+   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
 help: there is a config with a similar name and no value
    |
 LL | #[cfg(no_values)]
@@ -64,8 +64,8 @@ LL | #[cfg(no_values = "bar")]
    |                help: remove the value
    |
    = note: no expected value for `no_values`
-   = help: consider using a Cargo feature instead or adding `println!("cargo:rustc-check-cfg=cfg(no_values, values(\"bar\"))");` to the top of a `build.rs`
-   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
+   = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(no_values, values(\"bar\"))");` to the top of the `build.rs`
+   = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
 
 warning: 6 warnings emitted
 
diff --git a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr
index 91afe766c8d..755373d7b77 100644
--- a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr
+++ b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key`
 LL | #[cfg(unknown_key = "value")]
    |       ^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
    = help: to expect this configuration use `--check-cfg=cfg(unknown_key, values("value"))`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
@@ -30,7 +30,7 @@ LL | #[cfg(feature = "unk")]
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `feature`
-  --> $DIR/exhaustive-names-values.rs:25:7
+  --> $DIR/exhaustive-names-values.rs:24:7
    |
 LL | #[cfg(feature = "std")]
    |       ^^^^^^^^^^^^^^^
diff --git a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr
index 93b0621e224..6344739ae76 100644
--- a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr
+++ b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key`
 LL | #[cfg(unknown_key = "value")]
    |       ^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
    = help: to expect this configuration use `--check-cfg=cfg(unknown_key, values("value"))`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/check-cfg/exhaustive-names-values.full.stderr b/tests/ui/check-cfg/exhaustive-names-values.full.stderr
index 93b0621e224..6344739ae76 100644
--- a/tests/ui/check-cfg/exhaustive-names-values.full.stderr
+++ b/tests/ui/check-cfg/exhaustive-names-values.full.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key`
 LL | #[cfg(unknown_key = "value")]
    |       ^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
    = help: to expect this configuration use `--check-cfg=cfg(unknown_key, values("value"))`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/check-cfg/exhaustive-names-values.rs b/tests/ui/check-cfg/exhaustive-names-values.rs
index a6190f15dbb..7b2d89b5781 100644
--- a/tests/ui/check-cfg/exhaustive-names-values.rs
+++ b/tests/ui/check-cfg/exhaustive-names-values.rs
@@ -16,15 +16,13 @@ pub fn f() {}
 pub fn f() {}
 
 #[cfg(feature = "unk")]
-//[empty_names_values]~^ WARNING unexpected `cfg` condition name
-//[empty_cfg]~^^ WARNING unexpected `cfg` condition name
-//[feature]~^^^ WARNING unexpected `cfg` condition value
-//[full]~^^^^ WARNING unexpected `cfg` condition value
+//[empty_cfg]~^ WARNING unexpected `cfg` condition name
+//[feature]~^^ WARNING unexpected `cfg` condition value
+//[full]~^^^ WARNING unexpected `cfg` condition value
 pub fn feat() {}
 
 #[cfg(feature = "std")]
-//[empty_names_values]~^ WARNING unexpected `cfg` condition name
-//[empty_cfg]~^^ WARNING unexpected `cfg` condition name
+//[empty_cfg]~^ WARNING unexpected `cfg` condition name
 pub fn feat() {}
 
 #[cfg(windows)]
diff --git a/tests/ui/check-cfg/exhaustive-names.stderr b/tests/ui/check-cfg/exhaustive-names.stderr
index f4eb5a640ae..605825cd4e5 100644
--- a/tests/ui/check-cfg/exhaustive-names.stderr
+++ b/tests/ui/check-cfg/exhaustive-names.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key`
 LL | #[cfg(unknown_key = "value")]
    |       ^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
    = help: to expect this configuration use `--check-cfg=cfg(unknown_key, values("value"))`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/check-cfg/invalid-arguments.any_values.stderr b/tests/ui/check-cfg/invalid-arguments.any_values.stderr
index f9a9c4a6e13..65ef5155fa1 100644
--- a/tests/ui/check-cfg/invalid-arguments.any_values.stderr
+++ b/tests/ui/check-cfg/invalid-arguments.any_values.stderr
@@ -1,2 +1,5 @@
-error: invalid `--check-cfg` argument: `cfg(any(),values())` (`values()` cannot be specified before the names)
+error: invalid `--check-cfg` argument: `cfg(any(),values())`
+   |
+   = note: `values()` cannot be specified before the names
+   = note: visit <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details
 
diff --git a/tests/ui/check-cfg/invalid-arguments.anything_else.stderr b/tests/ui/check-cfg/invalid-arguments.anything_else.stderr
index 925664bb3fc..f3bc0b782e2 100644
--- a/tests/ui/check-cfg/invalid-arguments.anything_else.stderr
+++ b/tests/ui/check-cfg/invalid-arguments.anything_else.stderr
@@ -1,2 +1,5 @@
-error: invalid `--check-cfg` argument: `anything_else(...)` (expected `cfg(name, values("value1", "value2", ... "valueN"))`)
+error: invalid `--check-cfg` argument: `anything_else(...)`
+   |
+   = note: expected `cfg(name, values("value1", "value2", ... "valueN"))`
+   = note: visit <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details
 
diff --git a/tests/ui/check-cfg/invalid-arguments.boolean.stderr b/tests/ui/check-cfg/invalid-arguments.boolean.stderr
new file mode 100644
index 00000000000..18734de9dac
--- /dev/null
+++ b/tests/ui/check-cfg/invalid-arguments.boolean.stderr
@@ -0,0 +1,6 @@
+error: invalid `--check-cfg` argument: `cfg(true)`
+   |
+   = note: `true` is a boolean literal
+   = note: `cfg()` arguments must be simple identifiers, `any()` or `values(...)`
+   = note: visit <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details
+
diff --git a/tests/ui/check-cfg/invalid-arguments.cfg_none.stderr b/tests/ui/check-cfg/invalid-arguments.cfg_none.stderr
index 7992dbdff00..ef464260c29 100644
--- a/tests/ui/check-cfg/invalid-arguments.cfg_none.stderr
+++ b/tests/ui/check-cfg/invalid-arguments.cfg_none.stderr
@@ -1,2 +1,6 @@
-error: invalid `--check-cfg` argument: `cfg(none())` (`cfg()` arguments must be simple identifiers, `any()` or `values(...)`)
+error: invalid `--check-cfg` argument: `cfg(none())`
+   |
+   = note: `none()` is invalid
+   = note: `cfg()` arguments must be simple identifiers, `any()` or `values(...)`
+   = note: visit <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details
 
diff --git a/tests/ui/check-cfg/invalid-arguments.giberich.stderr b/tests/ui/check-cfg/invalid-arguments.giberich.stderr
index d427033fcc2..3e350145491 100644
--- a/tests/ui/check-cfg/invalid-arguments.giberich.stderr
+++ b/tests/ui/check-cfg/invalid-arguments.giberich.stderr
@@ -1,2 +1,5 @@
-error: invalid `--check-cfg` argument: `cfg(...)` (expected `cfg(name, values("value1", "value2", ... "valueN"))`)
+error: invalid `--check-cfg` argument: `cfg(...)`
+   |
+   = note: expected `cfg(name, values("value1", "value2", ... "valueN"))`
+   = note: visit <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details
 
diff --git a/tests/ui/check-cfg/invalid-arguments.ident_in_values_1.stderr b/tests/ui/check-cfg/invalid-arguments.ident_in_values_1.stderr
index 90308bdcd23..cfedb7ed517 100644
--- a/tests/ui/check-cfg/invalid-arguments.ident_in_values_1.stderr
+++ b/tests/ui/check-cfg/invalid-arguments.ident_in_values_1.stderr
@@ -1,2 +1,6 @@
-error: invalid `--check-cfg` argument: `cfg(foo,values(bar))` (`values()` arguments must be string literals, `none()` or `any()`)
+error: invalid `--check-cfg` argument: `cfg(foo,values(bar))`
+   |
+   = note: `bar` is invalid
+   = note: `values()` arguments must be string literals, `none()` or `any()`
+   = note: visit <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details
 
diff --git a/tests/ui/check-cfg/invalid-arguments.ident_in_values_2.stderr b/tests/ui/check-cfg/invalid-arguments.ident_in_values_2.stderr
index 16f92a504a5..ba194862284 100644
--- a/tests/ui/check-cfg/invalid-arguments.ident_in_values_2.stderr
+++ b/tests/ui/check-cfg/invalid-arguments.ident_in_values_2.stderr
@@ -1,2 +1,6 @@
-error: invalid `--check-cfg` argument: `cfg(foo,values("bar",bar,"bar"))` (`values()` arguments must be string literals, `none()` or `any()`)
+error: invalid `--check-cfg` argument: `cfg(foo,values("bar",bar,"bar"))`
+   |
+   = note: `bar` is invalid
+   = note: `values()` arguments must be string literals, `none()` or `any()`
+   = note: visit <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details
 
diff --git a/tests/ui/check-cfg/invalid-arguments.mixed_any.stderr b/tests/ui/check-cfg/invalid-arguments.mixed_any.stderr
index 9239f8cce94..512ecbe9eda 100644
--- a/tests/ui/check-cfg/invalid-arguments.mixed_any.stderr
+++ b/tests/ui/check-cfg/invalid-arguments.mixed_any.stderr
@@ -1,2 +1,5 @@
-error: invalid `--check-cfg` argument: `cfg(any(),values(any()))` (`values()` cannot be specified before the names)
+error: invalid `--check-cfg` argument: `cfg(any(),values(any()))`
+   |
+   = note: `values()` cannot be specified before the names
+   = note: visit <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details
 
diff --git a/tests/ui/check-cfg/invalid-arguments.mixed_values_any.stderr b/tests/ui/check-cfg/invalid-arguments.mixed_values_any.stderr
index 4c406143d08..2d59b12097d 100644
--- a/tests/ui/check-cfg/invalid-arguments.mixed_values_any.stderr
+++ b/tests/ui/check-cfg/invalid-arguments.mixed_values_any.stderr
@@ -1,2 +1,5 @@
-error: invalid `--check-cfg` argument: `cfg(foo,values("bar",any()))` (`values()` arguments cannot specify string literals and `any()` at the same time)
+error: invalid `--check-cfg` argument: `cfg(foo,values("bar",any()))`
+   |
+   = note: `values()` arguments cannot specify string literals and `any()` at the same time
+   = note: visit <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details
 
diff --git a/tests/ui/check-cfg/invalid-arguments.multiple_any.stderr b/tests/ui/check-cfg/invalid-arguments.multiple_any.stderr
index 6f1db1b13c3..6eb63de4252 100644
--- a/tests/ui/check-cfg/invalid-arguments.multiple_any.stderr
+++ b/tests/ui/check-cfg/invalid-arguments.multiple_any.stderr
@@ -1,2 +1,5 @@
-error: invalid `--check-cfg` argument: `cfg(any(),any())` (`any()` cannot be specified multiple times)
+error: invalid `--check-cfg` argument: `cfg(any(),any())`
+   |
+   = note: `any()` cannot be specified multiple times
+   = note: visit <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details
 
diff --git a/tests/ui/check-cfg/invalid-arguments.multiple_values.stderr b/tests/ui/check-cfg/invalid-arguments.multiple_values.stderr
index bce305b09c3..06060078bc0 100644
--- a/tests/ui/check-cfg/invalid-arguments.multiple_values.stderr
+++ b/tests/ui/check-cfg/invalid-arguments.multiple_values.stderr
@@ -1,2 +1,5 @@
-error: invalid `--check-cfg` argument: `cfg(foo,values(),values())` (`values()` cannot be specified multiple times)
+error: invalid `--check-cfg` argument: `cfg(foo,values(),values())`
+   |
+   = note: `values()` cannot be specified multiple times
+   = note: visit <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details
 
diff --git a/tests/ui/check-cfg/invalid-arguments.multiple_values_any.stderr b/tests/ui/check-cfg/invalid-arguments.multiple_values_any.stderr
index 748ce231af7..72554ac3ead 100644
--- a/tests/ui/check-cfg/invalid-arguments.multiple_values_any.stderr
+++ b/tests/ui/check-cfg/invalid-arguments.multiple_values_any.stderr
@@ -1,2 +1,6 @@
-error: invalid `--check-cfg` argument: `cfg(foo,values(any(),any()))` (`any()` in `values()` cannot be specified multiple times)
+error: invalid `--check-cfg` argument: `cfg(foo,values(any(),any()))`
+   |
+   = note: `any()` is invalid
+   = note: `any()` in `values()` cannot be specified multiple times
+   = note: visit <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details
 
diff --git a/tests/ui/check-cfg/invalid-arguments.none_not_empty.stderr b/tests/ui/check-cfg/invalid-arguments.none_not_empty.stderr
index 0a6c6ffd42f..6e9d87bace2 100644
--- a/tests/ui/check-cfg/invalid-arguments.none_not_empty.stderr
+++ b/tests/ui/check-cfg/invalid-arguments.none_not_empty.stderr
@@ -1,2 +1,6 @@
-error: invalid `--check-cfg` argument: `cfg(foo,values(none("test")))` (`none()` must be empty)
+error: invalid `--check-cfg` argument: `cfg(foo,values(none("test")))`
+   |
+   = note: `none("test")` is invalid
+   = note: `none()` in `values()` takes no argument
+   = note: visit <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details
 
diff --git a/tests/ui/check-cfg/invalid-arguments.not_empty_any.stderr b/tests/ui/check-cfg/invalid-arguments.not_empty_any.stderr
index daf38147fe5..35eb1949ad7 100644
--- a/tests/ui/check-cfg/invalid-arguments.not_empty_any.stderr
+++ b/tests/ui/check-cfg/invalid-arguments.not_empty_any.stderr
@@ -1,2 +1,6 @@
-error: invalid `--check-cfg` argument: `cfg(any(foo))` (`any()` must be empty)
+error: invalid `--check-cfg` argument: `cfg(any(foo))`
+   |
+   = note: `any(foo)` is invalid
+   = note: `any()` takes no argument
+   = note: visit <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details
 
diff --git a/tests/ui/check-cfg/invalid-arguments.not_empty_values_any.stderr b/tests/ui/check-cfg/invalid-arguments.not_empty_values_any.stderr
index 79f83e802ca..cc41d21bec6 100644
--- a/tests/ui/check-cfg/invalid-arguments.not_empty_values_any.stderr
+++ b/tests/ui/check-cfg/invalid-arguments.not_empty_values_any.stderr
@@ -1,2 +1,6 @@
-error: invalid `--check-cfg` argument: `cfg(foo,values(any(bar)))` (`any()` must be empty)
+error: invalid `--check-cfg` argument: `cfg(foo,values(any(bar)))`
+   |
+   = note: `any(bar)` is invalid
+   = note: `any()` in `values()` takes no argument
+   = note: visit <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details
 
diff --git a/tests/ui/check-cfg/invalid-arguments.rs b/tests/ui/check-cfg/invalid-arguments.rs
index c0b58ede97f..b8588ecb4ff 100644
--- a/tests/ui/check-cfg/invalid-arguments.rs
+++ b/tests/ui/check-cfg/invalid-arguments.rs
@@ -2,7 +2,7 @@
 //
 //@ check-fail
 //@ no-auto-check-cfg
-//@ revisions: anything_else
+//@ revisions: anything_else boolean
 //@ revisions: string_for_name_1 string_for_name_2 multiple_any multiple_values
 //@ revisions: multiple_values_any not_empty_any not_empty_values_any
 //@ revisions: values_any_missing_values values_any_before_ident ident_in_values_1
@@ -11,6 +11,7 @@
 //@ revisions: none_not_empty cfg_none
 //
 //@ [anything_else]compile-flags: --check-cfg=anything_else(...)
+//@ [boolean]compile-flags: --check-cfg=cfg(true)
 //@ [string_for_name_1]compile-flags: --check-cfg=cfg("NOT_IDENT")
 //@ [string_for_name_2]compile-flags: --check-cfg=cfg(foo,"NOT_IDENT",bar)
 //@ [multiple_any]compile-flags: --check-cfg=cfg(any(),any())
diff --git a/tests/ui/check-cfg/invalid-arguments.string_for_name_1.stderr b/tests/ui/check-cfg/invalid-arguments.string_for_name_1.stderr
index c6f6834ffd3..7022b709b64 100644
--- a/tests/ui/check-cfg/invalid-arguments.string_for_name_1.stderr
+++ b/tests/ui/check-cfg/invalid-arguments.string_for_name_1.stderr
@@ -1,2 +1,6 @@
-error: invalid `--check-cfg` argument: `cfg("NOT_IDENT")` (`cfg()` arguments must be simple identifiers, `any()` or `values(...)`)
+error: invalid `--check-cfg` argument: `cfg("NOT_IDENT")`
+   |
+   = note: `"NOT_IDENT"` is a string literal
+   = note: `cfg()` arguments must be simple identifiers, `any()` or `values(...)`
+   = note: visit <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details
 
diff --git a/tests/ui/check-cfg/invalid-arguments.string_for_name_2.stderr b/tests/ui/check-cfg/invalid-arguments.string_for_name_2.stderr
index ab3dc86cd1a..ea96b913907 100644
--- a/tests/ui/check-cfg/invalid-arguments.string_for_name_2.stderr
+++ b/tests/ui/check-cfg/invalid-arguments.string_for_name_2.stderr
@@ -1,2 +1,6 @@
-error: invalid `--check-cfg` argument: `cfg(foo,"NOT_IDENT",bar)` (`cfg()` arguments must be simple identifiers, `any()` or `values(...)`)
+error: invalid `--check-cfg` argument: `cfg(foo,"NOT_IDENT",bar)`
+   |
+   = note: `"NOT_IDENT"` is a string literal
+   = note: `cfg()` arguments must be simple identifiers, `any()` or `values(...)`
+   = note: visit <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details
 
diff --git a/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_1.stderr b/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_1.stderr
index c04b15ec265..f82c520c62a 100644
--- a/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_1.stderr
+++ b/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_1.stderr
@@ -1,2 +1,5 @@
-error: invalid `--check-cfg` argument: `abc()` (expected `cfg(name, values("value1", "value2", ... "valueN"))`)
+error: invalid `--check-cfg` argument: `abc()`
+   |
+   = note: expected `cfg(name, values("value1", "value2", ... "valueN"))`
+   = note: visit <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details
 
diff --git a/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_2.stderr b/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_2.stderr
index cee65f9887b..ee62c25b41c 100644
--- a/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_2.stderr
+++ b/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_2.stderr
@@ -1,2 +1,6 @@
-error: invalid `--check-cfg` argument: `cfg(foo,test())` (`cfg()` arguments must be simple identifiers, `any()` or `values(...)`)
+error: invalid `--check-cfg` argument: `cfg(foo,test())`
+   |
+   = note: `test()` is invalid
+   = note: `cfg()` arguments must be simple identifiers, `any()` or `values(...)`
+   = note: visit <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details
 
diff --git a/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_3.stderr b/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_3.stderr
index a023779b35a..a8ab9cc9d30 100644
--- a/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_3.stderr
+++ b/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_3.stderr
@@ -1,2 +1,6 @@
-error: invalid `--check-cfg` argument: `cfg(foo,values(test()))` (`values()` arguments must be string literals, `none()` or `any()`)
+error: invalid `--check-cfg` argument: `cfg(foo,values(test()))`
+   |
+   = note: `test()` is invalid
+   = note: `values()` arguments must be string literals, `none()` or `any()`
+   = note: visit <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details
 
diff --git a/tests/ui/check-cfg/invalid-arguments.unterminated.stderr b/tests/ui/check-cfg/invalid-arguments.unterminated.stderr
index 80161a6aa0f..150e1d66426 100644
--- a/tests/ui/check-cfg/invalid-arguments.unterminated.stderr
+++ b/tests/ui/check-cfg/invalid-arguments.unterminated.stderr
@@ -1,2 +1,5 @@
-error: invalid `--check-cfg` argument: `cfg(` (expected `cfg(name, values("value1", "value2", ... "valueN"))`)
+error: invalid `--check-cfg` argument: `cfg(`
+   |
+   = note: expected `cfg(name, values("value1", "value2", ... "valueN"))`
+   = note: visit <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details
 
diff --git a/tests/ui/check-cfg/invalid-arguments.values_any_before_ident.stderr b/tests/ui/check-cfg/invalid-arguments.values_any_before_ident.stderr
index fc93ec8fbdf..7013bb8e095 100644
--- a/tests/ui/check-cfg/invalid-arguments.values_any_before_ident.stderr
+++ b/tests/ui/check-cfg/invalid-arguments.values_any_before_ident.stderr
@@ -1,2 +1,5 @@
-error: invalid `--check-cfg` argument: `cfg(values(any()),foo)` (`values()` cannot be specified before the names)
+error: invalid `--check-cfg` argument: `cfg(values(any()),foo)`
+   |
+   = note: `values()` cannot be specified before the names
+   = note: visit <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details
 
diff --git a/tests/ui/check-cfg/invalid-arguments.values_any_missing_values.stderr b/tests/ui/check-cfg/invalid-arguments.values_any_missing_values.stderr
index f41672fcbdb..ad1af73c690 100644
--- a/tests/ui/check-cfg/invalid-arguments.values_any_missing_values.stderr
+++ b/tests/ui/check-cfg/invalid-arguments.values_any_missing_values.stderr
@@ -1,2 +1,5 @@
-error: invalid `--check-cfg` argument: `cfg(foo,any())` (`cfg(any())` can only be provided in isolation)
+error: invalid `--check-cfg` argument: `cfg(foo,any())`
+   |
+   = note: `cfg(any())` can only be provided in isolation
+   = note: visit <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details
 
diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr
index 1ccdd10d123..54591699145 100644
--- a/tests/ui/check-cfg/mix.stderr
+++ b/tests/ui/check-cfg/mix.stderr
@@ -44,7 +44,7 @@ warning: unexpected `cfg` condition name: `uu`
 LL | #[cfg_attr(uu, test)]
    |            ^^
    |
-   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
    = help: to expect this configuration use `--check-cfg=cfg(uu)`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
diff --git a/tests/ui/check-cfg/stmt-no-ice.stderr b/tests/ui/check-cfg/stmt-no-ice.stderr
index a6c72b0e6bf..ab0deae428d 100644
--- a/tests/ui/check-cfg/stmt-no-ice.stderr
+++ b/tests/ui/check-cfg/stmt-no-ice.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `crossbeam_loom`
 LL |     #[cfg(crossbeam_loom)]
    |           ^^^^^^^^^^^^^^
    |
-   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
    = help: to expect this configuration use `--check-cfg=cfg(crossbeam_loom)`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/check-cfg/values-none.concat_1.stderr b/tests/ui/check-cfg/values-none.concat_1.stderr
new file mode 100644
index 00000000000..b8f0b02b4c5
--- /dev/null
+++ b/tests/ui/check-cfg/values-none.concat_1.stderr
@@ -0,0 +1,13 @@
+warning: unexpected `cfg` condition value: `bar`
+  --> $DIR/values-none.rs:16:7
+   |
+LL | #[cfg(foo = "bar")]
+   |       ^^^^^^^^^^^
+   |
+   = note: expected values for `foo` are: (none), `too`
+   = help: to expect this configuration use `--check-cfg=cfg(foo, values("bar"))`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
+   = note: `#[warn(unexpected_cfgs)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/check-cfg/values-none.concat_2.stderr b/tests/ui/check-cfg/values-none.concat_2.stderr
new file mode 100644
index 00000000000..b8f0b02b4c5
--- /dev/null
+++ b/tests/ui/check-cfg/values-none.concat_2.stderr
@@ -0,0 +1,13 @@
+warning: unexpected `cfg` condition value: `bar`
+  --> $DIR/values-none.rs:16:7
+   |
+LL | #[cfg(foo = "bar")]
+   |       ^^^^^^^^^^^
+   |
+   = note: expected values for `foo` are: (none), `too`
+   = help: to expect this configuration use `--check-cfg=cfg(foo, values("bar"))`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
+   = note: `#[warn(unexpected_cfgs)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/check-cfg/values-none.rs b/tests/ui/check-cfg/values-none.rs
index 6856d2f33af..447fde2bfcc 100644
--- a/tests/ui/check-cfg/values-none.rs
+++ b/tests/ui/check-cfg/values-none.rs
@@ -1,7 +1,7 @@
 //@ check-pass
 //
 //@ no-auto-check-cfg
-//@ revisions: explicit implicit
+//@ revisions: explicit implicit simple concat_1 concat_2
 //@ [explicit]compile-flags: --check-cfg=cfg(foo,values(none()))
 //@ [implicit]compile-flags: --check-cfg=cfg(foo)
 //@ [simple]  compile-flags: --check-cfg=cfg(foo,values(none(),"too"))
diff --git a/tests/ui/check-cfg/values-none.simple.stderr b/tests/ui/check-cfg/values-none.simple.stderr
new file mode 100644
index 00000000000..b8f0b02b4c5
--- /dev/null
+++ b/tests/ui/check-cfg/values-none.simple.stderr
@@ -0,0 +1,13 @@
+warning: unexpected `cfg` condition value: `bar`
+  --> $DIR/values-none.rs:16:7
+   |
+LL | #[cfg(foo = "bar")]
+   |       ^^^^^^^^^^^
+   |
+   = note: expected values for `foo` are: (none), `too`
+   = help: to expect this configuration use `--check-cfg=cfg(foo, values("bar"))`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
+   = note: `#[warn(unexpected_cfgs)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/check-cfg/well-known-names.stderr b/tests/ui/check-cfg/well-known-names.stderr
index 2f07174b905..2ce6fe80ef2 100644
--- a/tests/ui/check-cfg/well-known-names.stderr
+++ b/tests/ui/check-cfg/well-known-names.stderr
@@ -18,7 +18,7 @@ warning: unexpected `cfg` condition name: `features`
 LL | #[cfg(features = "foo")]
    |       ^^^^^^^^^^^^^^^^
    |
-   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
    = help: to expect this configuration use `--check-cfg=cfg(features, values("foo"))`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
diff --git a/tests/ui/check-cfg/well-known-values.rs b/tests/ui/check-cfg/well-known-values.rs
index b821f8092dd..d5fe7464792 100644
--- a/tests/ui/check-cfg/well-known-values.rs
+++ b/tests/ui/check-cfg/well-known-values.rs
@@ -43,6 +43,8 @@
     //~^ WARN unexpected `cfg` condition value
     relocation_model = "_UNEXPECTED_VALUE",
     //~^ WARN unexpected `cfg` condition value
+    rustfmt = "_UNEXPECTED_VALUE",
+    //~^ WARN unexpected `cfg` condition value
     sanitize = "_UNEXPECTED_VALUE",
     //~^ WARN unexpected `cfg` condition value
     target_abi = "_UNEXPECTED_VALUE",
@@ -115,4 +117,7 @@ fn doc() {}
 #[cfg(clippy)]
 fn clippy() {}
 
+#[cfg_attr(rustfmt, rustfmt::skip)]
+fn rustfmt() {}
+
 fn main() {}
diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr
index cd5cdf3df3c..db4a5fd49e6 100644
--- a/tests/ui/check-cfg/well-known-values.stderr
+++ b/tests/ui/check-cfg/well-known-values.stderr
@@ -97,6 +97,17 @@ LL |     relocation_model = "_UNEXPECTED_VALUE",
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
   --> $DIR/well-known-values.rs:46:5
    |
+LL |     rustfmt = "_UNEXPECTED_VALUE",
+   |     ^^^^^^^----------------------
+   |            |
+   |            help: remove the value
+   |
+   = note: no expected value for `rustfmt`
+   = 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`
+  --> $DIR/well-known-values.rs:48:5
+   |
 LL |     sanitize = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
@@ -104,7 +115,7 @@ LL |     sanitize = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:48:5
+  --> $DIR/well-known-values.rs:50:5
    |
 LL |     target_abi = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -113,7 +124,7 @@ LL |     target_abi = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:50:5
+  --> $DIR/well-known-values.rs:52:5
    |
 LL |     target_arch = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -122,7 +133,7 @@ LL |     target_arch = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:52:5
+  --> $DIR/well-known-values.rs:54:5
    |
 LL |     target_endian = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -131,7 +142,7 @@ LL |     target_endian = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:54:5
+  --> $DIR/well-known-values.rs:56:5
    |
 LL |     target_env = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -140,7 +151,7 @@ LL |     target_env = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:56:5
+  --> $DIR/well-known-values.rs:58:5
    |
 LL |     target_family = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -149,7 +160,7 @@ LL |     target_family = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:58:5
+  --> $DIR/well-known-values.rs:60:5
    |
 LL |     target_feature = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -158,7 +169,7 @@ LL |     target_feature = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:60:5
+  --> $DIR/well-known-values.rs:62:5
    |
 LL |     target_has_atomic = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -167,7 +178,7 @@ LL |     target_has_atomic = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:62:5
+  --> $DIR/well-known-values.rs:64:5
    |
 LL |     target_has_atomic_equal_alignment = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -176,7 +187,7 @@ LL |     target_has_atomic_equal_alignment = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:64:5
+  --> $DIR/well-known-values.rs:66:5
    |
 LL |     target_has_atomic_load_store = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -185,7 +196,7 @@ LL |     target_has_atomic_load_store = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:66:5
+  --> $DIR/well-known-values.rs:68:5
    |
 LL |     target_os = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -194,7 +205,7 @@ LL |     target_os = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:68:5
+  --> $DIR/well-known-values.rs:70:5
    |
 LL |     target_pointer_width = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -203,7 +214,7 @@ LL |     target_pointer_width = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:70:5
+  --> $DIR/well-known-values.rs:72:5
    |
 LL |     target_thread_local = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^----------------------
@@ -214,7 +225,7 @@ LL |     target_thread_local = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:72:5
+  --> $DIR/well-known-values.rs:74:5
    |
 LL |     target_vendor = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -223,7 +234,7 @@ LL |     target_vendor = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:74:5
+  --> $DIR/well-known-values.rs:76:5
    |
 LL |     test = "_UNEXPECTED_VALUE",
    |     ^^^^----------------------
@@ -234,7 +245,7 @@ LL |     test = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:76:5
+  --> $DIR/well-known-values.rs:78:5
    |
 LL |     ub_checks = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^----------------------
@@ -245,7 +256,7 @@ LL |     ub_checks = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:78:5
+  --> $DIR/well-known-values.rs:80:5
    |
 LL |     unix = "_UNEXPECTED_VALUE",
    |     ^^^^----------------------
@@ -256,7 +267,7 @@ LL |     unix = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:80:5
+  --> $DIR/well-known-values.rs:82:5
    |
 LL |     windows = "_UNEXPECTED_VALUE",
    |     ^^^^^^^----------------------
@@ -267,7 +278,7 @@ LL |     windows = "_UNEXPECTED_VALUE",
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `linuz`
-  --> $DIR/well-known-values.rs:86:7
+  --> $DIR/well-known-values.rs:88:7
    |
 LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux`
    |       ^^^^^^^^^^^^-------
@@ -277,5 +288,5 @@ LL | #[cfg(target_os = "linuz")] // testing that we suggest `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`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, `zkvm`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
-warning: 28 warnings emitted
+warning: 29 warnings emitted
 
diff --git a/tests/ui/coercion/coerce-loop-issue-122561.rs b/tests/ui/coercion/coerce-loop-issue-122561.rs
new file mode 100644
index 00000000000..e08884ad6a4
--- /dev/null
+++ b/tests/ui/coercion/coerce-loop-issue-122561.rs
@@ -0,0 +1,110 @@
+// Regression test for #122561
+
+fn for_infinite() -> bool {
+    for i in 0.. {
+    //~^ ERROR mismatched types
+        return false;
+    }
+}
+
+fn for_finite() -> String {
+    for i in 0..5 {
+    //~^ ERROR mismatched types
+        return String::from("test");
+    }
+}
+
+fn for_zero_times() -> bool {
+    for i in 0..0 {
+    //~^ ERROR mismatched types
+        return true;
+    }
+}
+
+fn for_never_type() -> ! {
+    for i in 0..5 {
+    //~^ ERROR mismatched types
+    }
+}
+
+// Entire function on a single line.
+// Tests that we format the suggestion
+// correctly in this case
+fn for_single_line() -> bool { for i in 0.. { return false; } }
+//~^ ERROR mismatched types
+
+// Loop in an anon const in function args
+// Tests that we:
+// a. deal properly with this complex case
+// b. format the suggestion correctly so
+//    that it's readable
+fn for_in_arg(a: &[(); for x in 0..2 {}]) -> bool {
+//~^ ERROR `for` is not allowed in a `const`
+//~| ERROR mismatched types
+    true
+}
+
+fn while_inifinite() -> bool {
+    while true {
+    //~^ ERROR mismatched types
+    //~| WARN denote infinite loops with `loop { ... }` [while_true]
+        return true;
+    }
+}
+
+fn while_finite() -> bool {
+    let mut i = 0;
+    while i < 3 {
+    //~^ ERROR mismatched types
+        i += 1;
+        return true;
+    }
+}
+
+fn while_zero_times() -> bool {
+    while false {
+    //~^ ERROR mismatched types
+        return true;
+    }
+}
+
+fn while_never_type() -> ! {
+    while true {
+    //~^ ERROR mismatched types
+    //~| WARN denote infinite loops with `loop { ... }` [while_true]
+    }
+}
+
+// No type mismatch error in this case
+fn loop_() -> bool {
+    loop {
+        return true;
+    }
+}
+
+const C: i32 = {
+    for i in 0.. {
+    //~^ ERROR `for` is not allowed in a `const`
+    //~| ERROR mismatched types
+    }
+};
+
+fn main() {
+    let _ = [10; {
+        for i in 0..5 {
+        //~^ ERROR `for` is not allowed in a `const`
+        //~| ERROR mismatched types
+        }
+    }];
+
+    let _ = [10; {
+        while false {
+        //~^ ERROR mismatched types
+        }
+    }];
+
+
+    let _ = |a: &[(); for x in 0..2 {}]| {};
+    //~^ ERROR `for` is not allowed in a `const`
+    //~| ERROR mismatched types
+}
diff --git a/tests/ui/coercion/coerce-loop-issue-122561.stderr b/tests/ui/coercion/coerce-loop-issue-122561.stderr
new file mode 100644
index 00000000000..0f77fd1364d
--- /dev/null
+++ b/tests/ui/coercion/coerce-loop-issue-122561.stderr
@@ -0,0 +1,299 @@
+warning: denote infinite loops with `loop { ... }`
+  --> $DIR/coerce-loop-issue-122561.rs:48:5
+   |
+LL |     while true {
+   |     ^^^^^^^^^^ help: use `loop`
+   |
+   = note: `#[warn(while_true)]` on by default
+
+warning: denote infinite loops with `loop { ... }`
+  --> $DIR/coerce-loop-issue-122561.rs:72:5
+   |
+LL |     while true {
+   |     ^^^^^^^^^^ help: use `loop`
+
+error[E0658]: `for` is not allowed in a `const`
+  --> $DIR/coerce-loop-issue-122561.rs:41:24
+   |
+LL | fn for_in_arg(a: &[(); for x in 0..2 {}]) -> bool {
+   |                        ^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
+   = help: add `#![feature(const_for)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: `for` is not allowed in a `const`
+  --> $DIR/coerce-loop-issue-122561.rs:86:5
+   |
+LL | /     for i in 0.. {
+LL | |
+LL | |
+LL | |     }
+   | |_____^
+   |
+   = note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
+   = help: add `#![feature(const_for)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: `for` is not allowed in a `const`
+  --> $DIR/coerce-loop-issue-122561.rs:94:9
+   |
+LL | /         for i in 0..5 {
+LL | |
+LL | |
+LL | |         }
+   | |_________^
+   |
+   = note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
+   = help: add `#![feature(const_for)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: `for` is not allowed in a `const`
+  --> $DIR/coerce-loop-issue-122561.rs:107:23
+   |
+LL |     let _ = |a: &[(); for x in 0..2 {}]| {};
+   |                       ^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
+   = help: add `#![feature(const_for)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-loop-issue-122561.rs:41:24
+   |
+LL | fn for_in_arg(a: &[(); for x in 0..2 {}]) -> bool {
+   |                        ^^^^^^^^^^^^^^^^ expected `usize`, found `()`
+   |
+   = note: `for` loops evaluate to unit type `()`
+help: consider returning a value here
+   |
+LL | fn for_in_arg(a: &[(); for x in 0..2 {} /* `usize` value */]) -> bool {
+   |                                         +++++++++++++++++++
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-loop-issue-122561.rs:86:5
+   |
+LL | /     for i in 0.. {
+LL | |
+LL | |
+LL | |     }
+   | |_____^ expected `i32`, found `()`
+   |
+   = note: `for` loops evaluate to unit type `()`
+help: consider returning a value here
+   |
+LL ~     }
+LL +     /* `i32` value */
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-loop-issue-122561.rs:4:5
+   |
+LL |   fn for_infinite() -> bool {
+   |                        ---- expected `bool` because of return type
+LL | /     for i in 0.. {
+LL | |
+LL | |         return false;
+LL | |     }
+   | |_____^ expected `bool`, found `()`
+   |
+   = note: `for` loops evaluate to unit type `()`
+help: consider returning a value here
+   |
+LL ~     }
+LL +     /* `bool` value */
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-loop-issue-122561.rs:11:5
+   |
+LL |   fn for_finite() -> String {
+   |                      ------ expected `String` because of return type
+LL | /     for i in 0..5 {
+LL | |
+LL | |         return String::from("test");
+LL | |     }
+   | |_____^ expected `String`, found `()`
+   |
+   = note: `for` loops evaluate to unit type `()`
+help: consider returning a value here
+   |
+LL ~     }
+LL +     /* `String` value */
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-loop-issue-122561.rs:18:5
+   |
+LL |   fn for_zero_times() -> bool {
+   |                          ---- expected `bool` because of return type
+LL | /     for i in 0..0 {
+LL | |
+LL | |         return true;
+LL | |     }
+   | |_____^ expected `bool`, found `()`
+   |
+   = note: `for` loops evaluate to unit type `()`
+help: consider returning a value here
+   |
+LL ~     }
+LL +     /* `bool` value */
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-loop-issue-122561.rs:25:5
+   |
+LL |   fn for_never_type() -> ! {
+   |                          - expected `!` because of return type
+LL | /     for i in 0..5 {
+LL | |
+LL | |     }
+   | |_____^ expected `!`, found `()`
+   |
+   = note:   expected type `!`
+           found unit type `()`
+   = note: `for` loops evaluate to unit type `()`
+help: consider adding a diverging expression here
+   |
+LL ~     }
+LL +     /* `loop {}` or `panic!("...")` */
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-loop-issue-122561.rs:33:32
+   |
+LL | fn for_single_line() -> bool { for i in 0.. { return false; } }
+   |                         ----   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()`
+   |                         |
+   |                         expected `bool` because of return type
+   |
+   = note: `for` loops evaluate to unit type `()`
+help: consider returning a value here
+   |
+LL | fn for_single_line() -> bool { for i in 0.. { return false; } /* `bool` value */ }
+   |                                                               ++++++++++++++++++
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-loop-issue-122561.rs:48:5
+   |
+LL |   fn while_inifinite() -> bool {
+   |                           ---- expected `bool` because of return type
+LL | /     while true {
+LL | |
+LL | |
+LL | |         return true;
+LL | |     }
+   | |_____^ expected `bool`, found `()`
+   |
+   = note: `while` loops evaluate to unit type `()`
+help: consider returning a value here
+   |
+LL ~     }
+LL +     /* `bool` value */
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-loop-issue-122561.rs:57:5
+   |
+LL |   fn while_finite() -> bool {
+   |                        ---- expected `bool` because of return type
+LL |       let mut i = 0;
+LL | /     while i < 3 {
+LL | |
+LL | |         i += 1;
+LL | |         return true;
+LL | |     }
+   | |_____^ expected `bool`, found `()`
+   |
+   = note: `while` loops evaluate to unit type `()`
+help: consider returning a value here
+   |
+LL ~     }
+LL +     /* `bool` value */
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-loop-issue-122561.rs:65:5
+   |
+LL |   fn while_zero_times() -> bool {
+   |                            ---- expected `bool` because of return type
+LL | /     while false {
+LL | |
+LL | |         return true;
+LL | |     }
+   | |_____^ expected `bool`, found `()`
+   |
+   = note: `while` loops evaluate to unit type `()`
+help: consider returning a value here
+   |
+LL ~     }
+LL +     /* `bool` value */
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-loop-issue-122561.rs:72:5
+   |
+LL |   fn while_never_type() -> ! {
+   |                            - expected `!` because of return type
+LL | /     while true {
+LL | |
+LL | |
+LL | |     }
+   | |_____^ expected `!`, found `()`
+   |
+   = note:   expected type `!`
+           found unit type `()`
+   = note: `while` loops evaluate to unit type `()`
+help: consider adding a diverging expression here
+   |
+LL ~     }
+LL +     /* `loop {}` or `panic!("...")` */
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-loop-issue-122561.rs:94:9
+   |
+LL | /         for i in 0..5 {
+LL | |
+LL | |
+LL | |         }
+   | |_________^ expected `usize`, found `()`
+   |
+   = note: `for` loops evaluate to unit type `()`
+help: consider returning a value here
+   |
+LL ~         }
+LL +         /* `usize` value */
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-loop-issue-122561.rs:101:9
+   |
+LL | /         while false {
+LL | |
+LL | |         }
+   | |_________^ expected `usize`, found `()`
+   |
+   = note: `while` loops evaluate to unit type `()`
+help: consider returning a value here
+   |
+LL ~         }
+LL +         /* `usize` value */
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-loop-issue-122561.rs:107:23
+   |
+LL |     let _ = |a: &[(); for x in 0..2 {}]| {};
+   |                       ^^^^^^^^^^^^^^^^ expected `usize`, found `()`
+   |
+   = note: `for` loops evaluate to unit type `()`
+help: consider returning a value here
+   |
+LL |     let _ = |a: &[(); for x in 0..2 {} /* `usize` value */]| {};
+   |                                        +++++++++++++++++++
+
+error: aborting due to 18 previous errors; 2 warnings emitted
+
+Some errors have detailed explanations: E0308, E0658.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs
index 408eaffccf7..d8852812492 100644
--- a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs
+++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs
@@ -28,8 +28,8 @@ struct S9;
 macro_rules! generate_s10 {
     ($expr: expr) => {
         #[cfg(feature = $expr)]
-        //~^ ERROR expected unsuffixed literal or identifier, found `concat!("nonexistent")`
-        //~| ERROR expected unsuffixed literal or identifier, found `concat!("nonexistent")`
+        //~^ ERROR expected unsuffixed literal, found `concat!("nonexistent")`
+        //~| ERROR expected unsuffixed literal, found `concat!("nonexistent")`
         struct S10;
     }
 }
diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr
index 12557ff6360..3dd0823389c 100644
--- a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr
+++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr
@@ -54,7 +54,7 @@ LL | #[cfg(a = b"hi")]
    |           |
    |           help: consider removing the prefix
 
-error: expected unsuffixed literal or identifier, found `concat!("nonexistent")`
+error: expected unsuffixed literal, found `concat!("nonexistent")`
   --> $DIR/cfg-attr-syntax-validation.rs:30:25
    |
 LL |         #[cfg(feature = $expr)]
@@ -65,7 +65,7 @@ LL | generate_s10!(concat!("nonexistent"));
    |
    = note: this error originates in the macro `generate_s10` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: expected unsuffixed literal or identifier, found `concat!("nonexistent")`
+error: expected unsuffixed literal, found `concat!("nonexistent")`
   --> $DIR/cfg-attr-syntax-validation.rs:30:25
    |
 LL |         #[cfg(feature = $expr)]
diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs
index 5e7845e4e82..fa3ca6928e3 100644
--- a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs
+++ b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs
@@ -2,7 +2,7 @@
 //@ aux-build:static_cross_crate.rs
 //@ normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)"
 //@ normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?(<imm>)?─*╼ )+ *│.*" -> "HEX_DUMP"
-#![feature(exclusive_range_pattern, half_open_range_patterns_in_slices)]
+#![feature(half_open_range_patterns_in_slices)]
 #![allow(static_mut_refs)]
 
 extern crate static_cross_crate;
diff --git a/tests/ui/consts/offset_from_ub.rs b/tests/ui/consts/offset_from_ub.rs
index 51163e650d6..e0dd2707915 100644
--- a/tests/ui/consts/offset_from_ub.rs
+++ b/tests/ui/consts/offset_from_ub.rs
@@ -42,7 +42,7 @@ pub const DIFFERENT_INT: isize = { // offset_from with two different integers: l
     let ptr1 = 8 as *const u8;
     let ptr2 = 16 as *const u8;
     unsafe { ptr_offset_from(ptr2, ptr1) } //~ERROR evaluation of constant value failed
-    //~| 0x8[noalloc] is a dangling pointer
+    //~| different pointers without provenance
 };
 
 const OUT_OF_BOUNDS_1: isize = {
@@ -81,13 +81,13 @@ pub const DIFFERENT_ALLOC_UNSIGNED: usize = {
 };
 
 pub const TOO_FAR_APART1: isize = {
-    let ptr1 = ptr::null::<u8>();
+    let ptr1 = &0u8 as *const u8;
     let ptr2 = ptr1.wrapping_add(isize::MAX as usize + 42);
     unsafe { ptr_offset_from(ptr2, ptr1) } //~ERROR evaluation of constant value failed
     //~| too far ahead
 };
 pub const TOO_FAR_APART2: isize = {
-    let ptr1 = ptr::null::<u8>();
+    let ptr1 = &0u8 as *const u8;
     let ptr2 = ptr1.wrapping_add(isize::MAX as usize + 42);
     unsafe { ptr_offset_from(ptr1, ptr2) } //~ERROR evaluation of constant value failed
     //~| too far before
@@ -100,7 +100,7 @@ const WRONG_ORDER_UNSIGNED: usize = {
     //~| first pointer has smaller offset than second: 0 < 8
 };
 pub const TOO_FAR_APART_UNSIGNED: usize = {
-    let ptr1 = ptr::null::<u8>();
+    let ptr1 = &0u8 as *const u8;
     let ptr2 = ptr1.wrapping_add(isize::MAX as usize + 42);
     // This would fit into a `usize` but we still don't allow it.
     unsafe { ptr_offset_from_unsigned(ptr2, ptr1) } //~ERROR evaluation of constant value failed
diff --git a/tests/ui/consts/offset_from_ub.stderr b/tests/ui/consts/offset_from_ub.stderr
index 4fbb2f00100..e3bac8d5e31 100644
--- a/tests/ui/consts/offset_from_ub.stderr
+++ b/tests/ui/consts/offset_from_ub.stderr
@@ -33,7 +33,7 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/offset_from_ub.rs:44:14
    |
 LL |     unsafe { ptr_offset_from(ptr2, ptr1) }
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: 0x8[noalloc] is a dangling pointer (it has no provenance)
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called on different pointers without provenance (i.e., without an associated allocation)
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/offset_from_ub.rs:53:14
@@ -86,7 +86,7 @@ LL |     unsafe { ptr_offset_from_unsigned(ptr2, ptr1) }
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-   = note: out-of-bounds `offset_from`: null pointer is a dangling pointer (it has no provenance)
+   = note: `ptr_offset_from` called on different pointers without provenance (i.e., without an associated allocation)
    |
 note: inside `std::ptr::const_ptr::<impl *const u8>::offset_from`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
@@ -99,7 +99,7 @@ LL |     unsafe { ptr2.offset_from(ptr1) }
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-   = note: out-of-bounds `offset_from`: null pointer is a dangling pointer (it has no provenance)
+   = note: `ptr_offset_from` called on different pointers without provenance (i.e., without an associated allocation)
    |
 note: inside `std::ptr::const_ptr::<impl *const u8>::offset_from`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
diff --git a/tests/ui/coroutine/break-inside-coroutine-issue-124495.rs b/tests/ui/coroutine/break-inside-coroutine-issue-124495.rs
new file mode 100644
index 00000000000..5d93db56722
--- /dev/null
+++ b/tests/ui/coroutine/break-inside-coroutine-issue-124495.rs
@@ -0,0 +1,26 @@
+//@ edition: 2024
+//@ compile-flags: -Z unstable-options
+
+#![feature(gen_blocks)]
+#![feature(async_closure)]
+
+async fn async_fn() {
+    break; //~ ERROR `break` inside `async` function
+}
+
+gen fn gen_fn() {
+    break; //~ ERROR `break` inside `gen` function
+}
+
+async gen fn async_gen_fn() {
+    break; //~ ERROR `break` inside `async gen` function
+}
+
+fn main() {
+    let _ = async { break; }; //~ ERROR `break` inside `async` block
+    let _ = async || { break; }; //~ ERROR `break` inside `async` closure
+
+    let _ = gen { break; }; //~ ERROR `break` inside `gen` block
+
+    let _ = async gen { break; }; //~ ERROR `break` inside `async gen` block
+}
diff --git a/tests/ui/coroutine/break-inside-coroutine-issue-124495.stderr b/tests/ui/coroutine/break-inside-coroutine-issue-124495.stderr
new file mode 100644
index 00000000000..a7f37fad35e
--- /dev/null
+++ b/tests/ui/coroutine/break-inside-coroutine-issue-124495.stderr
@@ -0,0 +1,69 @@
+error[E0267]: `break` inside `async` function
+  --> $DIR/break-inside-coroutine-issue-124495.rs:8:5
+   |
+LL |   async fn async_fn() {
+   |  _____________________-
+LL | |     break;
+   | |     ^^^^^ cannot `break` inside `async` function
+LL | | }
+   | |_- enclosing `async` function
+
+error[E0267]: `break` inside `gen` function
+  --> $DIR/break-inside-coroutine-issue-124495.rs:12:5
+   |
+LL |   gen fn gen_fn() {
+   |  _________________-
+LL | |     break;
+   | |     ^^^^^ cannot `break` inside `gen` function
+LL | | }
+   | |_- enclosing `gen` function
+
+error[E0267]: `break` inside `async gen` function
+  --> $DIR/break-inside-coroutine-issue-124495.rs:16:5
+   |
+LL |   async gen fn async_gen_fn() {
+   |  _____________________________-
+LL | |     break;
+   | |     ^^^^^ cannot `break` inside `async gen` function
+LL | | }
+   | |_- enclosing `async gen` function
+
+error[E0267]: `break` inside `async` block
+  --> $DIR/break-inside-coroutine-issue-124495.rs:20:21
+   |
+LL |     let _ = async { break; };
+   |             --------^^^^^---
+   |             |       |
+   |             |       cannot `break` inside `async` block
+   |             enclosing `async` block
+
+error[E0267]: `break` inside `async` closure
+  --> $DIR/break-inside-coroutine-issue-124495.rs:21:24
+   |
+LL |     let _ = async || { break; };
+   |                      --^^^^^---
+   |                      | |
+   |                      | cannot `break` inside `async` closure
+   |                      enclosing `async` closure
+
+error[E0267]: `break` inside `gen` block
+  --> $DIR/break-inside-coroutine-issue-124495.rs:23:19
+   |
+LL |     let _ = gen { break; };
+   |             ------^^^^^---
+   |             |     |
+   |             |     cannot `break` inside `gen` block
+   |             enclosing `gen` block
+
+error[E0267]: `break` inside `async gen` block
+  --> $DIR/break-inside-coroutine-issue-124495.rs:25:25
+   |
+LL |     let _ = async gen { break; };
+   |             ------------^^^^^---
+   |             |           |
+   |             |           cannot `break` inside `async gen` block
+   |             enclosing `async gen` block
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0267`.
diff --git a/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr b/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr
index 078c766deed..a030da5068c 100644
--- a/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr
+++ b/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr
@@ -4,7 +4,7 @@ error: expected unsuffixed literal, found `test`
 LL | #[deprecated(note = test)]
    |                     ^^^^
    |
-help: surround the identifier with quotation marks to parse it as a string
+help: surround the identifier with quotation marks to make it into a string literal
    |
 LL | #[deprecated(note = "test")]
    |                     +    +
diff --git a/tests/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr b/tests/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr
index d0b14ef94c1..e88a523ef4f 100644
--- a/tests/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr
+++ b/tests/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr
@@ -1,4 +1,4 @@
-error[E0369]: binary operation `==` cannot be applied to type `Error`
+error[E0369]: binary operation `==` cannot be applied to type `&Error`
   --> $DIR/derives-span-PartialEq-enum-struct-variant.rs:9:6
    |
 LL | #[derive(PartialEq)]
diff --git a/tests/ui/derives/derives-span-PartialEq-enum.stderr b/tests/ui/derives/derives-span-PartialEq-enum.stderr
index f69451ac793..80b225446b4 100644
--- a/tests/ui/derives/derives-span-PartialEq-enum.stderr
+++ b/tests/ui/derives/derives-span-PartialEq-enum.stderr
@@ -1,4 +1,4 @@
-error[E0369]: binary operation `==` cannot be applied to type `Error`
+error[E0369]: binary operation `==` cannot be applied to type `&Error`
   --> $DIR/derives-span-PartialEq-enum.rs:9:6
    |
 LL | #[derive(PartialEq)]
diff --git a/tests/ui/deriving/deriving-all-codegen.rs b/tests/ui/deriving/deriving-all-codegen.rs
index 498930fc0c6..6fa4f74f2a5 100644
--- a/tests/ui/deriving/deriving-all-codegen.rs
+++ b/tests/ui/deriving/deriving-all-codegen.rs
@@ -156,6 +156,20 @@ enum EnumGeneric<T, U> {
     Two(U),
 }
 
+// An enum that has variant, which does't implement `Copy`.
+#[derive(PartialEq)]
+enum NonCopyEnum {
+    // The `dyn NonCopyTrait` implements `PartialEq`, but it doesn't require `Copy`.
+    // So we cannot generate `PartialEq` with dereference.
+    NonCopyField(Box<dyn NonCopyTrait>),
+}
+trait NonCopyTrait {}
+impl PartialEq for dyn NonCopyTrait {
+    fn eq(&self, _other: &Self) -> bool {
+        true
+    }
+}
+
 // A union. Most builtin traits are not derivable for unions.
 #[derive(Clone, Copy)]
 pub union Union {
diff --git a/tests/ui/deriving/deriving-all-codegen.stdout b/tests/ui/deriving/deriving-all-codegen.stdout
index 9f8a9f30ff6..6b69b57c516 100644
--- a/tests/ui/deriving/deriving-all-codegen.stdout
+++ b/tests/ui/deriving/deriving-all-codegen.stdout
@@ -876,7 +876,7 @@ impl ::core::cmp::PartialEq for Enum1 {
     fn eq(&self, other: &Enum1) -> bool {
         match (self, other) {
             (Enum1::Single { x: __self_0 }, Enum1::Single { x: __arg1_0 }) =>
-                *__self_0 == *__arg1_0,
+                __self_0 == __arg1_0,
         }
     }
 }
@@ -1119,10 +1119,10 @@ impl ::core::cmp::PartialEq for Mixed {
         __self_discr == __arg1_discr &&
             match (self, other) {
                 (Mixed::R(__self_0), Mixed::R(__arg1_0)) =>
-                    *__self_0 == *__arg1_0,
+                    __self_0 == __arg1_0,
                 (Mixed::S { d1: __self_0, d2: __self_1 }, Mixed::S {
                     d1: __arg1_0, d2: __arg1_1 }) =>
-                    *__self_0 == *__arg1_0 && *__self_1 == *__arg1_1,
+                    __self_0 == __arg1_0 && __self_1 == __arg1_1,
                 _ => true,
             }
     }
@@ -1245,11 +1245,11 @@ impl ::core::cmp::PartialEq for Fielded {
         __self_discr == __arg1_discr &&
             match (self, other) {
                 (Fielded::X(__self_0), Fielded::X(__arg1_0)) =>
-                    *__self_0 == *__arg1_0,
+                    __self_0 == __arg1_0,
                 (Fielded::Y(__self_0), Fielded::Y(__arg1_0)) =>
-                    *__self_0 == *__arg1_0,
+                    __self_0 == __arg1_0,
                 (Fielded::Z(__self_0), Fielded::Z(__arg1_0)) =>
-                    *__self_0 == *__arg1_0,
+                    __self_0 == __arg1_0,
                 _ => unsafe { ::core::intrinsics::unreachable() }
             }
     }
@@ -1368,9 +1368,9 @@ impl<T: ::core::cmp::PartialEq, U: ::core::cmp::PartialEq>
         __self_discr == __arg1_discr &&
             match (self, other) {
                 (EnumGeneric::One(__self_0), EnumGeneric::One(__arg1_0)) =>
-                    *__self_0 == *__arg1_0,
+                    __self_0 == __arg1_0,
                 (EnumGeneric::Two(__self_0), EnumGeneric::Two(__arg1_0)) =>
-                    *__self_0 == *__arg1_0,
+                    __self_0 == __arg1_0,
                 _ => unsafe { ::core::intrinsics::unreachable() }
             }
     }
@@ -1426,6 +1426,30 @@ impl<T: ::core::cmp::Ord, U: ::core::cmp::Ord> ::core::cmp::Ord for
     }
 }
 
+// An enum that has variant, which does't implement `Copy`.
+enum NonCopyEnum {
+
+    // The `dyn NonCopyTrait` implements `PartialEq`, but it doesn't require `Copy`.
+    // So we cannot generate `PartialEq` with dereference.
+    NonCopyField(Box<dyn NonCopyTrait>),
+}
+#[automatically_derived]
+impl ::core::marker::StructuralPartialEq for NonCopyEnum { }
+#[automatically_derived]
+impl ::core::cmp::PartialEq for NonCopyEnum {
+    #[inline]
+    fn eq(&self, other: &NonCopyEnum) -> bool {
+        match (self, other) {
+            (NonCopyEnum::NonCopyField(__self_0),
+                NonCopyEnum::NonCopyField(__arg1_0)) => __self_0 == __arg1_0,
+        }
+    }
+}
+trait NonCopyTrait {}
+impl PartialEq for dyn NonCopyTrait {
+    fn eq(&self, _other: &Self) -> bool { true }
+}
+
 // A union. Most builtin traits are not derivable for unions.
 pub union Union {
     pub b: bool,
diff --git a/tests/ui/diagnostic_namespace/auxiliary/bad_on_unimplemented.rs b/tests/ui/diagnostic_namespace/auxiliary/bad_on_unimplemented.rs
new file mode 100644
index 00000000000..e44c7e4e850
--- /dev/null
+++ b/tests/ui/diagnostic_namespace/auxiliary/bad_on_unimplemented.rs
@@ -0,0 +1,26 @@
+#[diagnostic::on_unimplemented(aa = "broken")]
+pub trait MissingAttr {}
+
+#[diagnostic::on_unimplemented(label = "a", label = "b")]
+pub trait DuplicateAttr {}
+
+#[diagnostic::on_unimplemented = "broken"]
+pub trait NotMetaList {}
+
+#[diagnostic::on_unimplemented]
+pub trait Empty {}
+
+#[diagnostic::on_unimplemented {}]
+pub trait WrongDelim {}
+
+#[diagnostic::on_unimplemented(label = "{A:.3}")]
+pub trait BadFormatter<A> {}
+
+#[diagnostic::on_unimplemented(label = "test {}")]
+pub trait NoImplicitArgs {}
+
+#[diagnostic::on_unimplemented(label = "{missing}")]
+pub trait MissingArg {}
+
+#[diagnostic::on_unimplemented(label = "{_}")]
+pub trait BadArg {}
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr
new file mode 100644
index 00000000000..a4d4b7b359e
--- /dev/null
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr
@@ -0,0 +1,20 @@
+error[E0277]: the trait bound `*mut (): Foo` is not satisfied
+  --> $DIR/simple.rs:19:17
+   |
+LL |     needs_foo::<*mut ()>();
+   |                 ^^^^^^^ the trait `Send` is not implemented for `*mut ()`, which is required by `*mut (): Foo`
+   |
+note: required for `*mut ()` to implement `Foo`
+  --> $DIR/simple.rs:10:9
+   |
+LL | impl<T> Foo for T where T: Send {}
+   |         ^^^     ^          ---- unsatisfied trait bound introduced here
+note: required by a bound in `needs_foo`
+  --> $DIR/simple.rs:14:17
+   |
+LL | fn needs_foo<T: Foo>() {}
+   |                 ^^^ required by this bound in `needs_foo`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr
new file mode 100644
index 00000000000..1341ca8175a
--- /dev/null
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `*mut (): Foo` is not satisfied
+  --> $DIR/simple.rs:19:17
+   |
+LL |     needs_foo::<*mut ()>();
+   |                 ^^^^^^^ the trait `Foo` is not implemented for `*mut ()`
+   |
+note: required by a bound in `needs_foo`
+  --> $DIR/simple.rs:14:17
+   |
+LL | fn needs_foo<T: Foo>() {}
+   |                 ^^^ required by this bound in `needs_foo`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs b/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs
new file mode 100644
index 00000000000..15ff80ae4d9
--- /dev/null
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs
@@ -0,0 +1,23 @@
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+#![feature(do_not_recommend)]
+
+trait Foo {}
+
+#[do_not_recommend]
+impl<T> Foo for T where T: Send {}
+//[current]~^ NOTE required for `*mut ()` to implement `Foo`
+//[current]~| NOTE unsatisfied trait bound introduced here
+
+fn needs_foo<T: Foo>() {}
+//~^ NOTE required by a bound in `needs_foo`
+//~| NOTE required by this bound in `needs_foo`
+
+fn main() {
+    needs_foo::<*mut ()>();
+    //~^ ERROR the trait bound `*mut (): Foo` is not satisfied
+    //[current]~| NOTE the trait `Send` is not implemented for `*mut ()`
+    //[next]~| NOTE the trait `Foo` is not implemented for `*mut ()`
+}
diff --git a/tests/ui/diagnostic_namespace/malformed_foreign_on_unimplemented.rs b/tests/ui/diagnostic_namespace/malformed_foreign_on_unimplemented.rs
new file mode 100644
index 00000000000..8b7467a17d0
--- /dev/null
+++ b/tests/ui/diagnostic_namespace/malformed_foreign_on_unimplemented.rs
@@ -0,0 +1,31 @@
+//@ edition:2021
+//@ aux-build:bad_on_unimplemented.rs
+
+// Do not ICE when encountering a malformed `#[diagnostic::on_unimplemented]` annotation in a
+// dependency when incorrectly used (#124651).
+
+extern crate bad_on_unimplemented;
+
+use bad_on_unimplemented::*;
+
+fn missing_attr<T: MissingAttr>(_: T) {}
+fn duplicate_attr<T: DuplicateAttr>(_: T) {}
+fn not_meta_list<T: NotMetaList>(_: T) {}
+fn empty<T: Empty>(_: T) {}
+fn wrong_delim<T: WrongDelim>(_: T) {}
+fn bad_formatter<T: BadFormatter<()>>(_: T) {}
+fn no_implicit_args<T: NoImplicitArgs>(_: T) {}
+fn missing_arg<T: MissingArg>(_: T) {}
+fn bad_arg<T: BadArg>(_: T) {}
+
+fn main() {
+    missing_attr(()); //~ ERROR E0277
+    duplicate_attr(()); //~ ERROR E0277
+    not_meta_list(()); //~ ERROR E0277
+    empty(()); //~ ERROR E0277
+    wrong_delim(()); //~ ERROR E0277
+    bad_formatter(()); //~ ERROR E0277
+    no_implicit_args(()); //~ ERROR E0277
+    missing_arg(()); //~ ERROR E0277
+    bad_arg(()); //~ ERROR E0277
+}
diff --git a/tests/ui/diagnostic_namespace/malformed_foreign_on_unimplemented.stderr b/tests/ui/diagnostic_namespace/malformed_foreign_on_unimplemented.stderr
new file mode 100644
index 00000000000..c3e56550b70
--- /dev/null
+++ b/tests/ui/diagnostic_namespace/malformed_foreign_on_unimplemented.stderr
@@ -0,0 +1,134 @@
+error[E0277]: the trait bound `(): bad_on_unimplemented::MissingAttr` is not satisfied
+  --> $DIR/malformed_foreign_on_unimplemented.rs:22:18
+   |
+LL |     missing_attr(());
+   |     ------------ ^^ the trait `bad_on_unimplemented::MissingAttr` is not implemented for `()`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `missing_attr`
+  --> $DIR/malformed_foreign_on_unimplemented.rs:11:20
+   |
+LL | fn missing_attr<T: MissingAttr>(_: T) {}
+   |                    ^^^^^^^^^^^ required by this bound in `missing_attr`
+
+error[E0277]: the trait bound `(): bad_on_unimplemented::DuplicateAttr` is not satisfied
+  --> $DIR/malformed_foreign_on_unimplemented.rs:23:20
+   |
+LL |     duplicate_attr(());
+   |     -------------- ^^ a
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `bad_on_unimplemented::DuplicateAttr` is not implemented for `()`
+note: required by a bound in `duplicate_attr`
+  --> $DIR/malformed_foreign_on_unimplemented.rs:12:22
+   |
+LL | fn duplicate_attr<T: DuplicateAttr>(_: T) {}
+   |                      ^^^^^^^^^^^^^ required by this bound in `duplicate_attr`
+
+error[E0277]: the trait bound `(): bad_on_unimplemented::NotMetaList` is not satisfied
+  --> $DIR/malformed_foreign_on_unimplemented.rs:24:19
+   |
+LL |     not_meta_list(());
+   |     ------------- ^^ the trait `bad_on_unimplemented::NotMetaList` is not implemented for `()`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `not_meta_list`
+  --> $DIR/malformed_foreign_on_unimplemented.rs:13:21
+   |
+LL | fn not_meta_list<T: NotMetaList>(_: T) {}
+   |                     ^^^^^^^^^^^ required by this bound in `not_meta_list`
+
+error[E0277]: the trait bound `(): bad_on_unimplemented::Empty` is not satisfied
+  --> $DIR/malformed_foreign_on_unimplemented.rs:25:11
+   |
+LL |     empty(());
+   |     ----- ^^ the trait `bad_on_unimplemented::Empty` is not implemented for `()`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `empty`
+  --> $DIR/malformed_foreign_on_unimplemented.rs:14:13
+   |
+LL | fn empty<T: Empty>(_: T) {}
+   |             ^^^^^ required by this bound in `empty`
+
+error[E0277]: the trait bound `(): bad_on_unimplemented::WrongDelim` is not satisfied
+  --> $DIR/malformed_foreign_on_unimplemented.rs:26:17
+   |
+LL |     wrong_delim(());
+   |     ----------- ^^ the trait `bad_on_unimplemented::WrongDelim` is not implemented for `()`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `wrong_delim`
+  --> $DIR/malformed_foreign_on_unimplemented.rs:15:19
+   |
+LL | fn wrong_delim<T: WrongDelim>(_: T) {}
+   |                   ^^^^^^^^^^ required by this bound in `wrong_delim`
+
+error[E0277]: the trait bound `(): bad_on_unimplemented::BadFormatter<()>` is not satisfied
+  --> $DIR/malformed_foreign_on_unimplemented.rs:27:19
+   |
+LL |     bad_formatter(());
+   |     ------------- ^^ ()
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `bad_on_unimplemented::BadFormatter<()>` is not implemented for `()`
+note: required by a bound in `bad_formatter`
+  --> $DIR/malformed_foreign_on_unimplemented.rs:16:21
+   |
+LL | fn bad_formatter<T: BadFormatter<()>>(_: T) {}
+   |                     ^^^^^^^^^^^^^^^^ required by this bound in `bad_formatter`
+
+error[E0277]: the trait bound `(): bad_on_unimplemented::NoImplicitArgs` is not satisfied
+  --> $DIR/malformed_foreign_on_unimplemented.rs:28:22
+   |
+LL |     no_implicit_args(());
+   |     ---------------- ^^ test {}
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `bad_on_unimplemented::NoImplicitArgs` is not implemented for `()`
+note: required by a bound in `no_implicit_args`
+  --> $DIR/malformed_foreign_on_unimplemented.rs:17:24
+   |
+LL | fn no_implicit_args<T: NoImplicitArgs>(_: T) {}
+   |                        ^^^^^^^^^^^^^^ required by this bound in `no_implicit_args`
+
+error[E0277]: the trait bound `(): bad_on_unimplemented::MissingArg` is not satisfied
+  --> $DIR/malformed_foreign_on_unimplemented.rs:29:17
+   |
+LL |     missing_arg(());
+   |     ----------- ^^ {missing}
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `bad_on_unimplemented::MissingArg` is not implemented for `()`
+note: required by a bound in `missing_arg`
+  --> $DIR/malformed_foreign_on_unimplemented.rs:18:19
+   |
+LL | fn missing_arg<T: MissingArg>(_: T) {}
+   |                   ^^^^^^^^^^ required by this bound in `missing_arg`
+
+error[E0277]: the trait bound `(): bad_on_unimplemented::BadArg` is not satisfied
+  --> $DIR/malformed_foreign_on_unimplemented.rs:30:13
+   |
+LL |     bad_arg(());
+   |     ------- ^^ {_}
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `bad_on_unimplemented::BadArg` is not implemented for `()`
+note: required by a bound in `bad_arg`
+  --> $DIR/malformed_foreign_on_unimplemented.rs:19:15
+   |
+LL | fn bad_arg<T: BadArg>(_: T) {}
+   |               ^^^^^^ required by this bound in `bad_arg`
+
+error: aborting due to 9 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/did_you_mean/compatible-variants.stderr b/tests/ui/did_you_mean/compatible-variants.stderr
index f2bbd8ced8f..2c75537ca19 100644
--- a/tests/ui/did_you_mean/compatible-variants.stderr
+++ b/tests/ui/did_you_mean/compatible-variants.stderr
@@ -11,6 +11,7 @@ LL | |     }
    |
    = note:   expected enum `Option<()>`
            found unit type `()`
+   = note: `while` loops evaluate to unit type `()`
 help: try adding an expression at the end of the block
    |
 LL ~     }
@@ -49,6 +50,7 @@ LL | |     }
    |
    = note:   expected enum `Option<()>`
            found unit type `()`
+   = note: `for` loops evaluate to unit type `()`
 help: try adding an expression at the end of the block
    |
 LL ~     }
@@ -106,6 +108,7 @@ LL |         while false {}
    |
    = note:   expected enum `Option<()>`
            found unit type `()`
+   = note: `while` loops evaluate to unit type `()`
 help: try adding an expression at the end of the block
    |
 LL ~         while false {}
diff --git a/tests/ui/dyn-star/param-env-region-infer.current.stderr b/tests/ui/dyn-star/param-env-region-infer.current.stderr
index b50117c1efb..6e464c17014 100644
--- a/tests/ui/dyn-star/param-env-region-infer.current.stderr
+++ b/tests/ui/dyn-star/param-env-region-infer.current.stderr
@@ -1,5 +1,5 @@
 error[E0282]: type annotations needed
-  --> $DIR/param-env-region-infer.rs:19:10
+  --> $DIR/param-env-region-infer.rs:20:10
    |
 LL |     t as _
    |          ^ cannot infer type
diff --git a/tests/ui/dyn-star/param-env-region-infer.rs b/tests/ui/dyn-star/param-env-region-infer.rs
index c53861065c7..842964ad284 100644
--- a/tests/ui/dyn-star/param-env-region-infer.rs
+++ b/tests/ui/dyn-star/param-env-region-infer.rs
@@ -1,9 +1,10 @@
 //@ revisions: current
 //@ incremental
 
-// FIXME(-Znext-solver): THis currently results in unstable query results:
+// FIXME(-Znext-solver): This currently results in unstable query results:
 // `normalizes-to(opaque, opaque)` changes from `Maybe(Ambiguous)` to `Maybe(Overflow)`
 // once the hidden type of the opaque is already defined to be itself.
+//@ unused-revision-names: next
 
 // checks that we don't ICE if there are region inference variables in the environment
 // when computing `PointerLike` builtin candidates.
diff --git a/tests/ui/feature-gates/feature-gate-exclusive-range-pattern.rs b/tests/ui/feature-gates/feature-gate-exclusive-range-pattern.rs
deleted file mode 100644
index ded08b93fe8..00000000000
--- a/tests/ui/feature-gates/feature-gate-exclusive-range-pattern.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-pub fn main() {
-    match 22 {
-        0 .. 3 => {} //~ ERROR exclusive range pattern syntax is experimental
-        _ => {}
-    }
-}
diff --git a/tests/ui/feature-gates/feature-gate-exclusive-range-pattern.stderr b/tests/ui/feature-gates/feature-gate-exclusive-range-pattern.stderr
deleted file mode 100644
index 5e3d34aa9f3..00000000000
--- a/tests/ui/feature-gates/feature-gate-exclusive-range-pattern.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0658]: exclusive range pattern syntax is experimental
-  --> $DIR/feature-gate-exclusive-range-pattern.rs:3:9
-   |
-LL |         0 .. 3 => {}
-   |         ^^^^^^
-   |
-   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
-   = help: add `#![feature(exclusive_range_pattern)]` 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: use an inclusive range pattern, like N..=M
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-result_ffi_guarantees.rs b/tests/ui/feature-gates/feature-gate-result_ffi_guarantees.rs
new file mode 100644
index 00000000000..dda317aecc3
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-result_ffi_guarantees.rs
@@ -0,0 +1,99 @@
+#![allow(dead_code)]
+#![deny(improper_ctypes)]
+#![feature(ptr_internals)]
+
+use std::num;
+
+enum Z {}
+
+#[repr(transparent)]
+struct TransparentStruct<T>(T, std::marker::PhantomData<Z>);
+
+#[repr(transparent)]
+enum TransparentEnum<T> {
+    Variant(T, std::marker::PhantomData<Z>),
+}
+
+struct NoField;
+
+extern "C" {
+    fn result_ref_t(x: Result<&'static u8, ()>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_fn_t(x: Result<extern "C" fn(), ()>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_nonnull_t(x: Result<std::ptr::NonNull<u8>, ()>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_unique_t(x: Result<std::ptr::Unique<u8>, ()>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_nonzero_u8_t(x: Result<num::NonZero<u8>, ()>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_nonzero_u16_t(x: Result<num::NonZero<u16>, ()>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_nonzero_u32_t(x: Result<num::NonZero<u32>, ()>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_nonzero_u64_t(x: Result<num::NonZero<u64>, ()>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_nonzero_usize_t(x: Result<num::NonZero<usize>, ()>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_nonzero_i8_t(x: Result<num::NonZero<i8>, ()>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_nonzero_i16_t(x: Result<num::NonZero<i16>, ()>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_nonzero_i32_t(x: Result<num::NonZero<i32>, ()>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_nonzero_i64_t(x: Result<num::NonZero<i64>, ()>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_nonzero_isize_t(x: Result<num::NonZero<isize>, ()>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_transparent_struct_t(x: Result<TransparentStruct<num::NonZero<u8>>, ()>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_transparent_enum_t(x: Result<TransparentEnum<num::NonZero<u8>>, ()>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_phantom_t(x: Result<num::NonZero<u8>, std::marker::PhantomData<()>>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_1zst_exhaustive_no_variant_t(x: Result<num::NonZero<u8>, Z>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_1zst_exhaustive_no_field_t(x: Result<num::NonZero<u8>, NoField>);
+    //~^ ERROR `extern` block uses type `Result
+
+    fn result_ref_e(x: Result<(), &'static u8>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_fn_e(x: Result<(), extern "C" fn()>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_nonnull_e(x: Result<(), std::ptr::NonNull<u8>>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_unique_e(x: Result<(), std::ptr::Unique<u8>>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_nonzero_u8_e(x: Result<(), num::NonZero<u8>>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_nonzero_u16_e(x: Result<(), num::NonZero<u16>>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_nonzero_u32_e(x: Result<(), num::NonZero<u32>>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_nonzero_u64_e(x: Result<(), num::NonZero<u64>>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_nonzero_usize_e(x: Result<(), num::NonZero<usize>>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_nonzero_i8_e(x: Result<(), num::NonZero<i8>>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_nonzero_i16_e(x: Result<(), num::NonZero<i16>>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_nonzero_i32_e(x: Result<(), num::NonZero<i32>>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_nonzero_i64_e(x: Result<(), num::NonZero<i64>>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_nonzero_isize_e(x: Result<(), num::NonZero<isize>>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_transparent_struct_e(x: Result<(), TransparentStruct<num::NonZero<u8>>>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_transparent_enum_e(x: Result<(), TransparentEnum<num::NonZero<u8>>>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_phantom_e(x: Result<num::NonZero<u8>, std::marker::PhantomData<()>>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_1zst_exhaustive_no_variant_e(x: Result<Z, num::NonZero<u8>>);
+    //~^ ERROR `extern` block uses type `Result
+    fn result_1zst_exhaustive_no_field_e(x: Result<NoField, num::NonZero<u8>>);
+    //~^ ERROR `extern` block uses type `Result
+}
+
+pub fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-result_ffi_guarantees.stderr b/tests/ui/feature-gates/feature-gate-result_ffi_guarantees.stderr
new file mode 100644
index 00000000000..94416eb99c8
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-result_ffi_guarantees.stderr
@@ -0,0 +1,349 @@
+error: `extern` block uses type `Result<&u8, ()>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:20:24
+   |
+LL |     fn result_ref_t(x: Result<&'static u8, ()>);
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+note: the lint level is defined here
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:2:9
+   |
+LL | #![deny(improper_ctypes)]
+   |         ^^^^^^^^^^^^^^^
+
+error: `extern` block uses type `Result<extern "C" fn(), ()>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:22:23
+   |
+LL |     fn result_fn_t(x: Result<extern "C" fn(), ()>);
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<NonNull<u8>, ()>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:24:28
+   |
+LL |     fn result_nonnull_t(x: Result<std::ptr::NonNull<u8>, ()>);
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<Unique<u8>, ()>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:26:27
+   |
+LL |     fn result_unique_t(x: Result<std::ptr::Unique<u8>, ()>);
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<NonZero<u8>, ()>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:28:31
+   |
+LL |     fn result_nonzero_u8_t(x: Result<num::NonZero<u8>, ()>);
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<NonZero<u16>, ()>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:30:32
+   |
+LL |     fn result_nonzero_u16_t(x: Result<num::NonZero<u16>, ()>);
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<NonZero<u32>, ()>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:32:32
+   |
+LL |     fn result_nonzero_u32_t(x: Result<num::NonZero<u32>, ()>);
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<NonZero<u64>, ()>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:34:32
+   |
+LL |     fn result_nonzero_u64_t(x: Result<num::NonZero<u64>, ()>);
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<NonZero<usize>, ()>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:36:34
+   |
+LL |     fn result_nonzero_usize_t(x: Result<num::NonZero<usize>, ()>);
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<NonZero<i8>, ()>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:38:31
+   |
+LL |     fn result_nonzero_i8_t(x: Result<num::NonZero<i8>, ()>);
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<NonZero<i16>, ()>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:40:32
+   |
+LL |     fn result_nonzero_i16_t(x: Result<num::NonZero<i16>, ()>);
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<NonZero<i32>, ()>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:42:32
+   |
+LL |     fn result_nonzero_i32_t(x: Result<num::NonZero<i32>, ()>);
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<NonZero<i64>, ()>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:44:32
+   |
+LL |     fn result_nonzero_i64_t(x: Result<num::NonZero<i64>, ()>);
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<NonZero<isize>, ()>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:46:34
+   |
+LL |     fn result_nonzero_isize_t(x: Result<num::NonZero<isize>, ()>);
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<TransparentStruct<NonZero<u8>>, ()>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:48:39
+   |
+LL |     fn result_transparent_struct_t(x: Result<TransparentStruct<num::NonZero<u8>>, ()>);
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<TransparentEnum<NonZero<u8>>, ()>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:50:37
+   |
+LL |     fn result_transparent_enum_t(x: Result<TransparentEnum<num::NonZero<u8>>, ()>);
+   |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<NonZero<u8>, PhantomData<()>>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:52:28
+   |
+LL |     fn result_phantom_t(x: Result<num::NonZero<u8>, std::marker::PhantomData<()>>);
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<NonZero<u8>, Z>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:54:47
+   |
+LL |     fn result_1zst_exhaustive_no_variant_t(x: Result<num::NonZero<u8>, Z>);
+   |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<NonZero<u8>, NoField>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:56:45
+   |
+LL |     fn result_1zst_exhaustive_no_field_t(x: Result<num::NonZero<u8>, NoField>);
+   |                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<(), &u8>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:59:24
+   |
+LL |     fn result_ref_e(x: Result<(), &'static u8>);
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<(), extern "C" fn()>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:61:23
+   |
+LL |     fn result_fn_e(x: Result<(), extern "C" fn()>);
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<(), NonNull<u8>>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:63:28
+   |
+LL |     fn result_nonnull_e(x: Result<(), std::ptr::NonNull<u8>>);
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<(), Unique<u8>>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:65:27
+   |
+LL |     fn result_unique_e(x: Result<(), std::ptr::Unique<u8>>);
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<(), NonZero<u8>>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:67:31
+   |
+LL |     fn result_nonzero_u8_e(x: Result<(), num::NonZero<u8>>);
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<(), NonZero<u16>>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:69:32
+   |
+LL |     fn result_nonzero_u16_e(x: Result<(), num::NonZero<u16>>);
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<(), NonZero<u32>>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:71:32
+   |
+LL |     fn result_nonzero_u32_e(x: Result<(), num::NonZero<u32>>);
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<(), NonZero<u64>>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:73:32
+   |
+LL |     fn result_nonzero_u64_e(x: Result<(), num::NonZero<u64>>);
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<(), NonZero<usize>>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:75:34
+   |
+LL |     fn result_nonzero_usize_e(x: Result<(), num::NonZero<usize>>);
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<(), NonZero<i8>>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:77:31
+   |
+LL |     fn result_nonzero_i8_e(x: Result<(), num::NonZero<i8>>);
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<(), NonZero<i16>>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:79:32
+   |
+LL |     fn result_nonzero_i16_e(x: Result<(), num::NonZero<i16>>);
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<(), NonZero<i32>>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:81:32
+   |
+LL |     fn result_nonzero_i32_e(x: Result<(), num::NonZero<i32>>);
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<(), NonZero<i64>>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:83:32
+   |
+LL |     fn result_nonzero_i64_e(x: Result<(), num::NonZero<i64>>);
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<(), NonZero<isize>>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:85:34
+   |
+LL |     fn result_nonzero_isize_e(x: Result<(), num::NonZero<isize>>);
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<(), TransparentStruct<NonZero<u8>>>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:87:39
+   |
+LL |     fn result_transparent_struct_e(x: Result<(), TransparentStruct<num::NonZero<u8>>>);
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<(), TransparentEnum<NonZero<u8>>>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:89:37
+   |
+LL |     fn result_transparent_enum_e(x: Result<(), TransparentEnum<num::NonZero<u8>>>);
+   |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<NonZero<u8>, PhantomData<()>>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:91:28
+   |
+LL |     fn result_phantom_e(x: Result<num::NonZero<u8>, std::marker::PhantomData<()>>);
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<Z, NonZero<u8>>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:93:47
+   |
+LL |     fn result_1zst_exhaustive_no_variant_e(x: Result<Z, num::NonZero<u8>>);
+   |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<NoField, NonZero<u8>>`, which is not FFI-safe
+  --> $DIR/feature-gate-result_ffi_guarantees.rs:95:45
+   |
+LL |     fn result_1zst_exhaustive_no_field_e(x: Result<NoField, num::NonZero<u8>>);
+   |                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: aborting due to 38 previous errors
+
diff --git a/tests/ui/for-loop-while/break-while-condition.stderr b/tests/ui/for-loop-while/break-while-condition.stderr
index 48b29f44fa1..07a57424575 100644
--- a/tests/ui/for-loop-while/break-while-condition.stderr
+++ b/tests/ui/for-loop-while/break-while-condition.stderr
@@ -20,6 +20,12 @@ LL | |             }
    |
    = note:   expected type `!`
            found unit type `()`
+   = note: `while` loops evaluate to unit type `()`
+help: consider adding a diverging expression here
+   |
+LL ~             }
+LL +             /* `loop {}` or `panic!("...")` */
+   |
 
 error[E0308]: mismatched types
   --> $DIR/break-while-condition.rs:24:13
@@ -31,14 +37,12 @@ LL | |             }
    |
    = note:   expected type `!`
            found unit type `()`
-note: the function expects a value to always be returned, but loops might run zero times
-  --> $DIR/break-while-condition.rs:24:13
+   = note: `while` loops evaluate to unit type `()`
+help: consider adding a diverging expression here
+   |
+LL ~             }
+LL +             /* `loop {}` or `panic!("...")` */
    |
-LL |             while false {
-   |             ^^^^^^^^^^^ this might have zero elements to iterate on
-LL |                 return
-   |                 ------ if the loop doesn't execute, this value would never get returned
-   = help: return a value for the case when the loop has zero elements to iterate on, otherwise consider changing the return type to account for that possibility
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.rs b/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.rs
index b2e9ffb5772..dd4fe7c78b7 100644
--- a/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.rs
+++ b/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.rs
@@ -1,5 +1,4 @@
 #![feature(half_open_range_patterns_in_slices)]
-#![feature(exclusive_range_pattern)]
 
 fn main() {
     match [5..4, 99..105, 43..44] {
diff --git a/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr b/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr
index 357d3a4a124..5ee31a0a23b 100644
--- a/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr
+++ b/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/exclusive_range_pattern_syntax_collision.rs:6:13
+  --> $DIR/exclusive_range_pattern_syntax_collision.rs:5:13
    |
 LL |     match [5..4, 99..105, 43..44] {
    |           ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
diff --git a/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.rs b/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.rs
index 20f4d8f882a..1b06181464f 100644
--- a/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.rs
+++ b/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.rs
@@ -1,5 +1,4 @@
 #![feature(half_open_range_patterns_in_slices)]
-#![feature(exclusive_range_pattern)]
 
 fn main() {
     match [5..4, 99..105, 43..44] {
diff --git a/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr b/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr
index 6f56ecd4c1c..9ad6d5363ad 100644
--- a/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr
+++ b/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr
@@ -1,11 +1,11 @@
 error[E0527]: pattern requires 2 elements but array has 3
-  --> $DIR/exclusive_range_pattern_syntax_collision2.rs:6:9
+  --> $DIR/exclusive_range_pattern_syntax_collision2.rs:5:9
    |
 LL |         [_, 99..] => {},
    |         ^^^^^^^^^ expected 3 elements
 
 error[E0308]: mismatched types
-  --> $DIR/exclusive_range_pattern_syntax_collision2.rs:6:13
+  --> $DIR/exclusive_range_pattern_syntax_collision2.rs:5:13
    |
 LL |     match [5..4, 99..105, 43..44] {
    |           ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
diff --git a/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.rs b/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.rs
index 14ca07d0a53..a3aca8dfac7 100644
--- a/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.rs
+++ b/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.rs
@@ -1,5 +1,3 @@
-#![feature(exclusive_range_pattern)]
-
 fn main() {
     match [5..4, 99..105, 43..44] {
         [..9, 99..100, _] => {},
diff --git a/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr b/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr
index b9b272c4c7c..4a4a4c00b2e 100644
--- a/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr
+++ b/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:12
+  --> $DIR/exclusive_range_pattern_syntax_collision3.rs:3:12
    |
 LL |     match [5..4, 99..105, 43..44] {
    |           ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
@@ -10,7 +10,7 @@ LL |         [..9, 99..100, _] => {},
                 found type `{integer}`
 
 error[E0308]: mismatched types
-  --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:15
+  --> $DIR/exclusive_range_pattern_syntax_collision3.rs:3:15
    |
 LL |     match [5..4, 99..105, 43..44] {
    |           ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
@@ -23,7 +23,7 @@ LL |         [..9, 99..100, _] => {},
                 found type `{integer}`
 
 error[E0308]: mismatched types
-  --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:19
+  --> $DIR/exclusive_range_pattern_syntax_collision3.rs:3:19
    |
 LL |     match [5..4, 99..105, 43..44] {
    |           ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
diff --git a/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.rs b/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.rs
index 99de7845d7b..a7b0ca6fe4a 100644
--- a/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.rs
+++ b/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.rs
@@ -1,5 +1,3 @@
-#![feature(exclusive_range_pattern)]
-
 fn main() {
     let xs = [13, 1, 5, 2, 3, 1, 21, 8];
     let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs;
diff --git a/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.stderr b/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.stderr
index b011044f4dd..af11bc82d0c 100644
--- a/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.stderr
+++ b/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.stderr
@@ -1,5 +1,5 @@
 error[E0658]: `X..` patterns in slices are experimental
-  --> $DIR/feature-gate-half-open-range-patterns-in-slices.rs:5:10
+  --> $DIR/feature-gate-half-open-range-patterns-in-slices.rs:3:10
    |
 LL |     let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs;
    |          ^^^^^^^
@@ -9,7 +9,7 @@ LL |     let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs;
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/feature-gate-half-open-range-patterns-in-slices.rs:5:9
+  --> $DIR/feature-gate-half-open-range-patterns-in-slices.rs:3:9
    |
 LL |     let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `[i32::MIN..=2_i32, ..]` not covered
diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-bad-types.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-bad-types.rs
index 17ea2b13f69..b133e32452f 100644
--- a/tests/ui/half-open-range-patterns/half-open-range-pats-bad-types.rs
+++ b/tests/ui/half-open-range-patterns/half-open-range-pats-bad-types.rs
@@ -1,5 +1,3 @@
-#![feature(exclusive_range_pattern)]
-
 fn main() {
     let "a".. = "a"; //~ ERROR only `char` and numeric types are allowed in range patterns
     let .."a" = "a"; //~ ERROR only `char` and numeric types are allowed in range patterns
diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-bad-types.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-bad-types.stderr
index f7c59a19619..c14c38eca6e 100644
--- a/tests/ui/half-open-range-patterns/half-open-range-pats-bad-types.stderr
+++ b/tests/ui/half-open-range-patterns/half-open-range-pats-bad-types.stderr
@@ -1,17 +1,17 @@
 error[E0029]: only `char` and numeric types are allowed in range patterns
-  --> $DIR/half-open-range-pats-bad-types.rs:4:9
+  --> $DIR/half-open-range-pats-bad-types.rs:2:9
    |
 LL |     let "a".. = "a";
    |         ^^^ this is of type `&'static str` but it should be `char` or numeric
 
 error[E0029]: only `char` and numeric types are allowed in range patterns
-  --> $DIR/half-open-range-pats-bad-types.rs:5:11
+  --> $DIR/half-open-range-pats-bad-types.rs:3:11
    |
 LL |     let .."a" = "a";
    |           ^^^ this is of type `&'static str` but it should be `char` or numeric
 
 error[E0029]: only `char` and numeric types are allowed in range patterns
-  --> $DIR/half-open-range-pats-bad-types.rs:6:12
+  --> $DIR/half-open-range-pats-bad-types.rs:4:12
    |
 LL |     let ..="a" = "a";
    |            ^^^ this is of type `&'static str` but it should be `char` or numeric
diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs
index 9d067229b6d..2059c9707d2 100644
--- a/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs
+++ b/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs
@@ -1,6 +1,5 @@
 // Test various non-exhaustive matches for `X..`, `..=X` and `..X` ranges.
 
-#![feature(exclusive_range_pattern)]
 #![allow(non_contiguous_range_endpoints)]
 
 fn main() {}
diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr
index bb4c2a4c523..78970f8c649 100644
--- a/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr
+++ b/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr
@@ -1,5 +1,5 @@
 error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:15:8
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:14:8
    |
 LL |     m!(0f32, f32::NEG_INFINITY..);
    |        ^^^^ pattern `_` not covered
@@ -11,7 +11,7 @@ LL |         match $s { $($t)+ => {}, _ => todo!() }
    |                                ++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:16:8
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:15:8
    |
 LL |     m!(0f32, ..f32::INFINITY);
    |        ^^^^ pattern `_` not covered
@@ -23,7 +23,7 @@ LL |         match $s { $($t)+ => {}, _ => todo!() }
    |                                ++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `'\u{10ffff}'` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:25:8
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:24:8
    |
 LL |     m!('a', ..core::char::MAX);
    |        ^^^ pattern `'\u{10ffff}'` not covered
@@ -35,7 +35,7 @@ LL |         match $s { $($t)+ => {}, '\u{10ffff}' => todo!() }
    |                                +++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `'\u{10fffe}'..='\u{10ffff}'` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:26:8
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:25:8
    |
 LL |     m!('a', ..ALMOST_MAX);
    |        ^^^ pattern `'\u{10fffe}'..='\u{10ffff}'` not covered
@@ -47,7 +47,7 @@ LL |         match $s { $($t)+ => {}, '\u{10fffe}'..='\u{10ffff}' => todo!() }
    |                                ++++++++++++++++++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `'\0'` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:27:8
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:26:8
    |
 LL |     m!('a', ALMOST_MIN..);
    |        ^^^ pattern `'\0'` not covered
@@ -59,7 +59,7 @@ LL |         match $s { $($t)+ => {}, '\0' => todo!() }
    |                                +++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `'\u{10ffff}'` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:28:8
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:27:8
    |
 LL |     m!('a', ..=ALMOST_MAX);
    |        ^^^ pattern `'\u{10ffff}'` not covered
@@ -71,7 +71,7 @@ LL |         match $s { $($t)+ => {}, '\u{10ffff}' => todo!() }
    |                                +++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `'b'` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:29:8
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:28:8
    |
 LL |     m!('a', ..=VAL | VAL_2..);
    |        ^^^ pattern `'b'` not covered
@@ -83,7 +83,7 @@ LL |         match $s { $($t)+ => {}, 'b' => todo!() }
    |                                ++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `'b'` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:30:8
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:29:8
    |
 LL |     m!('a', ..VAL_1 | VAL_2..);
    |        ^^^ pattern `'b'` not covered
@@ -95,7 +95,7 @@ LL |         match $s { $($t)+ => {}, 'b' => todo!() }
    |                                ++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `u8::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:40:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:39:12
    |
 LL |         m!(0, ..u8::MAX);
    |            ^ pattern `u8::MAX` not covered
@@ -107,7 +107,7 @@ LL |         match $s { $($t)+ => {}, u8::MAX => todo!() }
    |                                ++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `254_u8..=u8::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:41:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:40:12
    |
 LL |         m!(0, ..ALMOST_MAX);
    |            ^ pattern `254_u8..=u8::MAX` not covered
@@ -119,7 +119,7 @@ LL |         match $s { $($t)+ => {}, 254_u8..=u8::MAX => todo!() }
    |                                +++++++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `0_u8` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:42:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:41:12
    |
 LL |         m!(0, ALMOST_MIN..);
    |            ^ pattern `0_u8` not covered
@@ -131,7 +131,7 @@ LL |         match $s { $($t)+ => {}, 0_u8 => todo!() }
    |                                +++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `u8::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:43:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:42:12
    |
 LL |         m!(0, ..=ALMOST_MAX);
    |            ^ pattern `u8::MAX` not covered
@@ -143,7 +143,7 @@ LL |         match $s { $($t)+ => {}, u8::MAX => todo!() }
    |                                ++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_u8` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:44:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:43:12
    |
 LL |         m!(0, ..=VAL | VAL_2..);
    |            ^ pattern `43_u8` not covered
@@ -155,7 +155,7 @@ LL |         match $s { $($t)+ => {}, 43_u8 => todo!() }
    |                                ++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_u8` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:45:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:44:12
    |
 LL |         m!(0, ..VAL_1 | VAL_2..);
    |            ^ pattern `43_u8` not covered
@@ -167,7 +167,7 @@ LL |         match $s { $($t)+ => {}, 43_u8 => todo!() }
    |                                ++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `u16::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:53:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:52:12
    |
 LL |         m!(0, ..u16::MAX);
    |            ^ pattern `u16::MAX` not covered
@@ -179,7 +179,7 @@ LL |         match $s { $($t)+ => {}, u16::MAX => todo!() }
    |                                +++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `65534_u16..=u16::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:54:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:53:12
    |
 LL |         m!(0, ..ALMOST_MAX);
    |            ^ pattern `65534_u16..=u16::MAX` not covered
@@ -191,7 +191,7 @@ LL |         match $s { $($t)+ => {}, 65534_u16..=u16::MAX => todo!() }
    |                                +++++++++++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `0_u16` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:55:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:54:12
    |
 LL |         m!(0, ALMOST_MIN..);
    |            ^ pattern `0_u16` not covered
@@ -203,7 +203,7 @@ LL |         match $s { $($t)+ => {}, 0_u16 => todo!() }
    |                                ++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `u16::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:56:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:55:12
    |
 LL |         m!(0, ..=ALMOST_MAX);
    |            ^ pattern `u16::MAX` not covered
@@ -215,7 +215,7 @@ LL |         match $s { $($t)+ => {}, u16::MAX => todo!() }
    |                                +++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_u16` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:57:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:56:12
    |
 LL |         m!(0, ..=VAL | VAL_2..);
    |            ^ pattern `43_u16` not covered
@@ -227,7 +227,7 @@ LL |         match $s { $($t)+ => {}, 43_u16 => todo!() }
    |                                +++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_u16` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:58:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:57:12
    |
 LL |         m!(0, ..VAL_1 | VAL_2..);
    |            ^ pattern `43_u16` not covered
@@ -239,7 +239,7 @@ LL |         match $s { $($t)+ => {}, 43_u16 => todo!() }
    |                                +++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `u32::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:66:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:65:12
    |
 LL |         m!(0, ..u32::MAX);
    |            ^ pattern `u32::MAX` not covered
@@ -251,7 +251,7 @@ LL |         match $s { $($t)+ => {}, u32::MAX => todo!() }
    |                                +++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `4294967294_u32..=u32::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:67:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:66:12
    |
 LL |         m!(0, ..ALMOST_MAX);
    |            ^ pattern `4294967294_u32..=u32::MAX` not covered
@@ -263,7 +263,7 @@ LL |         match $s { $($t)+ => {}, 4294967294_u32..=u32::MAX => todo!() }
    |                                ++++++++++++++++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `0_u32` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:68:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:67:12
    |
 LL |         m!(0, ALMOST_MIN..);
    |            ^ pattern `0_u32` not covered
@@ -275,7 +275,7 @@ LL |         match $s { $($t)+ => {}, 0_u32 => todo!() }
    |                                ++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `u32::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:69:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:68:12
    |
 LL |         m!(0, ..=ALMOST_MAX);
    |            ^ pattern `u32::MAX` not covered
@@ -287,7 +287,7 @@ LL |         match $s { $($t)+ => {}, u32::MAX => todo!() }
    |                                +++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_u32` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:70:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:69:12
    |
 LL |         m!(0, ..=VAL | VAL_2..);
    |            ^ pattern `43_u32` not covered
@@ -299,7 +299,7 @@ LL |         match $s { $($t)+ => {}, 43_u32 => todo!() }
    |                                +++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_u32` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:71:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:70:12
    |
 LL |         m!(0, ..VAL_1 | VAL_2..);
    |            ^ pattern `43_u32` not covered
@@ -311,7 +311,7 @@ LL |         match $s { $($t)+ => {}, 43_u32 => todo!() }
    |                                +++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `u64::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:79:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:78:12
    |
 LL |         m!(0, ..u64::MAX);
    |            ^ pattern `u64::MAX` not covered
@@ -323,7 +323,7 @@ LL |         match $s { $($t)+ => {}, u64::MAX => todo!() }
    |                                +++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `18446744073709551614_u64..=u64::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:80:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:79:12
    |
 LL |         m!(0, ..ALMOST_MAX);
    |            ^ pattern `18446744073709551614_u64..=u64::MAX` not covered
@@ -335,7 +335,7 @@ LL |         match $s { $($t)+ => {}, 18446744073709551614_u64..=u64::MAX => tod
    |                                ++++++++++++++++++++++++++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `0_u64` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:81:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:80:12
    |
 LL |         m!(0, ALMOST_MIN..);
    |            ^ pattern `0_u64` not covered
@@ -347,7 +347,7 @@ LL |         match $s { $($t)+ => {}, 0_u64 => todo!() }
    |                                ++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `u64::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:82:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:81:12
    |
 LL |         m!(0, ..=ALMOST_MAX);
    |            ^ pattern `u64::MAX` not covered
@@ -359,7 +359,7 @@ LL |         match $s { $($t)+ => {}, u64::MAX => todo!() }
    |                                +++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_u64` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:83:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:82:12
    |
 LL |         m!(0, ..=VAL | VAL_2..);
    |            ^ pattern `43_u64` not covered
@@ -371,7 +371,7 @@ LL |         match $s { $($t)+ => {}, 43_u64 => todo!() }
    |                                +++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_u64` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:84:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:83:12
    |
 LL |         m!(0, ..VAL_1 | VAL_2..);
    |            ^ pattern `43_u64` not covered
@@ -383,7 +383,7 @@ LL |         match $s { $($t)+ => {}, 43_u64 => todo!() }
    |                                +++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `u128::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:92:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:91:12
    |
 LL |         m!(0, ..u128::MAX);
    |            ^ pattern `u128::MAX` not covered
@@ -395,7 +395,7 @@ LL |         match $s { $($t)+ => {}, u128::MAX => todo!() }
    |                                ++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `340282366920938463463374607431768211454_u128..` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:93:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:92:12
    |
 LL |         m!(0, ..ALMOST_MAX);
    |            ^ pattern `340282366920938463463374607431768211454_u128..` not covered
@@ -407,7 +407,7 @@ LL |         match $s { $($t)+ => {}, 340282366920938463463374607431768211454_u1
    |                                +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `0_u128` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:94:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:93:12
    |
 LL |         m!(0, ALMOST_MIN..);
    |            ^ pattern `0_u128` not covered
@@ -419,7 +419,7 @@ LL |         match $s { $($t)+ => {}, 0_u128 => todo!() }
    |                                +++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `u128::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:95:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:94:12
    |
 LL |         m!(0, ..=ALMOST_MAX);
    |            ^ pattern `u128::MAX` not covered
@@ -431,7 +431,7 @@ LL |         match $s { $($t)+ => {}, u128::MAX => todo!() }
    |                                ++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_u128` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:96:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:95:12
    |
 LL |         m!(0, ..=VAL | VAL_2..);
    |            ^ pattern `43_u128` not covered
@@ -443,7 +443,7 @@ LL |         match $s { $($t)+ => {}, 43_u128 => todo!() }
    |                                ++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_u128` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:97:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:96:12
    |
 LL |         m!(0, ..VAL_1 | VAL_2..);
    |            ^ pattern `43_u128` not covered
@@ -455,7 +455,7 @@ LL |         match $s { $($t)+ => {}, 43_u128 => todo!() }
    |                                ++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i8::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:108:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:107:12
    |
 LL |         m!(0, ..i8::MAX);
    |            ^ pattern `i8::MAX` not covered
@@ -467,7 +467,7 @@ LL |         match $s { $($t)+ => {}, i8::MAX => todo!() }
    |                                ++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `126_i8..=i8::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:109:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:108:12
    |
 LL |         m!(0, ..ALMOST_MAX);
    |            ^ pattern `126_i8..=i8::MAX` not covered
@@ -479,7 +479,7 @@ LL |         match $s { $($t)+ => {}, 126_i8..=i8::MAX => todo!() }
    |                                +++++++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i8::MIN` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:110:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:109:12
    |
 LL |         m!(0, ALMOST_MIN..);
    |            ^ pattern `i8::MIN` not covered
@@ -491,7 +491,7 @@ LL |         match $s { $($t)+ => {}, i8::MIN => todo!() }
    |                                ++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i8::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:111:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:110:12
    |
 LL |         m!(0, ..=ALMOST_MAX);
    |            ^ pattern `i8::MAX` not covered
@@ -503,7 +503,7 @@ LL |         match $s { $($t)+ => {}, i8::MAX => todo!() }
    |                                ++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_i8` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:112:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:111:12
    |
 LL |         m!(0, ..=VAL | VAL_2..);
    |            ^ pattern `43_i8` not covered
@@ -515,7 +515,7 @@ LL |         match $s { $($t)+ => {}, 43_i8 => todo!() }
    |                                ++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_i8` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:113:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:112:12
    |
 LL |         m!(0, ..VAL_1 | VAL_2..);
    |            ^ pattern `43_i8` not covered
@@ -527,7 +527,7 @@ LL |         match $s { $($t)+ => {}, 43_i8 => todo!() }
    |                                ++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i16::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:121:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:120:12
    |
 LL |         m!(0, ..i16::MAX);
    |            ^ pattern `i16::MAX` not covered
@@ -539,7 +539,7 @@ LL |         match $s { $($t)+ => {}, i16::MAX => todo!() }
    |                                +++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `32766_i16..=i16::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:122:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:121:12
    |
 LL |         m!(0, ..ALMOST_MAX);
    |            ^ pattern `32766_i16..=i16::MAX` not covered
@@ -551,7 +551,7 @@ LL |         match $s { $($t)+ => {}, 32766_i16..=i16::MAX => todo!() }
    |                                +++++++++++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i16::MIN` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:123:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:122:12
    |
 LL |         m!(0, ALMOST_MIN..);
    |            ^ pattern `i16::MIN` not covered
@@ -563,7 +563,7 @@ LL |         match $s { $($t)+ => {}, i16::MIN => todo!() }
    |                                +++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i16::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:124:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:123:12
    |
 LL |         m!(0, ..=ALMOST_MAX);
    |            ^ pattern `i16::MAX` not covered
@@ -575,7 +575,7 @@ LL |         match $s { $($t)+ => {}, i16::MAX => todo!() }
    |                                +++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_i16` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:125:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:124:12
    |
 LL |         m!(0, ..=VAL | VAL_2..);
    |            ^ pattern `43_i16` not covered
@@ -587,7 +587,7 @@ LL |         match $s { $($t)+ => {}, 43_i16 => todo!() }
    |                                +++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_i16` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:126:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:125:12
    |
 LL |         m!(0, ..VAL_1 | VAL_2..);
    |            ^ pattern `43_i16` not covered
@@ -599,7 +599,7 @@ LL |         match $s { $($t)+ => {}, 43_i16 => todo!() }
    |                                +++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i32::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:134:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:133:12
    |
 LL |         m!(0, ..i32::MAX);
    |            ^ pattern `i32::MAX` not covered
@@ -611,7 +611,7 @@ LL |         match $s { $($t)+ => {}, i32::MAX => todo!() }
    |                                +++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `2147483646_i32..=i32::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:135:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:134:12
    |
 LL |         m!(0, ..ALMOST_MAX);
    |            ^ pattern `2147483646_i32..=i32::MAX` not covered
@@ -623,7 +623,7 @@ LL |         match $s { $($t)+ => {}, 2147483646_i32..=i32::MAX => todo!() }
    |                                ++++++++++++++++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i32::MIN` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:136:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:135:12
    |
 LL |         m!(0, ALMOST_MIN..);
    |            ^ pattern `i32::MIN` not covered
@@ -635,7 +635,7 @@ LL |         match $s { $($t)+ => {}, i32::MIN => todo!() }
    |                                +++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i32::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:137:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:136:12
    |
 LL |         m!(0, ..=ALMOST_MAX);
    |            ^ pattern `i32::MAX` not covered
@@ -647,7 +647,7 @@ LL |         match $s { $($t)+ => {}, i32::MAX => todo!() }
    |                                +++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_i32` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:138:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:137:12
    |
 LL |         m!(0, ..=VAL | VAL_2..);
    |            ^ pattern `43_i32` not covered
@@ -659,7 +659,7 @@ LL |         match $s { $($t)+ => {}, 43_i32 => todo!() }
    |                                +++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_i32` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:139:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:138:12
    |
 LL |         m!(0, ..VAL_1 | VAL_2..);
    |            ^ pattern `43_i32` not covered
@@ -671,7 +671,7 @@ LL |         match $s { $($t)+ => {}, 43_i32 => todo!() }
    |                                +++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i64::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:147:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:146:12
    |
 LL |         m!(0, ..i64::MAX);
    |            ^ pattern `i64::MAX` not covered
@@ -683,7 +683,7 @@ LL |         match $s { $($t)+ => {}, i64::MAX => todo!() }
    |                                +++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `9223372036854775806_i64..=i64::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:148:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:147:12
    |
 LL |         m!(0, ..ALMOST_MAX);
    |            ^ pattern `9223372036854775806_i64..=i64::MAX` not covered
@@ -695,7 +695,7 @@ LL |         match $s { $($t)+ => {}, 9223372036854775806_i64..=i64::MAX => todo
    |                                +++++++++++++++++++++++++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i64::MIN` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:149:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:148:12
    |
 LL |         m!(0, ALMOST_MIN..);
    |            ^ pattern `i64::MIN` not covered
@@ -707,7 +707,7 @@ LL |         match $s { $($t)+ => {}, i64::MIN => todo!() }
    |                                +++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i64::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:150:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:149:12
    |
 LL |         m!(0, ..=ALMOST_MAX);
    |            ^ pattern `i64::MAX` not covered
@@ -719,7 +719,7 @@ LL |         match $s { $($t)+ => {}, i64::MAX => todo!() }
    |                                +++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_i64` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:151:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:150:12
    |
 LL |         m!(0, ..=VAL | VAL_2..);
    |            ^ pattern `43_i64` not covered
@@ -731,7 +731,7 @@ LL |         match $s { $($t)+ => {}, 43_i64 => todo!() }
    |                                +++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_i64` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:152:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:151:12
    |
 LL |         m!(0, ..VAL_1 | VAL_2..);
    |            ^ pattern `43_i64` not covered
@@ -743,7 +743,7 @@ LL |         match $s { $($t)+ => {}, 43_i64 => todo!() }
    |                                +++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i128::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:160:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:159:12
    |
 LL |         m!(0, ..i128::MAX);
    |            ^ pattern `i128::MAX` not covered
@@ -755,7 +755,7 @@ LL |         match $s { $($t)+ => {}, i128::MAX => todo!() }
    |                                ++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `170141183460469231731687303715884105726_i128..` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:161:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:160:12
    |
 LL |         m!(0, ..ALMOST_MAX);
    |            ^ pattern `170141183460469231731687303715884105726_i128..` not covered
@@ -767,7 +767,7 @@ LL |         match $s { $($t)+ => {}, 170141183460469231731687303715884105726_i1
    |                                +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i128::MIN` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:162:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:161:12
    |
 LL |         m!(0, ALMOST_MIN..);
    |            ^ pattern `i128::MIN` not covered
@@ -779,7 +779,7 @@ LL |         match $s { $($t)+ => {}, i128::MIN => todo!() }
    |                                ++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i128::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:163:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:162:12
    |
 LL |         m!(0, ..=ALMOST_MAX);
    |            ^ pattern `i128::MAX` not covered
@@ -791,7 +791,7 @@ LL |         match $s { $($t)+ => {}, i128::MAX => todo!() }
    |                                ++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_i128` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:164:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:163:12
    |
 LL |         m!(0, ..=VAL | VAL_2..);
    |            ^ pattern `43_i128` not covered
@@ -803,7 +803,7 @@ LL |         match $s { $($t)+ => {}, 43_i128 => todo!() }
    |                                ++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_i128` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:165:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:164:12
    |
 LL |         m!(0, ..VAL_1 | VAL_2..);
    |            ^ pattern `43_i128` not covered
diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-pass.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-pass.rs
index fe2db67013e..0d92ff90cc5 100644
--- a/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-pass.rs
+++ b/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-pass.rs
@@ -2,8 +2,6 @@
 
 // Test various exhaustive matches for `X..`, `..=X` and `..X` ranges.
 
-#![feature(exclusive_range_pattern)]
-
 fn main() {}
 
 macro_rules! m {
diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-semantics.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-semantics.rs
index 03ff706fe6a..3487bac5282 100644
--- a/tests/ui/half-open-range-patterns/half-open-range-pats-semantics.rs
+++ b/tests/ui/half-open-range-patterns/half-open-range-pats-semantics.rs
@@ -3,7 +3,6 @@
 // Test half-open range patterns against their expression equivalents
 // via `.contains(...)` and make sure the dynamic semantics match.
 
-#![feature(exclusive_range_pattern)]
 #![allow(unreachable_patterns)]
 
 macro_rules! yes {
diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs
index 98e8b2b0462..4e3fffbef2d 100644
--- a/tests/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs
+++ b/tests/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs
@@ -2,8 +2,6 @@
 
 // Test the parsing of half-open ranges.
 
-#![feature(exclusive_range_pattern)]
-
 fn main() {}
 
 #[cfg(FALSE)]
diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs
index 158da650966..9ca8dd25ed7 100644
--- a/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs
+++ b/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs
@@ -1,5 +1,3 @@
-#![feature(exclusive_range_pattern)]
-
 macro_rules! m {
     ($s:expr, $($t:tt)+) => {
         match $s { $($t)+ => {} }
diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr
index 169e776fc20..668b5c858f0 100644
--- a/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr
+++ b/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr
@@ -1,77 +1,77 @@
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:10:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:8:11
    |
 LL |     m!(0, ..u8::MIN);
    |           ^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:12:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:10:11
    |
 LL |     m!(0, ..u16::MIN);
    |           ^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:14:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:12:11
    |
 LL |     m!(0, ..u32::MIN);
    |           ^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:16:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:14:11
    |
 LL |     m!(0, ..u64::MIN);
    |           ^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:18:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:16:11
    |
 LL |     m!(0, ..u128::MIN);
    |           ^^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:21:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:19:11
    |
 LL |     m!(0, ..i8::MIN);
    |           ^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:23:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:21:11
    |
 LL |     m!(0, ..i16::MIN);
    |           ^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:25:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:23:11
    |
 LL |     m!(0, ..i32::MIN);
    |           ^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:27:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:25:11
    |
 LL |     m!(0, ..i64::MIN);
    |           ^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:29:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:27:11
    |
 LL |     m!(0, ..i128::MIN);
    |           ^^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:32:14
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:30:14
    |
 LL |     m!(0f32, ..f32::NEG_INFINITY);
    |              ^^^^^^^^^^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:34:14
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:32:14
    |
 LL |     m!(0f64, ..f64::NEG_INFINITY);
    |              ^^^^^^^^^^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:37:13
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:35:13
    |
 LL |     m!('a', ..'\u{0}');
    |             ^^^^^^^^^
diff --git a/tests/ui/half-open-range-patterns/pat-tuple-4.rs b/tests/ui/half-open-range-patterns/pat-tuple-4.rs
index 95aae25ada8..325293aa486 100644
--- a/tests/ui/half-open-range-patterns/pat-tuple-4.rs
+++ b/tests/ui/half-open-range-patterns/pat-tuple-4.rs
@@ -1,7 +1,5 @@
 //@ check-pass
 
-#![feature(exclusive_range_pattern)]
-
 fn main() {
     const PAT: u8 = 1;
 
diff --git a/tests/ui/half-open-range-patterns/pat-tuple-5.rs b/tests/ui/half-open-range-patterns/pat-tuple-5.rs
index 995ef03c83e..4ed43954e02 100644
--- a/tests/ui/half-open-range-patterns/pat-tuple-5.rs
+++ b/tests/ui/half-open-range-patterns/pat-tuple-5.rs
@@ -1,5 +1,3 @@
-#![feature(exclusive_range_pattern)]
-
 fn main() {
     const PAT: u8 = 1;
 
diff --git a/tests/ui/half-open-range-patterns/pat-tuple-5.stderr b/tests/ui/half-open-range-patterns/pat-tuple-5.stderr
index a7dd4139792..e6d33947d46 100644
--- a/tests/ui/half-open-range-patterns/pat-tuple-5.stderr
+++ b/tests/ui/half-open-range-patterns/pat-tuple-5.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/pat-tuple-5.rs:7:10
+  --> $DIR/pat-tuple-5.rs:5:10
    |
 LL |     match (0, 1) {
    |           ------ this expression has type `({integer}, {integer})`
diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions0.rs b/tests/ui/half-open-range-patterns/range_pat_interactions0.rs
index 53b6b89ed16..f943ea0271d 100644
--- a/tests/ui/half-open-range-patterns/range_pat_interactions0.rs
+++ b/tests/ui/half-open-range-patterns/range_pat_interactions0.rs
@@ -1,6 +1,5 @@
 //@ run-pass
 #![allow(non_contiguous_range_endpoints)]
-#![feature(exclusive_range_pattern)]
 #![feature(inline_const_pat)]
 
 fn main() {
diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions1.rs b/tests/ui/half-open-range-patterns/range_pat_interactions1.rs
index 0c050c550c4..4d7c9f10261 100644
--- a/tests/ui/half-open-range-patterns/range_pat_interactions1.rs
+++ b/tests/ui/half-open-range-patterns/range_pat_interactions1.rs
@@ -9,26 +9,19 @@ fn main() {
     for x in -9 + 1..=(9 - 2) {
         if let n @ 2..3|4 = x {
             //~^ error: variable `n` is not bound in all patterns
-            //~| exclusive range pattern syntax is experimental
             errors_only.push(x);
         } else if let 2..3 | 4 = x {
-            //~^ exclusive range pattern syntax is experimental
             if_lettable.push(x);
         }
         match x as i32 {
             0..5+1 => errors_only.push(x),
             //~^ error: expected a pattern range bound, found an expression
-            //~| error: exclusive range pattern syntax is experimental
             1 | -3..0 => first_or.push(x),
-            //~^ error: exclusive range pattern syntax is experimental
             y @ (0..5 | 6) => or_two.push(y),
-            //~^ error: exclusive range pattern syntax is experimental
             y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
-            //~^ error: exclusive range pattern syntax is experimental
-            //~| error: inline-const in pattern position is experimental
+            //~^ error: inline-const in pattern position is experimental [E0658]
             y @ -5.. => range_from.push(y),
             y @ ..-7 => assert_eq!(y, -8),
-            //~^ error: exclusive range pattern syntax is experimental
             y => bottom.push(y),
         }
     }
diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr
index cc481f7a79e..c14021e009b 100644
--- a/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr
+++ b/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr
@@ -1,5 +1,5 @@
 error: expected a pattern range bound, found an expression
-  --> $DIR/range_pat_interactions1.rs:19:16
+  --> $DIR/range_pat_interactions1.rs:17:16
    |
 LL |             0..5+1 => errors_only.push(x),
    |                ^^^ arbitrary expressions are not allowed in patterns
@@ -13,7 +13,7 @@ LL |         if let n @ 2..3|4 = x {
    |                variable not in all patterns
 
 error[E0658]: inline-const in pattern position is experimental
-  --> $DIR/range_pat_interactions1.rs:26:20
+  --> $DIR/range_pat_interactions1.rs:21:20
    |
 LL |             y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
    |                    ^^^^^
@@ -22,84 +22,7 @@ LL |             y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
    = help: add `#![feature(inline_const_pat)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: exclusive range pattern syntax is experimental
-  --> $DIR/range_pat_interactions1.rs:10:20
-   |
-LL |         if let n @ 2..3|4 = x {
-   |                    ^^^^
-   |
-   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
-   = help: add `#![feature(exclusive_range_pattern)]` 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: use an inclusive range pattern, like N..=M
-
-error[E0658]: exclusive range pattern syntax is experimental
-  --> $DIR/range_pat_interactions1.rs:14:23
-   |
-LL |         } else if let 2..3 | 4 = x {
-   |                       ^^^^
-   |
-   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
-   = help: add `#![feature(exclusive_range_pattern)]` 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: use an inclusive range pattern, like N..=M
-
-error[E0658]: exclusive range pattern syntax is experimental
-  --> $DIR/range_pat_interactions1.rs:19:13
-   |
-LL |             0..5+1 => errors_only.push(x),
-   |             ^^^^^^
-   |
-   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
-   = help: add `#![feature(exclusive_range_pattern)]` 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: use an inclusive range pattern, like N..=M
-
-error[E0658]: exclusive range pattern syntax is experimental
-  --> $DIR/range_pat_interactions1.rs:22:17
-   |
-LL |             1 | -3..0 => first_or.push(x),
-   |                 ^^^^^
-   |
-   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
-   = help: add `#![feature(exclusive_range_pattern)]` 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: use an inclusive range pattern, like N..=M
-
-error[E0658]: exclusive range pattern syntax is experimental
-  --> $DIR/range_pat_interactions1.rs:24:18
-   |
-LL |             y @ (0..5 | 6) => or_two.push(y),
-   |                  ^^^^
-   |
-   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
-   = help: add `#![feature(exclusive_range_pattern)]` 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: use an inclusive range pattern, like N..=M
-
-error[E0658]: exclusive range pattern syntax is experimental
-  --> $DIR/range_pat_interactions1.rs:26:17
-   |
-LL |             y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
-   |                 ^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
-   = help: add `#![feature(exclusive_range_pattern)]` 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: use an inclusive range pattern, like N..=M
-
-error[E0658]: exclusive range pattern syntax is experimental
-  --> $DIR/range_pat_interactions1.rs:30:17
-   |
-LL |             y @ ..-7 => assert_eq!(y, -8),
-   |                 ^^^^
-   |
-   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
-   = help: add `#![feature(exclusive_range_pattern)]` 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: use an inclusive range pattern, like N..=M
-
-error: aborting due to 10 previous errors
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0408, E0658.
 For more information about an error, try `rustc --explain E0408`.
diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions2.rs b/tests/ui/half-open-range-patterns/range_pat_interactions2.rs
index 068104c4b1b..0dbdb8fe7b6 100644
--- a/tests/ui/half-open-range-patterns/range_pat_interactions2.rs
+++ b/tests/ui/half-open-range-patterns/range_pat_interactions2.rs
@@ -11,15 +11,11 @@ fn main() {
             //~^ error: expected a pattern range bound, found an expression
             //~| error: range pattern bounds cannot have parentheses
             1 | -3..0 => first_or.push(x),
-            //~^ error: exclusive range pattern syntax is experimental
             y @ (0..5 | 6) => or_two.push(y),
-            //~^ error: exclusive range pattern syntax is experimental
             y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
             //~^ error: inline-const in pattern position is experimental
-            //~| error: exclusive range pattern syntax is experimental
             y @ -5.. => range_from.push(y),
             y @ ..-7 => assert_eq!(y, -8),
-            //~^ error: exclusive range pattern syntax is experimental
             y => bottom.push(y),
         }
     }
diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr
index 8f21a6149fb..136296fa5b0 100644
--- a/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr
+++ b/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr
@@ -17,7 +17,7 @@ LL +             0..=5+1 => errors_only.push(x),
    |
 
 error[E0658]: inline-const in pattern position is experimental
-  --> $DIR/range_pat_interactions2.rs:17:20
+  --> $DIR/range_pat_interactions2.rs:15:20
    |
 LL |             y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
    |                    ^^^^^
@@ -26,50 +26,6 @@ LL |             y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
    = help: add `#![feature(inline_const_pat)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: exclusive range pattern syntax is experimental
-  --> $DIR/range_pat_interactions2.rs:13:17
-   |
-LL |             1 | -3..0 => first_or.push(x),
-   |                 ^^^^^
-   |
-   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
-   = help: add `#![feature(exclusive_range_pattern)]` 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: use an inclusive range pattern, like N..=M
-
-error[E0658]: exclusive range pattern syntax is experimental
-  --> $DIR/range_pat_interactions2.rs:15:18
-   |
-LL |             y @ (0..5 | 6) => or_two.push(y),
-   |                  ^^^^
-   |
-   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
-   = help: add `#![feature(exclusive_range_pattern)]` 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: use an inclusive range pattern, like N..=M
-
-error[E0658]: exclusive range pattern syntax is experimental
-  --> $DIR/range_pat_interactions2.rs:17:17
-   |
-LL |             y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
-   |                 ^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
-   = help: add `#![feature(exclusive_range_pattern)]` 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: use an inclusive range pattern, like N..=M
-
-error[E0658]: exclusive range pattern syntax is experimental
-  --> $DIR/range_pat_interactions2.rs:21:17
-   |
-LL |             y @ ..-7 => assert_eq!(y, -8),
-   |                 ^^^^
-   |
-   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
-   = help: add `#![feature(exclusive_range_pattern)]` 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: use an inclusive range pattern, like N..=M
-
-error: aborting due to 7 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions3.rs b/tests/ui/half-open-range-patterns/range_pat_interactions3.rs
index 446ed45f9c6..2f2778095cf 100644
--- a/tests/ui/half-open-range-patterns/range_pat_interactions3.rs
+++ b/tests/ui/half-open-range-patterns/range_pat_interactions3.rs
@@ -8,15 +8,11 @@ fn main() {
         match x as i32 {
             8.. => bottom.push(x),
             1 | -3..0 => first_or.push(x),
-            //~^ exclusive range pattern syntax is experimental
             y @ (0..5 | 6) => or_two.push(y),
-            //~^ exclusive range pattern syntax is experimental
             y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
             //~^ inline-const in pattern position is experimental
-            //~| exclusive range pattern syntax is experimental
             y @ -5.. => range_from.push(y),
             y @ ..-7 => assert_eq!(y, -8),
-            //~^ exclusive range pattern syntax is experimental
             y => bottom.push(y),
         }
     }
diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions3.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions3.stderr
index 51cc22e7d56..dc7dc0efa7a 100644
--- a/tests/ui/half-open-range-patterns/range_pat_interactions3.stderr
+++ b/tests/ui/half-open-range-patterns/range_pat_interactions3.stderr
@@ -1,5 +1,5 @@
 error[E0658]: inline-const in pattern position is experimental
-  --> $DIR/range_pat_interactions3.rs:14:20
+  --> $DIR/range_pat_interactions3.rs:12:20
    |
 LL |             y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
    |                    ^^^^^
@@ -8,50 +8,6 @@ LL |             y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
    = help: add `#![feature(inline_const_pat)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: exclusive range pattern syntax is experimental
-  --> $DIR/range_pat_interactions3.rs:10:17
-   |
-LL |             1 | -3..0 => first_or.push(x),
-   |                 ^^^^^
-   |
-   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
-   = help: add `#![feature(exclusive_range_pattern)]` 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: use an inclusive range pattern, like N..=M
-
-error[E0658]: exclusive range pattern syntax is experimental
-  --> $DIR/range_pat_interactions3.rs:12:18
-   |
-LL |             y @ (0..5 | 6) => or_two.push(y),
-   |                  ^^^^
-   |
-   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
-   = help: add `#![feature(exclusive_range_pattern)]` 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: use an inclusive range pattern, like N..=M
-
-error[E0658]: exclusive range pattern syntax is experimental
-  --> $DIR/range_pat_interactions3.rs:14:17
-   |
-LL |             y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
-   |                 ^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
-   = help: add `#![feature(exclusive_range_pattern)]` 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: use an inclusive range pattern, like N..=M
-
-error[E0658]: exclusive range pattern syntax is experimental
-  --> $DIR/range_pat_interactions3.rs:18:17
-   |
-LL |             y @ ..-7 => assert_eq!(y, -8),
-   |                 ^^^^
-   |
-   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
-   = help: add `#![feature(exclusive_range_pattern)]` 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: use an inclusive range pattern, like N..=M
-
-error: aborting due to 5 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem0.rs b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem0.rs
index d54cbfbf4bb..aa2690f3777 100644
--- a/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem0.rs
+++ b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem0.rs
@@ -1,5 +1,4 @@
 #![feature(half_open_range_patterns_in_slices)]
-#![feature(exclusive_range_pattern)]
 
 fn main() {
     let xs = [13, 1, 5, 2, 3, 1, 21, 8];
diff --git a/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem0.stderr b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem0.stderr
index eca5c330180..5bcbe21a6a9 100644
--- a/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem0.stderr
+++ b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem0.stderr
@@ -1,5 +1,5 @@
 error[E0527]: pattern requires 2 elements but array has 8
-  --> $DIR/slice_pattern_syntax_problem0.rs:11:9
+  --> $DIR/slice_pattern_syntax_problem0.rs:10:9
    |
 LL |     let [first_three @ ..3, rest @ 2..] = xs;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 8 elements
diff --git a/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs
index cd381544372..60b056fbcb6 100644
--- a/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs
+++ b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs
@@ -3,7 +3,5 @@ fn main() {
     let xs = [13, 1, 5, 2, 3, 1, 21, 8];
     let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs;
     //~^ `X..` patterns in slices are experimental
-    //~| exclusive range pattern syntax is experimental
-    //~| exclusive range pattern syntax is experimental
     //~| ERROR: refutable pattern
 }
diff --git a/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr
index fc549eb65c0..49515919904 100644
--- a/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr
+++ b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr
@@ -8,28 +8,6 @@ LL |     let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs;
    = help: add `#![feature(half_open_range_patterns_in_slices)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: exclusive range pattern syntax is experimental
-  --> $DIR/slice_pattern_syntax_problem1.rs:4:23
-   |
-LL |     let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs;
-   |                       ^^^
-   |
-   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
-   = help: add `#![feature(exclusive_range_pattern)]` 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: use an inclusive range pattern, like N..=M
-
-error[E0658]: exclusive range pattern syntax is experimental
-  --> $DIR/slice_pattern_syntax_problem1.rs:4:32
-   |
-LL |     let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs;
-   |                                ^^^^
-   |
-   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
-   = help: add `#![feature(exclusive_range_pattern)]` 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: use an inclusive range pattern, like N..=M
-
 error[E0005]: refutable pattern in local binding
   --> $DIR/slice_pattern_syntax_problem1.rs:4:9
    |
@@ -44,7 +22,7 @@ help: you might want to use `let else` to handle the variant that isn't matched
 LL |     let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs else { todo!() };
    |                                               ++++++++++++++++
 
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0005, E0658.
 For more information about an error, try `rustc --explain E0005`.
diff --git a/tests/ui/impl-trait/dyn-trait-elided-two-inputs-ref-assoc.rs b/tests/ui/impl-trait/dyn-trait-elided-two-inputs-ref-assoc.rs
index 2dc19b9ad68..e9706b656f2 100644
--- a/tests/ui/impl-trait/dyn-trait-elided-two-inputs-ref-assoc.rs
+++ b/tests/ui/impl-trait/dyn-trait-elided-two-inputs-ref-assoc.rs
@@ -2,6 +2,9 @@
 // when there are multiple inputs.  The `dyn Bar` should default to `+
 // 'static`. This used to erroneously generate an error (cc #62517).
 //
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@ check-pass
 
 trait Foo {
diff --git a/tests/ui/impl-trait/in-trait/placeholder-implied-bounds.rs b/tests/ui/impl-trait/in-trait/placeholder-implied-bounds.rs
index f7546a05bfd..df03150e29a 100644
--- a/tests/ui/impl-trait/in-trait/placeholder-implied-bounds.rs
+++ b/tests/ui/impl-trait/in-trait/placeholder-implied-bounds.rs
@@ -1,3 +1,6 @@
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@ check-pass
 
 pub fn main() {}
diff --git a/tests/ui/impl-trait/issues/issue-105826.rs b/tests/ui/impl-trait/issues/issue-105826.rs
index e3488140dcc..33c5ed5fdeb 100644
--- a/tests/ui/impl-trait/issues/issue-105826.rs
+++ b/tests/ui/impl-trait/issues/issue-105826.rs
@@ -1,3 +1,6 @@
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@ check-pass
 
 use std::io::Write;
diff --git a/tests/ui/inline-const/const-match-pat-range.rs b/tests/ui/inline-const/const-match-pat-range.rs
index 7f51815cb77..7202c0c0452 100644
--- a/tests/ui/inline-const/const-match-pat-range.rs
+++ b/tests/ui/inline-const/const-match-pat-range.rs
@@ -1,6 +1,6 @@
 //@ build-pass
 
-#![feature(inline_const_pat, exclusive_range_pattern)]
+#![feature(inline_const_pat)]
 
 fn main() {
     const N: u32 = 10;
diff --git a/tests/ui/instrument-coverage/coverage-options.rs b/tests/ui/instrument-coverage/coverage-options.rs
index 332da32e435..2a80ce4ab2e 100644
--- a/tests/ui/instrument-coverage/coverage-options.rs
+++ b/tests/ui/instrument-coverage/coverage-options.rs
@@ -1,5 +1,5 @@
 //@ needs-profiler-support
-//@ revisions: block branch bad
+//@ revisions: block branch mcdc bad
 //@ compile-flags -Cinstrument-coverage
 
 //@ [block] check-pass
diff --git a/tests/ui/issues/issue-27042.stderr b/tests/ui/issues/issue-27042.stderr
index ba39399e46e..6586e61f2f6 100644
--- a/tests/ui/issues/issue-27042.stderr
+++ b/tests/ui/issues/issue-27042.stderr
@@ -40,6 +40,8 @@ error[E0308]: mismatched types
 LL | /         'c:
 LL | |         for _ in None { break }; // but here we cite the whole loop
    | |_______________________________^ expected `i32`, found `()`
+   |
+   = note: `for` loops evaluate to unit type `()`
 
 error[E0308]: mismatched types
   --> $DIR/issue-27042.rs:15:9
diff --git a/tests/ui/issues/issue-50585.stderr b/tests/ui/issues/issue-50585.stderr
index 13181f1cf7f..e7f13e63475 100644
--- a/tests/ui/issues/issue-50585.stderr
+++ b/tests/ui/issues/issue-50585.stderr
@@ -13,6 +13,12 @@ error[E0308]: mismatched types
    |
 LL |     |y: Vec<[(); for x in 0..2 {}]>| {};
    |                  ^^^^^^^^^^^^^^^^ expected `usize`, found `()`
+   |
+   = note: `for` loops evaluate to unit type `()`
+help: consider returning a value here
+   |
+LL |     |y: Vec<[(); for x in 0..2 {} /* `usize` value */]>| {};
+   |                                   +++++++++++++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/lint/lint-ctypes-enum.rs b/tests/ui/lint/lint-ctypes-enum.rs
index c60290f8553..cb8e9e80675 100644
--- a/tests/ui/lint/lint-ctypes-enum.rs
+++ b/tests/ui/lint/lint-ctypes-enum.rs
@@ -2,6 +2,7 @@
 #![deny(improper_ctypes)]
 #![feature(ptr_internals)]
 #![feature(transparent_unions)]
+#![feature(result_ffi_guarantees)]
 
 use std::num;
 
@@ -55,38 +56,123 @@ union TransparentUnion<T: Copy> {
 
 struct Rust<T>(T);
 
+struct NoField;
+
+#[repr(transparent)]
+struct Field(());
+
+#[non_exhaustive]
+enum NonExhaustive {}
+
 extern "C" {
-   fn zf(x: Z);
-   fn uf(x: U); //~ ERROR `extern` block uses type `U`
-   fn bf(x: B); //~ ERROR `extern` block uses type `B`
-   fn tf(x: T); //~ ERROR `extern` block uses type `T`
-   fn repr_c(x: ReprC);
-   fn repr_u8(x: U8);
-   fn repr_isize(x: Isize);
-   fn option_ref(x: Option<&'static u8>);
-   fn option_fn(x: Option<extern "C" fn()>);
-   fn nonnull(x: Option<std::ptr::NonNull<u8>>);
-   fn unique(x: Option<std::ptr::Unique<u8>>);
-   fn nonzero_u8(x: Option<num::NonZero<u8>>);
-   fn nonzero_u16(x: Option<num::NonZero<u16>>);
-   fn nonzero_u32(x: Option<num::NonZero<u32>>);
-   fn nonzero_u64(x: Option<num::NonZero<u64>>);
-   fn nonzero_u128(x: Option<num::NonZero<u128>>);
-   //~^ ERROR `extern` block uses type `u128`
-   fn nonzero_usize(x: Option<num::NonZero<usize>>);
-   fn nonzero_i8(x: Option<num::NonZero<i8>>);
-   fn nonzero_i16(x: Option<num::NonZero<i16>>);
-   fn nonzero_i32(x: Option<num::NonZero<i32>>);
-   fn nonzero_i64(x: Option<num::NonZero<i64>>);
-   fn nonzero_i128(x: Option<num::NonZero<i128>>);
-   //~^ ERROR `extern` block uses type `i128`
-   fn nonzero_isize(x: Option<num::NonZero<isize>>);
-   fn transparent_struct(x: Option<TransparentStruct<num::NonZero<u8>>>);
-   fn transparent_enum(x: Option<TransparentEnum<num::NonZero<u8>>>);
-   fn transparent_union(x: Option<TransparentUnion<num::NonZero<u8>>>);
-   //~^ ERROR `extern` block uses type
-   fn repr_rust(x: Option<Rust<num::NonZero<u8>>>); //~ ERROR `extern` block uses type
-   fn no_result(x: Result<(), num::NonZero<i32>>); //~ ERROR `extern` block uses type
+    fn zf(x: Z);
+    fn uf(x: U); //~ ERROR `extern` block uses type `U`
+    fn bf(x: B); //~ ERROR `extern` block uses type `B`
+    fn tf(x: T); //~ ERROR `extern` block uses type `T`
+    fn repr_c(x: ReprC);
+    fn repr_u8(x: U8);
+    fn repr_isize(x: Isize);
+    fn option_ref(x: Option<&'static u8>);
+    fn option_fn(x: Option<extern "C" fn()>);
+    fn option_nonnull(x: Option<std::ptr::NonNull<u8>>);
+    fn option_unique(x: Option<std::ptr::Unique<u8>>);
+    fn option_nonzero_u8(x: Option<num::NonZero<u8>>);
+    fn option_nonzero_u16(x: Option<num::NonZero<u16>>);
+    fn option_nonzero_u32(x: Option<num::NonZero<u32>>);
+    fn option_nonzero_u64(x: Option<num::NonZero<u64>>);
+    fn option_nonzero_u128(x: Option<num::NonZero<u128>>);
+    //~^ ERROR `extern` block uses type `u128`
+    fn option_nonzero_usize(x: Option<num::NonZero<usize>>);
+    fn option_nonzero_i8(x: Option<num::NonZero<i8>>);
+    fn option_nonzero_i16(x: Option<num::NonZero<i16>>);
+    fn option_nonzero_i32(x: Option<num::NonZero<i32>>);
+    fn option_nonzero_i64(x: Option<num::NonZero<i64>>);
+    fn option_nonzero_i128(x: Option<num::NonZero<i128>>);
+    //~^ ERROR `extern` block uses type `i128`
+    fn option_nonzero_isize(x: Option<num::NonZero<isize>>);
+    fn option_transparent_struct(x: Option<TransparentStruct<num::NonZero<u8>>>);
+    fn option_transparent_enum(x: Option<TransparentEnum<num::NonZero<u8>>>);
+    fn option_transparent_union(x: Option<TransparentUnion<num::NonZero<u8>>>);
+    //~^ ERROR `extern` block uses type
+    fn option_repr_rust(x: Option<Rust<num::NonZero<u8>>>); //~ ERROR `extern` block uses type
+
+    fn result_ref_t(x: Result<&'static u8, ()>);
+    fn result_fn_t(x: Result<extern "C" fn(), ()>);
+    fn result_nonnull_t(x: Result<std::ptr::NonNull<u8>, ()>);
+    fn result_unique_t(x: Result<std::ptr::Unique<u8>, ()>);
+    fn result_nonzero_u8_t(x: Result<num::NonZero<u8>, ()>);
+    fn result_nonzero_u16_t(x: Result<num::NonZero<u16>, ()>);
+    fn result_nonzero_u32_t(x: Result<num::NonZero<u32>, ()>);
+    fn result_nonzero_u64_t(x: Result<num::NonZero<u64>, ()>);
+    fn result_nonzero_u128_t(x: Result<num::NonZero<u128>, ()>);
+    //~^ ERROR `extern` block uses type `u128`
+    fn result_nonzero_usize_t(x: Result<num::NonZero<usize>, ()>);
+    fn result_nonzero_i8_t(x: Result<num::NonZero<i8>, ()>);
+    fn result_nonzero_i16_t(x: Result<num::NonZero<i16>, ()>);
+    fn result_nonzero_i32_t(x: Result<num::NonZero<i32>, ()>);
+    fn result_nonzero_i64_t(x: Result<num::NonZero<i64>, ()>);
+    fn result_nonzero_i128_t(x: Result<num::NonZero<i128>, ()>);
+    //~^ ERROR `extern` block uses type `i128`
+    fn result_nonzero_isize_t(x: Result<num::NonZero<isize>, ()>);
+    fn result_transparent_struct_t(x: Result<TransparentStruct<num::NonZero<u8>>, ()>);
+    fn result_transparent_enum_t(x: Result<TransparentEnum<num::NonZero<u8>>, ()>);
+    fn result_transparent_union_t(x: Result<TransparentUnion<num::NonZero<u8>>, ()>);
+    //~^ ERROR `extern` block uses type
+    fn result_repr_rust_t(x: Result<Rust<num::NonZero<u8>>, ()>);
+    //~^ ERROR `extern` block uses type
+    fn result_phantom_t(x: Result<num::NonZero<u8>, std::marker::PhantomData<()>>);
+    fn result_1zst_exhaustive_no_variant_t(x: Result<num::NonZero<u8>, Z>);
+    fn result_1zst_exhaustive_single_variant_t(x: Result<num::NonZero<u8>, U>);
+    //~^ ERROR `extern` block uses type
+    fn result_1zst_exhaustive_multiple_variant_t(x: Result<num::NonZero<u8>, B>);
+    //~^ ERROR `extern` block uses type
+    fn result_1zst_non_exhaustive_no_variant_t(x: Result<num::NonZero<u8>, NonExhaustive>);
+    //~^ ERROR `extern` block uses type
+    fn result_1zst_exhaustive_no_field_t(x: Result<num::NonZero<u8>, NoField>);
+    fn result_1zst_exhaustive_single_field_t(x: Result<num::NonZero<u8>, Field>);
+    //~^ ERROR `extern` block uses type
+    fn result_cascading_t(x: Result<Result<(), num::NonZero<u8>>, ()>);
+    //~^ ERROR `extern` block uses type
+
+    fn result_ref_e(x: Result<(), &'static u8>);
+    fn result_fn_e(x: Result<(), extern "C" fn()>);
+    fn result_nonnull_e(x: Result<(), std::ptr::NonNull<u8>>);
+    fn result_unique_e(x: Result<(), std::ptr::Unique<u8>>);
+    fn result_nonzero_u8_e(x: Result<(), num::NonZero<u8>>);
+    fn result_nonzero_u16_e(x: Result<(), num::NonZero<u16>>);
+    fn result_nonzero_u32_e(x: Result<(), num::NonZero<u32>>);
+    fn result_nonzero_u64_e(x: Result<(), num::NonZero<u64>>);
+    fn result_nonzero_u128_e(x: Result<(), num::NonZero<u128>>);
+    //~^ ERROR `extern` block uses type `u128`
+    fn result_nonzero_usize_e(x: Result<(), num::NonZero<usize>>);
+    fn result_nonzero_i8_e(x: Result<(), num::NonZero<i8>>);
+    fn result_nonzero_i16_e(x: Result<(), num::NonZero<i16>>);
+    fn result_nonzero_i32_e(x: Result<(), num::NonZero<i32>>);
+    fn result_nonzero_i64_e(x: Result<(), num::NonZero<i64>>);
+    fn result_nonzero_i128_e(x: Result<(), num::NonZero<i128>>);
+    //~^ ERROR `extern` block uses type `i128`
+    fn result_nonzero_isize_e(x: Result<(), num::NonZero<isize>>);
+    fn result_transparent_struct_e(x: Result<(), TransparentStruct<num::NonZero<u8>>>);
+    fn result_transparent_enum_e(x: Result<(), TransparentEnum<num::NonZero<u8>>>);
+    fn result_transparent_union_e(x: Result<(), TransparentUnion<num::NonZero<u8>>>);
+    //~^ ERROR `extern` block uses type
+    fn result_repr_rust_e(x: Result<(), Rust<num::NonZero<u8>>>);
+    //~^ ERROR `extern` block uses type
+    fn result_phantom_e(x: Result<num::NonZero<u8>, std::marker::PhantomData<()>>);
+    fn result_1zst_exhaustive_no_variant_e(x: Result<Z, num::NonZero<u8>>);
+    fn result_1zst_exhaustive_single_variant_e(x: Result<U, num::NonZero<u8>>);
+    //~^ ERROR `extern` block uses type
+    fn result_1zst_exhaustive_multiple_variant_e(x: Result<B, num::NonZero<u8>>);
+    //~^ ERROR `extern` block uses type
+    fn result_1zst_non_exhaustive_no_variant_e(x: Result<NonExhaustive, num::NonZero<u8>>);
+    //~^ ERROR `extern` block uses type
+    fn result_1zst_exhaustive_no_field_e(x: Result<NoField, num::NonZero<u8>>);
+    fn result_1zst_exhaustive_single_field_e(x: Result<Field, num::NonZero<u8>>);
+    //~^ ERROR `extern` block uses type
+    fn result_cascading_e(x: Result<(), Result<(), num::NonZero<u8>>>);
+    //~^ ERROR `extern` block uses type
+    fn result_unit_t_e(x: Result<(), ()>);
+    //~^ ERROR `extern` block uses type
 }
 
 pub fn main() {}
diff --git a/tests/ui/lint/lint-ctypes-enum.stderr b/tests/ui/lint/lint-ctypes-enum.stderr
index 103fda8d402..bba5b09b69c 100644
--- a/tests/ui/lint/lint-ctypes-enum.stderr
+++ b/tests/ui/lint/lint-ctypes-enum.stderr
@@ -1,13 +1,13 @@
 error: `extern` block uses type `U`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:60:13
+  --> $DIR/lint-ctypes-enum.rs:69:14
    |
-LL |    fn uf(x: U);
-   |             ^ not FFI-safe
+LL |     fn uf(x: U);
+   |              ^ not FFI-safe
    |
    = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
    = note: enum has no representation hint
 note: the type is defined here
-  --> $DIR/lint-ctypes-enum.rs:9:1
+  --> $DIR/lint-ctypes-enum.rs:10:1
    |
 LL | enum U {
    | ^^^^^^
@@ -18,75 +18,233 @@ LL | #![deny(improper_ctypes)]
    |         ^^^^^^^^^^^^^^^
 
 error: `extern` block uses type `B`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:61:13
+  --> $DIR/lint-ctypes-enum.rs:70:14
    |
-LL |    fn bf(x: B);
-   |             ^ not FFI-safe
+LL |     fn bf(x: B);
+   |              ^ not FFI-safe
    |
    = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
    = note: enum has no representation hint
 note: the type is defined here
-  --> $DIR/lint-ctypes-enum.rs:12:1
+  --> $DIR/lint-ctypes-enum.rs:13:1
    |
 LL | enum B {
    | ^^^^^^
 
 error: `extern` block uses type `T`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:62:13
+  --> $DIR/lint-ctypes-enum.rs:71:14
    |
-LL |    fn tf(x: T);
-   |             ^ not FFI-safe
+LL |     fn tf(x: T);
+   |              ^ not FFI-safe
    |
    = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
    = note: enum has no representation hint
 note: the type is defined here
-  --> $DIR/lint-ctypes-enum.rs:16:1
+  --> $DIR/lint-ctypes-enum.rs:17:1
    |
 LL | enum T {
    | ^^^^^^
 
 error: `extern` block uses type `u128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:74:23
+  --> $DIR/lint-ctypes-enum.rs:83:31
    |
-LL |    fn nonzero_u128(x: Option<num::NonZero<u128>>);
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+LL |     fn option_nonzero_u128(x: Option<num::NonZero<u128>>);
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
    |
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `i128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:81:23
+  --> $DIR/lint-ctypes-enum.rs:90:31
    |
-LL |    fn nonzero_i128(x: Option<num::NonZero<i128>>);
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+LL |     fn option_nonzero_i128(x: Option<num::NonZero<i128>>);
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
    |
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `Option<TransparentUnion<NonZero<u8>>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:86:28
+  --> $DIR/lint-ctypes-enum.rs:95:36
    |
-LL |    fn transparent_union(x: Option<TransparentUnion<num::NonZero<u8>>>);
-   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+LL |     fn option_transparent_union(x: Option<TransparentUnion<num::NonZero<u8>>>);
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
    |
    = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
    = note: enum has no representation hint
 
 error: `extern` block uses type `Option<Rust<NonZero<u8>>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:88:20
+  --> $DIR/lint-ctypes-enum.rs:97:28
    |
-LL |    fn repr_rust(x: Option<Rust<num::NonZero<u8>>>);
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+LL |     fn option_repr_rust(x: Option<Rust<num::NonZero<u8>>>);
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
    |
    = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
    = note: enum has no representation hint
 
-error: `extern` block uses type `Result<(), NonZero<i32>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:89:20
+error: `extern` block uses type `u128`, which is not FFI-safe
+  --> $DIR/lint-ctypes-enum.rs:107:33
+   |
+LL |     fn result_nonzero_u128_t(x: Result<num::NonZero<u128>, ()>);
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = note: 128-bit integers don't currently have a known stable ABI
+
+error: `extern` block uses type `i128`, which is not FFI-safe
+  --> $DIR/lint-ctypes-enum.rs:114:33
+   |
+LL |     fn result_nonzero_i128_t(x: Result<num::NonZero<i128>, ()>);
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = note: 128-bit integers don't currently have a known stable ABI
+
+error: `extern` block uses type `Result<TransparentUnion<NonZero<u8>>, ()>`, which is not FFI-safe
+  --> $DIR/lint-ctypes-enum.rs:119:38
+   |
+LL |     fn result_transparent_union_t(x: Result<TransparentUnion<num::NonZero<u8>>, ()>);
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<Rust<NonZero<u8>>, ()>`, which is not FFI-safe
+  --> $DIR/lint-ctypes-enum.rs:121:30
+   |
+LL |     fn result_repr_rust_t(x: Result<Rust<num::NonZero<u8>>, ()>);
+   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<NonZero<u8>, U>`, which is not FFI-safe
+  --> $DIR/lint-ctypes-enum.rs:125:51
+   |
+LL |     fn result_1zst_exhaustive_single_variant_t(x: Result<num::NonZero<u8>, U>);
+   |                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<NonZero<u8>, B>`, which is not FFI-safe
+  --> $DIR/lint-ctypes-enum.rs:127:53
+   |
+LL |     fn result_1zst_exhaustive_multiple_variant_t(x: Result<num::NonZero<u8>, B>);
+   |                                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<NonZero<u8>, NonExhaustive>`, which is not FFI-safe
+  --> $DIR/lint-ctypes-enum.rs:129:51
+   |
+LL |     fn result_1zst_non_exhaustive_no_variant_t(x: Result<num::NonZero<u8>, NonExhaustive>);
+   |                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<NonZero<u8>, Field>`, which is not FFI-safe
+  --> $DIR/lint-ctypes-enum.rs:132:49
+   |
+LL |     fn result_1zst_exhaustive_single_field_t(x: Result<num::NonZero<u8>, Field>);
+   |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<Result<(), NonZero<u8>>, ()>`, which is not FFI-safe
+  --> $DIR/lint-ctypes-enum.rs:134:30
+   |
+LL |     fn result_cascading_t(x: Result<Result<(), num::NonZero<u8>>, ()>);
+   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `u128`, which is not FFI-safe
+  --> $DIR/lint-ctypes-enum.rs:145:33
+   |
+LL |     fn result_nonzero_u128_e(x: Result<(), num::NonZero<u128>>);
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = note: 128-bit integers don't currently have a known stable ABI
+
+error: `extern` block uses type `i128`, which is not FFI-safe
+  --> $DIR/lint-ctypes-enum.rs:152:33
+   |
+LL |     fn result_nonzero_i128_e(x: Result<(), num::NonZero<i128>>);
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = note: 128-bit integers don't currently have a known stable ABI
+
+error: `extern` block uses type `Result<(), TransparentUnion<NonZero<u8>>>`, which is not FFI-safe
+  --> $DIR/lint-ctypes-enum.rs:157:38
+   |
+LL |     fn result_transparent_union_e(x: Result<(), TransparentUnion<num::NonZero<u8>>>);
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<(), Rust<NonZero<u8>>>`, which is not FFI-safe
+  --> $DIR/lint-ctypes-enum.rs:159:30
+   |
+LL |     fn result_repr_rust_e(x: Result<(), Rust<num::NonZero<u8>>>);
+   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<U, NonZero<u8>>`, which is not FFI-safe
+  --> $DIR/lint-ctypes-enum.rs:163:51
+   |
+LL |     fn result_1zst_exhaustive_single_variant_e(x: Result<U, num::NonZero<u8>>);
+   |                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<B, NonZero<u8>>`, which is not FFI-safe
+  --> $DIR/lint-ctypes-enum.rs:165:53
+   |
+LL |     fn result_1zst_exhaustive_multiple_variant_e(x: Result<B, num::NonZero<u8>>);
+   |                                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<NonExhaustive, NonZero<u8>>`, which is not FFI-safe
+  --> $DIR/lint-ctypes-enum.rs:167:51
+   |
+LL |     fn result_1zst_non_exhaustive_no_variant_e(x: Result<NonExhaustive, num::NonZero<u8>>);
+   |                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<Field, NonZero<u8>>`, which is not FFI-safe
+  --> $DIR/lint-ctypes-enum.rs:170:49
+   |
+LL |     fn result_1zst_exhaustive_single_field_e(x: Result<Field, num::NonZero<u8>>);
+   |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<(), Result<(), NonZero<u8>>>`, which is not FFI-safe
+  --> $DIR/lint-ctypes-enum.rs:172:30
+   |
+LL |     fn result_cascading_e(x: Result<(), Result<(), num::NonZero<u8>>>);
+   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `Result<(), ()>`, which is not FFI-safe
+  --> $DIR/lint-ctypes-enum.rs:174:27
    |
-LL |    fn no_result(x: Result<(), num::NonZero<i32>>);
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+LL |     fn result_unit_t_e(x: Result<(), ()>);
+   |                           ^^^^^^^^^^^^^^ not FFI-safe
    |
    = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
    = note: enum has no representation hint
 
-error: aborting due to 8 previous errors
+error: aborting due to 26 previous errors
 
diff --git a/tests/ui/lint/reference_casting.rs b/tests/ui/lint/reference_casting.rs
index d6897ab7b14..87a682249b0 100644
--- a/tests/ui/lint/reference_casting.rs
+++ b/tests/ui/lint/reference_casting.rs
@@ -247,6 +247,20 @@ unsafe fn bigger_layout() {
     unsafe fn from_ref(this: &i32) -> &i64 {
         &*(this as *const i32 as *const i64)
     }
+
+    // https://github.com/rust-lang/rust/issues/124685
+    unsafe fn slice_index(array: &mut [u8], offset: usize) {
+        let a1 = &mut array[offset];
+        let a2 = a1 as *mut u8;
+        let a3 = a2 as *mut u64;
+        unsafe { *a3 = 3 };
+    }
+
+    unsafe fn field_access(v: &mut Vec3<i32>) {
+        let r = &mut v.0;
+        let ptr = r as *mut i32 as *mut Vec3<i32>;
+        unsafe { *ptr = Vec3(0, 0, 0) }
+    }
 }
 
 const RAW_PTR: *mut u8 = 1 as *mut u8;
diff --git a/tests/crashes/97006.rs b/tests/ui/macros/genercs-in-path-with-prettry-hir.rs
index c8dfa52ebee..84370fcebbc 100644
--- a/tests/crashes/97006.rs
+++ b/tests/ui/macros/genercs-in-path-with-prettry-hir.rs
@@ -1,7 +1,6 @@
-//@ known-bug: #97006
 //@ compile-flags: -Zunpretty=hir
 
-#![allow(unused)]
+// issue#97006
 
 macro_rules! m {
     ($attr_path: path) => {
diff --git a/tests/ui/macros/genercs-in-path-with-prettry-hir.stderr b/tests/ui/macros/genercs-in-path-with-prettry-hir.stderr
new file mode 100644
index 00000000000..8fcc7c6fbff
--- /dev/null
+++ b/tests/ui/macros/genercs-in-path-with-prettry-hir.stderr
@@ -0,0 +1,8 @@
+error: unexpected generic arguments in path
+  --> $DIR/genercs-in-path-with-prettry-hir.rs:12:10
+   |
+LL | m!(inline<u8>);
+   |          ^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/macros/genercs-in-path-with-prettry-hir.stdout b/tests/ui/macros/genercs-in-path-with-prettry-hir.stdout
new file mode 100644
index 00000000000..e9ee59abfae
--- /dev/null
+++ b/tests/ui/macros/genercs-in-path-with-prettry-hir.stdout
@@ -0,0 +1,15 @@
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+#[macro_use]
+extern crate std;
+//@ compile-flags: -Zunpretty=hir
+
+// issue#97006
+
+macro_rules! m { ($attr_path: path) => { #[$attr_path] fn f() {} } }
+#[
+
+inline]
+fn f() { }
+
+fn main() { }
diff --git a/tests/ui/macros/macro-expand-within-generics-in-path.rs b/tests/ui/macros/macro-expand-within-generics-in-path.rs
new file mode 100644
index 00000000000..017d5152221
--- /dev/null
+++ b/tests/ui/macros/macro-expand-within-generics-in-path.rs
@@ -0,0 +1,19 @@
+// issue#123911
+// issue#123912
+
+macro_rules! m {
+    ($p: path) => {
+        #[$p]
+        struct S;
+    };
+}
+
+macro_rules! p {
+    () => {};
+}
+
+m!(generic<p!()>);
+//~^ ERROR: unexpected generic arguments in path
+//~| ERROR: cannot find attribute `generic` in this scope
+
+fn main() {}
diff --git a/tests/ui/macros/macro-expand-within-generics-in-path.stderr b/tests/ui/macros/macro-expand-within-generics-in-path.stderr
new file mode 100644
index 00000000000..72026c41050
--- /dev/null
+++ b/tests/ui/macros/macro-expand-within-generics-in-path.stderr
@@ -0,0 +1,14 @@
+error: unexpected generic arguments in path
+  --> $DIR/macro-expand-within-generics-in-path.rs:15:11
+   |
+LL | m!(generic<p!()>);
+   |           ^^^^^^
+
+error: cannot find attribute `generic` in this scope
+  --> $DIR/macro-expand-within-generics-in-path.rs:15:4
+   |
+LL | m!(generic<p!()>);
+   |    ^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/match/match-range-fail-2.rs b/tests/ui/match/match-range-fail-2.rs
index 4489cf1ab1f..524e84323e7 100644
--- a/tests/ui/match/match-range-fail-2.rs
+++ b/tests/ui/match/match-range-fail-2.rs
@@ -1,5 +1,3 @@
-#![feature(exclusive_range_pattern)]
-
 fn main() {
     match 5 {
         6 ..= 1 => { }
diff --git a/tests/ui/match/match-range-fail-2.stderr b/tests/ui/match/match-range-fail-2.stderr
index 089fa851f97..8bad2e6e147 100644
--- a/tests/ui/match/match-range-fail-2.stderr
+++ b/tests/ui/match/match-range-fail-2.stderr
@@ -1,17 +1,17 @@
 error[E0030]: lower range bound must be less than or equal to upper
-  --> $DIR/match-range-fail-2.rs:5:9
+  --> $DIR/match-range-fail-2.rs:3:9
    |
 LL |         6 ..= 1 => { }
    |         ^^^^^^^ lower bound larger than upper bound
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/match-range-fail-2.rs:11:9
+  --> $DIR/match-range-fail-2.rs:9:9
    |
 LL |         0 .. 0 => { }
    |         ^^^^^^
 
 error[E0030]: lower range bound must be less than or equal to upper
-  --> $DIR/match-range-fail-2.rs:17:9
+  --> $DIR/match-range-fail-2.rs:15:9
    |
 LL |         0xFFFF_FFFF_FFFF_FFFF ..= 1 => { }
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ lower bound larger than upper bound
diff --git a/tests/ui/match/validate-range-endpoints.rs b/tests/ui/match/validate-range-endpoints.rs
index 31d5bc3b65d..46d4239886d 100644
--- a/tests/ui/match/validate-range-endpoints.rs
+++ b/tests/ui/match/validate-range-endpoints.rs
@@ -1,4 +1,3 @@
-#![feature(exclusive_range_pattern)]
 #![feature(inline_const_pat)]
 #![allow(overlapping_range_endpoints)]
 
diff --git a/tests/ui/match/validate-range-endpoints.stderr b/tests/ui/match/validate-range-endpoints.stderr
index b3b4066cd91..2d0538804a3 100644
--- a/tests/ui/match/validate-range-endpoints.stderr
+++ b/tests/ui/match/validate-range-endpoints.stderr
@@ -1,59 +1,59 @@
 error: literal out of range for `u8`
-  --> $DIR/validate-range-endpoints.rs:8:12
+  --> $DIR/validate-range-endpoints.rs:7:12
    |
 LL |         1..257 => {}
    |            ^^^ this value does not fit into the type `u8` whose range is `0..=255`
 
 error: literal out of range for `u8`
-  --> $DIR/validate-range-endpoints.rs:10:13
+  --> $DIR/validate-range-endpoints.rs:9:13
    |
 LL |         1..=256 => {}
    |             ^^^ this value does not fit into the type `u8` whose range is `0..=255`
 
 error[E0030]: lower range bound must be less than or equal to upper
-  --> $DIR/validate-range-endpoints.rs:19:9
+  --> $DIR/validate-range-endpoints.rs:18:9
    |
 LL |         1..=TOO_BIG => {}
    |         ^^^^^^^^^^^ lower bound larger than upper bound
 
 error[E0030]: lower range bound must be less than or equal to upper
-  --> $DIR/validate-range-endpoints.rs:21:9
+  --> $DIR/validate-range-endpoints.rs:20:9
    |
 LL |         1..=const { 256 } => {}
    |         ^^^^^^^^^^^^^^^^^ lower bound larger than upper bound
 
 error: literal out of range for `u64`
-  --> $DIR/validate-range-endpoints.rs:27:32
+  --> $DIR/validate-range-endpoints.rs:26:32
    |
 LL |         10000000000000000000..=99999999999999999999 => {}
    |                                ^^^^^^^^^^^^^^^^^^^^ this value does not fit into the type `u64` whose range is `0..=18446744073709551615`
 
 error: literal out of range for `i8`
-  --> $DIR/validate-range-endpoints.rs:33:12
+  --> $DIR/validate-range-endpoints.rs:32:12
    |
 LL |         0..129 => {}
    |            ^^^ this value does not fit into the type `i8` whose range is `-128..=127`
 
 error: literal out of range for `i8`
-  --> $DIR/validate-range-endpoints.rs:35:13
+  --> $DIR/validate-range-endpoints.rs:34:13
    |
 LL |         0..=128 => {}
    |             ^^^ this value does not fit into the type `i8` whose range is `-128..=127`
 
 error: literal out of range for `i8`
-  --> $DIR/validate-range-endpoints.rs:37:9
+  --> $DIR/validate-range-endpoints.rs:36:9
    |
 LL |         -129..0 => {}
    |         ^^^^ this value does not fit into the type `i8` whose range is `-128..=127`
 
 error: literal out of range for `i8`
-  --> $DIR/validate-range-endpoints.rs:39:9
+  --> $DIR/validate-range-endpoints.rs:38:9
    |
 LL |         -10000..=-20 => {}
    |         ^^^^^^ this value does not fit into the type `i8` whose range is `-128..=127`
 
 error[E0004]: non-exhaustive patterns: `i8::MIN..=-17_i8` and `1_i8..=i8::MAX` not covered
-  --> $DIR/validate-range-endpoints.rs:50:11
+  --> $DIR/validate-range-endpoints.rs:49:11
    |
 LL |     match 0i8 {
    |           ^^^ patterns `i8::MIN..=-17_i8` and `1_i8..=i8::MAX` not covered
@@ -66,7 +66,7 @@ LL +         i8::MIN..=-17_i8 | 1_i8..=i8::MAX => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `i8::MIN..=-17_i8` not covered
-  --> $DIR/validate-range-endpoints.rs:54:11
+  --> $DIR/validate-range-endpoints.rs:53:11
    |
 LL |     match 0i8 {
    |           ^^^ pattern `i8::MIN..=-17_i8` not covered
diff --git a/tests/ui/meta/meta-expected-error-wrong-rev.a.stderr b/tests/ui/meta/meta-expected-error-wrong-rev.a.stderr
index 4221dd04cfa..a489040f32d 100644
--- a/tests/ui/meta/meta-expected-error-wrong-rev.a.stderr
+++ b/tests/ui/meta/meta-expected-error-wrong-rev.a.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/meta-expected-error-wrong-rev.rs:13:18
+  --> $DIR/meta-expected-error-wrong-rev.rs:14:18
    |
 LL |     let x: u32 = 22_usize;
    |            ---   ^^^^^^^^ expected `u32`, found `usize`
diff --git a/tests/ui/meta/meta-expected-error-wrong-rev.rs b/tests/ui/meta/meta-expected-error-wrong-rev.rs
index de276299482..1c3a3fc4923 100644
--- a/tests/ui/meta/meta-expected-error-wrong-rev.rs
+++ b/tests/ui/meta/meta-expected-error-wrong-rev.rs
@@ -1,6 +1,7 @@
 //@ ignore-compare-mode-polonius
 
 //@ revisions: a
+//@ unused-revision-names: b
 //@ should-fail
 
 // This is a "meta-test" of the compilertest framework itself.  In
diff --git a/tests/ui/methods/method-lookup-order.rs b/tests/ui/methods/method-lookup-order.rs
index f794e5a7241..ad56da96686 100644
--- a/tests/ui/methods/method-lookup-order.rs
+++ b/tests/ui/methods/method-lookup-order.rs
@@ -17,6 +17,7 @@
 // {mutbar_for_foo, valbar_for_etmut_foo} (which are lower precedent than the inherent `&mut self` method on `Foo`; e.g. b10101 *is* included.
 
 //@ revisions: b00001 b00010 b00011 b00100 b00101 b00110 b00111 b01000 b01001 b01100 b01101 b10000 b10001 b10010 b10011 b10101 b10111 b11000 b11001 b11101
+//@ unused-revision-names: b01010 b01011 b01110 b01111 b10100 b10110 b11010 b11011 b11100 b11110 b11111
 
 //@ compile-flags: --check-cfg=cfg(inherent_mut,bar_for_foo,mutbar_for_foo)
 //@ compile-flags: --check-cfg=cfg(valbar_for_et_foo,valbar_for_etmut_foo)
diff --git a/tests/ui/mir/mir_match_test.rs b/tests/ui/mir/mir_match_test.rs
index 0da8522f218..ad54a91646a 100644
--- a/tests/ui/mir/mir_match_test.rs
+++ b/tests/ui/mir/mir_match_test.rs
@@ -1,4 +1,3 @@
-#![feature(exclusive_range_pattern)]
 #![allow(overlapping_range_endpoints)]
 #![allow(non_contiguous_range_endpoints)]
 
diff --git a/tests/ui/mismatched_types/non_zero_assigned_something.rs b/tests/ui/mismatched_types/non_zero_assigned_something.rs
index d2adbe01c18..e94d5249d6a 100644
--- a/tests/ui/mismatched_types/non_zero_assigned_something.rs
+++ b/tests/ui/mismatched_types/non_zero_assigned_something.rs
@@ -1,9 +1,9 @@
 fn main() {
-    let _: std::num::NonZeroU64 = 1;
+    let _: std::num::NonZero<u64> = 1;
     //~^ ERROR mismatched types
-    //~| HELP  consider calling `NonZeroU64::new`
+    //~| HELP  consider calling `NonZero::new`
 
-    let _: Option<std::num::NonZeroU64> = 1;
+    let _: Option<std::num::NonZero<u64>> = 1;
     //~^ ERROR mismatched types
-    //~| HELP  consider calling `NonZeroU64::new`
+    //~| HELP  consider calling `NonZero::new`
 }
diff --git a/tests/ui/mismatched_types/non_zero_assigned_something.stderr b/tests/ui/mismatched_types/non_zero_assigned_something.stderr
index f8e86905ab9..aa015bd2efc 100644
--- a/tests/ui/mismatched_types/non_zero_assigned_something.stderr
+++ b/tests/ui/mismatched_types/non_zero_assigned_something.stderr
@@ -1,32 +1,32 @@
 error[E0308]: mismatched types
-  --> $DIR/non_zero_assigned_something.rs:2:35
+  --> $DIR/non_zero_assigned_something.rs:2:37
    |
-LL |     let _: std::num::NonZeroU64 = 1;
-   |            --------------------   ^ expected `NonZero<u64>`, found integer
+LL |     let _: std::num::NonZero<u64> = 1;
+   |            ----------------------   ^ expected `NonZero<u64>`, found integer
    |            |
    |            expected due to this
    |
    = note: expected struct `NonZero<u64>`
                 found type `{integer}`
-help: consider calling `NonZeroU64::new`
+help: consider calling `NonZero::new`
    |
-LL |     let _: std::num::NonZeroU64 = NonZeroU64::new(1).unwrap();
-   |                                   ++++++++++++++++ ++++++++++
+LL |     let _: std::num::NonZero<u64> = NonZero::new(1).unwrap();
+   |                                     +++++++++++++ ++++++++++
 
 error[E0308]: mismatched types
-  --> $DIR/non_zero_assigned_something.rs:6:43
+  --> $DIR/non_zero_assigned_something.rs:6:45
    |
-LL |     let _: Option<std::num::NonZeroU64> = 1;
-   |            ----------------------------   ^ expected `Option<NonZero<u64>>`, found integer
+LL |     let _: Option<std::num::NonZero<u64>> = 1;
+   |            ------------------------------   ^ expected `Option<NonZero<u64>>`, found integer
    |            |
    |            expected due to this
    |
    = note: expected enum `Option<NonZero<u64>>`
               found type `{integer}`
-help: consider calling `NonZeroU64::new`
+help: consider calling `NonZero::new`
    |
-LL |     let _: Option<std::num::NonZeroU64> = NonZeroU64::new(1);
-   |                                           ++++++++++++++++ +
+LL |     let _: Option<std::num::NonZero<u64>> = NonZero::new(1);
+   |                                             +++++++++++++ +
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/parser/attribute/attr-bad-meta-4.rs b/tests/ui/parser/attribute/attr-bad-meta-4.rs
index cedbd1d6686..2a69ae5ac06 100644
--- a/tests/ui/parser/attribute/attr-bad-meta-4.rs
+++ b/tests/ui/parser/attribute/attr-bad-meta-4.rs
@@ -1,12 +1,17 @@
 macro_rules! mac {
     ($attr_item: meta) => {
         #[cfg($attr_item)]
-        //~^ ERROR expected unsuffixed literal or identifier, found `an(arbitrary token stream)`
-        //~| ERROR expected unsuffixed literal or identifier, found `an(arbitrary token stream)`
+        //~^ ERROR expected unsuffixed literal, found `an(arbitrary token stream)`
+        //~| ERROR expected unsuffixed literal, found `an(arbitrary token stream)`
         struct S;
     }
 }
 
 mac!(an(arbitrary token stream));
 
+#[cfg(feature = -1)]
+//~^ ERROR expected unsuffixed literal, found `-`
+//~| ERROR expected unsuffixed literal, found `-`
+fn handler() {}
+
 fn main() {}
diff --git a/tests/ui/parser/attribute/attr-bad-meta-4.stderr b/tests/ui/parser/attribute/attr-bad-meta-4.stderr
index a543bcb692e..192be28db3f 100644
--- a/tests/ui/parser/attribute/attr-bad-meta-4.stderr
+++ b/tests/ui/parser/attribute/attr-bad-meta-4.stderr
@@ -1,4 +1,10 @@
-error: expected unsuffixed literal or identifier, found `an(arbitrary token stream)`
+error: expected unsuffixed literal, found `-`
+  --> $DIR/attr-bad-meta-4.rs:12:17
+   |
+LL | #[cfg(feature = -1)]
+   |                 ^
+
+error: expected unsuffixed literal, found `an(arbitrary token stream)`
   --> $DIR/attr-bad-meta-4.rs:3:15
    |
 LL |         #[cfg($attr_item)]
@@ -9,7 +15,7 @@ LL | mac!(an(arbitrary token stream));
    |
    = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: expected unsuffixed literal or identifier, found `an(arbitrary token stream)`
+error: expected unsuffixed literal, found `an(arbitrary token stream)`
   --> $DIR/attr-bad-meta-4.rs:3:15
    |
 LL |         #[cfg($attr_item)]
@@ -21,5 +27,13 @@ LL | mac!(an(arbitrary token stream));
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
    = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 2 previous errors
+error: expected unsuffixed literal, found `-`
+  --> $DIR/attr-bad-meta-4.rs:12:17
+   |
+LL | #[cfg(feature = -1)]
+   |                 ^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 4 previous errors
 
diff --git a/tests/ui/parser/attribute/attr-unquoted-ident.fixed b/tests/ui/parser/attribute/attr-unquoted-ident.fixed
deleted file mode 100644
index bc861ef69fb..00000000000
--- a/tests/ui/parser/attribute/attr-unquoted-ident.fixed
+++ /dev/null
@@ -1,17 +0,0 @@
-//@ compile-flags: -Zdeduplicate-diagnostics=yes
-//@ run-rustfix
-
-#![allow(unexpected_cfgs)]
-
-fn main() {
-    #[cfg(key="foo")]
-    //~^ ERROR expected unsuffixed literal, found `foo`
-    //~| HELP surround the identifier with quotation marks to parse it as a string
-    println!();
-    #[cfg(key="bar")]
-    println!();
-    #[cfg(key="foo bar baz")]
-    //~^ ERROR expected unsuffixed literal, found `foo`
-    //~| HELP surround the identifier with quotation marks to parse it as a string
-    println!();
-}
diff --git a/tests/ui/parser/attribute/attr-unquoted-ident.rs b/tests/ui/parser/attribute/attr-unquoted-ident.rs
index 8bdb8605ebb..5b15b8d69fc 100644
--- a/tests/ui/parser/attribute/attr-unquoted-ident.rs
+++ b/tests/ui/parser/attribute/attr-unquoted-ident.rs
@@ -1,17 +1,25 @@
 //@ compile-flags: -Zdeduplicate-diagnostics=yes
-//@ run-rustfix
 
 #![allow(unexpected_cfgs)]
 
 fn main() {
     #[cfg(key=foo)]
     //~^ ERROR expected unsuffixed literal, found `foo`
-    //~| HELP surround the identifier with quotation marks to parse it as a string
+    //~| HELP surround the identifier with quotation marks to make it into a string literal
     println!();
     #[cfg(key="bar")]
     println!();
     #[cfg(key=foo bar baz)]
     //~^ ERROR expected unsuffixed literal, found `foo`
-    //~| HELP surround the identifier with quotation marks to parse it as a string
+    //~| HELP surround the identifier with quotation marks to make it into a string literal
     println!();
 }
+
+// Don't suggest surrounding `$name` or `nickname` with quotes:
+
+macro_rules! make {
+    ($name:ident) => { #[doc(alias = $name)] pub struct S; }
+    //~^ ERROR expected unsuffixed literal, found `nickname`
+}
+
+make!(nickname); //~ NOTE in this expansion
diff --git a/tests/ui/parser/attribute/attr-unquoted-ident.stderr b/tests/ui/parser/attribute/attr-unquoted-ident.stderr
index 99484a51110..e0f99459c44 100644
--- a/tests/ui/parser/attribute/attr-unquoted-ident.stderr
+++ b/tests/ui/parser/attribute/attr-unquoted-ident.stderr
@@ -1,24 +1,35 @@
 error: expected unsuffixed literal, found `foo`
-  --> $DIR/attr-unquoted-ident.rs:7:15
+  --> $DIR/attr-unquoted-ident.rs:6:15
    |
 LL |     #[cfg(key=foo)]
    |               ^^^
    |
-help: surround the identifier with quotation marks to parse it as a string
+help: surround the identifier with quotation marks to make it into a string literal
    |
 LL |     #[cfg(key="foo")]
    |               +   +
 
 error: expected unsuffixed literal, found `foo`
-  --> $DIR/attr-unquoted-ident.rs:13:15
+  --> $DIR/attr-unquoted-ident.rs:12:15
    |
 LL |     #[cfg(key=foo bar baz)]
    |               ^^^
    |
-help: surround the identifier with quotation marks to parse it as a string
+help: surround the identifier with quotation marks to make it into a string literal
    |
 LL |     #[cfg(key="foo bar baz")]
    |               +           +
 
-error: aborting due to 2 previous errors
+error: expected unsuffixed literal, found `nickname`
+  --> $DIR/attr-unquoted-ident.rs:21:38
+   |
+LL |     ($name:ident) => { #[doc(alias = $name)] pub struct S; }
+   |                                      ^^^^^
+...
+LL | make!(nickname);
+   | --------------- in this macro invocation
+   |
+   = note: this error originates in the macro `make` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 3 previous errors
 
diff --git a/tests/ui/parser/issues/issue-63115-range-pat-interpolated.rs b/tests/ui/parser/issues/issue-63115-range-pat-interpolated.rs
index d1a5f32b954..9a6bd4442e5 100644
--- a/tests/ui/parser/issues/issue-63115-range-pat-interpolated.rs
+++ b/tests/ui/parser/issues/issue-63115-range-pat-interpolated.rs
@@ -1,7 +1,5 @@
 //@ check-pass
 
-#![feature(exclusive_range_pattern)]
-
 #![allow(ellipsis_inclusive_range_patterns)]
 
 fn main() {
diff --git a/tests/ui/parser/recover/recover-range-pats.rs b/tests/ui/parser/recover/recover-range-pats.rs
index 3dc525cd6e1..42cd69fd959 100644
--- a/tests/ui/parser/recover/recover-range-pats.rs
+++ b/tests/ui/parser/recover/recover-range-pats.rs
@@ -3,7 +3,6 @@
 // 1. Things parse as they should.
 // 2. Or at least we have parser recovery if they don't.
 
-#![feature(exclusive_range_pattern)]
 #![deny(ellipsis_inclusive_range_patterns)]
 
 fn main() {}
diff --git a/tests/ui/parser/recover/recover-range-pats.stderr b/tests/ui/parser/recover/recover-range-pats.stderr
index 2c0baf7e5f8..e0ea8ec24dc 100644
--- a/tests/ui/parser/recover/recover-range-pats.stderr
+++ b/tests/ui/parser/recover/recover-range-pats.stderr
@@ -1,47 +1,47 @@
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:21:12
+  --> $DIR/recover-range-pats.rs:20:12
    |
 LL |     if let .0..Y = 0 {}
    |            ^^ help: must have an integer part: `0.0`
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:23:16
+  --> $DIR/recover-range-pats.rs:22:16
    |
 LL |     if let X.. .0 = 0 {}
    |                ^^ help: must have an integer part: `0.0`
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:34:12
+  --> $DIR/recover-range-pats.rs:33:12
    |
 LL |     if let .0..=Y = 0 {}
    |            ^^ help: must have an integer part: `0.0`
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:36:16
+  --> $DIR/recover-range-pats.rs:35:16
    |
 LL |     if let X..=.0 = 0 {}
    |                ^^ help: must have an integer part: `0.0`
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:59:12
+  --> $DIR/recover-range-pats.rs:58:12
    |
 LL |     if let .0...Y = 0 {}
    |            ^^ help: must have an integer part: `0.0`
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:63:17
+  --> $DIR/recover-range-pats.rs:62:17
    |
 LL |     if let X... .0 = 0 {}
    |                 ^^ help: must have an integer part: `0.0`
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:74:12
+  --> $DIR/recover-range-pats.rs:73:12
    |
 LL |     if let .0.. = 0 {}
    |            ^^ help: must have an integer part: `0.0`
 
 error[E0586]: inclusive range with no end
-  --> $DIR/recover-range-pats.rs:80:13
+  --> $DIR/recover-range-pats.rs:79:13
    |
 LL |     if let 0..= = 0 {}
    |             ^^^ help: use `..` instead
@@ -49,7 +49,7 @@ LL |     if let 0..= = 0 {}
    = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error[E0586]: inclusive range with no end
-  --> $DIR/recover-range-pats.rs:81:13
+  --> $DIR/recover-range-pats.rs:80:13
    |
 LL |     if let X..= = 0 {}
    |             ^^^ help: use `..` instead
@@ -57,7 +57,7 @@ LL |     if let X..= = 0 {}
    = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error[E0586]: inclusive range with no end
-  --> $DIR/recover-range-pats.rs:82:16
+  --> $DIR/recover-range-pats.rs:81:16
    |
 LL |     if let true..= = 0 {}
    |                ^^^ help: use `..` instead
@@ -65,13 +65,13 @@ LL |     if let true..= = 0 {}
    = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:84:12
+  --> $DIR/recover-range-pats.rs:83:12
    |
 LL |     if let .0..= = 0 {}
    |            ^^ help: must have an integer part: `0.0`
 
 error[E0586]: inclusive range with no end
-  --> $DIR/recover-range-pats.rs:84:14
+  --> $DIR/recover-range-pats.rs:83:14
    |
 LL |     if let .0..= = 0 {}
    |              ^^^ help: use `..` instead
@@ -79,7 +79,7 @@ LL |     if let .0..= = 0 {}
    = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error[E0586]: inclusive range with no end
-  --> $DIR/recover-range-pats.rs:90:13
+  --> $DIR/recover-range-pats.rs:89:13
    |
 LL |     if let 0... = 0 {}
    |             ^^^ help: use `..` instead
@@ -87,7 +87,7 @@ LL |     if let 0... = 0 {}
    = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error[E0586]: inclusive range with no end
-  --> $DIR/recover-range-pats.rs:91:13
+  --> $DIR/recover-range-pats.rs:90:13
    |
 LL |     if let X... = 0 {}
    |             ^^^ help: use `..` instead
@@ -95,7 +95,7 @@ LL |     if let X... = 0 {}
    = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error[E0586]: inclusive range with no end
-  --> $DIR/recover-range-pats.rs:92:16
+  --> $DIR/recover-range-pats.rs:91:16
    |
 LL |     if let true... = 0 {}
    |                ^^^ help: use `..` instead
@@ -103,13 +103,13 @@ LL |     if let true... = 0 {}
    = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:94:12
+  --> $DIR/recover-range-pats.rs:93:12
    |
 LL |     if let .0... = 0 {}
    |            ^^ help: must have an integer part: `0.0`
 
 error[E0586]: inclusive range with no end
-  --> $DIR/recover-range-pats.rs:94:14
+  --> $DIR/recover-range-pats.rs:93:14
    |
 LL |     if let .0... = 0 {}
    |              ^^^ help: use `..` instead
@@ -117,49 +117,49 @@ LL |     if let .0... = 0 {}
    = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:104:15
+  --> $DIR/recover-range-pats.rs:103:15
    |
 LL |     if let .. .0 = 0 {}
    |               ^^ help: must have an integer part: `0.0`
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:114:15
+  --> $DIR/recover-range-pats.rs:113:15
    |
 LL |     if let ..=.0 = 0 {}
    |               ^^ help: must have an integer part: `0.0`
 
 error: range-to patterns with `...` are not allowed
-  --> $DIR/recover-range-pats.rs:120:12
+  --> $DIR/recover-range-pats.rs:119:12
    |
 LL |     if let ...3 = 0 {}
    |            ^^^ help: use `..=` instead
 
 error: range-to patterns with `...` are not allowed
-  --> $DIR/recover-range-pats.rs:122:12
+  --> $DIR/recover-range-pats.rs:121:12
    |
 LL |     if let ...Y = 0 {}
    |            ^^^ help: use `..=` instead
 
 error: range-to patterns with `...` are not allowed
-  --> $DIR/recover-range-pats.rs:124:12
+  --> $DIR/recover-range-pats.rs:123:12
    |
 LL |     if let ...true = 0 {}
    |            ^^^ help: use `..=` instead
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:127:15
+  --> $DIR/recover-range-pats.rs:126:15
    |
 LL |     if let ....3 = 0 {}
    |               ^^ help: must have an integer part: `0.3`
 
 error: range-to patterns with `...` are not allowed
-  --> $DIR/recover-range-pats.rs:127:12
+  --> $DIR/recover-range-pats.rs:126:12
    |
 LL |     if let ....3 = 0 {}
    |            ^^^ help: use `..=` instead
 
 error: range-to patterns with `...` are not allowed
-  --> $DIR/recover-range-pats.rs:153:17
+  --> $DIR/recover-range-pats.rs:152:17
    |
 LL |             let ...$e;
    |                 ^^^ help: use `..=` instead
@@ -170,7 +170,7 @@ LL |     mac!(0);
    = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0586]: inclusive range with no end
-  --> $DIR/recover-range-pats.rs:160:19
+  --> $DIR/recover-range-pats.rs:159:19
    |
 LL |             let $e...;
    |                   ^^^ help: use `..` instead
@@ -182,7 +182,7 @@ LL |     mac!(0);
    = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0586]: inclusive range with no end
-  --> $DIR/recover-range-pats.rs:162:19
+  --> $DIR/recover-range-pats.rs:161:19
    |
 LL |             let $e..=;
    |                   ^^^ help: use `..` instead
@@ -194,7 +194,7 @@ LL |     mac!(0);
    = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:41:13
+  --> $DIR/recover-range-pats.rs:40:13
    |
 LL |     if let 0...3 = 0 {}
    |             ^^^ help: use `..=` for an inclusive range
@@ -202,13 +202,13 @@ LL |     if let 0...3 = 0 {}
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 note: the lint level is defined here
-  --> $DIR/recover-range-pats.rs:7:9
+  --> $DIR/recover-range-pats.rs:6:9
    |
 LL | #![deny(ellipsis_inclusive_range_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:44:13
+  --> $DIR/recover-range-pats.rs:43:13
    |
 LL |     if let 0...Y = 0 {}
    |             ^^^ help: use `..=` for an inclusive range
@@ -217,7 +217,7 @@ LL |     if let 0...Y = 0 {}
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:47:13
+  --> $DIR/recover-range-pats.rs:46:13
    |
 LL |     if let X...3 = 0 {}
    |             ^^^ help: use `..=` for an inclusive range
@@ -226,7 +226,7 @@ LL |     if let X...3 = 0 {}
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:50:13
+  --> $DIR/recover-range-pats.rs:49:13
    |
 LL |     if let X...Y = 0 {}
    |             ^^^ help: use `..=` for an inclusive range
@@ -235,7 +235,7 @@ LL |     if let X...Y = 0 {}
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:53:16
+  --> $DIR/recover-range-pats.rs:52:16
    |
 LL |     if let true...Y = 0 {}
    |                ^^^ help: use `..=` for an inclusive range
@@ -244,7 +244,7 @@ LL |     if let true...Y = 0 {}
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:56:13
+  --> $DIR/recover-range-pats.rs:55:13
    |
 LL |     if let X...true = 0 {}
    |             ^^^ help: use `..=` for an inclusive range
@@ -253,7 +253,7 @@ LL |     if let X...true = 0 {}
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:59:14
+  --> $DIR/recover-range-pats.rs:58:14
    |
 LL |     if let .0...Y = 0 {}
    |              ^^^ help: use `..=` for an inclusive range
@@ -262,7 +262,7 @@ LL |     if let .0...Y = 0 {}
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:63:13
+  --> $DIR/recover-range-pats.rs:62:13
    |
 LL |     if let X... .0 = 0 {}
    |             ^^^ help: use `..=` for an inclusive range
@@ -271,7 +271,7 @@ LL |     if let X... .0 = 0 {}
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:138:20
+  --> $DIR/recover-range-pats.rs:137:20
    |
 LL |             let $e1...$e2;
    |                    ^^^ help: use `..=` for an inclusive range
@@ -284,7 +284,7 @@ LL |     mac2!(0, 1);
    = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0029]: only `char` and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:19:12
+  --> $DIR/recover-range-pats.rs:18:12
    |
 LL |     if let true..Y = 0 {}
    |            ^^^^  - this is of type `u8`
@@ -292,7 +292,7 @@ LL |     if let true..Y = 0 {}
    |            this is of type `bool` but it should be `char` or numeric
 
 error[E0029]: only `char` and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:20:15
+  --> $DIR/recover-range-pats.rs:19:15
    |
 LL |     if let X..true = 0 {}
    |            -  ^^^^ this is of type `bool` but it should be `char` or numeric
@@ -300,7 +300,7 @@ LL |     if let X..true = 0 {}
    |            this is of type `u8`
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:21:12
+  --> $DIR/recover-range-pats.rs:20:12
    |
 LL |     if let .0..Y = 0 {}
    |            ^^  -   - this expression has type `{integer}`
@@ -309,7 +309,7 @@ LL |     if let .0..Y = 0 {}
    |            expected integer, found floating-point number
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:23:16
+  --> $DIR/recover-range-pats.rs:22:16
    |
 LL |     if let X.. .0 = 0 {}
    |            -   ^^   - this expression has type `u8`
@@ -321,7 +321,7 @@ LL |     if let X.. .0 = 0 {}
               found type `{float}`
 
 error[E0029]: only `char` and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:32:12
+  --> $DIR/recover-range-pats.rs:31:12
    |
 LL |     if let true..=Y = 0 {}
    |            ^^^^   - this is of type `u8`
@@ -329,7 +329,7 @@ LL |     if let true..=Y = 0 {}
    |            this is of type `bool` but it should be `char` or numeric
 
 error[E0029]: only `char` and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:33:16
+  --> $DIR/recover-range-pats.rs:32:16
    |
 LL |     if let X..=true = 0 {}
    |            -   ^^^^ this is of type `bool` but it should be `char` or numeric
@@ -337,7 +337,7 @@ LL |     if let X..=true = 0 {}
    |            this is of type `u8`
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:34:12
+  --> $DIR/recover-range-pats.rs:33:12
    |
 LL |     if let .0..=Y = 0 {}
    |            ^^   -   - this expression has type `{integer}`
@@ -346,7 +346,7 @@ LL |     if let .0..=Y = 0 {}
    |            expected integer, found floating-point number
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:36:16
+  --> $DIR/recover-range-pats.rs:35:16
    |
 LL |     if let X..=.0 = 0 {}
    |            -   ^^   - this expression has type `u8`
@@ -358,7 +358,7 @@ LL |     if let X..=.0 = 0 {}
               found type `{float}`
 
 error[E0029]: only `char` and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:53:12
+  --> $DIR/recover-range-pats.rs:52:12
    |
 LL |     if let true...Y = 0 {}
    |            ^^^^   - this is of type `u8`
@@ -366,7 +366,7 @@ LL |     if let true...Y = 0 {}
    |            this is of type `bool` but it should be `char` or numeric
 
 error[E0029]: only `char` and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:56:16
+  --> $DIR/recover-range-pats.rs:55:16
    |
 LL |     if let X...true = 0 {}
    |            -   ^^^^ this is of type `bool` but it should be `char` or numeric
@@ -374,7 +374,7 @@ LL |     if let X...true = 0 {}
    |            this is of type `u8`
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:59:12
+  --> $DIR/recover-range-pats.rs:58:12
    |
 LL |     if let .0...Y = 0 {}
    |            ^^   -   - this expression has type `{integer}`
@@ -383,7 +383,7 @@ LL |     if let .0...Y = 0 {}
    |            expected integer, found floating-point number
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:63:17
+  --> $DIR/recover-range-pats.rs:62:17
    |
 LL |     if let X... .0 = 0 {}
    |            -    ^^   - this expression has type `u8`
@@ -395,13 +395,13 @@ LL |     if let X... .0 = 0 {}
               found type `{float}`
 
 error[E0029]: only `char` and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:72:12
+  --> $DIR/recover-range-pats.rs:71:12
    |
 LL |     if let true.. = 0 {}
    |            ^^^^ this is of type `bool` but it should be `char` or numeric
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:74:12
+  --> $DIR/recover-range-pats.rs:73:12
    |
 LL |     if let .0.. = 0 {}
    |            ^^     - this expression has type `{integer}`
@@ -409,13 +409,13 @@ LL |     if let .0.. = 0 {}
    |            expected integer, found floating-point number
 
 error[E0029]: only `char` and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:82:12
+  --> $DIR/recover-range-pats.rs:81:12
    |
 LL |     if let true..= = 0 {}
    |            ^^^^ this is of type `bool` but it should be `char` or numeric
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:84:12
+  --> $DIR/recover-range-pats.rs:83:12
    |
 LL |     if let .0..= = 0 {}
    |            ^^      - this expression has type `{integer}`
@@ -423,13 +423,13 @@ LL |     if let .0..= = 0 {}
    |            expected integer, found floating-point number
 
 error[E0029]: only `char` and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:92:12
+  --> $DIR/recover-range-pats.rs:91:12
    |
 LL |     if let true... = 0 {}
    |            ^^^^ this is of type `bool` but it should be `char` or numeric
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:94:12
+  --> $DIR/recover-range-pats.rs:93:12
    |
 LL |     if let .0... = 0 {}
    |            ^^      - this expression has type `{integer}`
@@ -437,13 +437,13 @@ LL |     if let .0... = 0 {}
    |            expected integer, found floating-point number
 
 error[E0029]: only `char` and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:102:14
+  --> $DIR/recover-range-pats.rs:101:14
    |
 LL |     if let ..true = 0 {}
    |              ^^^^ this is of type `bool` but it should be `char` or numeric
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:104:15
+  --> $DIR/recover-range-pats.rs:103:15
    |
 LL |     if let .. .0 = 0 {}
    |               ^^   - this expression has type `{integer}`
@@ -451,13 +451,13 @@ LL |     if let .. .0 = 0 {}
    |               expected integer, found floating-point number
 
 error[E0029]: only `char` and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:112:15
+  --> $DIR/recover-range-pats.rs:111:15
    |
 LL |     if let ..=true = 0 {}
    |               ^^^^ this is of type `bool` but it should be `char` or numeric
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:114:15
+  --> $DIR/recover-range-pats.rs:113:15
    |
 LL |     if let ..=.0 = 0 {}
    |               ^^   - this expression has type `{integer}`
@@ -465,13 +465,13 @@ LL |     if let ..=.0 = 0 {}
    |               expected integer, found floating-point number
 
 error[E0029]: only `char` and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:124:15
+  --> $DIR/recover-range-pats.rs:123:15
    |
 LL |     if let ...true = 0 {}
    |               ^^^^ this is of type `bool` but it should be `char` or numeric
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:127:15
+  --> $DIR/recover-range-pats.rs:126:15
    |
 LL |     if let ....3 = 0 {}
    |               ^^   - this expression has type `{integer}`
@@ -479,7 +479,7 @@ LL |     if let ....3 = 0 {}
    |               expected integer, found floating-point number
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/recover-range-pats.rs:136:17
+  --> $DIR/recover-range-pats.rs:135:17
    |
 LL |             let $e1..$e2;
    |                 ^^^^^^^^ patterns `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered
@@ -493,7 +493,7 @@ LL |     mac2!(0, 1);
    = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/recover-range-pats.rs:138:17
+  --> $DIR/recover-range-pats.rs:137:17
    |
 LL |             let $e1...$e2;
    |                 ^^^^^^^^^ patterns `i32::MIN..=-1_i32` and `2_i32..=i32::MAX` not covered
@@ -507,7 +507,7 @@ LL |     mac2!(0, 1);
    = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/recover-range-pats.rs:142:17
+  --> $DIR/recover-range-pats.rs:141:17
    |
 LL |             let $e1..=$e2;
    |                 ^^^^^^^^^ patterns `i32::MIN..=-1_i32` and `2_i32..=i32::MAX` not covered
@@ -521,7 +521,7 @@ LL |     mac2!(0, 1);
    = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/recover-range-pats.rs:151:17
+  --> $DIR/recover-range-pats.rs:150:17
    |
 LL |             let ..$e;
    |                 ^^^^ pattern `0_i32..=i32::MAX` not covered
@@ -535,7 +535,7 @@ LL |     mac!(0);
    = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/recover-range-pats.rs:153:17
+  --> $DIR/recover-range-pats.rs:152:17
    |
 LL |             let ...$e;
    |                 ^^^^^ pattern `1_i32..=i32::MAX` not covered
@@ -549,7 +549,7 @@ LL |     mac!(0);
    = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/recover-range-pats.rs:156:17
+  --> $DIR/recover-range-pats.rs:155:17
    |
 LL |             let ..=$e;
    |                 ^^^^^ pattern `1_i32..=i32::MAX` not covered
@@ -563,7 +563,7 @@ LL |     mac!(0);
    = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/recover-range-pats.rs:158:17
+  --> $DIR/recover-range-pats.rs:157:17
    |
 LL |             let $e..;
    |                 ^^^^ pattern `i32::MIN..=-1_i32` not covered
@@ -577,7 +577,7 @@ LL |     mac!(0);
    = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/recover-range-pats.rs:160:17
+  --> $DIR/recover-range-pats.rs:159:17
    |
 LL |             let $e...;
    |                 ^^^^^ pattern `i32::MIN..=-1_i32` not covered
@@ -591,7 +591,7 @@ LL |     mac!(0);
    = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/recover-range-pats.rs:162:17
+  --> $DIR/recover-range-pats.rs:161:17
    |
 LL |             let $e..=;
    |                 ^^^^^ pattern `i32::MIN..=-1_i32` not covered
diff --git a/tests/ui/parser/recover/turbofish-arg-with-stray-colon.rs b/tests/ui/parser/recover/turbofish-arg-with-stray-colon.rs
new file mode 100644
index 00000000000..32125211a91
--- /dev/null
+++ b/tests/ui/parser/recover/turbofish-arg-with-stray-colon.rs
@@ -0,0 +1,6 @@
+fn foo() {
+    let x = Tr<A, A:>;
+    //~^ ERROR expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `,`
+}
+
+fn main() {}
diff --git a/tests/ui/parser/recover/turbofish-arg-with-stray-colon.stderr b/tests/ui/parser/recover/turbofish-arg-with-stray-colon.stderr
new file mode 100644
index 00000000000..551b2e3ff09
--- /dev/null
+++ b/tests/ui/parser/recover/turbofish-arg-with-stray-colon.stderr
@@ -0,0 +1,14 @@
+error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `,`
+  --> $DIR/turbofish-arg-with-stray-colon.rs:2:17
+   |
+LL |     let x = Tr<A, A:>;
+   |                 ^ expected one of 8 possible tokens
+   |
+   = note: type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
+help: maybe write a path separator here
+   |
+LL |     let x = Tr<A, A::>;
+   |                    ~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.rs b/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.rs
index 1eba7aeb4d6..fe7655c2c4e 100644
--- a/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.rs
+++ b/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.rs
@@ -11,7 +11,6 @@ fn main() {
         [_, ..tail] => println!("{tail}"),
         //~^ ERROR cannot find value `tail` in this scope
         //~| ERROR cannot find value `tail` in this scope
-        //~| ERROR exclusive range pattern syntax is experimental
     }
     match &[7, 8, 9][..] {
         [] => {}
diff --git a/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.stderr b/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.stderr
index 3a19517c85b..37c02eb6ada 100644
--- a/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.stderr
+++ b/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.stderr
@@ -1,5 +1,5 @@
 error: range-to patterns with `...` are not allowed
-  --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:18:13
+  --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:17:13
    |
 LL |         [_, ...tail] => println!("{tail}"),
    |             ^^^ help: use `..=` instead
@@ -39,7 +39,7 @@ LL |         [_, ..tail] => println!("{tail}"),
    |                                   ^^^^ not found in this scope
 
 error[E0425]: cannot find value `tail` in this scope
-  --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:18:16
+  --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:17:16
    |
 LL |         [_, ...tail] => println!("{tail}"),
    |                ^^^^ not found in this scope
@@ -50,7 +50,7 @@ LL |         [_, tail @ ..] => println!("{tail}"),
    |             ~~~~~~~~~
 
 error[E0425]: cannot find value `tail` in this scope
-  --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:18:36
+  --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:17:36
    |
 LL |         [_, ...tail] => println!("{tail}"),
    |                                    ^^^^ not found in this scope
@@ -65,18 +65,7 @@ LL |         [1, rest..] => println!("{rest}"),
    = help: add `#![feature(half_open_range_patterns_in_slices)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: exclusive range pattern syntax is experimental
-  --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:11:13
-   |
-LL |         [_, ..tail] => println!("{tail}"),
-   |             ^^^^^^
-   |
-   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
-   = help: add `#![feature(exclusive_range_pattern)]` 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: use an inclusive range pattern, like N..=M
-
-error: aborting due to 9 previous errors
+error: aborting due to 8 previous errors
 
 Some errors have detailed explanations: E0425, E0658.
 For more information about an error, try `rustc --explain E0425`.
diff --git a/tests/ui/pattern/usefulness/floats.rs b/tests/ui/pattern/usefulness/floats.rs
index 63ce26adab2..b3d49ba8e15 100644
--- a/tests/ui/pattern/usefulness/floats.rs
+++ b/tests/ui/pattern/usefulness/floats.rs
@@ -1,4 +1,3 @@
-#![feature(exclusive_range_pattern)]
 #![deny(unreachable_patterns)]
 
 fn main() {
diff --git a/tests/ui/pattern/usefulness/floats.stderr b/tests/ui/pattern/usefulness/floats.stderr
index d99f05f5284..04f2fe3cd94 100644
--- a/tests/ui/pattern/usefulness/floats.stderr
+++ b/tests/ui/pattern/usefulness/floats.stderr
@@ -1,5 +1,5 @@
 error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/floats.rs:10:11
+  --> $DIR/floats.rs:9:11
    |
 LL |     match 0.0 {
    |           ^^^ pattern `_` not covered
@@ -12,49 +12,49 @@ LL +         _ => todo!()
    |
 
 error: unreachable pattern
-  --> $DIR/floats.rs:18:9
+  --> $DIR/floats.rs:17:9
    |
 LL |         0.01f64 => {}
    |         ^^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/floats.rs:2:9
+  --> $DIR/floats.rs:1:9
    |
 LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/floats.rs:19:9
+  --> $DIR/floats.rs:18:9
    |
 LL |         0.02f64 => {}
    |         ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/floats.rs:20:9
+  --> $DIR/floats.rs:19:9
    |
 LL |         6.5f64 => {}
    |         ^^^^^^
 
 error: unreachable pattern
-  --> $DIR/floats.rs:22:9
+  --> $DIR/floats.rs:21:9
    |
 LL |         1.0f64..=4.0f64 => {}
    |         ^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/floats.rs:34:9
+  --> $DIR/floats.rs:33:9
    |
 LL |         0.01f32 => {}
    |         ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/floats.rs:35:9
+  --> $DIR/floats.rs:34:9
    |
 LL |         0.02f32 => {}
    |         ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/floats.rs:36:9
+  --> $DIR/floats.rs:35:9
    |
 LL |         6.5f32 => {}
    |         ^^^^^^
diff --git a/tests/ui/pattern/usefulness/guards.rs b/tests/ui/pattern/usefulness/guards.rs
index b15440cf608..94ee8ee14ad 100644
--- a/tests/ui/pattern/usefulness/guards.rs
+++ b/tests/ui/pattern/usefulness/guards.rs
@@ -1,4 +1,3 @@
-#![feature(exclusive_range_pattern)]
 #![deny(unreachable_patterns)]
 
 enum Q { R(Option<usize>) }
diff --git a/tests/ui/pattern/usefulness/guards.stderr b/tests/ui/pattern/usefulness/guards.stderr
index ad9046fe248..82ed2a93c55 100644
--- a/tests/ui/pattern/usefulness/guards.stderr
+++ b/tests/ui/pattern/usefulness/guards.stderr
@@ -1,5 +1,5 @@
 error[E0004]: non-exhaustive patterns: `128_u8..=u8::MAX` not covered
-  --> $DIR/guards.rs:12:11
+  --> $DIR/guards.rs:11:11
    |
 LL |     match 0u8 {
    |           ^^^ pattern `128_u8..=u8::MAX` not covered
diff --git a/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.rs b/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.rs
index 07156d9a08a..026175e3abf 100644
--- a/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.rs
+++ b/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.rs
@@ -1,4 +1,3 @@
-#![feature(exclusive_range_pattern)]
 #![allow(overlapping_range_endpoints)]
 #![allow(non_contiguous_range_endpoints)]
 #![deny(unreachable_patterns)]
diff --git a/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr b/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr
index 68976c1b057..cc250b79274 100644
--- a/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr
+++ b/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr
@@ -1,5 +1,5 @@
 error[E0004]: non-exhaustive patterns: `u8::MAX` not covered
-  --> $DIR/exhaustiveness.rs:48:8
+  --> $DIR/exhaustiveness.rs:47:8
    |
 LL |     m!(0u8, 0..255);
    |        ^^^ pattern `u8::MAX` not covered
@@ -11,7 +11,7 @@ LL |         match $s { $($t)+ => {}, u8::MAX => todo!() }
    |                                ++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `u8::MAX` not covered
-  --> $DIR/exhaustiveness.rs:49:8
+  --> $DIR/exhaustiveness.rs:48:8
    |
 LL |     m!(0u8, 0..=254);
    |        ^^^ pattern `u8::MAX` not covered
@@ -23,7 +23,7 @@ LL |         match $s { $($t)+ => {}, u8::MAX => todo!() }
    |                                ++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `0_u8` not covered
-  --> $DIR/exhaustiveness.rs:50:8
+  --> $DIR/exhaustiveness.rs:49:8
    |
 LL |     m!(0u8, 1..=255);
    |        ^^^ pattern `0_u8` not covered
@@ -35,7 +35,7 @@ LL |         match $s { $($t)+ => {}, 0_u8 => todo!() }
    |                                +++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `42_u8` not covered
-  --> $DIR/exhaustiveness.rs:51:8
+  --> $DIR/exhaustiveness.rs:50:8
    |
 LL |     m!(0u8, 0..42 | 43..=255);
    |        ^^^ pattern `42_u8` not covered
@@ -47,7 +47,7 @@ LL |         match $s { $($t)+ => {}, 42_u8 => todo!() }
    |                                ++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i8::MAX` not covered
-  --> $DIR/exhaustiveness.rs:52:8
+  --> $DIR/exhaustiveness.rs:51:8
    |
 LL |     m!(0i8, -128..127);
    |        ^^^ pattern `i8::MAX` not covered
@@ -59,7 +59,7 @@ LL |         match $s { $($t)+ => {}, i8::MAX => todo!() }
    |                                ++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i8::MAX` not covered
-  --> $DIR/exhaustiveness.rs:53:8
+  --> $DIR/exhaustiveness.rs:52:8
    |
 LL |     m!(0i8, -128..=126);
    |        ^^^ pattern `i8::MAX` not covered
@@ -71,7 +71,7 @@ LL |         match $s { $($t)+ => {}, i8::MAX => todo!() }
    |                                ++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i8::MIN` not covered
-  --> $DIR/exhaustiveness.rs:54:8
+  --> $DIR/exhaustiveness.rs:53:8
    |
 LL |     m!(0i8, -127..=127);
    |        ^^^ pattern `i8::MIN` not covered
@@ -83,7 +83,7 @@ LL |         match $s { $($t)+ => {}, i8::MIN => todo!() }
    |                                ++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `0_i8` not covered
-  --> $DIR/exhaustiveness.rs:55:11
+  --> $DIR/exhaustiveness.rs:54:11
    |
 LL |     match 0i8 {
    |           ^^^ pattern `0_i8` not covered
@@ -96,7 +96,7 @@ LL +         0_i8 => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `u128::MAX` not covered
-  --> $DIR/exhaustiveness.rs:60:8
+  --> $DIR/exhaustiveness.rs:59:8
    |
 LL |     m!(0u128, 0..=ALMOST_MAX);
    |        ^^^^^ pattern `u128::MAX` not covered
@@ -108,7 +108,7 @@ LL |         match $s { $($t)+ => {}, u128::MAX => todo!() }
    |                                ++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `5_u128..` not covered
-  --> $DIR/exhaustiveness.rs:61:8
+  --> $DIR/exhaustiveness.rs:60:8
    |
 LL |     m!(0u128, 0..=4);
    |        ^^^^^ pattern `5_u128..` not covered
@@ -120,7 +120,7 @@ LL |         match $s { $($t)+ => {}, 5_u128.. => todo!() }
    |                                +++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `0_u128` not covered
-  --> $DIR/exhaustiveness.rs:62:8
+  --> $DIR/exhaustiveness.rs:61:8
    |
 LL |     m!(0u128, 1..=u128::MAX);
    |        ^^^^^ pattern `0_u128` not covered
@@ -132,7 +132,7 @@ LL |         match $s { $($t)+ => {}, 0_u128 => todo!() }
    |                                +++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `(126_u8..=127_u8, false)` not covered
-  --> $DIR/exhaustiveness.rs:70:11
+  --> $DIR/exhaustiveness.rs:69:11
    |
 LL |     match (0u8, true) {
    |           ^^^^^^^^^^^ pattern `(126_u8..=127_u8, false)` not covered
diff --git a/tests/ui/pattern/usefulness/integer-ranges/gap_between_ranges.rs b/tests/ui/pattern/usefulness/integer-ranges/gap_between_ranges.rs
index 78849d7e143..2e2519d1b6d 100644
--- a/tests/ui/pattern/usefulness/integer-ranges/gap_between_ranges.rs
+++ b/tests/ui/pattern/usefulness/integer-ranges/gap_between_ranges.rs
@@ -1,4 +1,3 @@
-#![feature(exclusive_range_pattern)]
 #![deny(non_contiguous_range_endpoints)]
 
 macro_rules! m {
diff --git a/tests/ui/pattern/usefulness/integer-ranges/gap_between_ranges.stderr b/tests/ui/pattern/usefulness/integer-ranges/gap_between_ranges.stderr
index e5c2d788ba4..8a029073f05 100644
--- a/tests/ui/pattern/usefulness/integer-ranges/gap_between_ranges.stderr
+++ b/tests/ui/pattern/usefulness/integer-ranges/gap_between_ranges.stderr
@@ -1,5 +1,5 @@
 error: multiple ranges are one apart
-  --> $DIR/gap_between_ranges.rs:16:9
+  --> $DIR/gap_between_ranges.rs:15:9
    |
 LL |         20..30 => {}
    |         ^^^^^^
@@ -10,13 +10,13 @@ LL |         31..=40 => {}
    |         ------- this could appear to continue range `20_u8..30_u8`, but `30_u8` isn't matched by either of them
    |
 note: the lint level is defined here
-  --> $DIR/gap_between_ranges.rs:2:9
+  --> $DIR/gap_between_ranges.rs:1:9
    |
 LL | #![deny(non_contiguous_range_endpoints)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: multiple ranges are one apart
-  --> $DIR/gap_between_ranges.rs:21:9
+  --> $DIR/gap_between_ranges.rs:20:9
    |
 LL |         20..30 => {}
    |         ^^^^^^
@@ -27,7 +27,7 @@ LL |         31 => {}
    |         -- this could appear to continue range `20_u8..30_u8`, but `30_u8` isn't matched by either of them
 
 error: multiple ranges are one apart
-  --> $DIR/gap_between_ranges.rs:26:13
+  --> $DIR/gap_between_ranges.rs:25:13
    |
 LL |     m!(0u8, 20..30, 31..=40);
    |             ^^^^^^  ------- this could appear to continue range `20_u8..30_u8`, but `30_u8` isn't matched by either of them
@@ -36,7 +36,7 @@ LL |     m!(0u8, 20..30, 31..=40);
    |             help: use an inclusive range instead: `20_u8..=30_u8`
 
 error: multiple ranges are one apart
-  --> $DIR/gap_between_ranges.rs:27:22
+  --> $DIR/gap_between_ranges.rs:26:22
    |
 LL |     m!(0u8, 31..=40, 20..30);
    |             -------  ^^^^^^
@@ -46,7 +46,7 @@ LL |     m!(0u8, 31..=40, 20..30);
    |             this could appear to continue range `20_u8..30_u8`, but `30_u8` isn't matched by either of them
 
 warning: multiple patterns overlap on their endpoints
-  --> $DIR/gap_between_ranges.rs:28:21
+  --> $DIR/gap_between_ranges.rs:27:21
    |
 LL |     m!(0u8, 20..30, 29..=40);
    |             ------  ^^^^^^^ ... with this range
@@ -57,7 +57,7 @@ LL |     m!(0u8, 20..30, 29..=40);
    = note: `#[warn(overlapping_range_endpoints)]` on by default
 
 error: multiple ranges are one apart
-  --> $DIR/gap_between_ranges.rs:30:13
+  --> $DIR/gap_between_ranges.rs:29:13
    |
 LL |     m!(0u8, 20..30, 31..=40);
    |             ^^^^^^  ------- this could appear to continue range `20_u8..30_u8`, but `30_u8` isn't matched by either of them
@@ -66,7 +66,7 @@ LL |     m!(0u8, 20..30, 31..=40);
    |             help: use an inclusive range instead: `20_u8..=30_u8`
 
 error: multiple ranges are one apart
-  --> $DIR/gap_between_ranges.rs:32:13
+  --> $DIR/gap_between_ranges.rs:31:13
    |
 LL |     m!(0u8, 20..30, 31..=32);
    |             ^^^^^^  ------- this could appear to continue range `20_u8..30_u8`, but `30_u8` isn't matched by either of them
@@ -75,7 +75,7 @@ LL |     m!(0u8, 20..30, 31..=32);
    |             help: use an inclusive range instead: `20_u8..=30_u8`
 
 error: exclusive range missing `u8::MAX`
-  --> $DIR/gap_between_ranges.rs:42:9
+  --> $DIR/gap_between_ranges.rs:41:9
    |
 LL |         0..255 => {}
    |         ^^^^^^
@@ -84,7 +84,7 @@ LL |         0..255 => {}
    |         help: use an inclusive range instead: `0_u8..=u8::MAX`
 
 error: multiple ranges are one apart
-  --> $DIR/gap_between_ranges.rs:71:9
+  --> $DIR/gap_between_ranges.rs:70:9
    |
 LL |         0..10 => {}
    |         ^^^^^
@@ -97,7 +97,7 @@ LL |         11..30 => {}
    |         ------ this could appear to continue range `0_u8..10_u8`, but `10_u8` isn't matched by either of them
 
 error: multiple ranges are one apart
-  --> $DIR/gap_between_ranges.rs:77:9
+  --> $DIR/gap_between_ranges.rs:76:9
    |
 LL |         0..10 => {}
    |         ^^^^^
@@ -108,7 +108,7 @@ LL |         11..20 => {}
    |         ------ this could appear to continue range `0_u8..10_u8`, but `10_u8` isn't matched by either of them
 
 error: multiple ranges are one apart
-  --> $DIR/gap_between_ranges.rs:78:9
+  --> $DIR/gap_between_ranges.rs:77:9
    |
 LL |         11..20 => {}
    |         ^^^^^^
@@ -119,7 +119,7 @@ LL |         21..30 => {}
    |         ------ this could appear to continue range `11_u8..20_u8`, but `20_u8` isn't matched by either of them
 
 error: multiple ranges are one apart
-  --> $DIR/gap_between_ranges.rs:83:9
+  --> $DIR/gap_between_ranges.rs:82:9
    |
 LL |         00..20 => {}
    |         ^^^^^^
@@ -133,7 +133,7 @@ LL |         21..40 => {}
    |         ------ this could appear to continue range `0_u8..20_u8`, but `20_u8` isn't matched by either of them
 
 error: multiple ranges are one apart
-  --> $DIR/gap_between_ranges.rs:84:9
+  --> $DIR/gap_between_ranges.rs:83:9
    |
 LL |         10..20 => {}
    |         ^^^^^^
@@ -146,7 +146,7 @@ LL |         21..40 => {}
    |         ------ this could appear to continue range `10_u8..20_u8`, but `20_u8` isn't matched by either of them
 
 error: multiple ranges are one apart
-  --> $DIR/gap_between_ranges.rs:92:10
+  --> $DIR/gap_between_ranges.rs:91:10
    |
 LL |         (0..10, true) => {}
    |          ^^^^^
@@ -157,7 +157,7 @@ LL |         (11..20, true) => {}
    |          ------ this could appear to continue range `0_u8..10_u8`, but `10_u8` isn't matched by either of them
 
 error: multiple ranges are one apart
-  --> $DIR/gap_between_ranges.rs:97:16
+  --> $DIR/gap_between_ranges.rs:96:16
    |
 LL |         (true, 0..10) => {}
    |                ^^^^^
@@ -168,7 +168,7 @@ LL |         (true, 11..20) => {}
    |                ------ this could appear to continue range `0_u8..10_u8`, but `10_u8` isn't matched by either of them
 
 error: multiple ranges are one apart
-  --> $DIR/gap_between_ranges.rs:103:10
+  --> $DIR/gap_between_ranges.rs:102:10
    |
 LL |         (0..10, true) => {}
    |          ^^^^^
@@ -179,7 +179,7 @@ LL |         (11..20, false) => {}
    |          ------ this could appear to continue range `0_u8..10_u8`, but `10_u8` isn't matched by either of them
 
 error: multiple ranges are one apart
-  --> $DIR/gap_between_ranges.rs:113:14
+  --> $DIR/gap_between_ranges.rs:112:14
    |
 LL |         Some(0..10) => {}
    |              ^^^^^
diff --git a/tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.rs b/tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.rs
index 7e56880a87f..a5b7a901616 100644
--- a/tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.rs
+++ b/tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.rs
@@ -1,4 +1,3 @@
-#![feature(exclusive_range_pattern)]
 #![deny(overlapping_range_endpoints)]
 
 macro_rules! m {
diff --git a/tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr b/tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr
index aa37bd9bc9c..6634532d5ed 100644
--- a/tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr
+++ b/tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr
@@ -1,5 +1,5 @@
 error: multiple patterns overlap on their endpoints
-  --> $DIR/overlapping_range_endpoints.rs:15:22
+  --> $DIR/overlapping_range_endpoints.rs:14:22
    |
 LL |     m!(0u8, 20..=30, 30..=40);
    |             -------  ^^^^^^^ ... with this range
@@ -8,13 +8,13 @@ LL |     m!(0u8, 20..=30, 30..=40);
    |
    = note: you likely meant to write mutually exclusive ranges
 note: the lint level is defined here
-  --> $DIR/overlapping_range_endpoints.rs:2:9
+  --> $DIR/overlapping_range_endpoints.rs:1:9
    |
 LL | #![deny(overlapping_range_endpoints)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: multiple patterns overlap on their endpoints
-  --> $DIR/overlapping_range_endpoints.rs:16:22
+  --> $DIR/overlapping_range_endpoints.rs:15:22
    |
 LL |     m!(0u8, 30..=40, 20..=30);
    |             -------  ^^^^^^^ ... with this range
@@ -24,7 +24,7 @@ LL |     m!(0u8, 30..=40, 20..=30);
    = note: you likely meant to write mutually exclusive ranges
 
 error: multiple patterns overlap on their endpoints
-  --> $DIR/overlapping_range_endpoints.rs:19:21
+  --> $DIR/overlapping_range_endpoints.rs:18:21
    |
 LL |     m!(0u8, 20..30, 29..=40);
    |             ------  ^^^^^^^ ... with this range
@@ -34,7 +34,7 @@ LL |     m!(0u8, 20..30, 29..=40);
    = note: you likely meant to write mutually exclusive ranges
 
 error: multiple patterns overlap on their endpoints
-  --> $DIR/overlapping_range_endpoints.rs:23:22
+  --> $DIR/overlapping_range_endpoints.rs:22:22
    |
 LL |     m!(0u8, 20..=30, 30..=31);
    |             -------  ^^^^^^^ ... with this range
@@ -44,7 +44,7 @@ LL |     m!(0u8, 20..=30, 30..=31);
    = note: you likely meant to write mutually exclusive ranges
 
 error: multiple patterns overlap on their endpoints
-  --> $DIR/overlapping_range_endpoints.rs:27:22
+  --> $DIR/overlapping_range_endpoints.rs:26:22
    |
 LL |     m!(0u8, 20..=30, 19..=20);
    |             -------  ^^^^^^^ ... with this range
@@ -54,7 +54,7 @@ LL |     m!(0u8, 20..=30, 19..=20);
    = note: you likely meant to write mutually exclusive ranges
 
 error: multiple patterns overlap on their endpoints
-  --> $DIR/overlapping_range_endpoints.rs:39:9
+  --> $DIR/overlapping_range_endpoints.rs:38:9
    |
 LL |         0..=10 => {}
    |         ------ this range overlaps on `10_u8`...
@@ -65,7 +65,7 @@ LL |         10..=20 => {}
    = note: you likely meant to write mutually exclusive ranges
 
 error: multiple patterns overlap on their endpoints
-  --> $DIR/overlapping_range_endpoints.rs:39:9
+  --> $DIR/overlapping_range_endpoints.rs:38:9
    |
 LL |         20..=30 => {}
    |         ------- this range overlaps on `20_u8`...
@@ -75,7 +75,7 @@ LL |         10..=20 => {}
    = note: you likely meant to write mutually exclusive ranges
 
 error: multiple patterns overlap on their endpoints
-  --> $DIR/overlapping_range_endpoints.rs:46:10
+  --> $DIR/overlapping_range_endpoints.rs:45:10
    |
 LL |         (0..=10, true) => {}
    |          ------ this range overlaps on `10_u8`...
@@ -85,7 +85,7 @@ LL |         (10..20, true) => {}
    = note: you likely meant to write mutually exclusive ranges
 
 error: multiple patterns overlap on their endpoints
-  --> $DIR/overlapping_range_endpoints.rs:52:16
+  --> $DIR/overlapping_range_endpoints.rs:51:16
    |
 LL |         (true, 0..=10) => {}
    |                ------ this range overlaps on `10_u8`...
@@ -95,7 +95,7 @@ LL |         (true, 10..20) => {}
    = note: you likely meant to write mutually exclusive ranges
 
 error: multiple patterns overlap on their endpoints
-  --> $DIR/overlapping_range_endpoints.rs:58:14
+  --> $DIR/overlapping_range_endpoints.rs:57:14
    |
 LL |         Some(0..=10) => {}
    |              ------ this range overlaps on `10_u8`...
diff --git a/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr b/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr
index 416523213c0..914c6ed60c8 100644
--- a/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr
+++ b/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr
@@ -1,5 +1,5 @@
 error[E0004]: non-exhaustive patterns: `usize::MAX..` not covered
-  --> $DIR/pointer-sized-int.rs:13:11
+  --> $DIR/pointer-sized-int.rs:12:11
    |
 LL |     match 0usize {
    |           ^^^^^^ pattern `usize::MAX..` not covered
@@ -13,7 +13,7 @@ LL +         usize::MAX.. => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `..isize::MIN` and `isize::MAX..` not covered
-  --> $DIR/pointer-sized-int.rs:18:11
+  --> $DIR/pointer-sized-int.rs:17:11
    |
 LL |     match 0isize {
    |           ^^^^^^ patterns `..isize::MIN` and `isize::MAX..` not covered
@@ -27,7 +27,7 @@ LL +         ..isize::MIN | isize::MAX.. => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `usize::MAX..` not covered
-  --> $DIR/pointer-sized-int.rs:23:8
+  --> $DIR/pointer-sized-int.rs:22:8
    |
 LL |     m!(0usize, 0..=usize::MAX);
    |        ^^^^^^ pattern `usize::MAX..` not covered
@@ -40,7 +40,7 @@ LL |         match $s { $($t)+ => {}, usize::MAX.. => todo!() }
    |                                +++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `usize::MAX..` not covered
-  --> $DIR/pointer-sized-int.rs:25:8
+  --> $DIR/pointer-sized-int.rs:24:8
    |
 LL |     m!(0usize, 0..5 | 5..=usize::MAX);
    |        ^^^^^^ pattern `usize::MAX..` not covered
@@ -53,7 +53,7 @@ LL |         match $s { $($t)+ => {}, usize::MAX.. => todo!() }
    |                                +++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `usize::MAX..` not covered
-  --> $DIR/pointer-sized-int.rs:27:8
+  --> $DIR/pointer-sized-int.rs:26:8
    |
 LL |     m!(0usize, 0..usize::MAX | usize::MAX);
    |        ^^^^^^ pattern `usize::MAX..` not covered
@@ -66,7 +66,7 @@ LL |         match $s { $($t)+ => {}, usize::MAX.. => todo!() }
    |                                +++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `(usize::MAX.., _)` not covered
-  --> $DIR/pointer-sized-int.rs:29:8
+  --> $DIR/pointer-sized-int.rs:28:8
    |
 LL |     m!((0usize, true), (0..5, true) | (5..=usize::MAX, true) | (0..=usize::MAX, false));
    |        ^^^^^^^^^^^^^^ pattern `(usize::MAX.., _)` not covered
@@ -79,7 +79,7 @@ LL |         match $s { $($t)+ => {}, (usize::MAX.., _) => todo!() }
    |                                ++++++++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `..isize::MIN` and `isize::MAX..` not covered
-  --> $DIR/pointer-sized-int.rs:38:8
+  --> $DIR/pointer-sized-int.rs:37:8
    |
 LL |     m!(0isize, isize::MIN..=isize::MAX);
    |        ^^^^^^ patterns `..isize::MIN` and `isize::MAX..` not covered
@@ -92,7 +92,7 @@ LL |         match $s { $($t)+ => {}, ..isize::MIN | isize::MAX.. => todo!() }
    |                                ++++++++++++++++++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `..isize::MIN` and `isize::MAX..` not covered
-  --> $DIR/pointer-sized-int.rs:40:8
+  --> $DIR/pointer-sized-int.rs:39:8
    |
 LL |     m!(0isize, isize::MIN..5 | 5..=isize::MAX);
    |        ^^^^^^ patterns `..isize::MIN` and `isize::MAX..` not covered
@@ -105,7 +105,7 @@ LL |         match $s { $($t)+ => {}, ..isize::MIN | isize::MAX.. => todo!() }
    |                                ++++++++++++++++++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `..isize::MIN` and `isize::MAX..` not covered
-  --> $DIR/pointer-sized-int.rs:42:8
+  --> $DIR/pointer-sized-int.rs:41:8
    |
 LL |     m!(0isize, isize::MIN..=-1 | 0 | 1..=isize::MAX);
    |        ^^^^^^ patterns `..isize::MIN` and `isize::MAX..` not covered
@@ -118,7 +118,7 @@ LL |         match $s { $($t)+ => {}, ..isize::MIN | isize::MAX.. => todo!() }
    |                                ++++++++++++++++++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `..isize::MIN` and `isize::MAX..` not covered
-  --> $DIR/pointer-sized-int.rs:44:8
+  --> $DIR/pointer-sized-int.rs:43:8
    |
 LL |     m!(0isize, isize::MIN..isize::MAX | isize::MAX);
    |        ^^^^^^ patterns `..isize::MIN` and `isize::MAX..` not covered
@@ -131,7 +131,7 @@ LL |         match $s { $($t)+ => {}, ..isize::MIN | isize::MAX.. => todo!() }
    |                                ++++++++++++++++++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `(..isize::MIN, _)` and `(isize::MAX.., _)` not covered
-  --> $DIR/pointer-sized-int.rs:47:9
+  --> $DIR/pointer-sized-int.rs:46:9
    |
 LL |         (0isize, true),
    |         ^^^^^^^^^^^^^^ patterns `(..isize::MIN, _)` and `(isize::MAX.., _)` not covered
@@ -144,7 +144,7 @@ LL |         match $s { $($t)+ => {}, (..isize::MIN, _) | (isize::MAX.., _) => t
    |                                ++++++++++++++++++++++++++++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: type `usize` is non-empty
-  --> $DIR/pointer-sized-int.rs:58:11
+  --> $DIR/pointer-sized-int.rs:57:11
    |
 LL |     match 7usize {}
    |           ^^^^^^
diff --git a/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.rs b/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.rs
index 40f086dcc71..0d6056e228f 100644
--- a/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.rs
+++ b/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.rs
@@ -1,5 +1,4 @@
 //@ revisions: deny
-#![feature(exclusive_range_pattern)]
 #![allow(overlapping_range_endpoints)]
 
 macro_rules! m {
diff --git a/tests/ui/pattern/usefulness/integer-ranges/reachability.rs b/tests/ui/pattern/usefulness/integer-ranges/reachability.rs
index 13b84e2c44b..a72588b623c 100644
--- a/tests/ui/pattern/usefulness/integer-ranges/reachability.rs
+++ b/tests/ui/pattern/usefulness/integer-ranges/reachability.rs
@@ -1,4 +1,3 @@
-#![feature(exclusive_range_pattern)]
 #![allow(overlapping_range_endpoints)]
 #![allow(non_contiguous_range_endpoints)]
 #![deny(unreachable_patterns)]
diff --git a/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr b/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr
index 0f52dfd83b9..c5b028d2038 100644
--- a/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr
+++ b/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr
@@ -1,137 +1,137 @@
 error: unreachable pattern
-  --> $DIR/reachability.rs:19:17
+  --> $DIR/reachability.rs:18:17
    |
 LL |     m!(0u8, 42, 42);
    |                 ^^
    |
 note: the lint level is defined here
-  --> $DIR/reachability.rs:4:9
+  --> $DIR/reachability.rs:3:9
    |
 LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:23:22
+  --> $DIR/reachability.rs:22:22
    |
 LL |     m!(0u8, 20..=30, 20);
    |                      ^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:24:22
+  --> $DIR/reachability.rs:23:22
    |
 LL |     m!(0u8, 20..=30, 21);
    |                      ^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:25:22
+  --> $DIR/reachability.rs:24:22
    |
 LL |     m!(0u8, 20..=30, 25);
    |                      ^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:26:22
+  --> $DIR/reachability.rs:25:22
    |
 LL |     m!(0u8, 20..=30, 29);
    |                      ^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:27:22
+  --> $DIR/reachability.rs:26:22
    |
 LL |     m!(0u8, 20..=30, 30);
    |                      ^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:30:21
+  --> $DIR/reachability.rs:29:21
    |
 LL |     m!(0u8, 20..30, 20);
    |                     ^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:31:21
+  --> $DIR/reachability.rs:30:21
    |
 LL |     m!(0u8, 20..30, 21);
    |                     ^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:32:21
+  --> $DIR/reachability.rs:31:21
    |
 LL |     m!(0u8, 20..30, 25);
    |                     ^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:33:21
+  --> $DIR/reachability.rs:32:21
    |
 LL |     m!(0u8, 20..30, 29);
    |                     ^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:37:22
+  --> $DIR/reachability.rs:36:22
    |
 LL |     m!(0u8, 20..=30, 20..=30);
    |                      ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:38:22
+  --> $DIR/reachability.rs:37:22
    |
 LL |     m!(0u8, 20.. 30, 20.. 30);
    |                      ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:39:22
+  --> $DIR/reachability.rs:38:22
    |
 LL |     m!(0u8, 20..=30, 20.. 30);
    |                      ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:41:22
+  --> $DIR/reachability.rs:40:22
    |
 LL |     m!(0u8, 20..=30, 21..=30);
    |                      ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:42:22
+  --> $DIR/reachability.rs:41:22
    |
 LL |     m!(0u8, 20..=30, 20..=29);
    |                      ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:44:24
+  --> $DIR/reachability.rs:43:24
    |
 LL |     m!('a', 'A'..='z', 'a'..='z');
    |                        ^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:51:9
+  --> $DIR/reachability.rs:50:9
    |
 LL |         5..=8 => {},
    |         ^^^^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:57:9
+  --> $DIR/reachability.rs:56:9
    |
 LL |         5..15 => {},
    |         ^^^^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:64:9
+  --> $DIR/reachability.rs:63:9
    |
 LL |         5..25 => {},
    |         ^^^^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:72:9
+  --> $DIR/reachability.rs:71:9
    |
 LL |         5..25 => {},
    |         ^^^^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:78:9
+  --> $DIR/reachability.rs:77:9
    |
 LL |         5..15 => {},
    |         ^^^^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:85:9
+  --> $DIR/reachability.rs:84:9
    |
 LL |         _ => {},
    |         - matches any value
@@ -139,19 +139,19 @@ LL |         '\u{D7FF}'..='\u{E000}' => {},
    |         ^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:90:9
+  --> $DIR/reachability.rs:89:9
    |
 LL |         '\u{D7FF}'..='\u{E000}' => {},
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:106:9
+  --> $DIR/reachability.rs:105:9
    |
 LL |         &FOO => {}
    |         ^^^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:107:9
+  --> $DIR/reachability.rs:106:9
    |
 LL |         BAR => {}
    |         ^^^
diff --git a/tests/ui/range/range-pattern-out-of-bounds-issue-68972.rs b/tests/ui/range/range-pattern-out-of-bounds-issue-68972.rs
index 206f05d0d3c..50203d3cf4f 100644
--- a/tests/ui/range/range-pattern-out-of-bounds-issue-68972.rs
+++ b/tests/ui/range/range-pattern-out-of-bounds-issue-68972.rs
@@ -1,4 +1,3 @@
-#![feature(exclusive_range_pattern)]
 #![allow(unreachable_patterns)]
 fn main() {
     match 0u8 {
diff --git a/tests/ui/range/range-pattern-out-of-bounds-issue-68972.stderr b/tests/ui/range/range-pattern-out-of-bounds-issue-68972.stderr
index 21f1fdba886..38ce1a8a240 100644
--- a/tests/ui/range/range-pattern-out-of-bounds-issue-68972.stderr
+++ b/tests/ui/range/range-pattern-out-of-bounds-issue-68972.stderr
@@ -1,11 +1,11 @@
 error: literal out of range for `u8`
-  --> $DIR/range-pattern-out-of-bounds-issue-68972.rs:5:14
+  --> $DIR/range-pattern-out-of-bounds-issue-68972.rs:4:14
    |
 LL |         251..257 => {}
    |              ^^^ this value does not fit into the type `u8` whose range is `0..=255`
 
 error: literal out of range for `u8`
-  --> $DIR/range-pattern-out-of-bounds-issue-68972.rs:7:15
+  --> $DIR/range-pattern-out-of-bounds-issue-68972.rs:6:15
    |
 LL |         251..=256 => {}
    |               ^^^ this value does not fit into the type `u8` whose range is `0..=255`
diff --git a/tests/ui/resolve/issue-50599.stderr b/tests/ui/resolve/issue-50599.stderr
index 25e98b4746b..e5eacd741fb 100644
--- a/tests/ui/resolve/issue-50599.stderr
+++ b/tests/ui/resolve/issue-50599.stderr
@@ -6,6 +6,10 @@ LL |     const M: usize = (f64::from(N) * std::f64::LOG10_2) as usize;
    |
 help: consider importing one of these items
    |
+LL + use std::f128::consts::LOG10_2;
+   |
+LL + use std::f16::consts::LOG10_2;
+   |
 LL + use std::f32::consts::LOG10_2;
    |
 LL + use std::f64::consts::LOG10_2;
diff --git a/tests/ui/resolve/issue-73427.stderr b/tests/ui/resolve/issue-73427.stderr
index 622de9b39bd..c5e245d884b 100644
--- a/tests/ui/resolve/issue-73427.stderr
+++ b/tests/ui/resolve/issue-73427.stderr
@@ -107,6 +107,10 @@ LL |     (E::TupleWithFields(/* fields */)).foo();
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 help: consider importing one of these items instead
    |
+LL + use std::f128::consts::E;
+   |
+LL + use std::f16::consts::E;
+   |
 LL + use std::f32::consts::E;
    |
 LL + use std::f64::consts::E;
diff --git a/tests/ui/resolve/privacy-enum-ctor.stderr b/tests/ui/resolve/privacy-enum-ctor.stderr
index b10eded015f..01c8a38d2a4 100644
--- a/tests/ui/resolve/privacy-enum-ctor.stderr
+++ b/tests/ui/resolve/privacy-enum-ctor.stderr
@@ -84,6 +84,10 @@ LL |     let _: E = m::f;
    |                   ~
 help: consider importing one of these items instead
    |
+LL + use std::f128::consts::E;
+   |
+LL + use std::f16::consts::E;
+   |
 LL + use std::f32::consts::E;
    |
 LL + use std::f64::consts::E;
@@ -121,6 +125,10 @@ LL |     let _: E = (E::Fn(/* fields */));
    |                ~~~~~~~~~~~~~~~~~~~~~
 help: consider importing one of these items instead
    |
+LL + use std::f128::consts::E;
+   |
+LL + use std::f16::consts::E;
+   |
 LL + use std::f32::consts::E;
    |
 LL + use std::f64::consts::E;
diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/check.rs b/tests/ui/rfcs/rfc-0000-never_patterns/check.rs
index 0831477e749..dc13dd05fa6 100644
--- a/tests/ui/rfcs/rfc-0000-never_patterns/check.rs
+++ b/tests/ui/rfcs/rfc-0000-never_patterns/check.rs
@@ -1,3 +1,4 @@
+// Check that never patterns can't have bodies or guards.
 #![feature(never_patterns)]
 #![allow(incomplete_features)]
 
diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr
index 25f7343a8a8..fbf7aa02ac2 100644
--- a/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr
+++ b/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr
@@ -1,5 +1,5 @@
 error: a never pattern is always unreachable
-  --> $DIR/check.rs:14:20
+  --> $DIR/check.rs:15:20
    |
 LL |         Some(!) => {}
    |                    ^^
@@ -8,13 +8,13 @@ LL |         Some(!) => {}
    |                    help: remove this expression
 
 error: a guard on a never pattern will never be run
-  --> $DIR/check.rs:19:20
+  --> $DIR/check.rs:20:20
    |
 LL |         Some(!) if true,
    |                    ^^^^ help: remove this guard
 
 error: a never pattern is always unreachable
-  --> $DIR/check.rs:24:28
+  --> $DIR/check.rs:25:28
    |
 LL |         Some(!) if true => {}
    |                            ^^
@@ -23,7 +23,7 @@ LL |         Some(!) if true => {}
    |                            help: remove this expression
 
 error: a never pattern is always unreachable
-  --> $DIR/check.rs:29:27
+  --> $DIR/check.rs:30:27
    |
 LL |         Some(never!()) => {}
    |                           ^^
@@ -32,7 +32,7 @@ LL |         Some(never!()) => {}
    |                           help: remove this expression
 
 error[E0004]: non-exhaustive patterns: `Some(!)` not covered
-  --> $DIR/check.rs:18:11
+  --> $DIR/check.rs:19:11
    |
 LL |     match None::<Void> {
    |           ^^^^^^^^^^^^ pattern `Some(!)` not covered
@@ -50,7 +50,7 @@ LL +         Some(!)
    |
 
 error[E0004]: non-exhaustive patterns: `Some(!)` not covered
-  --> $DIR/check.rs:23:11
+  --> $DIR/check.rs:24:11
    |
 LL |     match None::<Void> {
    |           ^^^^^^^^^^^^ pattern `Some(!)` not covered
diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/check_place_is_initialized.rs b/tests/ui/rfcs/rfc-0000-never_patterns/check_place_is_initialized.rs
new file mode 100644
index 00000000000..f8f9d7a9aa6
--- /dev/null
+++ b/tests/ui/rfcs/rfc-0000-never_patterns/check_place_is_initialized.rs
@@ -0,0 +1,12 @@
+#![feature(never_patterns)]
+#![allow(incomplete_features)]
+
+enum Void {}
+
+fn main() {}
+
+fn anything<T>() -> T {
+    let x: Void;
+    match x { ! }
+    //~^ ERROR used binding `x` isn't initialized
+}
diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/check_place_is_initialized.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/check_place_is_initialized.stderr
new file mode 100644
index 00000000000..1a6c4127085
--- /dev/null
+++ b/tests/ui/rfcs/rfc-0000-never_patterns/check_place_is_initialized.stderr
@@ -0,0 +1,16 @@
+error[E0381]: used binding `x` isn't initialized
+  --> $DIR/check_place_is_initialized.rs:10:15
+   |
+LL |     let x: Void;
+   |         - binding declared here but left uninitialized
+LL |     match x { ! }
+   |               ^ `x` used here but it isn't initialized
+   |
+help: consider assigning a value
+   |
+LL |     let x: Void = /* value */;
+   |                 +++++++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs
index e8bfa9245f5..8300f953dc1 100644
--- a/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs
+++ b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs
@@ -123,3 +123,15 @@ fn never_pattern_typeck_pass(void: Void) {
         Some(!),
     }
 }
+
+struct Unsized {
+    void: Void,
+    slice: [u8],
+}
+
+#[cfg(pass)]
+fn not_sized(x: &Unsized) {
+    match *x {
+        !,
+    }
+}
diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/use-bindings.rs b/tests/ui/rfcs/rfc-0000-never_patterns/use-bindings.rs
new file mode 100644
index 00000000000..33da6f02ce2
--- /dev/null
+++ b/tests/ui/rfcs/rfc-0000-never_patterns/use-bindings.rs
@@ -0,0 +1,29 @@
+//@ check-pass
+#![feature(never_patterns)]
+#![allow(incomplete_features)]
+
+#[derive(Copy, Clone)]
+enum Void {}
+
+fn main() {
+    let res_void: Result<bool, Void> = Ok(true);
+
+    let (Ok(x) | Err(!)) = res_void;
+    println!("{x}");
+    let (Ok(x) | Err(!)) = &res_void;
+    println!("{x}");
+    let (Err(!) | Ok(x)) = res_void;
+    println!("{x}");
+
+    match res_void {
+        Ok(x) | Err(!) => println!("{x}"),
+    }
+    match res_void {
+        Err(!) | Ok(x) => println!("{x}"),
+    }
+
+    let res_res_void: Result<Result<bool, Void>, Void> = Ok(Ok(true));
+    match res_res_void {
+        Ok(Ok(x) | Err(!)) | Err(!) => println!("{x}"),
+    }
+}
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.rs
index d43db576b38..6d6a336e688 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.rs
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.rs
@@ -1,5 +1,4 @@
 // Matching against NaN should result in an error
-#![feature(exclusive_range_pattern)]
 #![allow(unused)]
 
 const NAN: f64 = f64::NAN;
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr
index 167ada783c2..baca1d75048 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr
@@ -1,5 +1,5 @@
 error: cannot use NaN in patterns
-  --> $DIR/issue-6804-nan-match.rs:15:9
+  --> $DIR/issue-6804-nan-match.rs:14:9
    |
 LL |         NAN => {},
    |         ^^^
@@ -8,7 +8,7 @@ LL |         NAN => {},
    = help: try using the `is_nan` method instead
 
 error: cannot use NaN in patterns
-  --> $DIR/issue-6804-nan-match.rs:20:10
+  --> $DIR/issue-6804-nan-match.rs:19:10
    |
 LL |         [NAN, _] => {},
    |          ^^^
@@ -17,7 +17,7 @@ LL |         [NAN, _] => {},
    = help: try using the `is_nan` method instead
 
 error: cannot use NaN in patterns
-  --> $DIR/issue-6804-nan-match.rs:25:9
+  --> $DIR/issue-6804-nan-match.rs:24:9
    |
 LL |         C => {},
    |         ^
@@ -26,7 +26,7 @@ LL |         C => {},
    = help: try using the `is_nan` method instead
 
 error: cannot use NaN in patterns
-  --> $DIR/issue-6804-nan-match.rs:31:9
+  --> $DIR/issue-6804-nan-match.rs:30:9
    |
 LL |         NAN..=1.0 => {},
    |         ^^^
@@ -35,13 +35,13 @@ LL |         NAN..=1.0 => {},
    = help: try using the `is_nan` method instead
 
 error[E0030]: lower range bound must be less than or equal to upper
-  --> $DIR/issue-6804-nan-match.rs:31:9
+  --> $DIR/issue-6804-nan-match.rs:30:9
    |
 LL |         NAN..=1.0 => {},
    |         ^^^^^^^^^ lower bound larger than upper bound
 
 error: cannot use NaN in patterns
-  --> $DIR/issue-6804-nan-match.rs:33:16
+  --> $DIR/issue-6804-nan-match.rs:32:16
    |
 LL |         -1.0..=NAN => {},
    |                ^^^
@@ -50,13 +50,13 @@ LL |         -1.0..=NAN => {},
    = help: try using the `is_nan` method instead
 
 error[E0030]: lower range bound must be less than or equal to upper
-  --> $DIR/issue-6804-nan-match.rs:33:9
+  --> $DIR/issue-6804-nan-match.rs:32:9
    |
 LL |         -1.0..=NAN => {},
    |         ^^^^^^^^^^ lower bound larger than upper bound
 
 error: cannot use NaN in patterns
-  --> $DIR/issue-6804-nan-match.rs:35:9
+  --> $DIR/issue-6804-nan-match.rs:34:9
    |
 LL |         NAN.. => {},
    |         ^^^
@@ -65,13 +65,13 @@ LL |         NAN.. => {},
    = help: try using the `is_nan` method instead
 
 error[E0030]: lower range bound must be less than or equal to upper
-  --> $DIR/issue-6804-nan-match.rs:35:9
+  --> $DIR/issue-6804-nan-match.rs:34:9
    |
 LL |         NAN.. => {},
    |         ^^^^^ lower bound larger than upper bound
 
 error: cannot use NaN in patterns
-  --> $DIR/issue-6804-nan-match.rs:37:11
+  --> $DIR/issue-6804-nan-match.rs:36:11
    |
 LL |         ..NAN => {},
    |           ^^^
@@ -80,7 +80,7 @@ LL |         ..NAN => {},
    = help: try using the `is_nan` method instead
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/issue-6804-nan-match.rs:37:9
+  --> $DIR/issue-6804-nan-match.rs:36:9
    |
 LL |         ..NAN => {},
    |         ^^^^^
diff --git a/tests/ui/rust-2018/async-ident.fixed b/tests/ui/rust-2018/async-ident.fixed
index 4e31f674435..639a8a245fb 100644
--- a/tests/ui/rust-2018/async-ident.fixed
+++ b/tests/ui/rust-2018/async-ident.fixed
@@ -9,16 +9,14 @@ fn r#async() {} //~ ERROR async
 
 macro_rules! foo {
     ($foo:ident) => {};
-    ($r#async:expr, r#async) => {};
+    ($async:expr, r#async) => {};
     //~^ ERROR async
-    //~| ERROR async
-    //~| WARN this is accepted in the current edition
     //~| WARN this is accepted in the current edition
 }
 
 foo!(r#async);
-    //~^ ERROR async
-    //~| WARN this is accepted in the current edition
+//~^ ERROR async
+//~| WARN this is accepted in the current edition
 
 mod dont_lint_raw {
     fn r#async() {}
diff --git a/tests/ui/rust-2018/async-ident.rs b/tests/ui/rust-2018/async-ident.rs
index 4c5134a2923..7921f05f481 100644
--- a/tests/ui/rust-2018/async-ident.rs
+++ b/tests/ui/rust-2018/async-ident.rs
@@ -11,14 +11,12 @@ macro_rules! foo {
     ($foo:ident) => {};
     ($async:expr, async) => {};
     //~^ ERROR async
-    //~| ERROR async
-    //~| WARN this is accepted in the current edition
     //~| WARN this is accepted in the current edition
 }
 
 foo!(async);
-    //~^ ERROR async
-    //~| WARN this is accepted in the current edition
+//~^ ERROR async
+//~| WARN this is accepted in the current edition
 
 mod dont_lint_raw {
     fn r#async() {}
diff --git a/tests/ui/rust-2018/async-ident.stderr b/tests/ui/rust-2018/async-ident.stderr
index 5b8d8184f4f..4ab061dd6f5 100644
--- a/tests/ui/rust-2018/async-ident.stderr
+++ b/tests/ui/rust-2018/async-ident.stderr
@@ -14,15 +14,6 @@ LL | #![deny(keyword_idents)]
    = note: `#[deny(keyword_idents_2018)]` implied by `#[deny(keyword_idents)]`
 
 error: `async` is a keyword in the 2018 edition
-  --> $DIR/async-ident.rs:12:7
-   |
-LL |     ($async:expr, async) => {};
-   |       ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
-   |
-   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
-   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
-
-error: `async` is a keyword in the 2018 edition
   --> $DIR/async-ident.rs:12:19
    |
 LL |     ($async:expr, async) => {};
@@ -32,7 +23,7 @@ LL |     ($async:expr, async) => {};
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
-  --> $DIR/async-ident.rs:19:6
+  --> $DIR/async-ident.rs:17:6
    |
 LL | foo!(async);
    |      ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
@@ -41,7 +32,7 @@ LL | foo!(async);
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
-  --> $DIR/async-ident.rs:28:11
+  --> $DIR/async-ident.rs:26:11
    |
 LL |     trait async {}
    |           ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
@@ -50,7 +41,7 @@ LL |     trait async {}
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
-  --> $DIR/async-ident.rs:32:10
+  --> $DIR/async-ident.rs:30:10
    |
 LL |     impl async for MyStruct {}
    |          ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
@@ -59,7 +50,7 @@ LL |     impl async for MyStruct {}
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
-  --> $DIR/async-ident.rs:38:12
+  --> $DIR/async-ident.rs:36:12
    |
 LL |     static async: u32 = 0;
    |            ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
@@ -68,7 +59,7 @@ LL |     static async: u32 = 0;
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
-  --> $DIR/async-ident.rs:44:11
+  --> $DIR/async-ident.rs:42:11
    |
 LL |     const async: u32 = 0;
    |           ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
@@ -77,7 +68,7 @@ LL |     const async: u32 = 0;
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
-  --> $DIR/async-ident.rs:50:15
+  --> $DIR/async-ident.rs:48:15
    |
 LL | impl Foo { fn async() {} }
    |               ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
@@ -86,7 +77,7 @@ LL | impl Foo { fn async() {} }
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
-  --> $DIR/async-ident.rs:55:12
+  --> $DIR/async-ident.rs:53:12
    |
 LL |     struct async {}
    |            ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
@@ -95,7 +86,7 @@ LL |     struct async {}
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
-  --> $DIR/async-ident.rs:58:9
+  --> $DIR/async-ident.rs:56:9
    |
 LL |     let async: async = async {};
    |         ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
@@ -104,7 +95,7 @@ LL |     let async: async = async {};
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
-  --> $DIR/async-ident.rs:58:16
+  --> $DIR/async-ident.rs:56:16
    |
 LL |     let async: async = async {};
    |                ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
@@ -113,7 +104,7 @@ LL |     let async: async = async {};
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
-  --> $DIR/async-ident.rs:58:24
+  --> $DIR/async-ident.rs:56:24
    |
 LL |     let async: async = async {};
    |                        ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
@@ -122,7 +113,7 @@ LL |     let async: async = async {};
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
-  --> $DIR/async-ident.rs:69:19
+  --> $DIR/async-ident.rs:67:19
    |
 LL |     () => (pub fn async() {})
    |                   ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
@@ -131,7 +122,7 @@ LL |     () => (pub fn async() {})
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `async` is a keyword in the 2018 edition
-  --> $DIR/async-ident.rs:76:6
+  --> $DIR/async-ident.rs:74:6
    |
 LL |     (async) => (1)
    |      ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
@@ -139,5 +130,5 @@ LL |     (async) => (1)
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
-error: aborting due to 15 previous errors
+error: aborting due to 14 previous errors
 
diff --git a/tests/ui/rust-2024/gen-kw-in-macro.rs b/tests/ui/rust-2024/gen-kw-in-macro.rs
new file mode 100644
index 00000000000..3ccbe05b226
--- /dev/null
+++ b/tests/ui/rust-2024/gen-kw-in-macro.rs
@@ -0,0 +1,13 @@
+//@ check-pass
+
+#![deny(keyword_idents_2024)]
+
+macro_rules! foo {
+    ($gen:expr) => {
+        $gen
+    };
+}
+
+fn main() {
+    foo!(println!("hello, world"));
+}
diff --git a/tests/ui/rust-2024/gen-kw.e2015.stderr b/tests/ui/rust-2024/gen-kw.e2015.stderr
index b12363184b7..b1074f77e00 100644
--- a/tests/ui/rust-2024/gen-kw.e2015.stderr
+++ b/tests/ui/rust-2024/gen-kw.e2015.stderr
@@ -22,5 +22,14 @@ LL |     let gen = r#gen;
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
-error: aborting due to 2 previous errors
+error: `gen` is a keyword in the 2024 edition
+  --> $DIR/gen-kw.rs:19:27
+   |
+LL |     () => { mod test { fn gen() {} } }
+   |                           ^^^ help: you can use a raw identifier to stay compatible: `r#gen`
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: aborting due to 3 previous errors
 
diff --git a/tests/ui/rust-2024/gen-kw.e2018.stderr b/tests/ui/rust-2024/gen-kw.e2018.stderr
index e10fc4c4512..b902cff7fdb 100644
--- a/tests/ui/rust-2024/gen-kw.e2018.stderr
+++ b/tests/ui/rust-2024/gen-kw.e2018.stderr
@@ -22,5 +22,14 @@ LL |     let gen = r#gen;
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2024!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
-error: aborting due to 2 previous errors
+error: `gen` is a keyword in the 2024 edition
+  --> $DIR/gen-kw.rs:19:27
+   |
+LL |     () => { mod test { fn gen() {} } }
+   |                           ^^^ help: you can use a raw identifier to stay compatible: `r#gen`
+   |
+   = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2024!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: aborting due to 3 previous errors
 
diff --git a/tests/ui/rust-2024/gen-kw.rs b/tests/ui/rust-2024/gen-kw.rs
index 3d2a3f95165..04251cbcac4 100644
--- a/tests/ui/rust-2024/gen-kw.rs
+++ b/tests/ui/rust-2024/gen-kw.rs
@@ -14,3 +14,12 @@ fn main() {
     //[e2015]~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
     //[e2018]~| WARNING this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2024!
 }
+
+macro_rules! t {
+    () => { mod test { fn gen() {} } }
+    //~^ ERROR `gen` is a keyword in the 2024 edition
+    //[e2015]~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
+    //[e2018]~| WARNING this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2024!
+}
+
+t!();
diff --git a/tests/ui/span/macro-ty-params.rs b/tests/ui/span/macro-ty-params.rs
index cf28b0255d1..c7ce9b9faed 100644
--- a/tests/ui/span/macro-ty-params.rs
+++ b/tests/ui/span/macro-ty-params.rs
@@ -11,5 +11,4 @@ fn main() {
     foo::<>!(); //~ ERROR generic arguments in macro path
     m!(Default<>);
     //~^ ERROR unexpected generic arguments in path
-    //~^^ ERROR generic arguments in macro path
 }
diff --git a/tests/ui/span/macro-ty-params.stderr b/tests/ui/span/macro-ty-params.stderr
index 7023ef8cd1c..138cd2598a1 100644
--- a/tests/ui/span/macro-ty-params.stderr
+++ b/tests/ui/span/macro-ty-params.stderr
@@ -16,11 +16,5 @@ error: unexpected generic arguments in path
 LL |     m!(Default<>);
    |               ^^
 
-error: generic arguments in macro path
-  --> $DIR/macro-ty-params.rs:12:15
-   |
-LL |     m!(Default<>);
-   |               ^^
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/tests/ui/stdlib-unit-tests/eq-multidispatch.rs b/tests/ui/stdlib-unit-tests/eq-multidispatch.rs
deleted file mode 100644
index 4a991624e34..00000000000
--- a/tests/ui/stdlib-unit-tests/eq-multidispatch.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-//@ run-pass
-
-#[derive(PartialEq, Debug)]
-struct Bar;
-#[derive(Debug)]
-struct Baz;
-#[derive(Debug)]
-struct Foo;
-#[derive(Debug)]
-struct Fu;
-
-impl PartialEq for Baz { fn eq(&self, _: &Baz) -> bool  { true } }
-
-impl PartialEq<Fu> for Foo { fn eq(&self, _: &Fu) -> bool { true } }
-impl PartialEq<Foo> for Fu { fn eq(&self, _: &Foo) -> bool { true } }
-
-impl PartialEq<Bar> for Foo { fn eq(&self, _: &Bar) -> bool { false } }
-impl PartialEq<Foo> for Bar { fn eq(&self, _: &Foo) -> bool { false } }
-
-fn main() {
-    assert!(Bar != Foo);
-    assert!(Foo != Bar);
-
-    assert_eq!(Bar, Bar);
-
-    assert_eq!(Baz, Baz);
-
-    assert_eq!(Foo, Fu);
-    assert_eq!(Fu, Foo);
-}
diff --git a/tests/crashes/113272.rs b/tests/ui/structs/ice-struct-tail-normalization-113272.rs
index d161575c657..85d3d1b4886 100644
--- a/tests/crashes/113272.rs
+++ b/tests/ui/structs/ice-struct-tail-normalization-113272.rs
@@ -1,9 +1,10 @@
-//@ known-bug: #113272
 trait Trait {
     type RefTarget;
 }
 
 impl Trait for () where Missing: Trait {}
+//~^ ERROR cannot find type `Missing` in this scope
+//~| ERROR not all trait items implemented, missing: `RefTarget`
 
 struct Other {
     data: <() as Trait>::RefTarget,
diff --git a/tests/ui/structs/ice-struct-tail-normalization-113272.stderr b/tests/ui/structs/ice-struct-tail-normalization-113272.stderr
new file mode 100644
index 00000000000..a205eb80f5c
--- /dev/null
+++ b/tests/ui/structs/ice-struct-tail-normalization-113272.stderr
@@ -0,0 +1,19 @@
+error[E0412]: cannot find type `Missing` in this scope
+  --> $DIR/ice-struct-tail-normalization-113272.rs:5:25
+   |
+LL | impl Trait for () where Missing: Trait {}
+   |                         ^^^^^^^ not found in this scope
+
+error[E0046]: not all trait items implemented, missing: `RefTarget`
+  --> $DIR/ice-struct-tail-normalization-113272.rs:5:1
+   |
+LL |     type RefTarget;
+   |     -------------- `RefTarget` from trait
+...
+LL | impl Trait for () where Missing: Trait {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `RefTarget` in implementation
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0046, E0412.
+For more information about an error, try `rustc --explain E0046`.
diff --git a/tests/ui/suggestions/unused-imports.fixed b/tests/ui/suggestions/unused-imports.fixed
new file mode 100644
index 00000000000..57dd091c043
--- /dev/null
+++ b/tests/ui/suggestions/unused-imports.fixed
@@ -0,0 +1,35 @@
+//@ run-rustfix
+//@ check-pass
+
+#![warn(unused_imports)]
+
+pub mod nested {
+    pub struct A;
+    pub struct B;
+    pub struct C;
+    pub struct D;
+    pub mod even_more {
+        pub struct E;
+        pub struct F;
+        pub struct G;
+    }
+    pub mod another {
+        pub struct H;
+        pub struct I;
+    }
+}
+
+use nested::B;
+//~^ WARN unused import
+
+use nested::even_more::F;
+//~^^^^^^^ WARN unused import
+
+// Note that the following fix should result in `::{self}`, not `::self`. The latter is invalid
+// Rust syntax, so the braces should not be removed.
+use nested::another::{self};
+//~^ WARN unused import
+
+fn main() {
+    let _ = (B, F, another::I);
+}
diff --git a/tests/ui/suggestions/unused-imports.rs b/tests/ui/suggestions/unused-imports.rs
new file mode 100644
index 00000000000..5f9dd243bdd
--- /dev/null
+++ b/tests/ui/suggestions/unused-imports.rs
@@ -0,0 +1,42 @@
+//@ run-rustfix
+//@ check-pass
+
+#![warn(unused_imports)]
+
+pub mod nested {
+    pub struct A;
+    pub struct B;
+    pub struct C;
+    pub struct D;
+    pub mod even_more {
+        pub struct E;
+        pub struct F;
+        pub struct G;
+    }
+    pub mod another {
+        pub struct H;
+        pub struct I;
+    }
+}
+
+use nested::{A, B, C};
+//~^ WARN unused import
+
+use nested::{
+    D,
+    even_more::{
+        E,
+        F,
+        G,
+                         },
+            };
+//~^^^^^^^ WARN unused import
+
+// Note that the following fix should result in `::{self}`, not `::self`. The latter is invalid
+// Rust syntax, so the braces should not be removed.
+use nested::another::{self, I};
+//~^ WARN unused import
+
+fn main() {
+    let _ = (B, F, another::I);
+}
diff --git a/tests/ui/suggestions/unused-imports.stderr b/tests/ui/suggestions/unused-imports.stderr
new file mode 100644
index 00000000000..bf112608da7
--- /dev/null
+++ b/tests/ui/suggestions/unused-imports.stderr
@@ -0,0 +1,32 @@
+warning: unused imports: `A`, `C`
+  --> $DIR/unused-imports.rs:22:14
+   |
+LL | use nested::{A, B, C};
+   |              ^     ^
+   |
+note: the lint level is defined here
+  --> $DIR/unused-imports.rs:4:9
+   |
+LL | #![warn(unused_imports)]
+   |         ^^^^^^^^^^^^^^
+
+warning: unused imports: `D`, `E`, `G`
+  --> $DIR/unused-imports.rs:26:5
+   |
+LL |     D,
+   |     ^
+LL |     even_more::{
+LL |         E,
+   |         ^
+LL |         F,
+LL |         G,
+   |         ^
+
+warning: unused import: `I`
+  --> $DIR/unused-imports.rs:37:29
+   |
+LL | use nested::another::{self, I};
+   |                             ^
+
+warning: 3 warnings emitted
+
diff --git a/tests/ui/target-feature/tied-features-cli.rs b/tests/ui/target-feature/tied-features-cli.rs
index 1168245461f..17c13826ce9 100644
--- a/tests/ui/target-feature/tied-features-cli.rs
+++ b/tests/ui/target-feature/tied-features-cli.rs
@@ -1,4 +1,4 @@
-//@ revisions: one two three
+//@ revisions: one two three four
 //@ compile-flags: --crate-type=rlib --target=aarch64-unknown-linux-gnu
 //@ needs-llvm-components: aarch64
 //
diff --git a/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.rs b/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.rs
new file mode 100644
index 00000000000..26d63fdde99
--- /dev/null
+++ b/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.rs
@@ -0,0 +1,9 @@
+//@ compile-flags: -Znext-solver
+
+#[derive(Debug)]
+struct X<const FN: fn() = { || {} }>;
+//~^ ERROR using function pointers as const generic parameters is forbidden
+//~| ERROR using function pointers as const generic parameters is forbidden
+//~| ERROR type annotations needed
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr b/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr
new file mode 100644
index 00000000000..044c24fd2b2
--- /dev/null
+++ b/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr
@@ -0,0 +1,26 @@
+error[E0282]: type annotations needed
+  --> $DIR/const-region-infer-to-static-in-binder.rs:4:10
+   |
+LL | struct X<const FN: fn() = { || {} }>;
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer the value of the constant `{ || {} }`
+
+error: using function pointers as const generic parameters is forbidden
+  --> $DIR/const-region-infer-to-static-in-binder.rs:4:20
+   |
+LL | struct X<const FN: fn() = { || {} }>;
+   |                    ^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+
+error: using function pointers as const generic parameters is forbidden
+  --> $DIR/const-region-infer-to-static-in-binder.rs:4:20
+   |
+LL | struct X<const FN: fn() = { || {} }>;
+   |                    ^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/next-solver/canonicalize-effect-var.rs b/tests/ui/traits/next-solver/canonical/effect-var.rs
index 6d0f09bb9be..6d0f09bb9be 100644
--- a/tests/ui/traits/next-solver/canonicalize-effect-var.rs
+++ b/tests/ui/traits/next-solver/canonical/effect-var.rs
diff --git a/tests/ui/traits/next-solver/canonical-int-var-eq-in-response.rs b/tests/ui/traits/next-solver/canonical/int-var-eq-in-response.rs
index 6c07817ff03..6c07817ff03 100644
--- a/tests/ui/traits/next-solver/canonical-int-var-eq-in-response.rs
+++ b/tests/ui/traits/next-solver/canonical/int-var-eq-in-response.rs
diff --git a/tests/ui/traits/next-solver/canonical-ty-var-eq-in-response.rs b/tests/ui/traits/next-solver/canonical/ty-var-eq-in-response.rs
index 2f9e919da2e..2f9e919da2e 100644
--- a/tests/ui/traits/next-solver/canonical-ty-var-eq-in-response.rs
+++ b/tests/ui/traits/next-solver/canonical/ty-var-eq-in-response.rs
diff --git a/tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-1.rs b/tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-1.rs
new file mode 100644
index 00000000000..151c3b226c1
--- /dev/null
+++ b/tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-1.rs
@@ -0,0 +1,43 @@
+//@ compile-flags: -Znext-solver=coherence
+//@ check-pass
+
+// A regression test for #124791. Computing ambiguity causes
+// for the overlap of the `ToString` impls caused an ICE.
+#![crate_type = "lib"]
+#![feature(min_specialization)]
+trait Display {}
+
+trait ToOwned {
+    type Owned;
+}
+
+impl<T> ToOwned for T {
+    type Owned = T;
+}
+
+struct Cow<B: ?Sized>(B);
+
+impl<B: ?Sized> Display for Cow<B>
+where
+    B: ToOwned,
+    B::Owned: Display,
+{
+}
+
+impl Display for () {}
+
+trait ToString {
+    fn to_string();
+}
+
+impl<T: Display + ?Sized> ToString for T {
+    default fn to_string() {}
+}
+
+impl ToString for Cow<str> {
+    fn to_string() {}
+}
+
+impl ToOwned for str {
+    type Owned = ();
+}
diff --git a/tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-2.rs b/tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-2.rs
new file mode 100644
index 00000000000..b472499cb0b
--- /dev/null
+++ b/tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-2.rs
@@ -0,0 +1,19 @@
+//@ compile-flags: -Znext-solver=coherence
+
+// A regression test for #124791. Computing ambiguity causes
+// for the overlap of the `ToString` impls caused an ICE.
+#![crate_type = "lib"]
+trait ToOwned {
+    type Owned;
+}
+impl<T> ToOwned for T {
+    type Owned = u8;
+}
+impl ToOwned for str {
+    type Owned = i8;
+}
+
+trait Overlap {}
+impl<T: ToOwned<Owned = i8> + ?Sized> Overlap for T {}
+impl Overlap for str {}
+//~^ ERROR conflicting implementations of trait `Overlap`
diff --git a/tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-2.stderr b/tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-2.stderr
new file mode 100644
index 00000000000..469f7a909b1
--- /dev/null
+++ b/tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-2.stderr
@@ -0,0 +1,11 @@
+error[E0119]: conflicting implementations of trait `Overlap` for type `str`
+  --> $DIR/ambiguity-causes-canonical-state-ice-2.rs:18:1
+   |
+LL | impl<T: ToOwned<Owned = i8> + ?Sized> Overlap for T {}
+   | --------------------------------------------------- first implementation here
+LL | impl Overlap for str {}
+   | ^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `str`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs
index bc9bb6ce2d7..7eea81ce03c 100644
--- a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs
+++ b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs
@@ -61,7 +61,7 @@ where
     // entering the cycle from `A` fails, but would work if we were to use the cache
     // result of `B<X>`.
     impls_trait::<A<X>, _, _, _>();
-    //~^ ERROR the trait bound `X: IncompleteGuidance<_, _>` is not satisfied
+    //~^ ERROR the trait bound `A<X>: Trait<_, _, _>` is not satisfied
 }
 
 fn main() {
diff --git a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.stderr b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.stderr
index 78116ebba82..ffa3f29e4bd 100644
--- a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.stderr
+++ b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.stderr
@@ -1,21 +1,20 @@
-error[E0277]: the trait bound `X: IncompleteGuidance<_, _>` is not satisfied
+error[E0277]: the trait bound `A<X>: Trait<_, _, _>` is not satisfied
   --> $DIR/incompleteness-unstable-result.rs:63:19
    |
 LL |     impls_trait::<A<X>, _, _, _>();
-   |                   ^^^^ the trait `IncompleteGuidance<_, _>` is not implemented for `X`, which is required by `A<X>: Trait<_, _, _>`
+   |                   ^^^^ the trait `Trait<_, _, _>` is not implemented for `A<X>`, which is required by `A<X>: Trait<_, _, _>`
    |
-   = help: the following other types implement trait `IncompleteGuidance<T, V>`:
-             <T as IncompleteGuidance<U, i16>>
-             <T as IncompleteGuidance<U, i8>>
-             <T as IncompleteGuidance<U, u8>>
-note: required for `A<X>` to implement `Trait<_, _, u8>`
+   = help: the trait `Trait<U, V, D>` is implemented for `A<T>`
+note: required for `A<X>` to implement `Trait<_, _, _>`
   --> $DIR/incompleteness-unstable-result.rs:32:50
    |
 LL | impl<T: ?Sized, U: ?Sized, V: ?Sized, D: ?Sized> Trait<U, V, D> for A<T>
    |                                                  ^^^^^^^^^^^^^^     ^^^^
-LL | where
-LL |     T: IncompleteGuidance<U, V>,
-   |        ------------------------ unsatisfied trait bound introduced here
+...
+LL |     A<T>: Trait<U, D, V>,
+   |           -------------- unsatisfied trait bound introduced here
+   = note: 8 redundant requirements hidden
+   = note: required for `A<X>` to implement `Trait<_, _, _>`
 note: required by a bound in `impls_trait`
   --> $DIR/incompleteness-unstable-result.rs:51:28
    |
diff --git a/tests/ui/traits/next-solver/diagnostics/point-at-failing-nested.rs b/tests/ui/traits/next-solver/diagnostics/point-at-failing-nested.rs
new file mode 100644
index 00000000000..840a4eb648c
--- /dev/null
+++ b/tests/ui/traits/next-solver/diagnostics/point-at-failing-nested.rs
@@ -0,0 +1,24 @@
+//@ compile-flags: -Znext-solver
+
+trait Foo {}
+trait Bar {}
+trait Constrain {
+    type Output;
+}
+
+impl<T, U> Foo for T
+where
+    T: Constrain<Output = U>,
+    U: Bar,
+{
+}
+
+impl Constrain for () {
+    type Output = ();
+}
+
+fn needs_foo<T: Foo>() {}
+fn main() {
+    needs_foo::<()>();
+    //~^ the trait bound `(): Foo` is not satisfied
+}
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
new file mode 100644
index 00000000000..6bf4e3cb534
--- /dev/null
+++ b/tests/ui/traits/next-solver/diagnostics/point-at-failing-nested.stderr
@@ -0,0 +1,23 @@
+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`
+   |
+note: required for `()` to implement `Foo`
+  --> $DIR/point-at-failing-nested.rs:9:12
+   |
+LL | impl<T, U> Foo for T
+   |            ^^^     ^
+...
+LL |     U: Bar,
+   |        --- unsatisfied trait bound introduced here
+note: required by a bound in `needs_foo`
+  --> $DIR/point-at-failing-nested.rs:20:17
+   |
+LL | fn needs_foo<T: Foo>() {}
+   |                 ^^^ required by this bound in `needs_foo`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/next-solver/diagnostics/where-clause-doesnt-apply.rs b/tests/ui/traits/next-solver/diagnostics/where-clause-doesnt-apply.rs
new file mode 100644
index 00000000000..4737546e404
--- /dev/null
+++ b/tests/ui/traits/next-solver/diagnostics/where-clause-doesnt-apply.rs
@@ -0,0 +1,22 @@
+trait Foo {}
+trait Bar {}
+
+impl<T> Foo for T where T: Bar {}
+fn needs_foo(_: impl Foo) {}
+
+trait Mirror {
+    type Mirror;
+}
+impl<T> Mirror for T {
+    type Mirror = T;
+}
+
+// Make sure the `Alias: Foo` bound doesn't "shadow" the impl, since the
+// impl is really the only candidate we care about here for the purpose
+// of error reporting.
+fn hello<T>() where <T as Mirror>::Mirror: Foo {
+    needs_foo(());
+    //~^ ERROR the trait bound `(): Foo` is not satisfied
+}
+
+fn main() {}
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
new file mode 100644
index 00000000000..77a0cc49754
--- /dev/null
+++ b/tests/ui/traits/next-solver/diagnostics/where-clause-doesnt-apply.stderr
@@ -0,0 +1,22 @@
+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`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required for `()` to implement `Foo`
+  --> $DIR/where-clause-doesnt-apply.rs:4:9
+   |
+LL | impl<T> Foo for T where T: Bar {}
+   |         ^^^     ^          --- unsatisfied trait bound introduced here
+note: required by a bound in `needs_foo`
+  --> $DIR/where-clause-doesnt-apply.rs:5:22
+   |
+LL | fn needs_foo(_: impl Foo) {}
+   |                      ^^^ required by this bound in `needs_foo`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/next-solver/generalize/hr-alias-non-hr-alias-self-ty-1.rs b/tests/ui/traits/next-solver/generalize/hr-alias-non-hr-alias-self-ty-1.rs
new file mode 100644
index 00000000000..3be118a5b39
--- /dev/null
+++ b/tests/ui/traits/next-solver/generalize/hr-alias-non-hr-alias-self-ty-1.rs
@@ -0,0 +1,36 @@
+//@ revisions: old next
+//@[next] compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@ check-pass
+
+// Generalizing an alias referencing escaping bound variables
+// is hard. We previously didn't replace this alias with inference
+// variables but did replace nested alias which do not reference
+// any bound variables. This caused us to stall with the following
+// goal, which cannot make any progress:
+//
+// <<T as Id>::Refl as HigherRanked>::Output<'a>
+//    alias-relate
+// <?unconstrained as HigherRanked>::Output<'a>
+//
+//
+// cc trait-system-refactor-initiative#110
+
+#![allow(unused)]
+trait HigherRanked {
+    type Output<'a>;
+}
+trait Id {
+    type Refl: HigherRanked;
+}
+
+fn foo<T: Id>() -> for<'a> fn(<<T as Id>::Refl as HigherRanked>::Output<'a>) {
+    todo!()
+}
+
+fn bar<T: Id>() {
+    // we generalize here
+    let x = foo::<T>();
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/generalize/hr-alias-non-hr-alias-self-ty-2.rs b/tests/ui/traits/next-solver/generalize/hr-alias-non-hr-alias-self-ty-2.rs
new file mode 100644
index 00000000000..560eb34a977
--- /dev/null
+++ b/tests/ui/traits/next-solver/generalize/hr-alias-non-hr-alias-self-ty-2.rs
@@ -0,0 +1,32 @@
+//@ revisions: old next
+//@[next] compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@ check-pass
+
+// A minimization of an ambiguity error in `icu_provider`.
+//
+// cc trait-system-refactor-initiative#110
+
+trait Yokeable<'a> {
+    type Output;
+}
+trait Id {
+    type Refl;
+}
+
+fn into_deserialized<M: Id>() -> M
+where
+    M::Refl: for<'a> Yokeable<'a>,
+{
+    try_map_project::<M, _>(|_| todo!())
+}
+
+fn try_map_project<M: Id, F>(_f: F) -> M
+where
+    M::Refl: for<'a> Yokeable<'a>,
+    F: for<'a> FnOnce(&'a ()) -> <<M as Id>::Refl as Yokeable<'a>>::Output,
+{
+    todo!()
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/generalize/hr-alias-universe-lowering-ambiguity.rs b/tests/ui/traits/next-solver/generalize/hr-alias-universe-lowering-ambiguity.rs
new file mode 100644
index 00000000000..1e2ba81129d
--- /dev/null
+++ b/tests/ui/traits/next-solver/generalize/hr-alias-universe-lowering-ambiguity.rs
@@ -0,0 +1,51 @@
+//@ compile-flags: -Znext-solver
+//@ check-pass
+
+// A regression test for a fairly subtle issue with how we
+// generalize aliases referencing higher-ranked regions
+// which previously caused unexpected ambiguity errors.
+//
+// The explanations in the test may end up being out of date
+// in the future as we may refine our approach to generalization
+// going forward.
+//
+// cc trait-system-refactor-initiative#108
+trait Trait<'a> {
+    type Assoc;
+}
+
+impl<'a> Trait<'a> for () {
+    type Assoc = ();
+}
+
+fn foo<T: for<'a> Trait<'a>>(x: T) -> for<'a> fn(<T as Trait<'a>>::Assoc) {
+    |_| ()
+}
+
+fn unconstrained<T>() -> T {
+    todo!()
+}
+
+fn main() {
+    // create `?x.0` in the root universe
+    let mut x = unconstrained();
+
+    // bump the current universe of the inference context
+    let bump: for<'a, 'b> fn(&'a (), &'b ()) = |_, _| ();
+    let _: for<'a> fn(&'a (), &'a ()) = bump;
+
+    // create `?y.1` in a higher universe
+    let mut y = Default::default();
+
+    // relate `?x.0` with `for<'a> fn(<?y.1 as Trait<'a>>::Assoc)`
+    // -> instantiate `?x.0` with `for<'a> fn(<?y_new.0 as Trait<'a>>::Assoc)`
+    x = foo(y);
+
+    // Constrain `?y.1` to `()`
+    let _: () = y;
+
+    // `AliasRelate(<?y_new.0 as Trait<'a>>::Assoc, <() as Trait<'a>>::Assoc)`
+    // remains ambiguous unless we somehow constrain `?y_new.0` during
+    // generalization to be equal to `?y.1`, which is exactly what we
+    // did to fix this issue.
+}
diff --git a/tests/ui/traits/next-solver/generalize/occurs-check-nested-alias.rs b/tests/ui/traits/next-solver/generalize/occurs-check-nested-alias.rs
index 536e7e97c40..00dc7a9d337 100644
--- a/tests/ui/traits/next-solver/generalize/occurs-check-nested-alias.rs
+++ b/tests/ui/traits/next-solver/generalize/occurs-check-nested-alias.rs
@@ -1,5 +1,6 @@
 //@ revisions: old next
 //@[next] compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@ check-pass
 
 // case 3 of https://github.com/rust-lang/trait-system-refactor-initiative/issues/8.
diff --git a/tests/ui/traits/next-solver/select-alias-bound-as-param.rs b/tests/ui/traits/next-solver/select-alias-bound-as-param.rs
new file mode 100644
index 00000000000..fd40ef1f872
--- /dev/null
+++ b/tests/ui/traits/next-solver/select-alias-bound-as-param.rs
@@ -0,0 +1,13 @@
+//@ check-pass
+//@ compile-flags: -Znext-solver
+
+pub(crate) fn y() -> impl FnMut() {
+    || {}
+}
+
+pub(crate) fn x(a: (), b: ()) {
+    let x = ();
+    y()()
+}
+
+fn main() {}
diff --git a/tests/ui/traits/normalize-supertrait.rs b/tests/ui/traits/normalize-supertrait.rs
index 1ab2b8ecfc1..3ba4a8b8bab 100644
--- a/tests/ui/traits/normalize-supertrait.rs
+++ b/tests/ui/traits/normalize-supertrait.rs
@@ -4,6 +4,9 @@
 // comparing the supertrait `Derived<()>` to the expected trait.
 
 //@ build-pass
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
 
 trait Proj {
     type S;
diff --git a/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl-opaque.next.stderr b/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl-opaque.next.stderr
deleted file mode 100644
index 3c2bc0b9190..00000000000
--- a/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl-opaque.next.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error: internal compiler error: error performing operation: query type op
-  --> $DIR/illegal-upcast-from-impl-opaque.rs:25:1
-   |
-LL | fn illegal(x: &dyn Sub<Assoc = Foo>) -> &dyn Super<Assoc = i32> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: 
-  --> $DIR/illegal-upcast-from-impl-opaque.rs:25:1
-   |
-LL | fn illegal(x: &dyn Sub<Assoc = Foo>) -> &dyn Super<Assoc = i32> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-query stack during panic:
-end of query stack
diff --git a/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl-opaque.rs b/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl-opaque.rs
deleted file mode 100644
index f344474054a..00000000000
--- a/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl-opaque.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-//@ revisions: current next
-//@[next] compile-flags: -Znext-solver
-//@[next] failure-status: 101
-//@[next] known-bug: unknown
-//@[next] normalize-stderr-test "note: .*\n\n" -> ""
-//@[next] normalize-stderr-test "thread 'rustc' panicked.*\n.*\n" -> ""
-//@[next] normalize-stderr-test "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: "
-//@[next] normalize-stderr-test "delayed at .*" -> ""
-//@[next] rustc-env:RUST_BACKTRACE=0
-
-#![feature(trait_upcasting, type_alias_impl_trait)]
-
-trait Super {
-    type Assoc;
-}
-
-trait Sub: Super {}
-
-impl<T: ?Sized> Super for T {
-    type Assoc = i32;
-}
-
-type Foo = impl Sized;
-
-fn illegal(x: &dyn Sub<Assoc = Foo>) -> &dyn Super<Assoc = i32> {
-    x //[current]~ mismatched types
-}
-
-fn main() {}
diff --git a/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl-opaque.current.stderr b/tests/ui/traits/trait-upcasting/upcast-defining-opaque.current.stderr
index c54a1c42bad..a259abb28ae 100644
--- a/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl-opaque.current.stderr
+++ b/tests/ui/traits/trait-upcasting/upcast-defining-opaque.current.stderr
@@ -1,11 +1,11 @@
 error[E0308]: mismatched types
-  --> $DIR/illegal-upcast-from-impl-opaque.rs:26:5
+  --> $DIR/upcast-defining-opaque.rs:21:5
    |
 LL | type Foo = impl Sized;
    |            ---------- the found opaque type
 LL |
-LL | fn illegal(x: &dyn Sub<Assoc = Foo>) -> &dyn Super<Assoc = i32> {
-   |                                         ----------------------- expected `&dyn Super<Assoc = i32>` because of return type
+LL | fn upcast(x: &dyn Sub<Assoc = Foo>) -> &dyn Super<Assoc = i32> {
+   |                                        ----------------------- expected `&dyn Super<Assoc = i32>` because of return type
 LL |     x
    |     ^ expected trait `Super`, found trait `Sub`
    |
diff --git a/tests/ui/traits/trait-upcasting/upcast-defining-opaque.rs b/tests/ui/traits/trait-upcasting/upcast-defining-opaque.rs
new file mode 100644
index 00000000000..cb1501a94a2
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/upcast-defining-opaque.rs
@@ -0,0 +1,24 @@
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] check-pass
+
+#![feature(trait_upcasting, type_alias_impl_trait)]
+
+trait Super {
+    type Assoc;
+}
+
+trait Sub: Super {}
+
+impl<T: ?Sized> Super for T {
+    type Assoc = i32;
+}
+
+type Foo = impl Sized;
+
+fn upcast(x: &dyn Sub<Assoc = Foo>) -> &dyn Super<Assoc = i32> {
+    x //[current]~ mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/transmutability/primitives/bool-mut.rs b/tests/ui/transmutability/primitives/bool-mut.rs
index 5f3f4f3a8c5..09b6d582d87 100644
--- a/tests/ui/transmutability/primitives/bool-mut.rs
+++ b/tests/ui/transmutability/primitives/bool-mut.rs
@@ -1,5 +1,4 @@
 //@ check-fail
-//@[next] compile-flags: -Znext-solver
 
 #![feature(transmutability)]
 mod assert {
diff --git a/tests/ui/transmutability/primitives/bool-mut.stderr b/tests/ui/transmutability/primitives/bool-mut.stderr
index 464c2755e11..a6cf146659e 100644
--- a/tests/ui/transmutability/primitives/bool-mut.stderr
+++ b/tests/ui/transmutability/primitives/bool-mut.stderr
@@ -1,11 +1,11 @@
 error[E0277]: `u8` cannot be safely transmuted into `bool`
-  --> $DIR/bool-mut.rs:15:50
+  --> $DIR/bool-mut.rs:14:50
    |
 LL |     assert::is_transmutable::<&'static mut bool, &'static mut u8>()
    |                                                  ^^^^^^^^^^^^^^^ at least one value of `u8` isn't a bit-valid value of `bool`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/bool-mut.rs:10:14
+  --> $DIR/bool-mut.rs:9:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
diff --git a/tests/ui/type/pattern_types/range_patterns_usage.rs b/tests/ui/type/pattern_types/range_patterns_usage.rs
index 7fe50423c51..2a9f736ae61 100644
--- a/tests/ui/type/pattern_types/range_patterns_usage.rs
+++ b/tests/ui/type/pattern_types/range_patterns_usage.rs
@@ -8,7 +8,7 @@
 
 use std::pat::pattern_type;
 
-type X = std::num::NonZeroU32;
+type X = std::num::NonZero<u32>;
 type Y = pattern_type!(u32 is 1..);
 type Z = Option<pattern_type!(u32 is 1..)>;
 struct NonZeroU32New(pattern_type!(u32 is 1..));
diff --git a/tests/ui/typeck/issue-100285.rs b/tests/ui/typeck/issue-100285.rs
index 460e0457105..bea4b2bc2bb 100644
--- a/tests/ui/typeck/issue-100285.rs
+++ b/tests/ui/typeck/issue-100285.rs
@@ -1,4 +1,4 @@
-fn foo(n: i32) -> i32 { //~ HELP otherwise consider changing the return type to account for that possibility
+fn foo(n: i32) -> i32 {
     for i in 0..0 { //~ ERROR mismatched types [E0308]
        if n < 0 {
         return i;
@@ -14,7 +14,7 @@ fn foo(n: i32) -> i32 { //~ HELP otherwise consider changing the return type to
           return 5;
         }
 
-    } //~ HELP return a value for the case when the loop has zero elements to iterate on
+    } //~ HELP consider returning a value here
 }
 
 fn main() {}
diff --git a/tests/ui/typeck/issue-100285.stderr b/tests/ui/typeck/issue-100285.stderr
index c0deb63af59..6f86fd18e0f 100644
--- a/tests/ui/typeck/issue-100285.stderr
+++ b/tests/ui/typeck/issue-100285.stderr
@@ -12,47 +12,12 @@ LL | |
 LL | |     }
    | |_____^ expected `i32`, found `()`
    |
-note: the function expects a value to always be returned, but loops might run zero times
-  --> $DIR/issue-100285.rs:2:5
-   |
-LL |     for i in 0..0 {
-   |     ^^^^^^^^^^^^^ this might have zero elements to iterate on
-LL |        if n < 0 {
-LL |         return i;
-   |         -------- if the loop doesn't execute, this value would never get returned
-LL |         } else if n < 10 {
-LL |           return 1;
-   |           -------- if the loop doesn't execute, this value would never get returned
-LL |         } else if n < 20 {
-LL |           return 2;
-   |           -------- if the loop doesn't execute, this value would never get returned
-   = note: if the loop doesn't execute, 3 other values would never get returned
-help: return a value for the case when the loop has zero elements to iterate on
+   = note: `for` loops evaluate to unit type `()`
+help: consider returning a value here
    |
 LL ~     }
 LL ~     /* `i32` value */
    |
-help: otherwise consider changing the return type to account for that possibility
-   |
-LL ~ fn foo(n: i32) -> Option<i32> {
-LL |     for i in 0..0 {
-LL |        if n < 0 {
-LL ~         return Some(i);
-LL |         } else if n < 10 {
-LL ~           return Some(1);
-LL |         } else if n < 20 {
-LL ~           return Some(2);
-LL |         } else if n < 30 {
-LL ~           return Some(3);
-LL |         } else if n < 40 {
-LL ~           return Some(4);
-LL |         } else {
-LL ~           return Some(5);
-LL |         }
-LL |
-LL ~     }
-LL ~     None
-   |
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/typeck/issue-98982.rs b/tests/ui/typeck/issue-98982.rs
index f875d20fa4c..3eff9fbe360 100644
--- a/tests/ui/typeck/issue-98982.rs
+++ b/tests/ui/typeck/issue-98982.rs
@@ -1,7 +1,7 @@
-fn foo() -> i32 { //~ HELP otherwise consider changing the return type to account for that possibility
+fn foo() -> i32 {
     for i in 0..0 { //~ ERROR mismatched types [E0308]
         return i;
-    } //~ HELP return a value for the case when the loop has zero elements to iterate on
+    } //~ HELP consider returning a value here
 }
 
 fn main() {}
diff --git a/tests/ui/typeck/issue-98982.stderr b/tests/ui/typeck/issue-98982.stderr
index d8d5a86b157..3d40ff4d5af 100644
--- a/tests/ui/typeck/issue-98982.stderr
+++ b/tests/ui/typeck/issue-98982.stderr
@@ -8,26 +8,12 @@ LL | |         return i;
 LL | |     }
    | |_____^ expected `i32`, found `()`
    |
-note: the function expects a value to always be returned, but loops might run zero times
-  --> $DIR/issue-98982.rs:2:5
-   |
-LL |     for i in 0..0 {
-   |     ^^^^^^^^^^^^^ this might have zero elements to iterate on
-LL |         return i;
-   |         -------- if the loop doesn't execute, this value would never get returned
-help: return a value for the case when the loop has zero elements to iterate on
+   = note: `for` loops evaluate to unit type `()`
+help: consider returning a value here
    |
 LL ~     }
 LL ~     /* `i32` value */
    |
-help: otherwise consider changing the return type to account for that possibility
-   |
-LL ~ fn foo() -> Option<i32> {
-LL |     for i in 0..0 {
-LL ~         return Some(i);
-LL ~     }
-LL ~     None
-   |
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/version/version-info-flags.rs b/tests/ui/version/version-info-flags.rs
index 612113452c4..96be9c5385b 100644
--- a/tests/ui/version/version-info-flags.rs
+++ b/tests/ui/version/version-info-flags.rs
@@ -4,6 +4,6 @@
 //@ check-pass
 //@[version] compile-flags: -V
 //@[verbose-version] compile-flags: -vV
-//@[long-verbose-verison] compile-flags: --version --verbose
+//@[long-verbose-version] compile-flags: --version --verbose
 
 fn main() {}
diff --git a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.rs b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.rs
new file mode 100644
index 00000000000..2995f26af4a
--- /dev/null
+++ b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.rs
@@ -0,0 +1,21 @@
+// Regression test for ICE #122989
+trait Foo<const N: Bar<2>> {
+//~^ WARN trait objects without an explicit `dyn` are deprecated
+//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+//~| ERROR cycle detected when computing type of `Foo::N`
+//~| ERROR cycle detected when computing type of `Foo::N`
+//~| ERROR the trait `Foo` cannot be made into an object
+//~| ERROR the trait `Foo` cannot be made into an object
+//~| ERROR the trait `Foo` cannot be made into an object
+//~| ERROR `(dyn Bar<2> + 'static)` is forbidden as the type of a const generic parameter
+    fn func() {
+    }
+}
+
+trait Bar<const M: Foo<2>> {}
+//~^ WARN trait objects without an explicit `dyn` are deprecated
+//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+//~| ERROR the trait `Foo` cannot be made into an object
+//~| ERROR `(dyn Foo<2> + 'static)` is forbidden as the type of a const generic parameter
+
+fn main() {}
diff --git a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr
new file mode 100644
index 00000000000..e6fdc440873
--- /dev/null
+++ b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr
@@ -0,0 +1,179 @@
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:20
+   |
+LL | trait Foo<const N: Bar<2>> {
+   |                    ^^^^^^
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: `#[warn(bare_trait_objects)]` on by default
+help: if this is an object-safe trait, use `dyn`
+   |
+LL | trait Foo<const N: dyn Bar<2>> {
+   |                    +++
+
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:15:20
+   |
+LL | trait Bar<const M: Foo<2>> {}
+   |                    ^^^^^^
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+help: if this is an object-safe trait, use `dyn`
+   |
+LL | trait Bar<const M: dyn Foo<2>> {}
+   |                    +++
+
+error[E0391]: cycle detected when computing type of `Foo::N`
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:11
+   |
+LL | trait Foo<const N: Bar<2>> {
+   |           ^^^^^^^^^^^^^^^
+   |
+note: ...which requires computing type of `Bar::M`...
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:15:11
+   |
+LL | trait Bar<const M: Foo<2>> {}
+   |           ^^^^^^^^^^^^^^^
+   = note: ...which again requires computing type of `Foo::N`, completing the cycle
+note: cycle used when computing explicit predicates of trait `Foo`
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:1
+   |
+LL | trait Foo<const N: Bar<2>> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = 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[E0391]: cycle detected when computing type of `Foo::N`
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:11
+   |
+LL | trait Foo<const N: Bar<2>> {
+   |           ^^^^^^^^^^^^^^^
+   |
+note: ...which requires computing type of `Bar::M`...
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:15:11
+   |
+LL | trait Bar<const M: Foo<2>> {}
+   |           ^^^^^^^^^^^^^^^
+   = note: ...which again requires computing type of `Foo::N`, completing the cycle
+note: cycle used when computing explicit predicates of trait `Foo`
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:1
+   |
+LL | trait Foo<const N: Bar<2>> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = 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
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:24
+   |
+LL | trait Foo<const N: Bar<2>> {
+   |                        ^ `Foo` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:8
+   |
+LL | trait Foo<const N: Bar<2>> {
+   |       --- this trait cannot be made into an object...
+...
+LL |     fn func() {
+   |        ^^^^ ...because associated function `func` has no `self` parameter
+help: consider turning `func` into a method by giving it a `&self` argument
+   |
+LL |     fn func(&self) {
+   |             +++++
+help: alternatively, consider constraining `func` so it does not apply to trait objects
+   |
+LL |     fn func() where Self: Sized {
+   |               +++++++++++++++++
+
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:11
+   |
+LL | trait Foo<const N: Bar<2>> {
+   |           ^^^^^^^^^^^^^^^ `Foo` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:8
+   |
+LL | trait Foo<const N: Bar<2>> {
+   |       --- this trait cannot be made into an object...
+...
+LL |     fn func() {
+   |        ^^^^ ...because associated function `func` has no `self` parameter
+help: consider turning `func` into a method by giving it a `&self` argument
+   |
+LL |     fn func(&self) {
+   |             +++++
+help: alternatively, consider constraining `func` so it does not apply to trait objects
+   |
+LL |     fn func() where Self: Sized {
+   |               +++++++++++++++++
+
+error: `(dyn Bar<2> + 'static)` is forbidden as the type of a const generic parameter
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:20
+   |
+LL | trait Foo<const N: Bar<2>> {
+   |                    ^^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:15:11
+   |
+LL | trait Bar<const M: Foo<2>> {}
+   |           ^^^^^^^^^^^^^^^ `Foo` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:8
+   |
+LL | trait Foo<const N: Bar<2>> {
+   |       --- this trait cannot be made into an object...
+...
+LL |     fn func() {
+   |        ^^^^ ...because associated function `func` has no `self` parameter
+help: consider turning `func` into a method by giving it a `&self` argument
+   |
+LL |     fn func(&self) {
+   |             +++++
+help: alternatively, consider constraining `func` so it does not apply to trait objects
+   |
+LL |     fn func() where Self: Sized {
+   |               +++++++++++++++++
+
+error: `(dyn Foo<2> + 'static)` is forbidden as the type of a const generic parameter
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:15:20
+   |
+LL | trait Bar<const M: Foo<2>> {}
+   |                    ^^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:11
+   |
+LL | trait Foo<const N: Bar<2>> {
+   |           ^^^^^^^^^^^^^^^ `Foo` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:8
+   |
+LL | trait Foo<const N: Bar<2>> {
+   |       --- this trait cannot be made into an object...
+...
+LL |     fn func() {
+   |        ^^^^ ...because associated function `func` has no `self` parameter
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: consider turning `func` into a method by giving it a `&self` argument
+   |
+LL |     fn func(&self) {
+   |             +++++
+help: alternatively, consider constraining `func` so it does not apply to trait objects
+   |
+LL |     fn func() where Self: Sized {
+   |               +++++++++++++++++
+
+error: aborting due to 8 previous errors; 2 warnings emitted
+
+Some errors have detailed explanations: E0038, E0391.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/triagebot.toml b/triagebot.toml
index 499ba6e470c..dd6a03faaaf 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -106,12 +106,18 @@ resolved/implemented on Fuchsia. Could one of you weigh in?
 """
 label = "O-fuchsia"
 
-[ping.macos]
+[ping.apple]
+alias = ["macos", "ios", "tvos", "watchos", "visionos"]
 message = """\
-Hey MacOS Group! This issue or PR could use some MacOS-specific guidance. Could one
-of you weigh in? Thanks <3
+Hey Apple notification group! This issue or PR could use some Apple-specific
+guidance. Could one of you weigh in? Thanks <3
+
+(In case it's useful, here are some [instructions] for tackling these sorts of
+issues).
+
+[instructions]: https://rustc-dev-guide.rust-lang.org/notification-groups/apple.html
 """
-label = "O-macos"
+label = "O-apple"
 
 [prioritize]
 label = "I-prioritize"
@@ -227,7 +233,9 @@ trigger_files = [
 
 [autolabel."O-macos"]
 trigger_files = [
-    "library/std/src/os/macos"
+    "library/std/src/os/macos",
+    "library/std/src/sys/pal/unix/thread_parking/darwin.rs",
+    "compiler/rustc_target/src/spec/base/apple",
 ]
 
 [autolabel."O-netbsd"]
@@ -1057,3 +1065,7 @@ project-exploit-mitigations = [
 # Enable tracking of PR review assignment
 # Documentation at: https://forge.rust-lang.org/triagebot/pr-assignment-tracking.html
 [pr-tracking]
+
+# Enable issue transfers within the org
+# Documentation at: https://forge.rust-lang.org/triagebot/transfer.html
+[transfer]